summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2020-03-04 09:54:35 +0100
committerShawn Rutledge <shawn.rutledge@qt.io>2020-03-04 14:39:18 +0000
commit2a4b95778993b00499eb94f61a87330fdbadf947 (patch)
tree168147adcc2854cb6723335b5abffe9d7585c7f4
parentb4e17a48646a1d2156b7d56ab6003db46af79cec (diff)
parent048f0a00fa7b46f531fbe3ed6d1babae9858e8c2 (diff)
Merge remote-tracking branch 'origin/5.15' into dev
-rw-r--r--doc/global/manifest-meta.qdocconf175
-rw-r--r--examples/network/http/main.cpp6
-rw-r--r--examples/widgets/graphicsview/collidingmice/main.cpp3
-rw-r--r--examples/widgets/graphicsview/diagramscene/main.cpp3
-rw-r--r--examples/widgets/itemviews/addressbook/main.cpp3
-rw-r--r--examples/widgets/itemviews/spreadsheet/main.cpp4
-rw-r--r--examples/widgets/layouts/basiclayouts/main.cpp4
-rw-r--r--examples/widgets/layouts/dynamiclayouts/main.cpp5
-rw-r--r--examples/widgets/mainwindows/application/main.cpp3
-rw-r--r--examples/widgets/mainwindows/dockwidgets/main.cpp3
-rw-r--r--examples/widgets/painting/affine/main.cpp4
-rw-r--r--examples/widgets/painting/affine/xform.cpp22
-rw-r--r--examples/widgets/painting/concentriccircles/main.cpp3
-rw-r--r--examples/widgets/painting/fontsampler/main.cpp3
-rw-r--r--examples/widgets/painting/gradients/gradients.cpp23
-rw-r--r--examples/widgets/painting/gradients/main.cpp3
-rw-r--r--examples/widgets/painting/pathstroke/main.cpp3
-rw-r--r--examples/widgets/tools/undo/main.cpp3
-rw-r--r--examples/widgets/widgets/calculator/main.cpp3
-rw-r--r--examples/widgets/widgets/elidedlabel/main.cpp3
-rw-r--r--examples/widgets/widgets/scribble/main.cpp3
-rw-r--r--examples/widgets/widgets/sliders/main.cpp3
-rw-r--r--examples/xml/rsslisting/rsslisting.cpp2
-rw-r--r--mkspecs/features/qt_common.prf2
-rw-r--r--src/corelib/global/qfloat16.cpp2
-rw-r--r--src/corelib/kernel/qeventdispatcher_win.cpp8
-rw-r--r--src/corelib/kernel/qeventdispatcher_win_p.h1
-rw-r--r--src/corelib/kernel/qwineventnotifier.cpp5
-rw-r--r--src/corelib/mimetypes/qmimeprovider.cpp10
-rw-r--r--src/corelib/mimetypes/qmimeprovider_p.h5
-rw-r--r--src/corelib/text/qstring.cpp3
-rw-r--r--src/corelib/time/qdatetime.cpp24
-rw-r--r--src/corelib/tools/qhash.cpp8
-rw-r--r--src/corelib/tools/qhash.h43
-rw-r--r--src/corelib/tools/qiterator.h26
-rw-r--r--src/corelib/tools/qiterator.qdoc13
-rw-r--r--src/corelib/tools/qmap.cpp8
-rw-r--r--src/corelib/tools/qmap.h53
-rw-r--r--src/gui/image/qbmphandler.cpp7
-rw-r--r--src/gui/image/qbmphandler_p.h3
-rw-r--r--src/gui/image/qpnghandler.cpp7
-rw-r--r--src/gui/image/qpnghandler_p.h4
-rw-r--r--src/gui/image/qppmhandler.cpp7
-rw-r--r--src/gui/image/qppmhandler_p.h4
-rw-r--r--src/gui/image/qxbmhandler.cpp7
-rw-r--r--src/gui/image/qxbmhandler_p.h4
-rw-r--r--src/gui/image/qxpmhandler.cpp7
-rw-r--r--src/gui/image/qxpmhandler_p.h4
-rw-r--r--src/gui/kernel/qwindow.cpp10
-rw-r--r--src/gui/kernel/qwindowsysteminterface.cpp13
-rw-r--r--src/gui/rhi/qrhi.cpp33
-rw-r--r--src/gui/rhi/qrhi_p.h1
-rw-r--r--src/gui/rhi/qrhid3d11.cpp269
-rw-r--r--src/gui/rhi/qrhid3d11_p_p.h24
-rw-r--r--src/gui/rhi/qrhimetal.mm23
-rw-r--r--src/gui/rhi/qrhimetal_p_p.h1
-rw-r--r--src/gui/rhi/qrhivulkan.cpp90
-rw-r--r--src/gui/rhi/qrhivulkan_p.h1
-rw-r--r--src/gui/rhi/qrhivulkan_p_p.h4
-rw-r--r--src/gui/rhi/qshader.cpp3
-rw-r--r--src/gui/rhi/qshader_p_p.h3
-rw-r--r--src/gui/rhi/qshaderdescription.cpp57
-rw-r--r--src/gui/rhi/qshaderdescription_p.h3
-rw-r--r--src/gui/rhi/qshaderdescription_p_p.h2
-rw-r--r--src/gui/text/qtextmarkdownimporter.cpp7
-rw-r--r--src/gui/text/qtextmarkdownimporter_p.h3
-rw-r--r--src/gui/vulkan/qvulkaninstance.cpp2
-rw-r--r--src/gui/vulkan/qvulkanwindow.cpp13
-rw-r--r--src/gui/vulkan/qvulkanwindow.h1
-rw-r--r--src/network/access/qnetworkreply.cpp15
-rw-r--r--src/network/access/qnetworkreply.h4
-rw-r--r--src/network/access/qnetworkreplydataimpl.cpp2
-rw-r--r--src/network/access/qnetworkreplyhttpimpl.cpp2
-rw-r--r--src/network/access/qnetworkreplyimpl.cpp4
-rw-r--r--src/plugins/imageformats/gif/qgifhandler.cpp7
-rw-r--r--src/plugins/imageformats/gif/qgifhandler_p.h4
-rw-r--r--src/plugins/imageformats/ico/qicohandler.cpp11
-rw-r--r--src/plugins/imageformats/ico/qicohandler.h4
-rw-r--r--src/plugins/imageformats/jpeg/qjpeghandler.cpp7
-rw-r--r--src/plugins/imageformats/jpeg/qjpeghandler_p.h4
-rw-r--r--src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp25
-rw-r--r--src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm61
-rw-r--r--src/plugins/platforms/cocoa/qcocoanativeinterface.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoavulkaninstance.h6
-rw-r--r--src/plugins/platforms/cocoa/qcocoavulkaninstance.mm9
-rw-r--r--src/plugins/platforms/cocoa/qpaintengine_mac.mm21
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp4
-rw-r--r--src/plugins/platforms/windows/qwindowssystemtrayicon.cpp6
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp4
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp4
-rw-r--r--src/tools/uic/python/pythonwriteimports.cpp2
-rw-r--r--src/widgets/widgets/qmenu.cpp9
-rw-r--r--tests/auto/corelib/kernel/qdeadlinetimer/tst_qdeadlinetimer.cpp50
-rw-r--r--tests/auto/corelib/kernel/qelapsedtimer/tst_qelapsedtimer.cpp47
-rw-r--r--tests/auto/corelib/text/qstring/tst_qstring.cpp3
-rw-r--r--tests/auto/corelib/tools/qhash/tst_qhash.cpp6
-rw-r--r--tests/auto/corelib/tools/qmap/tst_qmap.cpp6
-rw-r--r--tests/auto/gui/rhi/qshader/tst_qshader.cpp4
-rw-r--r--tests/auto/gui/text/qtextmarkdownimporter/data/fuzz20450.md5
-rw-r--r--tests/auto/gui/text/qtextmarkdownimporter/data/fuzz20580.md1
-rw-r--r--tests/auto/gui/text/qtextmarkdownimporter/qtextmarkdownimporter.pro2
-rw-r--r--tests/auto/gui/text/qtextmarkdownimporter/tst_qtextmarkdownimporter.cpp24
-rw-r--r--tests/auto/network/access/http2/tst_http2.cpp2
-rw-r--r--tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp6
-rw-r--r--tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp2
-rw-r--r--tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp42
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp4
-rw-r--r--tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp79
-rwxr-xr-xutil/locale_database/cldr2qlocalexml.py6
-rw-r--r--util/locale_database/qlocalexml.py (renamed from util/locale_database/localexml.py)9
-rwxr-xr-xutil/locale_database/qlocalexml2cpp.py6
111 files changed, 1067 insertions, 569 deletions
diff --git a/doc/global/manifest-meta.qdocconf b/doc/global/manifest-meta.qdocconf
index 3db67a3131..f5e5dbf8db 100644
--- a/doc/global/manifest-meta.qdocconf
+++ b/doc/global/manifest-meta.qdocconf
@@ -32,84 +32,103 @@ manifestmeta.filters = highlighted android thumbnail ios
manifestmeta.highlighted.attributes = isHighlighted:true
-manifestmeta.android.names = "QtQuick/Qt Quick Demo - Calqlatr" \
- "QtWidgets/Application Chooser Example" \
- "QtWidgets/Stickman Example" \
- "QtWidgets/Move Blocks Example" \
- "QtWidgets/Border Layout Example" \
- "QtWidgets/Flow Layout Example" \
- "QtWidgets/Dock Widgets Example" \
- "QtWidgets/Recent Files Example" \
- "QtWidgets/Concentric Circles Example" \
- "QtWidgets/Gradients" \
- "QtWidgets/Font Sampler Example" \
- "QtWidgets/Path Stroking" \
- "QtWidgets/Transformations Example" \
- "QtWidgets/Syntax Highlighter Example" \
- "QtWidgets/Calendar Example" \
- "QtWidgets/Analog Clock Example" \
- "QtWidgets/Calculator Example" \
- "QtWidgets/Mouse Button Tester" \
- "QtWidgets/Character Map Example" \
- "QtWidgets/Digital Clock Example" \
- "QtWidgets/Elided Label Example" \
- "QtWidgets/Sliders Example" \
- "QtWidgets/Tetrix Example" \
- "QtWidgets/Group Box Example" \
- "QtWidgets/Undo Framework" \
- "QtWidgets/Colliding Mice Example" \
- "QtWidgets/Diagram Scene Example" \
- "QtWidgets/Elastic Nodes Example" \
- "QtWidgets/Weather Anchor Layout Example" \
- "QtNetwork/Torrent Example" \
- "QtNetwork/Network Chat Example" \
- "QtSQL/Master Detail Example" \
- "QtLinguist/Arrow Pad Example" \
- "QtGui/Raster Window Example" \
- "QtGui/Analog Clock Window Example" \
- "QtAndroidExtras/Qt Notifier" \
- "QtMultimedia/QML Video Shader Effects Example" \
- "QtMultimedia/QML Video Example" \
- "QtMultimedia/QML Camera Example" \
- "QtSVG/Text Object Example" \
- "QtQML/Qt Quick Examples - XMLHttpRequest" \
- "QtQuick/Qt Quick Particles Examples - *" \
- "QtQuick/Qt Quick Examples - Touch Interaction" \
- "QtQuick/Scene Graph - Custom Geometry" \
- "QtQuick/Scene Graph - Graph" \
- "QtQuick/Scene Graph - OpenGL Under QML" \
- "QtQuick/Scene Graph - Painted Item" \
- "QtQuick/Scene Graph - Rendering FBOs" \
- "QtQuick/Scene Graph - Simple Material" \
- "QtQuick/Qt Quick Examples - Image Elements" \
- "QtQuick/Qt Quick Examples - Key Interaction" \
- "QtQuick/Qt Quick Examples - Text" \
- "QtQuick/Qt Quick Examples - Animation" \
- "QtQuick/Qt Quick Examples - Shader Effects" \
- "QtQuick/Qt Quick Examples - Canvas" \
- "QtQuick/Qt Quick Examples - MouseArea" \
- "QtQuick/Qt Quick Examples - Positioners" \
- "QtQuick/Qt Quick Examples - Right to Left" \
- "QtWidgets/Interview" \
- "QtWidgets/Spreadsheet" \
- "QtWidgets/Pixelator Example" \
- "QtWidgets/Animated Tiles Example" \
- "QtWidgets/Affine Transformations" \
- "QtWidgets/Image Composition Example" \
- "QtWidgets/Basic Drawing Example" \
- "QtWidgets/Vector Deformation" \
- "QtWidgets/Painter Paths Example" \
- "QtWidgets/Style Sheet Example" \
- "QtWidgets/Code Editor Example" \
- "QtWidgets/Scribble Example" \
- "QtWidgets/Line Edits Example" \
- "QtWidgets/Calendar Widget Example" \
- "QtWidgets/Completer Example" \
- "QtWidgets/I18N Example" \
- "QtQML/Extending QML - Grouped Properties Example" \
- "QtQML/Extending QML - Methods Example" \
- "QtQML/Extending QML - Signal Support Example" \
- "QtQML/Extending QML - Attached Properties Example"
+manifestmeta.android.names = "Qt3D/Qt 3D: Basic Shapes C++ Example" \
+ "Qt3D/Qt 3D: Planets QML Example" \
+ "Qt3D/Qt 3D: Simple Custom Material QML Example" \
+ "QtAndroidExtras/Qt Notifier" \
+ "QtBluetooth/Bluetooth Low Energy Scanner Example" \
+ "QtBluetooth/Bluetooth Scanner Example" \
+ "QtBluetooth/QML Bluetooth Scanner Example" \
+ "QtCharts/*" \
+ "QtConcurrent/QtConcurrent Progress Dialog Example" \
+ "QtDataVisualization/Audiolevels Example" \
+ "QtDataVisualization/Qt Quick 2 Scatter Example" \
+ "QtDataVisualization/Qt Quick 2 Surface Multiseries Example" \
+ "QtGui/Analog Clock Window Example" \
+ "QtGui/OpenGL Window Example" \
+ "QtGui/Raster Window Example" \
+ "QtLinguist/Arrow Pad Example" \
+ "QtLinguistManual/Hello tr() Example" \
+ "QtLocation/Map Viewer (QML)" \
+ "QtLocation/Places Map (QML)" \
+ "QtLocation/Plane Spotter (QML)" \
+ "QtMultimedia/AudioEngine Example" \
+ "QtMultimedia/Camera Example" \
+ "QtMultimedia/QML Camera Example" \
+ "QtMultimedia/QML Video Example" \
+ "QtMultimedia/QML Video Shader Effects Example" \
+ "QtNFC/Annotated URL Example" \
+ "QtNFC/QML Poster Example" \
+ "QtOpenGL/2D Painting Example" \
+ "QtOpenGL/Hello GLES3 Example" \
+ "QtOpenGL/Textures Example" \
+ "QtPositioning/SatelliteInfo (C++/QML)" \
+ "QtPositioning/Weather Info (C++/QML)" \
+ "QtPurchasing/Qt Purchasing Examples - QtHangman" \
+ "QtQML/Extending QML - Attached Properties Example" \
+ "QtQML/Extending QML - Grouped Properties Example" \
+ "QtQML/Extending QML - Methods Example" \
+ "QtQML/Extending QML - Signal Support Example" \
+ "QtQML/Qt Quick Examples - XMLHttpRequest" \
+ "QtQml/Qt Quick Examples - XMLHttpRequest" \
+ "QtQuick/*" \
+ "QtQuickControls/*" \
+ "QtQuickControls1/Qt Quick Controls 1 - Calendar Example" \
+ "QtQuickControls1/Qt Quick Controls 1 - Gallery" \
+ "QtQuickControls1/Qt Quick Controls 1 - Styles Example" \
+ "QtQuickControls1/Qt Quick Controls 1 - Table View Example" \
+ "QtQuickControls1/Qt Quick Controls 1 - Touch Gallery" \
+ "QtQuickDialogs/*" \
+ "QtQuickExtras/*" \
+ "QtSCXML/Qt SCXML Calculator QML Example" \
+ "QtSCXML/Qt SCXML Sudoku Example" \
+ "QtSCXML/Qt SCXML Traffic Light Example (Dynamic)" \
+ "QtSCXML/Qt SCXML Traffic Light QML Example (Dynamic)" \
+ "QtSQL/Master Detail Example" \
+ "QtSVG/Text Object Example" \
+ "QtUiTools/Text Finder Example" \
+ "QtWebView/Qt WebView Examples - Minibrowser" \
+ "QtWidgets/Address Book Example" \
+ "QtWidgets/Affine Transformations" \
+ "QtWidgets/Analog Clock Example" \
+ "QtWidgets/Animated Tiles Example" \
+ "QtWidgets/Application Chooser Example" \
+ "QtWidgets/Basic Layouts Example" \
+ "QtWidgets/Border Layout Example" \
+ "QtWidgets/Code Editor Example" \
+ "QtWidgets/Colliding Mice Example" \
+ "QtWidgets/Concentric Circles Example" \
+ "QtWidgets/Digital Clock Example" \
+ "QtWidgets/Dynamic Layouts Example" \
+ "QtWidgets/Easing Curves Example" \
+ "QtWidgets/Editable Tree Model Example" \
+ "QtWidgets/Elided Label Example" \
+ "QtWidgets/Event Transitions Example" \
+ "QtWidgets/Fade Message Effect Example" \
+ "QtWidgets/Flow Layout Example" \
+ "QtWidgets/Font Sampler Example" \
+ "QtWidgets/Frozen Column Example" \
+ "QtWidgets/Gradients" \
+ "QtWidgets/Group Box Example" \
+ "QtWidgets/Image Composition Example" \
+ "QtWidgets/Line Edits Example" \
+ "QtWidgets/Mouse Button Tester" \
+ "QtWidgets/Move Blocks Example" \
+ "QtWidgets/Painter Paths Example" \
+ "QtWidgets/Painter Paths Example" \
+ "QtWidgets/Path Stroking" \
+ "QtWidgets/Pixelator Example" \
+ "QtWidgets/Recent Files Example" \
+ "QtWidgets/SDI Example" \
+ "QtWidgets/Scribble Example" \
+ "QtWidgets/Simple Tree Model Example" \
+ "QtWidgets/Sliders Example" \
+ "QtWidgets/Spreadsheet" \
+ "QtWidgets/Touch Dials Example" \
+ "QtWidgets/Transformations Example" \
+ "QtWidgets/Undo Framework" \
+ "QtWidgets/Vector Deformation" \
+ "QtWidgets/Wiggly Example"
manifestmeta.android.tags = android
diff --git a/examples/network/http/main.cpp b/examples/network/http/main.cpp
index 1339f2f693..6c86933fd6 100644
--- a/examples/network/http/main.cpp
+++ b/examples/network/http/main.cpp
@@ -81,7 +81,11 @@ int main(int argc, char *argv[])
const QRect availableSize = httpWin.screen()->availableGeometry();
httpWin.resize(availableSize.width() / 5, availableSize.height() / 5);
httpWin.move((availableSize.width() - httpWin.width()) / 2, (availableSize.height() - httpWin.height()) / 2);
-
+#ifdef Q_OS_ANDROID
+ httpWin.showMaximized();
+#else
httpWin.show();
+#endif
+
return app.exec();
}
diff --git a/examples/widgets/graphicsview/collidingmice/main.cpp b/examples/widgets/graphicsview/collidingmice/main.cpp
index ef6d6cca64..c9ad90260f 100644
--- a/examples/widgets/graphicsview/collidingmice/main.cpp
+++ b/examples/widgets/graphicsview/collidingmice/main.cpp
@@ -58,6 +58,9 @@ static constexpr int MouseCount = 7;
//! [0]
int main(int argc, char **argv)
{
+#ifdef Q_OS_ANDROID
+ QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+#endif
QApplication app(argc, argv);
//! [0]
diff --git a/examples/widgets/graphicsview/diagramscene/main.cpp b/examples/widgets/graphicsview/diagramscene/main.cpp
index eefaa86554..3e321259c5 100644
--- a/examples/widgets/graphicsview/diagramscene/main.cpp
+++ b/examples/widgets/graphicsview/diagramscene/main.cpp
@@ -55,6 +55,9 @@
int main(int argv, char *args[])
{
Q_INIT_RESOURCE(diagramscene);
+#ifdef Q_OS_ANDROID
+ QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+#endif
QApplication app(argv, args);
MainWindow mainWindow;
diff --git a/examples/widgets/itemviews/addressbook/main.cpp b/examples/widgets/itemviews/addressbook/main.cpp
index 0731287cdd..86a11c5850 100644
--- a/examples/widgets/itemviews/addressbook/main.cpp
+++ b/examples/widgets/itemviews/addressbook/main.cpp
@@ -55,6 +55,9 @@
//! [0]
int main(int argc, char *argv[])
{
+#ifdef Q_OS_ANDROID
+ QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+#endif
QApplication app(argc, argv);
MainWindow mw;
mw.show();
diff --git a/examples/widgets/itemviews/spreadsheet/main.cpp b/examples/widgets/itemviews/spreadsheet/main.cpp
index 548dc8d604..968312d097 100644
--- a/examples/widgets/itemviews/spreadsheet/main.cpp
+++ b/examples/widgets/itemviews/spreadsheet/main.cpp
@@ -56,6 +56,10 @@
int main(int argc, char **argv)
{
Q_INIT_RESOURCE(spreadsheet);
+#ifdef Q_OS_ANDROID
+ QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+#endif
+
QApplication app(argc, argv);
SpreadSheet sheet(10, 6);
sheet.setWindowIcon(QPixmap(":/images/interview.png"));
diff --git a/examples/widgets/layouts/basiclayouts/main.cpp b/examples/widgets/layouts/basiclayouts/main.cpp
index f59de1d385..cf0ff0a535 100644
--- a/examples/widgets/layouts/basiclayouts/main.cpp
+++ b/examples/widgets/layouts/basiclayouts/main.cpp
@@ -56,7 +56,11 @@ int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Dialog dialog;
+#ifdef Q_OS_ANDROID
+ dialog.showMaximized();
+#else
dialog.show();
+#endif
return app.exec();
}
diff --git a/examples/widgets/layouts/dynamiclayouts/main.cpp b/examples/widgets/layouts/dynamiclayouts/main.cpp
index 9959c472f4..cf0ff0a535 100644
--- a/examples/widgets/layouts/dynamiclayouts/main.cpp
+++ b/examples/widgets/layouts/dynamiclayouts/main.cpp
@@ -56,6 +56,11 @@ int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Dialog dialog;
+#ifdef Q_OS_ANDROID
+ dialog.showMaximized();
+#else
dialog.show();
+#endif
+
return app.exec();
}
diff --git a/examples/widgets/mainwindows/application/main.cpp b/examples/widgets/mainwindows/application/main.cpp
index 78db7134a3..b46e1116dc 100644
--- a/examples/widgets/mainwindows/application/main.cpp
+++ b/examples/widgets/mainwindows/application/main.cpp
@@ -58,6 +58,9 @@
int main(int argc, char *argv[])
{
Q_INIT_RESOURCE(application);
+#ifdef Q_OS_ANDROID
+ QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+#endif
QApplication app(argc, argv);
QCoreApplication::setOrganizationName("QtProject");
diff --git a/examples/widgets/mainwindows/dockwidgets/main.cpp b/examples/widgets/mainwindows/dockwidgets/main.cpp
index ff3ba506a8..bf3ad9bcf7 100644
--- a/examples/widgets/mainwindows/dockwidgets/main.cpp
+++ b/examples/widgets/mainwindows/dockwidgets/main.cpp
@@ -54,6 +54,9 @@
int main(int argc, char *argv[])
{
+#ifdef Q_OS_ANDROID
+ QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+#endif
QApplication app(argc, argv);
Q_INIT_RESOURCE(dockwidgets);
MainWindow mainWin;
diff --git a/examples/widgets/painting/affine/main.cpp b/examples/widgets/painting/affine/main.cpp
index 6ce8efe482..641fc5c204 100644
--- a/examples/widgets/painting/affine/main.cpp
+++ b/examples/widgets/painting/affine/main.cpp
@@ -55,7 +55,9 @@
int main(int argc, char **argv)
{
Q_INIT_RESOURCE(affine);
-
+#ifdef Q_OS_ANDROID
+ qputenv("QT_SCALE_FACTOR", "2");
+#endif
QApplication app(argc, argv);
XFormWidget xformWidget(nullptr);
diff --git a/examples/widgets/painting/affine/xform.cpp b/examples/widgets/painting/affine/xform.cpp
index 4e7cb91ce1..d7ed2125d2 100644
--- a/examples/widgets/painting/affine/xform.cpp
+++ b/examples/widgets/painting/affine/xform.cpp
@@ -787,8 +787,8 @@ XFormWidget::XFormWidget(QWidget *parent)
view = new XFormView(this);
view->setMinimumSize(200, 200);
- QGroupBox *mainGroup = new QGroupBox(this);
- mainGroup->setFixedWidth(180);
+ QWidget *mainContentWidget = new QWidget();
+ QGroupBox *mainGroup = new QGroupBox(mainContentWidget);
mainGroup->setTitle(tr("Affine Transformations"));
QGroupBox *rotateGroup = new QGroupBox(mainGroup);
@@ -837,10 +837,6 @@ XFormWidget::XFormWidget(QWidget *parent)
whatsThisButton->setText(tr("What's This?"));
whatsThisButton->setCheckable(true);
- QHBoxLayout *viewLayout = new QHBoxLayout(this);
- viewLayout->addWidget(view);
- viewLayout->addWidget(mainGroup);
-
QVBoxLayout *rotateGroupLayout = new QVBoxLayout(rotateGroup);
rotateGroupLayout->addWidget(rotateSlider);
@@ -871,6 +867,20 @@ XFormWidget::XFormWidget(QWidget *parent)
#endif
mainGroupLayout->addWidget(whatsThisButton);
+ mainGroup->setLayout(mainGroupLayout);
+
+ QVBoxLayout *mainContentLayout = new QVBoxLayout();
+ mainContentLayout->addWidget(mainGroup);
+ mainContentWidget->setLayout(mainContentLayout);
+
+ QScrollArea *mainScrollArea = new QScrollArea();
+ mainScrollArea->setWidget(mainContentWidget);
+ mainScrollArea->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
+
+ QHBoxLayout *viewLayout = new QHBoxLayout(this);
+ viewLayout->addWidget(view);
+ viewLayout->addWidget(mainScrollArea);
+
connect(rotateSlider, &QSlider::valueChanged, view, &XFormView::changeRotation);
connect(shearSlider, &QSlider::valueChanged, view, &XFormView::changeShear);
connect(scaleSlider, &QSlider::valueChanged, view, &XFormView::changeScale);
diff --git a/examples/widgets/painting/concentriccircles/main.cpp b/examples/widgets/painting/concentriccircles/main.cpp
index d9fa2879c4..00456195d9 100644
--- a/examples/widgets/painting/concentriccircles/main.cpp
+++ b/examples/widgets/painting/concentriccircles/main.cpp
@@ -54,6 +54,9 @@
int main(int argc, char *argv[])
{
+#ifdef Q_OS_ANDROID
+ QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+#endif
QApplication app(argc, argv);
Window window;
window.show();
diff --git a/examples/widgets/painting/fontsampler/main.cpp b/examples/widgets/painting/fontsampler/main.cpp
index 1bf46b226f..cec6929827 100644
--- a/examples/widgets/painting/fontsampler/main.cpp
+++ b/examples/widgets/painting/fontsampler/main.cpp
@@ -54,6 +54,9 @@
int main(int argc, char *argv[])
{
+#ifdef Q_OS_ANDROID
+ QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+#endif
QApplication app(argc, argv);
MainWindow window;
window.show();
diff --git a/examples/widgets/painting/gradients/gradients.cpp b/examples/widgets/painting/gradients/gradients.cpp
index d62ae93a15..cb1a0177e9 100644
--- a/examples/widgets/painting/gradients/gradients.cpp
+++ b/examples/widgets/painting/gradients/gradients.cpp
@@ -282,7 +282,8 @@ GradientWidget::GradientWidget(QWidget *parent)
m_renderer = new GradientRenderer(this);
- QGroupBox *mainGroup = new QGroupBox(this);
+ QWidget *mainContentWidget = new QWidget();
+ QGroupBox *mainGroup = new QGroupBox(mainContentWidget);
mainGroup->setTitle(tr("Gradients"));
QGroupBox *editorGroup = new QGroupBox(mainGroup);
@@ -327,11 +328,6 @@ GradientWidget::GradientWidget(QWidget *parent)
whatsThisButton->setText(tr("What's This?"));
whatsThisButton->setCheckable(true);
- // Layouts
- QHBoxLayout *mainLayout = new QHBoxLayout(this);
- mainLayout->addWidget(m_renderer);
- mainLayout->addWidget(mainGroup);
-
mainGroup->setFixedWidth(200);
QVBoxLayout *mainGroupLayout = new QVBoxLayout(mainGroup);
mainGroupLayout->addWidget(editorGroup);
@@ -370,6 +366,21 @@ GradientWidget::GradientWidget(QWidget *parent)
defaultsGroupLayout->addWidget(default3Button);
editorGroupLayout->addWidget(default4Button);
+ mainGroup->setLayout(mainGroupLayout);
+
+ QVBoxLayout *mainContentLayout = new QVBoxLayout();
+ mainContentLayout->addWidget(mainGroup);
+ mainContentWidget->setLayout(mainContentLayout);
+
+ QScrollArea *mainScrollArea = new QScrollArea();
+ mainScrollArea->setWidget(mainContentWidget);
+ mainScrollArea->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
+
+ // Layouts
+ QHBoxLayout *mainLayout = new QHBoxLayout(this);
+ mainLayout->addWidget(m_renderer);
+ mainLayout->addWidget(mainScrollArea);
+
connect(m_editor, &GradientEditor::gradientStopsChanged,
m_renderer, &GradientRenderer::setGradientStops);
connect(m_linearButton, &QRadioButton::clicked,
diff --git a/examples/widgets/painting/gradients/main.cpp b/examples/widgets/painting/gradients/main.cpp
index 0ddf7a4579..7ffb0326e9 100644
--- a/examples/widgets/painting/gradients/main.cpp
+++ b/examples/widgets/painting/gradients/main.cpp
@@ -55,6 +55,9 @@
int main(int argc, char *argv[])
{
Q_INIT_RESOURCE(gradients);
+#ifdef Q_OS_ANDROID
+ qputenv("QT_SCALE_FACTOR", "2");
+#endif
QApplication app(argc, argv);
diff --git a/examples/widgets/painting/pathstroke/main.cpp b/examples/widgets/painting/pathstroke/main.cpp
index 57c85d73a3..35317480a3 100644
--- a/examples/widgets/painting/pathstroke/main.cpp
+++ b/examples/widgets/painting/pathstroke/main.cpp
@@ -55,6 +55,9 @@
int main(int argc, char **argv)
{
Q_INIT_RESOURCE(pathstroke);
+#ifdef Q_OS_ANDROID
+ qputenv("QT_SCALE_FACTOR", "2");
+#endif
QApplication app(argc, argv);
diff --git a/examples/widgets/tools/undo/main.cpp b/examples/widgets/tools/undo/main.cpp
index a5ec1b1b83..1a6dcf8c48 100644
--- a/examples/widgets/tools/undo/main.cpp
+++ b/examples/widgets/tools/undo/main.cpp
@@ -54,6 +54,9 @@
int main(int argc, char **argv)
{
Q_INIT_RESOURCE(undo);
+#ifdef Q_OS_ANDROID
+ QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+#endif
QApplication app(argc, argv);
diff --git a/examples/widgets/widgets/calculator/main.cpp b/examples/widgets/widgets/calculator/main.cpp
index a034bb262e..5f59d00ca6 100644
--- a/examples/widgets/widgets/calculator/main.cpp
+++ b/examples/widgets/widgets/calculator/main.cpp
@@ -54,6 +54,9 @@
int main(int argc, char *argv[])
{
+#ifdef Q_OS_ANDROID
+ QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+#endif
QApplication app(argc, argv);
Calculator calc;
calc.show();
diff --git a/examples/widgets/widgets/elidedlabel/main.cpp b/examples/widgets/widgets/elidedlabel/main.cpp
index 1c620c1d41..58507766e7 100644
--- a/examples/widgets/widgets/elidedlabel/main.cpp
+++ b/examples/widgets/widgets/elidedlabel/main.cpp
@@ -55,6 +55,9 @@
//! [0]
int main( int argc, char *argv[] )
{
+#ifdef Q_OS_ANDROID
+ QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+#endif
QApplication application( argc, argv );
TestWidget w;
w.showFullScreen();
diff --git a/examples/widgets/widgets/scribble/main.cpp b/examples/widgets/widgets/scribble/main.cpp
index 1bf46b226f..cec6929827 100644
--- a/examples/widgets/widgets/scribble/main.cpp
+++ b/examples/widgets/widgets/scribble/main.cpp
@@ -54,6 +54,9 @@
int main(int argc, char *argv[])
{
+#ifdef Q_OS_ANDROID
+ QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+#endif
QApplication app(argc, argv);
MainWindow window;
window.show();
diff --git a/examples/widgets/widgets/sliders/main.cpp b/examples/widgets/widgets/sliders/main.cpp
index 99725195e5..9bf18cb6d4 100644
--- a/examples/widgets/widgets/sliders/main.cpp
+++ b/examples/widgets/widgets/sliders/main.cpp
@@ -54,6 +54,9 @@
int main(int argc, char *argv[])
{
+#ifdef Q_OS_ANDROID
+ QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+#endif
QApplication app(argc, argv);
Window window;
window.show();
diff --git a/examples/xml/rsslisting/rsslisting.cpp b/examples/xml/rsslisting/rsslisting.cpp
index d1b4373531..143ad6dcba 100644
--- a/examples/xml/rsslisting/rsslisting.cpp
+++ b/examples/xml/rsslisting/rsslisting.cpp
@@ -131,7 +131,7 @@ void RSSListing::get(const QUrl &url)
currentReply = manager.get(request);
connect(currentReply, SIGNAL(readyRead()), this, SLOT(readyRead()));
connect(currentReply, SIGNAL(metaDataChanged()), this, SLOT(metaDataChanged()));
- connect(currentReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(error(QNetworkReply::NetworkError)));
+ connect(currentReply, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), this, SLOT(error(QNetworkReply::NetworkError)));
}
/*
diff --git a/mkspecs/features/qt_common.prf b/mkspecs/features/qt_common.prf
index 02460a2e0c..ac24b03b6b 100644
--- a/mkspecs/features/qt_common.prf
+++ b/mkspecs/features/qt_common.prf
@@ -20,11 +20,11 @@ qtConfig(c++1z): CONFIG += c++1z
qtConfig(c++2a): CONFIG += c++2a
qtConfig(c99): CONFIG += c99
qtConfig(c11): CONFIG += c11
+qtConfig(separate_debug_info): CONFIG += separate_debug_info
qtConfig(stack-protector-strong): CONFIG += stack_protector_strong
contains(TEMPLATE, .*lib) {
# module and plugins
unix:qtConfig(reduce_relocations): CONFIG += bsymbolic_functions
- qtConfig(separate_debug_info): CONFIG += separate_debug_info
!isEmpty(_QMAKE_SUPER_CACHE_): \
rplbase = $$dirname(_QMAKE_SUPER_CACHE_)/[^/][^/]*
diff --git a/src/corelib/global/qfloat16.cpp b/src/corelib/global/qfloat16.cpp
index 80a851e4e4..3d82bbe95a 100644
--- a/src/corelib/global/qfloat16.cpp
+++ b/src/corelib/global/qfloat16.cpp
@@ -147,7 +147,7 @@ QT_BEGIN_NAMESPACE
/*!
\since 5.15
- \fn qfloat16::copySign(qfloat16 sign) const noexcept
+ \fn qfloat16 qfloat16::copySign(qfloat16 sign) const noexcept
Returns a qfloat16 with the sign of \a sign but the rest of its value taken
from this qfloat16. Serves as qfloat16's equivalent of std::copysign().
diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp
index 8616631603..f2216d4113 100644
--- a/src/corelib/kernel/qeventdispatcher_win.cpp
+++ b/src/corelib/kernel/qeventdispatcher_win.cpp
@@ -884,7 +884,11 @@ void QEventDispatcherWin32::unregisterEventNotifier(QWinEventNotifier *notifier)
return;
}
#endif
+ doUnregisterEventNotifier(notifier);
+}
+void QEventDispatcherWin32::doUnregisterEventNotifier(QWinEventNotifier *notifier)
+{
Q_D(QEventDispatcherWin32);
int i = d->winEventNotifierList.indexOf(notifier);
@@ -996,6 +1000,10 @@ void QEventDispatcherWin32::closingDown()
doUnregisterSocketNotifier((*(d->sn_except.begin()))->obj);
Q_ASSERT(d->active_fd.isEmpty());
+ // clean up any eventnotifiers
+ while (!d->winEventNotifierList.isEmpty())
+ doUnregisterEventNotifier(d->winEventNotifierList.first());
+
// clean up any timers
for (int i = 0; i < d->timerVec.count(); ++i)
d->unregisterTimer(d->timerVec.at(i));
diff --git a/src/corelib/kernel/qeventdispatcher_win_p.h b/src/corelib/kernel/qeventdispatcher_win_p.h
index e6620178d8..a482c8b7db 100644
--- a/src/corelib/kernel/qeventdispatcher_win_p.h
+++ b/src/corelib/kernel/qeventdispatcher_win_p.h
@@ -110,6 +110,7 @@ protected:
QEventDispatcherWin32(QEventDispatcherWin32Private &dd, QObject *parent = 0);
virtual void sendPostedEvents();
void doUnregisterSocketNotifier(QSocketNotifier *notifier);
+ void doUnregisterEventNotifier(QWinEventNotifier *notifier);
private:
friend LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp);
diff --git a/src/corelib/kernel/qwineventnotifier.cpp b/src/corelib/kernel/qwineventnotifier.cpp
index db5d44b276..0c574e9a4b 100644
--- a/src/corelib/kernel/qwineventnotifier.cpp
+++ b/src/corelib/kernel/qwineventnotifier.cpp
@@ -198,11 +198,8 @@ void QWinEventNotifier::setEnabled(bool enable)
d->enabled = enable;
QAbstractEventDispatcher *eventDispatcher = d->threadData.loadRelaxed()->eventDispatcher.loadRelaxed();
- if (!eventDispatcher) { // perhaps application is shutting down
- if (!enable && d->waitHandle != nullptr)
- d->unregisterWaitObject();
+ if (!eventDispatcher) // perhaps application is shutting down
return;
- }
if (Q_UNLIKELY(thread() != QThread::currentThread())) {
qWarning("QWinEventNotifier: Event notifiers cannot be enabled or disabled from another thread");
return;
diff --git a/src/corelib/mimetypes/qmimeprovider.cpp b/src/corelib/mimetypes/qmimeprovider.cpp
index 4aee772366..9dba72923a 100644
--- a/src/corelib/mimetypes/qmimeprovider.cpp
+++ b/src/corelib/mimetypes/qmimeprovider.cpp
@@ -664,7 +664,15 @@ QMimeXMLProvider::QMimeXMLProvider(QMimeDatabasePrivate *db, InternalDatabaseEnu
load(data, size);
}
-#endif
+#else // !QT_CONFIG(mimetype_database)
+// never called in release mode, but some debug builds may need
+// this to be defined.
+QMimeXMLProvider::QMimeXMLProvider(QMimeDatabasePrivate *db, InternalDatabaseEnum)
+ : QMimeProviderBase(db, QString())
+{
+ Q_UNREACHABLE();
+}
+#endif // QT_CONFIG(mimetype_database)
QMimeXMLProvider::QMimeXMLProvider(QMimeDatabasePrivate *db, const QString &directory)
: QMimeProviderBase(db, directory)
diff --git a/src/corelib/mimetypes/qmimeprovider_p.h b/src/corelib/mimetypes/qmimeprovider_p.h
index c4e712b318..9c91903684 100644
--- a/src/corelib/mimetypes/qmimeprovider_p.h
+++ b/src/corelib/mimetypes/qmimeprovider_p.h
@@ -135,13 +135,10 @@ public:
enum InternalDatabaseEnum { InternalDatabase };
#if QT_CONFIG(mimetype_database)
enum : bool { InternalDatabaseAvailable = true };
- QMimeXMLProvider(QMimeDatabasePrivate *db, InternalDatabaseEnum);
#else
enum : bool { InternalDatabaseAvailable = false };
- QMimeXMLProvider(QMimeDatabasePrivate *db, InternalDatabaseEnum)
- : QMimeProviderBase(db, QString())
- { Q_UNREACHABLE(); };
#endif
+ QMimeXMLProvider(QMimeDatabasePrivate *db, InternalDatabaseEnum);
QMimeXMLProvider(QMimeDatabasePrivate *db, const QString &directory);
~QMimeXMLProvider();
diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp
index da2c44bef6..757f248e8a 100644
--- a/src/corelib/text/qstring.cpp
+++ b/src/corelib/text/qstring.cpp
@@ -7626,7 +7626,10 @@ static ResultList splitString(const StringSource &source, const QChar *sep,
#if QT_DEPRECATED_SINCE(5, 15)
Qt::SplitBehavior mapSplitBehavior(QString::SplitBehavior sb)
{
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
return sb & QString::SkipEmptyParts ? Qt::SkipEmptyParts : Qt::KeepEmptyParts;
+QT_WARNING_POP
}
#endif
diff --git a/src/corelib/time/qdatetime.cpp b/src/corelib/time/qdatetime.cpp
index e9fe34110a..47539141bd 100644
--- a/src/corelib/time/qdatetime.cpp
+++ b/src/corelib/time/qdatetime.cpp
@@ -1383,6 +1383,10 @@ QT_WARNING_POP
If the datetime is invalid, an empty string will be returned.
+ \note If localized month and day names are desired, please switch to using
+ QLocale::system().toString() as QDate methods shall change to use English (C
+ locale) names at Qt 6.
+
\sa fromString(), QDateTime::toString(), QTime::toString(), QLocale::toString()
*/
@@ -1884,6 +1888,10 @@ QT_WARNING_POP
\snippet code/src_corelib_tools_qdatetime.cpp 3
+ \note If localized month and day names are used, please switch to using
+ QLocale::system().toDate() as QDate methods shall change to only recognize
+ English (C locale) names at Qt 6.
+
\sa toString(), QDateTime::fromString(), QTime::fromString(),
QLocale::toDate()
*/
@@ -2244,6 +2252,10 @@ QT_WARNING_POP
If the time is invalid, an empty string will be returned.
If \a format is empty, the default format "hh:mm:ss" is used.
+ \note If localized forms of am or pm (the AP, ap, A or a formats) are
+ desired, please switch to using QLocale::system().toString() as QTime
+ methods shall change to use English (C locale) at Qt 6.
+
\sa fromString(), QDate::toString(), QDateTime::toString(), QLocale::toString()
*/
QString QTime::toString(QStringView format) const
@@ -2641,6 +2653,10 @@ QT_WARNING_POP
\snippet code/src_corelib_tools_qdatetime.cpp 8
+ \note If localized forms of am or pm (the AP, ap, A or a formats) are used,
+ please switch to using QLocale::system().toTime() as QTime methods shall
+ change to only recognize English (C locale) at Qt 6.
+
\sa toString(), QDateTime::fromString(), QDate::fromString(),
QLocale::toTime()
*/
@@ -4541,6 +4557,10 @@ QT_WARNING_POP
If the datetime is invalid, an empty string will be returned.
+ \note If localized month and day names are desired, please switch to using
+ QLocale::system().toString() as QDateTime methods shall change to use
+ English (C locale) names at Qt 6.
+
\sa fromString(), QDate::toString(), QTime::toString(), QLocale::toString()
*/
QString QDateTime::toString(QStringView format) const
@@ -5580,6 +5600,10 @@ QT_WARNING_POP
\snippet code/src_corelib_tools_qdatetime.cpp 14
+ \note If localized month and day names are used, please switch to using
+ QLocale::system().toDateTime() as QDateTime methods shall change to only
+ recognize English (C locale) names at Qt 6.
+
\sa toString(), QDate::fromString(), QTime::fromString(),
QLocale::toDateTime()
*/
diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp
index 15f731a603..7ebc374d9f 100644
--- a/src/corelib/tools/qhash.cpp
+++ b/src/corelib/tools/qhash.cpp
@@ -1574,7 +1574,6 @@ uint qHash(long double key, uint seed) noexcept
*/
/*! \fn template <class Key, class T> int QHash<Key, T>::count(const Key &key) const
- \obsolete
Returns the number of items associated with the \a key.
@@ -2693,13 +2692,6 @@ uint qHash(long double key, uint seed) noexcept
\sa QHash::remove()
*/
-/*! \fn template <class Key, class T> int QMultiHash<Key, T>::count(const Key &key) const
-
- Returns the number of items associated with the \a key.
-
- \sa contains(), insert()
-*/
-
/*!
\fn template <class Key, class T> int QMultiHash<Key, T>::count(const Key &key, const T &value) const
\since 4.3
diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h
index 59883e3968..c87cf56988 100644
--- a/src/corelib/tools/qhash.h
+++ b/src/corelib/tools/qhash.h
@@ -309,10 +309,10 @@ public:
QList<Key> keys(const T &value) const;
QList<T> values() const;
#if QT_DEPRECATED_SINCE(5, 15)
- QT_DEPRECATED_X("Use QMultiHash for hashes storing multiple values with the same key.") QList<Key> uniqueKeys() const;
- QT_DEPRECATED_X("Use QMultiHash for hashes storing multiple values with the same key.") QList<T> values(const Key &key) const;
- QT_DEPRECATED_X("Use QMultiHash for hashes storing multiple values with the same key.") int count(const Key &key) const;
+ QT_DEPRECATED_VERSION_X_5_15("Use QMultiHash for hashes storing multiple values with the same key.") QList<Key> uniqueKeys() const;
+ QT_DEPRECATED_VERSION_X_5_15("Use QMultiHash for hashes storing multiple values with the same key.") QList<T> values(const Key &key) const;
#endif
+ int count(const Key &key) const;
class const_iterator;
@@ -512,8 +512,8 @@ public:
iterator insert(const Key &key, const T &value);
void insert(const QHash &hash);
#if QT_DEPRECATED_SINCE(5, 15)
- QT_DEPRECATED_X("Use QMultiHash for hashes storing multiple values with the same key.") iterator insertMulti(const Key &key, const T &value);
- QT_DEPRECATED_X("Use QMultiHash for hashes storing multiple values with the same key.") QHash &unite(const QHash &other);
+ QT_DEPRECATED_VERSION_X_5_15("Use QMultiHash for hashes storing multiple values with the same key.") iterator insertMulti(const Key &key, const T &value);
+ QT_DEPRECATED_VERSION_X_5_15("Use QMultiHash for hashes storing multiple values with the same key.") QHash &unite(const QHash &other);
#endif
// STL compatibility
@@ -711,6 +711,19 @@ Q_OUTOFLINE_TEMPLATE QList<T> QHash<Key, T>::values() const
}
template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE int QHash<Key, T>::count(const Key &akey) const
+{
+ int cnt = 0;
+ Node *node = *findNode(akey);
+ if (node != e) {
+ do {
+ ++cnt;
+ } while ((node = node->next) != e && node->key == akey);
+ }
+ return cnt;
+}
+
+template <class Key, class T>
Q_INLINE_TEMPLATE const T QHash<Key, T>::operator[](const Key &akey) const
{
return value(akey);
@@ -1053,7 +1066,6 @@ public:
int remove(const Key &key, const T &value);
- int count(const Key &key) const;
int count(const Key &key, const T &value) const;
QList<Key> uniqueKeys() const;
@@ -1207,12 +1219,6 @@ Q_OUTOFLINE_TEMPLATE QList<T> QHash<Key, T>::values(const Key &akey) const
}
template <class Key, class T>
-Q_OUTOFLINE_TEMPLATE int QHash<Key, T>::count(const Key &akey) const
-{
- return static_cast<const QMultiHash<Key, T> *>(this)->count(akey);
-}
-
-template <class Key, class T>
Q_OUTOFLINE_TEMPLATE QList<Key> QHash<Key, T>::uniqueKeys() const
{
return static_cast<const QMultiHash<Key, T> *>(this)->uniqueKeys();
@@ -1232,19 +1238,6 @@ Q_OUTOFLINE_TEMPLATE QList<T> QMultiHash<Key, T>::values(const Key &akey) const
return res;
}
-template <class Key, class T>
-Q_OUTOFLINE_TEMPLATE int QMultiHash<Key, T>::count(const Key &akey) const
-{
- int cnt = 0;
- Node *node = *findNode(akey);
- if (node != this->e) {
- do {
- ++cnt;
- } while ((node = node->next) != this->e && node->key == akey);
- }
- return cnt;
-}
-
#if !defined(QT_NO_JAVA_STYLE_ITERATORS)
template <class Key, class T>
class QHashIterator
diff --git a/src/corelib/tools/qiterator.h b/src/corelib/tools/qiterator.h
index 84a0e116ca..c4665c7c87 100644
--- a/src/corelib/tools/qiterator.h
+++ b/src/corelib/tools/qiterator.h
@@ -195,7 +195,6 @@ public:
typedef typename Iterator::iterator_category iterator_category;
typedef typename Iterator::difference_type difference_type;
typedef std::pair<Key, T> value_type;
- typedef const value_type *pointer;
typedef const value_type &reference;
QKeyValueIterator() = default;
@@ -206,6 +205,31 @@ public:
return std::pair<Key, T>(i.key(), i.value());
}
+ struct pointer {
+ pointer(value_type&& r_)
+ : r(std::move(r_))
+ {}
+
+ pointer() = default;
+ pointer(const pointer &other) = default;
+ pointer(pointer &&other) = default;
+ pointer& operator=(const pointer &other) = default;
+ pointer& operator=(pointer &&other) = default;
+
+ value_type& operator*() const {
+ return r;
+ }
+
+ value_type r;
+ const value_type *operator->() const {
+ return &r;
+ }
+ };
+
+ pointer operator->() const {
+ return pointer(std::pair<Key, T>(i.key(), i.value()));
+ }
+
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; }
diff --git a/src/corelib/tools/qiterator.qdoc b/src/corelib/tools/qiterator.qdoc
index 69f9d52ce5..8cfa665ffd 100644
--- a/src/corelib/tools/qiterator.qdoc
+++ b/src/corelib/tools/qiterator.qdoc
@@ -57,7 +57,7 @@
\internal
*/
-/*! \typedef QKeyValueIterator::pointer
+/*! \struct QKeyValueIterator::pointer
\internal
*/
@@ -75,11 +75,20 @@
Constructs a QKeyValueIterator on top of \a o.
*/
-/*! \fn template<typename Key, typename T, class Iterator> const T &QKeyValueIterator<Key, T, Iterator>::operator*() const
+/*! \fn template<typename Key, typename T, class Iterator> std::pair<Key, T> QKeyValueIterator<Key, T, Iterator>::operator*() const
Returns the current entry as a pair.
*/
+/*! \fn template<typename Key, typename T, class Iterator> pointer QKeyValueIterator<Key, T, Iterator>::operator->() const
+
+ Returns the current entry as a pointer-like object to the pair.
+
+ \since 5.15
+
+ \sa operator*()
+*/
+
/*! \fn template<typename Key, typename T, class Iterator> bool operator==(QKeyValueIterator<Key, T, Iterator> lhs, QKeyValueIterator<Key, T, Iterator> rhs)
\relates QKeyValueIterator
diff --git a/src/corelib/tools/qmap.cpp b/src/corelib/tools/qmap.cpp
index 6d2b8f7a3e..25ea5f25d7 100644
--- a/src/corelib/tools/qmap.cpp
+++ b/src/corelib/tools/qmap.cpp
@@ -814,11 +814,10 @@ void QMapDataBase::freeData(QMapDataBase *d)
*/
/*! \fn template <class Key, class T> int QMap<Key, T>::count(const Key &key) const
- \obsolete
Returns the number of items associated with key \a key.
- \sa QMultiMap::count()
+ \sa contains(), QMultiMap::count()
*/
/*! \fn template <class Key, class T> int QMap<Key, T>::count() const
@@ -2115,11 +2114,6 @@ void QMapDataBase::freeData(QMapDataBase *d)
inserted one.
*/
-/*! \fn template <class Key, class T> int QMultiMap<Key, T>::count(const Key &key) const
-
- Returns the number of items associated with key \a key.
-*/
-
/*! \fn template <class Key, class T> QList<Key> QMultiMap<Key, T>::uniqueKeys() const
\since 4.2
diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h
index a971919e54..6081019294 100644
--- a/src/corelib/tools/qmap.h
+++ b/src/corelib/tools/qmap.h
@@ -373,10 +373,10 @@ public:
QList<Key> keys(const T &value) const;
QList<T> values() const;
#if QT_DEPRECATED_SINCE(5, 15)
- QT_DEPRECATED_X("Use QMultiMap for maps storing multiple values with the same key.") QList<Key> uniqueKeys() const;
- QT_DEPRECATED_X("Use QMultiMap for maps storing multiple values with the same key.") QList<T> values(const Key &key) const;
- QT_DEPRECATED_X("Use QMultiMap for maps storing multiple values with the same key.") int count(const Key &key) const;
+ QT_DEPRECATED_VERSION_X_5_15("Use QMultiMap for maps storing multiple values with the same key.") QList<Key> uniqueKeys() const;
+ QT_DEPRECATED_VERSION_X_5_15("Use QMultiMap for maps storing multiple values with the same key.") QList<T> values(const Key &key) const;
#endif
+ int count(const Key &key) const;
inline const Key &firstKey() const { Q_ASSERT(!isEmpty()); return constBegin().key(); }
@@ -559,9 +559,9 @@ public:
iterator insert(const_iterator pos, const Key &key, const T &value);
void insert(const QMap<Key, T> &map);
#if QT_DEPRECATED_SINCE(5, 15)
- QT_DEPRECATED_X("Use QMultiMap for maps storing multiple values with the same key.") iterator insertMulti(const Key &key, const T &value);
- QT_DEPRECATED_X("Use QMultiMap for maps storing multiple values with the same key.") iterator insertMulti(const_iterator pos, const Key &akey, const T &avalue);
- QT_DEPRECATED_X("Use QMultiMap for maps storing multiple values with the same key.") QMap<Key, T> &unite(const QMap<Key, T> &other);
+ QT_DEPRECATED_VERSION_X_5_15("Use QMultiMap for maps storing multiple values with the same key.") iterator insertMulti(const Key &key, const T &value);
+ QT_DEPRECATED_VERSION_X_5_15("Use QMultiMap for maps storing multiple values with the same key.") iterator insertMulti(const_iterator pos, const Key &akey, const T &avalue);
+ QT_DEPRECATED_VERSION_X_5_15("Use QMultiMap for maps storing multiple values with the same key.") QMap<Key, T> &unite(const QMap<Key, T> &other);
#endif
// STL compatibility
@@ -655,6 +655,23 @@ Q_INLINE_TEMPLATE T &QMap<Key, T>::operator[](const Key &akey)
}
template <class Key, class T>
+Q_INLINE_TEMPLATE int QMap<Key, T>::count(const Key &akey) const
+{
+ Node *firstNode;
+ Node *lastNode;
+ d->nodeRange(akey, &firstNode, &lastNode);
+
+ const_iterator ci_first(firstNode);
+ const const_iterator ci_last(lastNode);
+ int cnt = 0;
+ while (ci_first != ci_last) {
+ ++cnt;
+ ++ci_first;
+ }
+ return cnt;
+}
+
+template <class Key, class T>
Q_INLINE_TEMPLATE bool QMap<Key, T>::contains(const Key &akey) const
{
return d->findNode(akey) != nullptr;
@@ -1116,7 +1133,6 @@ public:
int remove(const Key &key, const T &value);
- int count(const Key &key) const;
int count(const Key &key, const T &value) const;
typename QMap<Key, T>::iterator find(const Key &key, const T &value) {
@@ -1290,23 +1306,6 @@ Q_INLINE_TEMPLATE int QMultiMap<Key, T>::remove(const Key &key, const T &value)
}
template <class Key, class T>
-Q_INLINE_TEMPLATE int QMultiMap<Key, T>::count(const Key &akey) const
-{
- QMultiMap::Node *firstNode;
- QMultiMap::Node *lastNode;
- this->d->nodeRange(akey, &firstNode, &lastNode);
-
- typename QMap<Key, T>::const_iterator ci_first(firstNode);
- const typename QMap<Key, T>::const_iterator ci_last(lastNode);
- int cnt = 0;
- while (ci_first != ci_last) {
- ++cnt;
- ++ci_first;
- }
- return cnt;
-}
-
-template <class Key, class T>
Q_INLINE_TEMPLATE int QMultiMap<Key, T>::count(const Key &key, const T &value) const
{
int n = 0;
@@ -1334,12 +1333,6 @@ QList<T> QMap<Key, T>::values(const Key &key) const
}
template<class Key, class T>
-int QMap<Key, T>::count(const Key &key) const
-{
- return static_cast<const QMultiMap<Key, T> *>(this)->count(key);
-}
-
-template<class Key, class T>
typename QMap<Key, T>::iterator QMap<Key, T>::insertMulti(const Key &key, const T &value)
{
return static_cast<QMultiMap<Key, T> *>(this)->insert(key, value);
diff --git a/src/gui/image/qbmphandler.cpp b/src/gui/image/qbmphandler.cpp
index d447faaceb..d559913161 100644
--- a/src/gui/image/qbmphandler.cpp
+++ b/src/gui/image/qbmphandler.cpp
@@ -870,13 +870,6 @@ 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
#endif // QT_NO_IMAGEFORMAT_BMP
diff --git a/src/gui/image/qbmphandler_p.h b/src/gui/image/qbmphandler_p.h
index 33b5b9c501..fd044fc442 100644
--- a/src/gui/image/qbmphandler_p.h
+++ b/src/gui/image/qbmphandler_p.h
@@ -113,9 +113,6 @@ 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/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp
index e6a3604ad4..5738148718 100644
--- a/src/gui/image/qpnghandler.cpp
+++ b/src/gui/image/qpnghandler.cpp
@@ -1296,13 +1296,6 @@ 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
#endif // QT_NO_IMAGEFORMAT_PNG
diff --git a/src/gui/image/qpnghandler_p.h b/src/gui/image/qpnghandler_p.h
index 5d4da97395..9e12d2d081 100644
--- a/src/gui/image/qpnghandler_p.h
+++ b/src/gui/image/qpnghandler_p.h
@@ -69,10 +69,6 @@ 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;
bool supportsOption(ImageOption option) const override;
diff --git a/src/gui/image/qppmhandler.cpp b/src/gui/image/qppmhandler.cpp
index 195e58d283..16136e6be3 100644
--- a/src/gui/image/qppmhandler.cpp
+++ b/src/gui/image/qppmhandler.cpp
@@ -576,13 +576,6 @@ 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
#endif // QT_NO_IMAGEFORMAT_PPM
diff --git a/src/gui/image/qppmhandler_p.h b/src/gui/image/qppmhandler_p.h
index 2f3811b759..f2faf93984 100644
--- a/src/gui/image/qppmhandler_p.h
+++ b/src/gui/image/qppmhandler_p.h
@@ -67,10 +67,6 @@ 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 = nullptr);
QVariant option(ImageOption option) const override;
diff --git a/src/gui/image/qxbmhandler.cpp b/src/gui/image/qxbmhandler.cpp
index 3cd15b3e4d..f06561690c 100644
--- a/src/gui/image/qxbmhandler.cpp
+++ b/src/gui/image/qxbmhandler.cpp
@@ -357,13 +357,6 @@ 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
#endif // QT_NO_IMAGEFORMAT_XBM
diff --git a/src/gui/image/qxbmhandler_p.h b/src/gui/image/qxbmhandler_p.h
index ae590a1944..db5f352d46 100644
--- a/src/gui/image/qxbmhandler_p.h
+++ b/src/gui/image/qxbmhandler_p.h
@@ -66,10 +66,6 @@ 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/qxpmhandler.cpp b/src/gui/image/qxpmhandler.cpp
index f9424b62bb..07fec929bf 100644
--- a/src/gui/image/qxpmhandler.cpp
+++ b/src/gui/image/qxpmhandler.cpp
@@ -1280,13 +1280,6 @@ 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
#endif // QT_NO_IMAGEFORMAT_XPM
diff --git a/src/gui/image/qxpmhandler_p.h b/src/gui/image/qxpmhandler_p.h
index a4dd88cd17..646e8df69e 100644
--- a/src/gui/image/qxpmhandler_p.h
+++ b/src/gui/image/qxpmhandler_p.h
@@ -68,10 +68,6 @@ 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;
bool supportsOption(ImageOption option) const override;
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index c099ec9692..702c055fbb 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -1731,7 +1731,7 @@ void QWindow::setGeometry(const QRect &rect)
if (newScreen && isTopLevel())
nativeRect = QHighDpi::toNativePixels(rect, newScreen);
else
- nativeRect = QHighDpi::toNativePixels(rect, this);
+ nativeRect = QHighDpi::toNativeLocalPosition(rect, newScreen);
d->platformWindow->setGeometry(nativeRect);
} else {
d->geometry = rect;
@@ -1782,8 +1782,12 @@ QScreen *QWindowPrivate::screenForGeometry(const QRect &newGeometry) const
QRect QWindow::geometry() const
{
Q_D(const QWindow);
- if (d->platformWindow)
- return QHighDpi::fromNativePixels(d->platformWindow->geometry(), this);
+ if (d->platformWindow) {
+ const auto nativeGeometry = d->platformWindow->geometry();
+ return isTopLevel()
+ ? QHighDpi::fromNativePixels(nativeGeometry, this)
+ : QHighDpi::fromNativeLocalPosition(nativeGeometry, this);
+ }
return d->geometry;
}
diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp
index 2de0131640..6ecd908296 100644
--- a/src/gui/kernel/qwindowsysteminterface.cpp
+++ b/src/gui/kernel/qwindowsysteminterface.cpp
@@ -298,14 +298,21 @@ QWindowSystemInterfacePrivate::GeometryChangeEvent::GeometryChangeEvent(QWindow
, window(window)
, newGeometry(newGeometry)
{
- if (const QPlatformWindow *pw = window->handle())
- requestedGeometry = QHighDpi::fromNativePixels(pw->QPlatformWindow::geometry(), window);
+ if (const QPlatformWindow *pw = window->handle()) {
+ const auto nativeGeometry = pw->QPlatformWindow::geometry();
+ requestedGeometry = window->isTopLevel()
+ ? QHighDpi::fromNativePixels(nativeGeometry, window)
+ : QHighDpi::fromNativeLocalPosition(nativeGeometry, window);
+ }
}
QT_DEFINE_QPA_EVENT_HANDLER(void, handleGeometryChange, QWindow *window, const QRect &newRect)
{
Q_ASSERT(window);
- QWindowSystemInterfacePrivate::GeometryChangeEvent *e = new QWindowSystemInterfacePrivate::GeometryChangeEvent(window, QHighDpi::fromNativePixels(newRect, window));
+ const auto newRectDi = window->isTopLevel()
+ ? QHighDpi::fromNativePixels(newRect, window)
+ : QHighDpi::fromNativeLocalPosition(newRect, window);
+ auto e = new QWindowSystemInterfacePrivate::GeometryChangeEvent(window, newRectDi);
if (window->handle()) {
// Persist the new geometry so that QWindow::geometry() can be queried in the resize event
window->handle()->QPlatformWindow::setGeometry(newRect);
diff --git a/src/gui/rhi/qrhi.cpp b/src/gui/rhi/qrhi.cpp
index 7a0d53e1e4..c805e23ad0 100644
--- a/src/gui/rhi/qrhi.cpp
+++ b/src/gui/rhi/qrhi.cpp
@@ -2048,11 +2048,9 @@ QRhiResource::Type QRhiBuffer::resourceType() const
UniformBuffer may not even be backed by a native buffer object at all if
uniform buffers are not used or supported by a given backend and graphics
API. There are also differences to how data is written to the buffer and
- the type of backing memory used, and, if host visible memory is involved,
- when memory writes become available and visible. Therefore, in general it
- is recommended to limit native buffer object access to vertex and index
- buffers with types Static or Immutable, because these operate in a
- relatively uniform manner with all backends.
+ the type of backing memory used. For buffers backed by host visible memory,
+ calling this function guarantees that pending host writes are executed for
+ all the returned native buffers.
\sa QRhi::currentFrameSlot(), QRhi::FramesInFlight
*/
@@ -2342,6 +2340,31 @@ bool QRhiTexture::buildFrom(QRhiTexture::NativeTexture src)
}
/*!
+ With some graphics APIs, such as Vulkan, integrating custom rendering code
+ that uses the graphics API directly needs special care when it comes to
+ image layouts. This function allows communicating the expected layout the
+ image backing the QRhiTexture is in after the native rendering commands.
+
+ For example, consider rendering into a QRhiTexture's VkImage directly with
+ Vulkan in a code block enclosed by QRhiCommandBuffer::beginExternal() and
+ QRhiCommandBuffer::endExternal(), followed by using the image for texture
+ sampling in a QRhi-based render pass. To avoid potentially incorrect image
+ layout transitions, this function can be used to indicate what the image
+ layout will be once the commands recorded in said code block complete.
+
+ Calling this function makes sense only after
+ QRhiCommandBuffer::endExternal() and before a subsequent
+ QRhiCommandBuffer::beginPass().
+
+ This function has no effect with QRhi backends where the underlying
+ graphics API does not expose a concept of image layouts.
+ */
+void QRhiTexture::setNativeLayout(int layout)
+{
+ Q_UNUSED(layout);
+}
+
+/*!
\class QRhiSampler
\internal
\inmodule QtGui
diff --git a/src/gui/rhi/qrhi_p.h b/src/gui/rhi/qrhi_p.h
index 8f53808d34..17c911a5ff 100644
--- a/src/gui/rhi/qrhi_p.h
+++ b/src/gui/rhi/qrhi_p.h
@@ -791,6 +791,7 @@ public:
virtual bool build() = 0;
virtual NativeTexture nativeTexture();
virtual bool buildFrom(NativeTexture src);
+ virtual void setNativeLayout(int layout);
protected:
QRhiTexture(QRhiImplementation *rhi, Format format_, const QSize &pixelSize_,
diff --git a/src/gui/rhi/qrhid3d11.cpp b/src/gui/rhi/qrhid3d11.cpp
index f7c7f4a9f2..7b583e6fd2 100644
--- a/src/gui/rhi/qrhid3d11.cpp
+++ b/src/gui/rhi/qrhid3d11.cpp
@@ -580,6 +580,11 @@ void QRhiD3D11::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline
}
}
+static const int RBM_SUPPORTED_STAGES = 3;
+static const int RBM_VERTEX = 0;
+static const int RBM_FRAGMENT = 1;
+static const int RBM_COMPUTE = 2;
+
void QRhiD3D11::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBindings *srb,
int dynamicOffsetCount,
const QRhiCommandBuffer::DynamicOffset *dynamicOffsets)
@@ -608,7 +613,7 @@ void QRhiD3D11::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind
{
QD3D11Buffer *bufD = QRHI_RES(QD3D11Buffer, b->u.ubuf.buf);
if (bufD->m_type == QRhiBuffer::Dynamic)
- executeBufferHostWritesForCurrentFrame(bufD);
+ executeBufferHostWrites(bufD);
if (bufD->generation != bd.ubuf.generation || bufD->m_id != bd.ubuf.id) {
srbUpdate = true;
@@ -667,8 +672,17 @@ void QRhiD3D11::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind
}
}
- if (srbUpdate)
- updateShaderResourceBindings(srbD);
+ if (srbUpdate) {
+ const QShader::NativeResourceBindingMap *resBindMaps[RBM_SUPPORTED_STAGES];
+ memset(resBindMaps, 0, sizeof(resBindMaps));
+ if (gfxPsD) {
+ resBindMaps[RBM_VERTEX] = &gfxPsD->vs.nativeResourceBindingMap;
+ resBindMaps[RBM_FRAGMENT] = &gfxPsD->fs.nativeResourceBindingMap;
+ } else {
+ resBindMaps[RBM_COMPUTE] = &compPsD->cs.nativeResourceBindingMap;
+ }
+ updateShaderResourceBindings(srbD, resBindMaps);
+ }
const bool srbChanged = gfxPsD ? (cbD->currentGraphicsSrb != srb) : (cbD->currentComputeSrb != srb);
const bool srbRebuilt = cbD->currentSrbGeneration != srbD->generation;
@@ -725,7 +739,7 @@ void QRhiD3D11::setVertexInput(QRhiCommandBuffer *cb,
QD3D11Buffer *bufD = QRHI_RES(QD3D11Buffer, bindings[i].first);
Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::VertexBuffer));
if (bufD->m_type == QRhiBuffer::Dynamic)
- executeBufferHostWritesForCurrentFrame(bufD);
+ executeBufferHostWrites(bufD);
if (cbD->currentVertexBuffers[inputSlot] != bufD->buffer
|| cbD->currentVertexOffsets[inputSlot] != bindings[i].second)
@@ -757,7 +771,7 @@ void QRhiD3D11::setVertexInput(QRhiCommandBuffer *cb,
QD3D11Buffer *ibufD = QRHI_RES(QD3D11Buffer, indexBuf);
Q_ASSERT(ibufD->m_usage.testFlag(QRhiBuffer::IndexBuffer));
if (ibufD->m_type == QRhiBuffer::Dynamic)
- executeBufferHostWritesForCurrentFrame(ibufD);
+ executeBufferHostWrites(ibufD);
const DXGI_FORMAT dxgiFormat = indexFormat == QRhiCommandBuffer::IndexUInt16 ? DXGI_FORMAT_R16_UINT
: DXGI_FORMAT_R32_UINT;
@@ -1774,7 +1788,26 @@ void QRhiD3D11::dispatch(QRhiCommandBuffer *cb, int x, int y, int z)
cbD->commands.append(cmd);
}
-void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
+static inline QPair<int, int> mapBinding(int binding,
+ int stageIndex,
+ const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[])
+{
+ const QShader::NativeResourceBindingMap *map = nativeResourceBindingMaps[stageIndex];
+ if (!map || map->isEmpty())
+ return { binding, binding }; // old QShader versions do not have this map, assume 1:1 mapping then
+
+ auto it = map->constFind(binding);
+ if (it != map->cend())
+ return *it;
+
+ // Hitting this path is normal too. It is not given that the resource is
+ // present in the shaders for all the stages specified by the visibility
+ // mask in the QRhiShaderResourceBinding.
+ return { -1, -1 };
+}
+
+void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD,
+ const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[])
{
srbD->vsubufs.clear();
srbD->vsubufoffsets.clear();
@@ -1799,6 +1832,31 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
srbD->csUAVs.clear();
+ struct Stage {
+ struct Buffer {
+ int breg; // b0, b1, ...
+ ID3D11Buffer *buffer;
+ uint offsetInConstants;
+ uint sizeInConstants;
+ };
+ struct Texture {
+ int treg; // t0, t1, ...
+ ID3D11ShaderResourceView *srv;
+ };
+ struct Sampler {
+ int sreg; // s0, s1, ...
+ ID3D11SamplerState *sampler;
+ };
+ struct Uav {
+ int ureg;
+ ID3D11UnorderedAccessView *uav;
+ };
+ QVarLengthArray<Buffer, 8> buffers;
+ QVarLengthArray<Texture, 8> textures;
+ QVarLengthArray<Sampler, 8> samplers;
+ QVarLengthArray<Uav, 8> uavs;
+ } res[RBM_SUPPORTED_STAGES];
+
for (int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
const QRhiShaderResourceBinding::Data *b = srbD->sortedBindings.at(i).data();
QD3D11ShaderResourceBindings::BoundResourceData &bd(srbD->boundResourceData[i]);
@@ -1818,26 +1876,24 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
// (ByteWidth) is always a multiple of 256.
const uint sizeInConstants = uint(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);
+ QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps);
+ if (nativeBinding.first >= 0)
+ res[RBM_VERTEX].buffers.append({ nativeBinding.first, bufD->buffer, offsetInConstants, 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);
+ QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
+ if (nativeBinding.first >= 0)
+ res[RBM_FRAGMENT].buffers.append({ nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
}
if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
- srbD->csubufs.feed(b->binding, bufD->buffer);
- srbD->csubufoffsets.feed(b->binding, offsetInConstants);
- srbD->csubufsizes.feed(b->binding, sizeInConstants);
+ QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
+ if (nativeBinding.first >= 0)
+ res[RBM_COMPUTE].buffers.append({ nativeBinding.first, bufD->buffer, offsetInConstants, 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;
@@ -1845,16 +1901,25 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
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);
+ QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps);
+ if (nativeBinding.first >= 0 && nativeBinding.second >= 0) {
+ res[RBM_VERTEX].textures.append({ nativeBinding.first, texD->srv });
+ res[RBM_VERTEX].samplers.append({ nativeBinding.second, samplerD->samplerState });
+ }
}
if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
- srbD->fssamplers.feed(b->binding, samplerD->samplerState);
- srbD->fsshaderresources.feed(b->binding, texD->srv);
+ QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
+ if (nativeBinding.first >= 0 && nativeBinding.second >= 0) {
+ res[RBM_FRAGMENT].textures.append({ nativeBinding.first, texD->srv });
+ res[RBM_FRAGMENT].samplers.append({ nativeBinding.second, samplerD->samplerState });
+ }
}
if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
- srbD->cssamplers.feed(b->binding, samplerD->samplerState);
- srbD->csshaderresources.feed(b->binding, texD->srv);
+ QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
+ if (nativeBinding.first >= 0 && nativeBinding.second >= 0) {
+ res[RBM_COMPUTE].textures.append({ nativeBinding.first, texD->srv });
+ res[RBM_COMPUTE].samplers.append({ nativeBinding.second, samplerD->samplerState });
+ }
}
}
break;
@@ -1866,9 +1931,12 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
bd.simage.id = texD->m_id;
bd.simage.generation = texD->generation;
if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
- ID3D11UnorderedAccessView *uav = texD->unorderedAccessViewForLevel(b->u.simage.level);
- if (uav)
- srbD->csUAVs.feed(b->binding, uav);
+ QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
+ if (nativeBinding.first >= 0) {
+ ID3D11UnorderedAccessView *uav = texD->unorderedAccessViewForLevel(b->u.simage.level);
+ if (uav)
+ res[RBM_COMPUTE].uavs.append({ nativeBinding.first, uav });
+ }
} else {
qWarning("Unordered access only supported at compute stage");
}
@@ -1882,9 +1950,12 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
bd.sbuf.id = bufD->m_id;
bd.sbuf.generation = bufD->generation;
if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
- ID3D11UnorderedAccessView *uav = bufD->unorderedAccessView();
- if (uav)
- srbD->csUAVs.feed(b->binding, uav);
+ QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
+ if (nativeBinding.first >= 0) {
+ ID3D11UnorderedAccessView *uav = bufD->unorderedAccessView();
+ if (uav)
+ res[RBM_COMPUTE].uavs.append({ nativeBinding.first, uav });
+ }
} else {
qWarning("Unordered access only supported at compute stage");
}
@@ -1896,31 +1967,79 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
}
}
+ // QRhiBatchedBindings works with the native bindings and expects
+ // sorted input. The pre-sorted QRhiShaderResourceBinding list (based
+ // on the QRhi (SPIR-V) binding) is not helpful in this regard, so we
+ // have to sort here every time.
+ for (int stage = 0; stage < RBM_SUPPORTED_STAGES; ++stage) {
+ std::sort(res[stage].buffers.begin(), res[stage].buffers.end(), [](const Stage::Buffer &a, const Stage::Buffer &b) {
+ return a.breg < b.breg;
+ });
+ std::sort(res[stage].textures.begin(), res[stage].textures.end(), [](const Stage::Texture &a, const Stage::Texture &b) {
+ return a.treg < b.treg;
+ });
+ std::sort(res[stage].samplers.begin(), res[stage].samplers.end(), [](const Stage::Sampler &a, const Stage::Sampler &b) {
+ return a.sreg < b.sreg;
+ });
+ std::sort(res[stage].uavs.begin(), res[stage].uavs.end(), [](const Stage::Uav &a, const Stage::Uav &b) {
+ return a.ureg < b.ureg;
+ });
+ }
+
+ for (const Stage::Buffer &buf : qAsConst(res[RBM_VERTEX].buffers)) {
+ srbD->vsubufs.feed(buf.breg, buf.buffer);
+ srbD->vsubufoffsets.feed(buf.breg, buf.offsetInConstants);
+ srbD->vsubufsizes.feed(buf.breg, buf.sizeInConstants);
+ }
srbD->vsubufs.finish();
srbD->vsubufoffsets.finish();
srbD->vsubufsizes.finish();
+ for (const Stage::Buffer &buf : qAsConst(res[RBM_FRAGMENT].buffers)) {
+ srbD->fsubufs.feed(buf.breg, buf.buffer);
+ srbD->fsubufoffsets.feed(buf.breg, buf.offsetInConstants);
+ srbD->fsubufsizes.feed(buf.breg, buf.sizeInConstants);
+ }
srbD->fsubufs.finish();
srbD->fsubufoffsets.finish();
srbD->fsubufsizes.finish();
+ for (const Stage::Buffer &buf : qAsConst(res[RBM_COMPUTE].buffers)) {
+ srbD->csubufs.feed(buf.breg, buf.buffer);
+ srbD->csubufoffsets.feed(buf.breg, buf.offsetInConstants);
+ srbD->csubufsizes.feed(buf.breg, buf.sizeInConstants);
+ }
srbD->csubufs.finish();
srbD->csubufoffsets.finish();
srbD->csubufsizes.finish();
+ for (const Stage::Texture &t : qAsConst(res[RBM_VERTEX].textures))
+ srbD->vsshaderresources.feed(t.treg, t.srv);
+ for (const Stage::Sampler &s : qAsConst(res[RBM_VERTEX].samplers))
+ srbD->vssamplers.feed(s.sreg, s.sampler);
srbD->vssamplers.finish();
srbD->vsshaderresources.finish();
+ for (const Stage::Texture &t : qAsConst(res[RBM_FRAGMENT].textures))
+ srbD->fsshaderresources.feed(t.treg, t.srv);
+ for (const Stage::Sampler &s : qAsConst(res[RBM_FRAGMENT].samplers))
+ srbD->fssamplers.feed(s.sreg, s.sampler);
srbD->fssamplers.finish();
srbD->fsshaderresources.finish();
+ for (const Stage::Texture &t : qAsConst(res[RBM_COMPUTE].textures))
+ srbD->csshaderresources.feed(t.treg, t.srv);
+ for (const Stage::Sampler &s : qAsConst(res[RBM_COMPUTE].samplers))
+ srbD->cssamplers.feed(s.sreg, s.sampler);
srbD->cssamplers.finish();
srbD->csshaderresources.finish();
+ for (const Stage::Uav &u : qAsConst(res[RBM_COMPUTE].uavs))
+ srbD->csUAVs.feed(u.ureg, u.uav);
srbD->csUAVs.finish();
}
-void QRhiD3D11::executeBufferHostWritesForCurrentFrame(QD3D11Buffer *bufD)
+void QRhiD3D11::executeBufferHostWrites(QD3D11Buffer *bufD)
{
if (!bufD->hasPendingDynamicUpdates)
return;
@@ -2205,8 +2324,8 @@ void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *
case QD3D11CommandBuffer::Command::BindGraphicsPipeline:
{
QD3D11GraphicsPipeline *psD = cmd.args.bindGraphicsPipeline.ps;
- context->VSSetShader(psD->vs, nullptr, 0);
- context->PSSetShader(psD->fs, nullptr, 0);
+ context->VSSetShader(psD->vs.shader, nullptr, 0);
+ context->PSSetShader(psD->fs.shader, nullptr, 0);
context->IASetPrimitiveTopology(psD->d3dTopology);
context->IASetInputLayout(psD->inputLayout);
context->OMSetDepthStencilState(psD->dsState, stencilRef);
@@ -2281,7 +2400,7 @@ void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *
annotations->SetMarker(reinterpret_cast<LPCWSTR>(QString::fromLatin1(cmd.args.debugMark.s).utf16()));
break;
case QD3D11CommandBuffer::Command::BindComputePipeline:
- context->CSSetShader(cmd.args.bindComputePipeline.ps->cs, nullptr, 0);
+ context->CSSetShader(cmd.args.bindComputePipeline.ps->cs.shader, nullptr, 0);
break;
case QD3D11CommandBuffer::Command::Dispatch:
context->Dispatch(cmd.args.dispatch.x, cmd.args.dispatch.y, cmd.args.dispatch.z);
@@ -2388,6 +2507,10 @@ bool QD3D11Buffer::build()
QRhiBuffer::NativeBuffer QD3D11Buffer::nativeBuffer()
{
+ if (m_type == Dynamic) {
+ QRHI_RES_RHI(QRhiD3D11);
+ rhiD->executeBufferHostWrites(this);
+ }
return { { &buffer }, 1 };
}
@@ -3133,6 +3256,7 @@ QD3D11ShaderResourceBindings::~QD3D11ShaderResourceBindings()
void QD3D11ShaderResourceBindings::release()
{
sortedBindings.clear();
+ boundResourceData.clear();
}
bool QD3D11ShaderResourceBindings::build()
@@ -3149,8 +3273,8 @@ bool QD3D11ShaderResourceBindings::build()
boundResourceData.resize(sortedBindings.count());
- QRHI_RES_RHI(QRhiD3D11);
- rhiD->updateShaderResourceBindings(this);
+ for (BoundResourceData &bd : boundResourceData)
+ memset(&bd, 0, sizeof(BoundResourceData));
generation += 1;
return true;
@@ -3191,15 +3315,17 @@ void QD3D11GraphicsPipeline::release()
rastState = nullptr;
}
- if (vs) {
- vs->Release();
- vs = nullptr;
+ if (vs.shader) {
+ vs.shader->Release();
+ vs.shader = nullptr;
}
+ vs.nativeResourceBindingMap.clear();
- if (fs) {
- fs->Release();
- fs = nullptr;
+ if (fs.shader) {
+ fs.shader->Release();
+ fs.shader = nullptr;
}
+ fs.nativeResourceBindingMap.clear();
rhiD->unregisterResource(this);
}
@@ -3401,13 +3527,14 @@ static pD3DCompile resolveD3DCompile()
return nullptr;
}
-static QByteArray compileHlslShaderSource(const QShader &shader, QShader::Variant shaderVariant, QString *error)
+static QByteArray compileHlslShaderSource(const QShader &shader, QShader::Variant shaderVariant, QString *error, QShaderKey *usedShaderKey)
{
QShaderCode dxbc = shader.shader({ QShader::DxbcShader, 50, shaderVariant });
if (!dxbc.shader().isEmpty())
return dxbc.shader();
- QShaderCode hlslSource = shader.shader({ QShader::HlslShader, 50, shaderVariant });
+ const QShaderKey key = { QShader::HlslShader, 50, shaderVariant };
+ QShaderCode hlslSource = shader.shader(key);
if (hlslSource.shader().isEmpty()) {
qWarning() << "No HLSL (shader model 5.0) code found in baked shader" << shader;
return QByteArray();
@@ -3459,6 +3586,9 @@ static QByteArray compileHlslShaderSource(const QShader &shader, QShader::Varian
return QByteArray();
}
+ if (usedShaderKey)
+ *usedShaderKey = key;
+
QByteArray result;
result.resize(int(bytecode->GetBufferSize()));
memcpy(result.data(), bytecode->GetBufferPointer(), size_t(result.size()));
@@ -3550,20 +3680,23 @@ bool QD3D11GraphicsPipeline::build()
if (cacheIt != rhiD->m_shaderCache.constEnd()) {
switch (shaderStage.type()) {
case QRhiShaderStage::Vertex:
- vs = static_cast<ID3D11VertexShader *>(cacheIt->s);
- vs->AddRef();
+ vs.shader = static_cast<ID3D11VertexShader *>(cacheIt->s);
+ vs.shader->AddRef();
vsByteCode = cacheIt->bytecode;
+ vs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
break;
case QRhiShaderStage::Fragment:
- fs = static_cast<ID3D11PixelShader *>(cacheIt->s);
- fs->AddRef();
+ fs.shader = static_cast<ID3D11PixelShader *>(cacheIt->s);
+ fs.shader->AddRef();
+ fs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
break;
default:
break;
}
} else {
QString error;
- const QByteArray bytecode = compileHlslShaderSource(shaderStage.shader(), shaderStage.shaderVariant(), &error);
+ QShaderKey shaderKey;
+ const QByteArray bytecode = compileHlslShaderSource(shaderStage.shader(), shaderStage.shaderVariant(), &error, &shaderKey);
if (bytecode.isEmpty()) {
qWarning("HLSL shader compilation failed: %s", qPrintable(error));
return false;
@@ -3576,23 +3709,27 @@ bool QD3D11GraphicsPipeline::build()
switch (shaderStage.type()) {
case QRhiShaderStage::Vertex:
- hr = rhiD->dev->CreateVertexShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &vs);
+ hr = rhiD->dev->CreateVertexShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &vs.shader);
if (FAILED(hr)) {
qWarning("Failed to create vertex shader: %s", qPrintable(comErrorMessage(hr)));
return false;
}
vsByteCode = bytecode;
- rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(vs, bytecode));
- vs->AddRef();
+ if (const QShader::NativeResourceBindingMap *map = shaderStage.shader().nativeResourceBindingMap(shaderKey))
+ vs.nativeResourceBindingMap = *map;
+ rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(vs.shader, bytecode, vs.nativeResourceBindingMap));
+ vs.shader->AddRef();
break;
case QRhiShaderStage::Fragment:
- hr = rhiD->dev->CreatePixelShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &fs);
+ hr = rhiD->dev->CreatePixelShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &fs.shader);
if (FAILED(hr)) {
qWarning("Failed to create pixel shader: %s", qPrintable(comErrorMessage(hr)));
return false;
}
- rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(fs, bytecode));
- fs->AddRef();
+ if (const QShader::NativeResourceBindingMap *map = shaderStage.shader().nativeResourceBindingMap(shaderKey))
+ fs.nativeResourceBindingMap = *map;
+ rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(fs.shader, bytecode, fs.nativeResourceBindingMap));
+ fs.shader->AddRef();
break;
default:
break;
@@ -3651,46 +3788,52 @@ void QD3D11ComputePipeline::release()
{
QRHI_RES_RHI(QRhiD3D11);
- if (!cs)
+ if (!cs.shader)
return;
- cs->Release();
- cs = nullptr;
+ cs.shader->Release();
+ cs.shader = nullptr;
+ cs.nativeResourceBindingMap.clear();
rhiD->unregisterResource(this);
}
bool QD3D11ComputePipeline::build()
{
- if (cs)
+ if (cs.shader)
release();
QRHI_RES_RHI(QRhiD3D11);
auto cacheIt = rhiD->m_shaderCache.constFind(m_shaderStage);
if (cacheIt != rhiD->m_shaderCache.constEnd()) {
- cs = static_cast<ID3D11ComputeShader *>(cacheIt->s);
+ cs.shader = static_cast<ID3D11ComputeShader *>(cacheIt->s);
+ cs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
} else {
QString error;
- const QByteArray bytecode = compileHlslShaderSource(m_shaderStage.shader(), m_shaderStage.shaderVariant(), &error);
+ QShaderKey shaderKey;
+ const QByteArray bytecode = compileHlslShaderSource(m_shaderStage.shader(), m_shaderStage.shaderVariant(), &error, &shaderKey);
if (bytecode.isEmpty()) {
qWarning("HLSL compute shader compilation failed: %s", qPrintable(error));
return false;
}
- HRESULT hr = rhiD->dev->CreateComputeShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &cs);
+ HRESULT hr = rhiD->dev->CreateComputeShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &cs.shader);
if (FAILED(hr)) {
qWarning("Failed to create compute shader: %s", qPrintable(comErrorMessage(hr)));
return false;
}
+ if (const QShader::NativeResourceBindingMap *map = m_shaderStage.shader().nativeResourceBindingMap(shaderKey))
+ cs.nativeResourceBindingMap = *map;
+
if (rhiD->m_shaderCache.count() >= QRhiD3D11::MAX_SHADER_CACHE_ENTRIES)
rhiD->clearShaderCache();
- rhiD->m_shaderCache.insert(m_shaderStage, QRhiD3D11::Shader(cs, bytecode));
+ rhiD->m_shaderCache.insert(m_shaderStage, QRhiD3D11::Shader(cs.shader, bytecode, cs.nativeResourceBindingMap));
}
- cs->AddRef();
+ cs.shader->AddRef();
generation += 1;
rhiD->registerResource(this);
diff --git a/src/gui/rhi/qrhid3d11_p_p.h b/src/gui/rhi/qrhid3d11_p_p.h
index 04751397f7..f749b612b5 100644
--- a/src/gui/rhi/qrhid3d11_p_p.h
+++ b/src/gui/rhi/qrhid3d11_p_p.h
@@ -270,8 +270,14 @@ struct QD3D11GraphicsPipeline : public QRhiGraphicsPipeline
ID3D11DepthStencilState *dsState = nullptr;
ID3D11BlendState *blendState = nullptr;
- ID3D11VertexShader *vs = nullptr;
- ID3D11PixelShader *fs = nullptr;
+ struct {
+ ID3D11VertexShader *shader = nullptr;
+ QShader::NativeResourceBindingMap nativeResourceBindingMap;
+ } vs;
+ struct {
+ ID3D11PixelShader *shader = nullptr;
+ QShader::NativeResourceBindingMap nativeResourceBindingMap;
+ } fs;
ID3D11InputLayout *inputLayout = nullptr;
D3D11_PRIMITIVE_TOPOLOGY d3dTopology = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
ID3D11RasterizerState *rastState = nullptr;
@@ -286,7 +292,10 @@ struct QD3D11ComputePipeline : public QRhiComputePipeline
void release() override;
bool build() override;
- ID3D11ComputeShader *cs = nullptr;
+ struct {
+ ID3D11ComputeShader *shader = nullptr;
+ QShader::NativeResourceBindingMap nativeResourceBindingMap;
+ } cs;
uint generation = 0;
friend class QRhiD3D11;
};
@@ -642,8 +651,9 @@ public:
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 updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD,
+ const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[]);
+ void executeBufferHostWrites(QD3D11Buffer *bufD);
void bindShaderResources(QD3D11ShaderResourceBindings *srbD,
const uint *dynOfsPairs, int dynOfsPairCount,
bool offsetOnlyChange);
@@ -701,9 +711,11 @@ public:
struct Shader {
Shader() = default;
- Shader(IUnknown *s, const QByteArray &bytecode) : s(s), bytecode(bytecode) { }
+ Shader(IUnknown *s, const QByteArray &bytecode, const QShader::NativeResourceBindingMap &rbm)
+ : s(s), bytecode(bytecode), nativeResourceBindingMap(rbm) { }
IUnknown *s;
QByteArray bytecode;
+ QShader::NativeResourceBindingMap nativeResourceBindingMap;
};
QHash<QRhiShaderStage, Shader> m_shaderCache;
diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm
index 48a562ef1d..314c58b0b7 100644
--- a/src/gui/rhi/qrhimetal.mm
+++ b/src/gui/rhi/qrhimetal.mm
@@ -1827,16 +1827,15 @@ void QRhiMetal::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
}
// this handles all types of buffers, not just Dynamic
-void QRhiMetal::executeBufferHostWritesForCurrentFrame(QMetalBuffer *bufD)
+void QRhiMetal::executeBufferHostWritesForSlot(QMetalBuffer *bufD, int slot)
{
- const int idx = bufD->d->slotted ? currentFrameSlot : 0;
- if (bufD->d->pendingUpdates[idx].isEmpty())
+ if (bufD->d->pendingUpdates[slot].isEmpty())
return;
- void *p = [bufD->d->buf[idx] contents];
+ void *p = [bufD->d->buf[slot] contents];
int changeBegin = -1;
int changeEnd = -1;
- for (const QRhiResourceUpdateBatchPrivate::BufferOp &u : qAsConst(bufD->d->pendingUpdates[idx])) {
+ for (const QRhiResourceUpdateBatchPrivate::BufferOp &u : qAsConst(bufD->d->pendingUpdates[slot])) {
Q_ASSERT(bufD == QRHI_RES(QMetalBuffer, u.buf));
memcpy(static_cast<char *>(p) + u.offset, u.data.constData(), size_t(u.data.size()));
if (changeBegin == -1 || u.offset < changeBegin)
@@ -1846,10 +1845,15 @@ void QRhiMetal::executeBufferHostWritesForCurrentFrame(QMetalBuffer *bufD)
}
#ifdef Q_OS_MACOS
if (changeBegin >= 0 && bufD->d->managed)
- [bufD->d->buf[idx] didModifyRange: NSMakeRange(NSUInteger(changeBegin), NSUInteger(changeEnd - changeBegin))];
+ [bufD->d->buf[slot] didModifyRange: NSMakeRange(NSUInteger(changeBegin), NSUInteger(changeEnd - changeBegin))];
#endif
- bufD->d->pendingUpdates[idx].clear();
+ bufD->d->pendingUpdates[slot].clear();
+}
+
+void QRhiMetal::executeBufferHostWritesForCurrentFrame(QMetalBuffer *bufD)
+{
+ executeBufferHostWritesForSlot(bufD, bufD->d->slotted ? currentFrameSlot : 0);
}
void QRhiMetal::resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
@@ -2205,8 +2209,11 @@ QRhiBuffer::NativeBuffer QMetalBuffer::nativeBuffer()
if (d->slotted) {
NativeBuffer b;
Q_ASSERT(sizeof(b.objects) / sizeof(b.objects[0]) >= size_t(QMTL_FRAMES_IN_FLIGHT));
- for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i)
+ for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i) {
+ QRHI_RES_RHI(QRhiMetal);
+ rhiD->executeBufferHostWritesForSlot(this, i);
b.objects[i] = &d->buf[i];
+ }
b.slotCount = QMTL_FRAMES_IN_FLIGHT;
return b;
}
diff --git a/src/gui/rhi/qrhimetal_p_p.h b/src/gui/rhi/qrhimetal_p_p.h
index 212b731b71..a5af5611a6 100644
--- a/src/gui/rhi/qrhimetal_p_p.h
+++ b/src/gui/rhi/qrhimetal_p_p.h
@@ -437,6 +437,7 @@ public:
int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc,
qsizetype *curOfs);
void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates);
+ void executeBufferHostWritesForSlot(QMetalBuffer *bufD, int slot);
void executeBufferHostWritesForCurrentFrame(QMetalBuffer *bufD);
static const int SUPPORTED_STAGES = 3;
void enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD,
diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp
index d378e2a4ad..a92c3e14e9 100644
--- a/src/gui/rhi/qrhivulkan.cpp
+++ b/src/gui/rhi/qrhivulkan.cpp
@@ -149,6 +149,10 @@ QT_BEGIN_NAMESPACE
for other windows as well, as long as they all have their
QWindow::surfaceType() set to QSurface::VulkanSurface.
+ To request additional extensions to be enabled on the Vulkan device, list them
+ in deviceExtensions. This can be relevant when integrating with native Vulkan
+ rendering code.
+
\section2 Working with existing Vulkan devices
When interoperating with another graphics engine, it may be necessary to
@@ -299,6 +303,7 @@ QRhiVulkan::QRhiVulkan(QRhiVulkanInitParams *params, QRhiVulkanNativeHandles *im
{
inst = params->inst;
maybeWindow = params->window; // may be null
+ requestedDeviceExtensions = params->deviceExtensions;
importedDevice = importDevice != nullptr;
if (importedDevice) {
@@ -463,40 +468,59 @@ bool QRhiVulkan::create(QRhi::Flags flags)
if (inst->layers().contains("VK_LAYER_LUNARG_standard_validation"))
devLayers.append("VK_LAYER_LUNARG_standard_validation");
+ QVulkanInfoVector<QVulkanExtension> devExts;
uint32_t devExtCount = 0;
f->vkEnumerateDeviceExtensionProperties(physDev, nullptr, &devExtCount, nullptr);
- QVector<VkExtensionProperties> devExts(devExtCount);
- f->vkEnumerateDeviceExtensionProperties(physDev, nullptr, &devExtCount, devExts.data());
+ if (devExtCount) {
+ QVector<VkExtensionProperties> extProps(devExtCount);
+ f->vkEnumerateDeviceExtensionProperties(physDev, nullptr, &devExtCount, extProps.data());
+ for (const VkExtensionProperties &p : qAsConst(extProps))
+ devExts.append({ p.extensionName, p.specVersion });
+ }
qCDebug(QRHI_LOG_INFO, "%d device extensions available", devExts.count());
QVector<const char *> requestedDevExts;
requestedDevExts.append("VK_KHR_swapchain");
debugMarkersAvailable = false;
+ if (devExts.contains(VK_EXT_DEBUG_MARKER_EXTENSION_NAME)) {
+ requestedDevExts.append(VK_EXT_DEBUG_MARKER_EXTENSION_NAME);
+ debugMarkersAvailable = true;
+ }
+
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;
- }
+ if (devExts.contains(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;
}
}
- QByteArrayList envExtList;
- if (qEnvironmentVariableIsSet("QT_VULKAN_DEVICE_EXTENSIONS")) {
- envExtList = qgetenv("QT_VULKAN_DEVICE_EXTENSIONS").split(';');
- for (auto ext : requestedDevExts)
- envExtList.removeAll(ext);
- for (const QByteArray &ext : envExtList) {
- if (!ext.isEmpty())
+ for (const QByteArray &ext : requestedDeviceExtensions) {
+ if (!ext.isEmpty()) {
+ if (devExts.contains(ext))
requestedDevExts.append(ext.constData());
+ else
+ qWarning("Device extension %s is not supported", ext.constData());
}
}
+ QByteArrayList envExtList = qgetenv("QT_VULKAN_DEVICE_EXTENSIONS").split(';');
+ for (const QByteArray &ext : envExtList) {
+ if (!ext.isEmpty() && !requestedDevExts.contains(ext)) {
+ if (devExts.contains(ext))
+ requestedDevExts.append(ext.constData());
+ else
+ qWarning("Device extension %s is not supported", ext.constData());
+ }
+ }
+
+ if (QRHI_LOG_INFO().isEnabled(QtDebugMsg)) {
+ qCDebug(QRHI_LOG_INFO, "Enabling device extensions:");
+ for (const char *ext : requestedDevExts)
+ qCDebug(QRHI_LOG_INFO, " %s", ext);
+ }
+
VkDeviceCreateInfo devInfo;
memset(&devInfo, 0, sizeof(devInfo));
devInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
@@ -2903,7 +2927,7 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
} else if (u.type == QRhiResourceUpdateBatchPrivate::BufferOp::Read) {
QVkBuffer *bufD = QRHI_RES(QVkBuffer, u.buf);
if (bufD->m_type == QRhiBuffer::Dynamic) {
- executeBufferHostWritesForCurrentFrame(bufD);
+ executeBufferHostWritesForSlot(bufD, currentFrameSlot);
void *p = nullptr;
VmaAllocation a = toVmaAllocation(bufD->allocations[currentFrameSlot]);
VkResult err = vmaMapMemory(toVmaAllocator(allocator), a, &p);
@@ -3300,14 +3324,14 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
ud->free();
}
-void QRhiVulkan::executeBufferHostWritesForCurrentFrame(QVkBuffer *bufD)
+void QRhiVulkan::executeBufferHostWritesForSlot(QVkBuffer *bufD, int slot)
{
- if (bufD->pendingDynamicUpdates[currentFrameSlot].isEmpty())
+ if (bufD->pendingDynamicUpdates[slot].isEmpty())
return;
Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
void *p = nullptr;
- VmaAllocation a = toVmaAllocation(bufD->allocations[currentFrameSlot]);
+ VmaAllocation a = toVmaAllocation(bufD->allocations[slot]);
// 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.
@@ -3318,7 +3342,7 @@ void QRhiVulkan::executeBufferHostWritesForCurrentFrame(QVkBuffer *bufD)
}
int changeBegin = -1;
int changeEnd = -1;
- for (const QRhiResourceUpdateBatchPrivate::BufferOp &u : qAsConst(bufD->pendingDynamicUpdates[currentFrameSlot])) {
+ for (const QRhiResourceUpdateBatchPrivate::BufferOp &u : qAsConst(bufD->pendingDynamicUpdates[slot])) {
Q_ASSERT(bufD == QRHI_RES(QVkBuffer, u.buf));
memcpy(static_cast<char *>(p) + u.offset, u.data.constData(), size_t(u.data.size()));
if (changeBegin == -1 || u.offset < changeBegin)
@@ -3330,7 +3354,7 @@ void QRhiVulkan::executeBufferHostWritesForCurrentFrame(QVkBuffer *bufD)
if (changeBegin >= 0)
vmaFlushAllocation(toVmaAllocator(allocator), a, VkDeviceSize(changeBegin), VkDeviceSize(changeEnd - changeBegin));
- bufD->pendingDynamicUpdates[currentFrameSlot].clear();
+ bufD->pendingDynamicUpdates[slot].clear();
}
static void qrhivk_releaseBuffer(const QRhiVulkan::DeferredReleaseEntry &e, void *allocator)
@@ -4166,7 +4190,7 @@ void QRhiVulkan::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBin
Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::UniformBuffer));
if (bufD->m_type == QRhiBuffer::Dynamic)
- executeBufferHostWritesForCurrentFrame(bufD);
+ executeBufferHostWritesForSlot(bufD, currentFrameSlot);
bufD->lastActiveFrameSlot = currentFrameSlot;
trackedRegisterBuffer(&passResTracker, bufD, bufD->m_type == QRhiBuffer::Dynamic ? currentFrameSlot : 0,
@@ -4240,7 +4264,7 @@ void QRhiVulkan::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBin
Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::StorageBuffer));
if (bufD->m_type == QRhiBuffer::Dynamic)
- executeBufferHostWritesForCurrentFrame(bufD);
+ executeBufferHostWritesForSlot(bufD, currentFrameSlot);
bufD->lastActiveFrameSlot = currentFrameSlot;
QRhiPassResourceTracker::BufferAccess access;
@@ -4349,7 +4373,7 @@ void QRhiVulkan::setVertexInput(QRhiCommandBuffer *cb,
Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::VertexBuffer));
bufD->lastActiveFrameSlot = currentFrameSlot;
if (bufD->m_type == QRhiBuffer::Dynamic)
- executeBufferHostWritesForCurrentFrame(bufD);
+ executeBufferHostWritesForSlot(bufD, currentFrameSlot);
const VkBuffer vkvertexbuf = bufD->buffers[bufD->m_type == QRhiBuffer::Dynamic ? currentFrameSlot : 0];
if (cbD->currentVertexBuffers[inputSlot] != vkvertexbuf
@@ -4395,7 +4419,7 @@ void QRhiVulkan::setVertexInput(QRhiCommandBuffer *cb,
Q_ASSERT(ibufD->m_usage.testFlag(QRhiBuffer::IndexBuffer));
ibufD->lastActiveFrameSlot = currentFrameSlot;
if (ibufD->m_type == QRhiBuffer::Dynamic)
- executeBufferHostWritesForCurrentFrame(ibufD);
+ executeBufferHostWritesForSlot(ibufD, currentFrameSlot);
const int slot = ibufD->m_type == QRhiBuffer::Dynamic ? currentFrameSlot : 0;
const VkBuffer vkindexbuf = ibufD->buffers[slot];
@@ -5188,10 +5212,13 @@ bool QVkBuffer::build()
QRhiBuffer::NativeBuffer QVkBuffer::nativeBuffer()
{
if (m_type == Dynamic) {
+ QRHI_RES_RHI(QRhiVulkan);
NativeBuffer b;
Q_ASSERT(sizeof(b.objects) / sizeof(b.objects[0]) >= size_t(QVK_FRAMES_IN_FLIGHT));
- for (int i = 0; i < QVK_FRAMES_IN_FLIGHT; ++i)
+ for (int i = 0; i < QVK_FRAMES_IN_FLIGHT; ++i) {
+ rhiD->executeBufferHostWritesForSlot(this, i);
b.objects[i] = &buffers[i];
+ }
b.slotCount = QVK_FRAMES_IN_FLIGHT;
return b;
}
@@ -5536,6 +5563,11 @@ QRhiTexture::NativeTexture QVkTexture::nativeTexture()
return {&image, usageState.layout};
}
+void QVkTexture::setNativeLayout(int layout)
+{
+ usageState.layout = VkImageLayout(layout);
+}
+
VkImageView QVkTexture::imageViewForLevel(int level)
{
Q_ASSERT(level >= 0 && level < int(mipLevelCount));
diff --git a/src/gui/rhi/qrhivulkan_p.h b/src/gui/rhi/qrhivulkan_p.h
index d495919671..f8870dcd77 100644
--- a/src/gui/rhi/qrhivulkan_p.h
+++ b/src/gui/rhi/qrhivulkan_p.h
@@ -57,6 +57,7 @@ struct Q_GUI_EXPORT QRhiVulkanInitParams : public QRhiInitParams
{
QVulkanInstance *inst = nullptr;
QWindow *window = nullptr;
+ QByteArrayList deviceExtensions;
};
struct Q_GUI_EXPORT QRhiVulkanNativeHandles : public QRhiNativeHandles
diff --git a/src/gui/rhi/qrhivulkan_p_p.h b/src/gui/rhi/qrhivulkan_p_p.h
index 6322882569..fd65417e75 100644
--- a/src/gui/rhi/qrhivulkan_p_p.h
+++ b/src/gui/rhi/qrhivulkan_p_p.h
@@ -123,6 +123,7 @@ struct QVkTexture : public QRhiTexture
bool build() override;
bool buildFrom(NativeTexture src) override;
NativeTexture nativeTexture() override;
+ void setNativeLayout(int layout) override;
bool prepareBuild(QSize *adjustedSize = nullptr);
bool finishBuild();
@@ -778,7 +779,7 @@ public:
size_t *curOfs, void *mp,
BufferImageCopyList *copyInfos);
void enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdateBatch *resourceUpdates);
- void executeBufferHostWritesForCurrentFrame(QVkBuffer *bufD);
+ void executeBufferHostWritesForSlot(QVkBuffer *bufD, int slot);
void enqueueTransitionPassResources(QVkCommandBuffer *cbD);
void recordPrimaryCommandBuffer(QVkCommandBuffer *cbD);
void trackedRegisterBuffer(QRhiPassResourceTracker *passResTracker,
@@ -810,6 +811,7 @@ public:
QVulkanInstance *inst = nullptr;
QWindow *maybeWindow = nullptr;
+ QByteArrayList requestedDeviceExtensions;
bool importedDevice = false;
VkPhysicalDevice physDev = VK_NULL_HANDLE;
VkDevice dev = VK_NULL_HANDLE;
diff --git a/src/gui/rhi/qshader.cpp b/src/gui/rhi/qshader.cpp
index 69f4a68215..945f4820c2 100644
--- a/src/gui/rhi/qshader.cpp
+++ b/src/gui/rhi/qshader.cpp
@@ -428,6 +428,7 @@ QShader QShader::fromSerialized(const QByteArray &data)
ds >> intVal;
d->qsbVersion = intVal;
if (d->qsbVersion != QShaderPrivate::QSB_VERSION
+ && d->qsbVersion != QShaderPrivate::QSB_VERSION_WITHOUT_VAR_ARRAYDIMS
&& d->qsbVersion != QShaderPrivate::QSB_VERSION_WITH_CBOR
&& d->qsbVersion != QShaderPrivate::QSB_VERSION_WITH_BINARY_JSON
&& d->qsbVersion != QShaderPrivate::QSB_VERSION_WITHOUT_BINDINGS)
@@ -439,7 +440,7 @@ QShader QShader::fromSerialized(const QByteArray &data)
ds >> intVal;
d->stage = Stage(intVal);
if (d->qsbVersion > QShaderPrivate::QSB_VERSION_WITH_CBOR) {
- d->desc = QShaderDescription::deserialize(&ds);
+ d->desc = QShaderDescription::deserialize(&ds, d->qsbVersion);
} else if (d->qsbVersion > QShaderPrivate::QSB_VERSION_WITH_BINARY_JSON) {
QByteArray descBin;
ds >> descBin;
diff --git a/src/gui/rhi/qshader_p_p.h b/src/gui/rhi/qshader_p_p.h
index 66ef18f391..ec9d25971f 100644
--- a/src/gui/rhi/qshader_p_p.h
+++ b/src/gui/rhi/qshader_p_p.h
@@ -57,7 +57,8 @@ QT_BEGIN_NAMESPACE
struct Q_GUI_EXPORT QShaderPrivate
{
- static const int QSB_VERSION = 4;
+ static const int QSB_VERSION = 5;
+ static const int QSB_VERSION_WITHOUT_VAR_ARRAYDIMS = 4;
static const int QSB_VERSION_WITH_CBOR = 3;
static const int QSB_VERSION_WITH_BINARY_JSON = 2;
static const int QSB_VERSION_WITHOUT_BINDINGS = 1;
diff --git a/src/gui/rhi/qshaderdescription.cpp b/src/gui/rhi/qshaderdescription.cpp
index 96c8d082fc..f3ef5edd12 100644
--- a/src/gui/rhi/qshaderdescription.cpp
+++ b/src/gui/rhi/qshaderdescription.cpp
@@ -35,6 +35,7 @@
****************************************************************************/
#include "qshaderdescription_p_p.h"
+#include "qshader_p_p.h"
#include <QDebug>
#include <QDataStream>
#include <QJsonObject>
@@ -402,10 +403,10 @@ QShaderDescription QShaderDescription::fromCbor(const QByteArray &data)
return desc;
}
-QShaderDescription QShaderDescription::deserialize(QDataStream *stream)
+QShaderDescription QShaderDescription::deserialize(QDataStream *stream, int version)
{
QShaderDescription desc;
- QShaderDescriptionPrivate::get(&desc)->loadFromStream(stream);
+ QShaderDescriptionPrivate::get(&desc)->loadFromStream(stream, version);
return desc;
}
@@ -783,6 +784,8 @@ QDebug operator<<(QDebug dbg, const QShaderDescription::InOutVariable &var)
dbg.nospace() << " imageFormat=" << imageFormatStr(var.imageFormat);
if (var.imageFlags)
dbg.nospace() << " imageFlags=" << var.imageFlags;
+ if (!var.arrayDims.isEmpty())
+ dbg.nospace() << " array=" << var.arrayDims;
dbg.nospace() << ')';
return dbg;
}
@@ -878,6 +881,12 @@ static void addDeco(QJsonObject *obj, const QShaderDescription::InOutVariable &v
(*obj)[imageFormatKey] = imageFormatStr(v.imageFormat);
if (v.imageFlags)
(*obj)[imageFlagsKey] = int(v.imageFlags);
+ if (!v.arrayDims.isEmpty()) {
+ QJsonArray dimArr;
+ for (int dim : v.arrayDims)
+ dimArr.append(dim);
+ (*obj)[arrayDimsKey] = dimArr;
+ }
}
static void serializeDecorations(QDataStream *stream, const QShaderDescription::InOutVariable &v)
@@ -887,6 +896,9 @@ static void serializeDecorations(QDataStream *stream, const QShaderDescription::
(*stream) << v.descriptorSet;
(*stream) << int(v.imageFormat);
(*stream) << int(v.imageFlags);
+ (*stream) << v.arrayDims.count();
+ for (int dim : v.arrayDims)
+ (*stream) << dim;
}
static QJsonObject inOutObject(const QShaderDescription::InOutVariable &v)
@@ -1124,10 +1136,15 @@ static QShaderDescription::InOutVariable inOutVar(const QJsonObject &obj)
var.imageFormat = mapImageFormat(obj[imageFormatKey].toString());
if (obj.contains(imageFlagsKey))
var.imageFlags = QShaderDescription::ImageFlags(obj[imageFlagsKey].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());
+ }
return var;
}
-static void deserializeDecorations(QDataStream *stream, QShaderDescription::InOutVariable *v)
+static void deserializeDecorations(QDataStream *stream, int version, QShaderDescription::InOutVariable *v)
{
(*stream) >> v->location;
(*stream) >> v->binding;
@@ -1137,16 +1154,23 @@ static void deserializeDecorations(QDataStream *stream, QShaderDescription::InOu
v->imageFormat = QShaderDescription::ImageFormat(f);
(*stream) >> f;
v->imageFlags = QShaderDescription::ImageFlags(f);
+
+ if (version > QShaderPrivate::QSB_VERSION_WITHOUT_VAR_ARRAYDIMS) {
+ (*stream) >> f;
+ v->arrayDims.resize(f);
+ for (int i = 0; i < f; ++i)
+ (*stream) >> v->arrayDims[i];
+ }
}
-static QShaderDescription::InOutVariable deserializeInOutVar(QDataStream *stream)
+static QShaderDescription::InOutVariable deserializeInOutVar(QDataStream *stream, int version)
{
QShaderDescription::InOutVariable var;
(*stream) >> var.name;
int t;
(*stream) >> t;
var.type = QShaderDescription::VariableType(t);
- deserializeDecorations(stream, &var);
+ deserializeDecorations(stream, version, &var);
return var;
}
@@ -1176,7 +1200,7 @@ static QShaderDescription::BlockVariable blockVar(const QJsonObject &obj)
return var;
}
-static QShaderDescription::BlockVariable deserializeBlockMemberVar(QDataStream *stream)
+static QShaderDescription::BlockVariable deserializeBlockMemberVar(QDataStream *stream, int version)
{
QShaderDescription::BlockVariable var;
(*stream) >> var.name;
@@ -1196,7 +1220,7 @@ static QShaderDescription::BlockVariable deserializeBlockMemberVar(QDataStream *
(*stream) >> count;
var.structMembers.resize(count);
for (int i = 0; i < count; ++i)
- var.structMembers[i] = deserializeBlockMemberVar(stream);
+ var.structMembers[i] = deserializeBlockMemberVar(stream, version);
return var;
}
@@ -1304,7 +1328,7 @@ void QShaderDescriptionPrivate::loadDoc(const QJsonDocument &doc)
}
}
-void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream)
+void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream, int version)
{
Q_ASSERT(ref.loadRelaxed() == 1); // must be detached
@@ -1312,12 +1336,12 @@ void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream)
(*stream) >> count;
inVars.resize(count);
for (int i = 0; i < count; ++i)
- inVars[i] = deserializeInOutVar(stream);
+ inVars[i] = deserializeInOutVar(stream, version);
(*stream) >> count;
outVars.resize(count);
for (int i = 0; i < count; ++i)
- outVars[i] = deserializeInOutVar(stream);
+ outVars[i] = deserializeInOutVar(stream, version);
(*stream) >> count;
uniformBlocks.resize(count);
@@ -1331,7 +1355,7 @@ void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream)
(*stream) >> memberCount;
uniformBlocks[i].members.resize(memberCount);
for (int memberIdx = 0; memberIdx < memberCount; ++memberIdx)
- uniformBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream);
+ uniformBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream, version);
}
(*stream) >> count;
@@ -1343,7 +1367,7 @@ void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream)
(*stream) >> memberCount;
pushConstantBlocks[i].members.resize(memberCount);
for (int memberIdx = 0; memberIdx < memberCount; ++memberIdx)
- pushConstantBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream);
+ pushConstantBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream, version);
}
(*stream) >> count;
@@ -1358,7 +1382,7 @@ void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream)
(*stream) >> memberCount;
storageBlocks[i].members.resize(memberCount);
for (int memberIdx = 0; memberIdx < memberCount; ++memberIdx)
- storageBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream);
+ storageBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream, version);
}
(*stream) >> count;
@@ -1368,7 +1392,7 @@ void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream)
int t;
(*stream) >> t;
combinedImageSamplers[i].type = QShaderDescription::VariableType(t);
- deserializeDecorations(stream, &combinedImageSamplers[i]);
+ deserializeDecorations(stream, version, &combinedImageSamplers[i]);
}
(*stream) >> count;
@@ -1378,7 +1402,7 @@ void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream)
int t;
(*stream) >> t;
storageImages[i].type = QShaderDescription::VariableType(t);
- deserializeDecorations(stream, &storageImages[i]);
+ deserializeDecorations(stream, version, &storageImages[i]);
}
for (size_t i = 0; i < 3; ++i)
@@ -1420,7 +1444,8 @@ bool operator==(const QShaderDescription::InOutVariable &lhs, const QShaderDescr
&& lhs.binding == rhs.binding
&& lhs.descriptorSet == rhs.descriptorSet
&& lhs.imageFormat == rhs.imageFormat
- && lhs.imageFlags == rhs.imageFlags;
+ && lhs.imageFlags == rhs.imageFlags
+ && lhs.arrayDims == rhs.arrayDims;
}
/*!
diff --git a/src/gui/rhi/qshaderdescription_p.h b/src/gui/rhi/qshaderdescription_p.h
index 108fc32a56..e5650ed921 100644
--- a/src/gui/rhi/qshaderdescription_p.h
+++ b/src/gui/rhi/qshaderdescription_p.h
@@ -78,7 +78,7 @@ public:
static QShaderDescription fromBinaryJson(const QByteArray &data);
#endif
static QShaderDescription fromCbor(const QByteArray &data);
- static QShaderDescription deserialize(QDataStream *stream);
+ static QShaderDescription deserialize(QDataStream *stream, int version);
enum VariableType {
Unknown = 0,
@@ -216,6 +216,7 @@ public:
int descriptorSet = -1;
ImageFormat imageFormat = ImageFormatUnknown;
ImageFlags imageFlags;
+ QVector<int> arrayDims;
};
struct BlockVariable {
diff --git a/src/gui/rhi/qshaderdescription_p_p.h b/src/gui/rhi/qshaderdescription_p_p.h
index 69b6e811a1..ec2b0b6b4c 100644
--- a/src/gui/rhi/qshaderdescription_p_p.h
+++ b/src/gui/rhi/qshaderdescription_p_p.h
@@ -82,7 +82,7 @@ struct Q_GUI_EXPORT QShaderDescriptionPrivate
QJsonDocument makeDoc();
void writeToStream(QDataStream *stream);
void loadDoc(const QJsonDocument &doc);
- void loadFromStream(QDataStream *stream);
+ void loadFromStream(QDataStream *stream, int version);
QAtomicInt ref;
QVector<QShaderDescription::InOutVariable> inVars;
diff --git a/src/gui/text/qtextmarkdownimporter.cpp b/src/gui/text/qtextmarkdownimporter.cpp
index 7e18a10895..5e75e7816b 100644
--- a/src/gui/text/qtextmarkdownimporter.cpp
+++ b/src/gui/text/qtextmarkdownimporter.cpp
@@ -577,7 +577,10 @@ void QTextMarkdownImporter::insertBlock()
QTextBlockFormat blockFormat;
if (!m_listStack.isEmpty() && !m_needsInsertList && m_listItem) {
QTextList *list = m_listStack.top();
- blockFormat = list->item(list->count() - 1).blockFormat();
+ if (list)
+ blockFormat = list->item(list->count() - 1).blockFormat();
+ else
+ qWarning() << "attempted to insert into a list that no longer exists";
}
if (m_blockQuoteDepth) {
blockFormat.setProperty(QTextFormat::BlockQuoteLevel, m_blockQuoteDepth);
@@ -607,7 +610,7 @@ void QTextMarkdownImporter::insertBlock()
}
if (m_needsInsertList) {
m_listStack.push(m_cursor->createList(m_listFormat));
- } else if (!m_listStack.isEmpty() && m_listItem) {
+ } else if (!m_listStack.isEmpty() && m_listItem && m_listStack.top()) {
m_listStack.top()->add(m_cursor->block());
}
m_needsInsertList = false;
diff --git a/src/gui/text/qtextmarkdownimporter_p.h b/src/gui/text/qtextmarkdownimporter_p.h
index f450da5eb3..f12b725d8e 100644
--- a/src/gui/text/qtextmarkdownimporter_p.h
+++ b/src/gui/text/qtextmarkdownimporter_p.h
@@ -56,6 +56,7 @@
#include <QtGui/qpalette.h>
#include <QtGui/qtextdocument.h>
#include <QtGui/qtextlist.h>
+#include <QtCore/qpointer.h>
#include <QtCore/qstack.h>
QT_BEGIN_NAMESPACE
@@ -113,7 +114,7 @@ private:
#endif
QString m_blockCodeLanguage;
QVector<int> m_nonEmptyTableCells; // in the current row
- QStack<QTextList *> m_listStack;
+ QStack<QPointer<QTextList>> m_listStack;
QStack<QTextCharFormat> m_spanFormatStack;
QFont m_monoFont;
QPalette m_palette;
diff --git a/src/gui/vulkan/qvulkaninstance.cpp b/src/gui/vulkan/qvulkaninstance.cpp
index 4b961a6f20..555dee3a9c 100644
--- a/src/gui/vulkan/qvulkaninstance.cpp
+++ b/src/gui/vulkan/qvulkaninstance.cpp
@@ -781,6 +781,8 @@ bool QVulkanInstance::supportsPresent(VkPhysicalDevice physicalDevice, uint32_t
system dependent synchronization. For example, on Wayland this will
add send a wl_surface.frame request in order to prevent the driver from
blocking for minimized windows.
+
+ \since 5.15
*/
void QVulkanInstance::presentAboutToBeQueued(QWindow *window)
{
diff --git a/src/gui/vulkan/qvulkanwindow.cpp b/src/gui/vulkan/qvulkanwindow.cpp
index e211863f21..ee49cf0999 100644
--- a/src/gui/vulkan/qvulkanwindow.cpp
+++ b/src/gui/vulkan/qvulkanwindow.cpp
@@ -1596,19 +1596,6 @@ bool QVulkanWindow::event(QEvent *e)
*/
/*!
- Return a previously set queue create info modification function.
-
- \sa setQueueCreateInfoModifier()
-
- \since 5.15
- */
-QVulkanWindow::QueueCreateInfoModifier QVulkanWindow::queueCreateInfoModifier() const
-{
- Q_D(const QVulkanWindow);
- return d->queueCreateInfoModifier;
-}
-
-/*!
Set a queue create info modification function.
\sa queueCreateInfoModifier()
diff --git a/src/gui/vulkan/qvulkanwindow.h b/src/gui/vulkan/qvulkanwindow.h
index 530b6c0744..511b9501bd 100644
--- a/src/gui/vulkan/qvulkanwindow.h
+++ b/src/gui/vulkan/qvulkanwindow.h
@@ -106,7 +106,6 @@ public:
typedef std::function<void(const VkQueueFamilyProperties *,
uint32_t,
QVector<VkDeviceQueueCreateInfo> &)> QueueCreateInfoModifier;
- QueueCreateInfoModifier queueCreateInfoModifier() const;
void setQueueCreateInfoModifier(QueueCreateInfoModifier modifier);
bool isValid() const;
diff --git a/src/network/access/qnetworkreply.cpp b/src/network/access/qnetworkreply.cpp
index fb30bfd4f1..22c522756c 100644
--- a/src/network/access/qnetworkreply.cpp
+++ b/src/network/access/qnetworkreply.cpp
@@ -91,7 +91,7 @@ QNetworkReplyPrivate::QNetworkReplyPrivate()
content.
\note Do not delete the object in the slot connected to the
- error() or finished() signal. Use deleteLater().
+ errorOccurred() or finished() signal. Use deleteLater().
\sa QNetworkRequest, QNetworkAccessManager
*/
@@ -219,6 +219,7 @@ QNetworkReplyPrivate::QNetworkReplyPrivate()
the server response was detected
\sa error()
+ \sa errorOccurred()
*/
/*!
@@ -362,6 +363,14 @@ QNetworkReplyPrivate::QNetworkReplyPrivate()
/*!
\fn void QNetworkReply::error(QNetworkReply::NetworkError code)
+ \obsolete
+
+ Use errorOccurred() instead.
+*/
+
+/*!
+ \fn void QNetworkReply::errorOccurred(QNetworkReply::NetworkError code)
+ \since 5.15
This signal is emitted when the reply detects an error in
processing. The finished() signal will probably follow, indicating
@@ -442,7 +451,7 @@ QNetworkReplyPrivate::QNetworkReplyPrivate()
QNetworkAccessManager functions to do that.
*/
QNetworkReply::QNetworkReply(QObject *parent)
- : QIODevice(*new QNetworkReplyPrivate, parent)
+ : QNetworkReply(*new QNetworkReplyPrivate, parent)
{
}
@@ -452,6 +461,8 @@ QNetworkReply::QNetworkReply(QObject *parent)
QNetworkReply::QNetworkReply(QNetworkReplyPrivate &dd, QObject *parent)
: QIODevice(dd, parent)
{
+ // Support the deprecated error() signal:
+ connect(this, &QNetworkReply::errorOccurred, this, QOverload<QNetworkReply::NetworkError>::of(&QNetworkReply::error));
}
/*!
diff --git a/src/network/access/qnetworkreply.h b/src/network/access/qnetworkreply.h
index 4a402daa91..82349f9e2a 100644
--- a/src/network/access/qnetworkreply.h
+++ b/src/network/access/qnetworkreply.h
@@ -156,7 +156,11 @@ public Q_SLOTS:
Q_SIGNALS:
void metaDataChanged();
void finished();
+#if QT_DEPRECATED_SINCE(5,15)
+ QT_DEPRECATED_X("Use QNetworkReply::errorOccurred(QNetworkReply::NetworkError) instead")
void error(QNetworkReply::NetworkError);
+#endif
+ void errorOccurred(QNetworkReply::NetworkError);
#if QT_CONFIG(ssl)
void encrypted();
void sslErrors(const QList<QSslError> &errors);
diff --git a/src/network/access/qnetworkreplydataimpl.cpp b/src/network/access/qnetworkreplydataimpl.cpp
index 924c905b1a..2f75020446 100644
--- a/src/network/access/qnetworkreplydataimpl.cpp
+++ b/src/network/access/qnetworkreplydataimpl.cpp
@@ -88,7 +88,7 @@ QNetworkReplyDataImpl::QNetworkReplyDataImpl(QObject *parent, const QNetworkRequ
const QString msg = QCoreApplication::translate("QNetworkAccessDataBackend",
"Invalid URI: %1").arg(url.toString());
setError(QNetworkReply::ProtocolFailure, msg);
- QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
+ QMetaObject::invokeMethod(this, "errorOccurred", Qt::QueuedConnection,
Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ProtocolFailure));
QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection);
}
diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp
index c7d22be8f5..bb65660ba8 100644
--- a/src/network/access/qnetworkreplyhttpimpl.cpp
+++ b/src/network/access/qnetworkreplyhttpimpl.cpp
@@ -2253,7 +2253,7 @@ void QNetworkReplyHttpImplPrivate::error(QNetworkReplyImpl::NetworkError code, c
// note: might not be a good idea, since users could decide to delete us
// which would delete the backend too...
// maybe we should protect the backend
- emit q->error(code);
+ emit q->errorOccurred(code);
}
void QNetworkReplyHttpImplPrivate::_q_metaDataChanged()
diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp
index 51bb386186..a0b4ace470 100644
--- a/src/network/access/qnetworkreplyimpl.cpp
+++ b/src/network/access/qnetworkreplyimpl.cpp
@@ -855,7 +855,7 @@ void QNetworkReplyImplPrivate::error(QNetworkReplyImpl::NetworkError code, const
// note: might not be a good idea, since users could decide to delete us
// which would delete the backend too...
// maybe we should protect the backend
- emit q->error(code);
+ emit q->errorOccurred(code);
}
void QNetworkReplyImplPrivate::metaDataChanged()
@@ -1128,7 +1128,7 @@ QDisabledNetworkReply::QDisabledNetworkReply(QObject *parent,
"Network access is disabled.");
setError(UnknownNetworkError, msg);
- QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
+ QMetaObject::invokeMethod(this, "errorOccurred", Qt::QueuedConnection,
Q_ARG(QNetworkReply::NetworkError, UnknownNetworkError));
QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection);
}
diff --git a/src/plugins/imageformats/gif/qgifhandler.cpp b/src/plugins/imageformats/gif/qgifhandler.cpp
index a672e92006..d45ebfb314 100644
--- a/src/plugins/imageformats/gif/qgifhandler.cpp
+++ b/src/plugins/imageformats/gif/qgifhandler.cpp
@@ -1215,11 +1215,4 @@ int QGifHandler::currentImageNumber() const
return frameNumber;
}
-#if QT_DEPRECATED_SINCE(5, 13)
-QByteArray QGifHandler::name() const
-{
- return "gif";
-}
-#endif
-
QT_END_NAMESPACE
diff --git a/src/plugins/imageformats/gif/qgifhandler_p.h b/src/plugins/imageformats/gif/qgifhandler_p.h
index c6592043ce..f19777fa18 100644
--- a/src/plugins/imageformats/gif/qgifhandler_p.h
+++ b/src/plugins/imageformats/gif/qgifhandler_p.h
@@ -73,10 +73,6 @@ 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/plugins/imageformats/ico/qicohandler.cpp b/src/plugins/imageformats/ico/qicohandler.cpp
index 1982e05344..4c8ff7d489 100644
--- a/src/plugins/imageformats/ico/qicohandler.cpp
+++ b/src/plugins/imageformats/ico/qicohandler.cpp
@@ -809,17 +809,6 @@ bool QtIcoHandler::write(const QImage &image)
return ICOReader::write(device, imgs);
}
-#if QT_DEPRECATED_SINCE(5, 13)
-/*!
- * Return the common identifier of the format.
- * For ICO format this will return "ico".
- */
-QByteArray QtIcoHandler::name() const
-{
- return "ico";
-}
-#endif
-
/*! \reimp
*/
diff --git a/src/plugins/imageformats/ico/qicohandler.h b/src/plugins/imageformats/ico/qicohandler.h
index 328dfce47e..0d44a67dfc 100644
--- a/src/plugins/imageformats/ico/qicohandler.h
+++ b/src/plugins/imageformats/ico/qicohandler.h
@@ -54,10 +54,6 @@ public:
bool read(QImage *image) override;
bool write(const QImage &image) override;
-#if QT_DEPRECATED_SINCE(5, 13)
- QByteArray name() const override;
-#endif
-
int imageCount() const override;
bool jumpToImage(int imageNumber) override;
bool jumpToNextImage() override;
diff --git a/src/plugins/imageformats/jpeg/qjpeghandler.cpp b/src/plugins/imageformats/jpeg/qjpeghandler.cpp
index c31e2db3c5..fed585a82e 100644
--- a/src/plugins/imageformats/jpeg/qjpeghandler.cpp
+++ b/src/plugins/imageformats/jpeg/qjpeghandler.cpp
@@ -1184,11 +1184,4 @@ void QJpegHandler::setOption(ImageOption option, const QVariant &value)
}
}
-#if QT_DEPRECATED_SINCE(5, 13)
-QByteArray QJpegHandler::name() const
-{
- return "jpeg";
-}
-#endif
-
QT_END_NAMESPACE
diff --git a/src/plugins/imageformats/jpeg/qjpeghandler_p.h b/src/plugins/imageformats/jpeg/qjpeghandler_p.h
index fafa930c11..43ca17317a 100644
--- a/src/plugins/imageformats/jpeg/qjpeghandler_p.h
+++ b/src/plugins/imageformats/jpeg/qjpeghandler_p.h
@@ -68,10 +68,6 @@ 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/plugins/platforms/android/qandroidassetsfileenginehandler.cpp b/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp
index ca16efe34f..07776a4a76 100644
--- a/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp
+++ b/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp
@@ -202,9 +202,7 @@ public:
const QString &path)
: QAbstractFileEngineIterator(filters, nameFilters)
{
- m_stack.push_back(FolderIterator::fromCache(cleanedAssetPath(path), true));
- if (m_stack.last()->empty())
- m_stack.pop_back();
+ m_currentIterator = FolderIterator::fromCache(cleanedAssetPath(path), true);
}
QFileInfo currentFileInfo() const override
@@ -228,36 +226,23 @@ public:
bool hasNext() const override
{
- if (m_stack.empty())
+ if (!m_currentIterator)
return false;
- if (!m_stack.last()->hasNext()) {
- m_stack.pop_back();
- return hasNext();
- }
- return true;
+ return m_currentIterator->hasNext();
}
QString next() override
{
- if (m_stack.empty()) {
- m_currentIterator.reset();
+ if (!m_currentIterator)
return {};
- }
- m_currentIterator = m_stack.last();
auto res = m_currentIterator->next();
if (!res)
return {};
- if (res->second.type == AssetItem::Type::Folder) {
- m_stack.push_back(FolderIterator::fromCache(cleanedAssetPath(currentFilePath()), true));
- if (m_stack.last()->empty())
- m_stack.pop_back();
- }
return res->first;
}
private:
- mutable QSharedPointer<FolderIterator> m_currentIterator;
- mutable QVector<QSharedPointer<FolderIterator>> m_stack;
+ QSharedPointer<FolderIterator> m_currentIterator;
};
class AndroidAbstractFileEngine: public QAbstractFileEngine
diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
index 6aa21d78d1..8b76e45616 100644
--- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
+++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
@@ -419,8 +419,7 @@ static QString strippedText(QString s)
[mPopUpButton setHidden:chooseDirsOnly]; // TODO hide the whole sunken pane instead?
if (mOptions->acceptMode() == QFileDialogOptions::AcceptSave) {
- const QStringList ext = [self acceptableExtensionsForSave];
- [mSavePanel setAllowedFileTypes:ext.isEmpty() ? nil : qt_mac_QStringListToNSMutableArray(ext)];
+ [self recomputeAcceptableExtensionsForSave];
} else {
[mOpenPanel setAllowedFileTypes:nil]; // delegate panel:shouldEnableURL: does the file filtering for NSOpenPanel
}
@@ -457,25 +456,49 @@ static QString strippedText(QString s)
}
/*
- Returns a list of extensions (e.g. "png", "jpg", "gif")
- for the current name filter. If a filter do not conform
- to the format *.xyz or * or *.*, an empty list
- is returned meaning accept everything.
+ Computes a list of extensions (e.g. "png", "jpg", "gif")
+ for the current name filter, and updates the save panel.
+
+ If a filter do not conform to the format *.xyz or * or *.*,
+ all files types are allowed.
+
+ Extensions with more than one part (e.g. "tar.gz") are
+ reduced to their final part, as NSSavePanel does not deal
+ well with multi-part extensions.
*/
-- (QStringList)acceptableExtensionsForSave
-{
- QStringList result;
- for (int i=0; i<mSelectedNameFilter->count(); ++i) {
- const QString &filter = mSelectedNameFilter->at(i);
- if (filter.startsWith(QLatin1String("*."))
- && !filter.contains(QLatin1Char('?'))
- && filter.count(QLatin1Char('*')) == 1) {
- result += filter.mid(2);
- } else {
- return QStringList(); // Accept everything
- }
+- (void)recomputeAcceptableExtensionsForSave
+{
+ QStringList fileTypes;
+ for (const QString &filter : *mSelectedNameFilter) {
+ if (!filter.startsWith(QLatin1String("*.")))
+ continue;
+
+ if (filter.contains(QLatin1Char('?')))
+ continue;
+
+ if (filter.count(QLatin1Char('*')) != 1)
+ continue;
+
+ auto extensions = filter.split('.', Qt::SkipEmptyParts);
+ fileTypes += extensions.last();
+
+ // Explicitly show extensions if we detect a filter
+ // that has a multi-part extension. This prevents
+ // confusing situations where the user clicks e.g.
+ // 'foo.tar.gz' and 'foo.tar' is populated in the
+ // file name box, but when then clicking save macOS
+ // will warn that the file needs to end in .gz,
+ // due to thinking the user tried to save the file
+ // as a 'tar' file instead. Unfortunately this
+ // property can only be set before the panel is
+ // shown, so it will not have any effect when
+ // swithcing filters in an already opened dialog.
+ if (extensions.size() > 2)
+ mSavePanel.extensionHidden = NO;
}
- return result;
+
+ mSavePanel.allowedFileTypes = fileTypes.isEmpty() ? nil
+ : qt_mac_QStringListToNSMutableArray(fileTypes);
}
- (QString)removeExtensions:(const QString &)filter
diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
index d0e69bdca5..450329f569 100644
--- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
+++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
@@ -107,7 +107,7 @@ void *QCocoaNativeInterface::nativeResourceForWindow(const QByteArray &resourceS
#if QT_CONFIG(vulkan)
} else if (resourceString == "vkSurface") {
if (QVulkanInstance *instance = window->vulkanInstance())
- return static_cast<QCocoaVulkanInstance *>(instance->handle())->createSurface(window);
+ return static_cast<QCocoaVulkanInstance *>(instance->handle())->surface(window);
#endif
}
return nullptr;
diff --git a/src/plugins/platforms/cocoa/qcocoavulkaninstance.h b/src/plugins/platforms/cocoa/qcocoavulkaninstance.h
index 5fe6a612af..2a8d04757e 100644
--- a/src/plugins/platforms/cocoa/qcocoavulkaninstance.h
+++ b/src/plugins/platforms/cocoa/qcocoavulkaninstance.h
@@ -61,9 +61,11 @@ public:
void createOrAdoptInstance() override;
- VkSurfaceKHR *createSurface(QWindow *window);
- VkSurfaceKHR createSurface(NSView *view);
+ VkSurfaceKHR *surface(QWindow *window);
+
private:
+ VkSurfaceKHR createSurface(NSView *view);
+
QVulkanInstance *m_instance = nullptr;
QLibrary m_lib;
VkSurfaceKHR m_nullSurface = nullptr;
diff --git a/src/plugins/platforms/cocoa/qcocoavulkaninstance.mm b/src/plugins/platforms/cocoa/qcocoavulkaninstance.mm
index 7ce78ee738..9e714859f2 100644
--- a/src/plugins/platforms/cocoa/qcocoavulkaninstance.mm
+++ b/src/plugins/platforms/cocoa/qcocoavulkaninstance.mm
@@ -57,12 +57,11 @@ void QCocoaVulkanInstance::createOrAdoptInstance()
initInstance(m_instance, QByteArrayList() << QByteArrayLiteral("VK_MVK_macos_surface"));
}
-VkSurfaceKHR *QCocoaVulkanInstance::createSurface(QWindow *window)
+VkSurfaceKHR *QCocoaVulkanInstance::surface(QWindow *window)
{
QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window->handle());
- if (cocoaWindow->m_vulkanSurface)
- destroySurface(cocoaWindow->m_vulkanSurface);
- cocoaWindow->m_vulkanSurface = createSurface(cocoaWindow->m_view);
+ if (!cocoaWindow->m_vulkanSurface)
+ cocoaWindow->m_vulkanSurface = createSurface(cocoaWindow->m_view);
return &cocoaWindow->m_vulkanSurface;
}
@@ -81,7 +80,7 @@ VkSurfaceKHR QCocoaVulkanInstance::createSurface(NSView *view)
surfaceInfo.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
surfaceInfo.pNext = nullptr;
surfaceInfo.flags = 0;
- surfaceInfo.pView = view;
+ surfaceInfo.pView = view.layer;
VkSurfaceKHR surface = nullptr;
VkResult err = m_createSurface(m_vkInst, &surfaceInfo, nullptr, &surface);
diff --git a/src/plugins/platforms/cocoa/qpaintengine_mac.mm b/src/plugins/platforms/cocoa/qpaintengine_mac.mm
index cadb76d2e4..429c47dc3b 100644
--- a/src/plugins/platforms/cocoa/qpaintengine_mac.mm
+++ b/src/plugins/platforms/cocoa/qpaintengine_mac.mm
@@ -394,16 +394,19 @@ QCoreGraphicsPaintEngine::begin(QPaintDevice *pdev)
d->cosmeticPenSize = 1;
d->current.clipEnabled = false;
d->pixelSize = QPoint(1,1);
- QMacCGContext ctx(pdev);
- d->hd = CGContextRetain(ctx);
- if (d->hd) {
- d->saveGraphicsState();
- d->orig_xform = CGContextGetCTM(d->hd);
- if (d->shading) {
- CGShadingRelease(d->shading);
- d->shading = nullptr;
+
+ if (pdev->devType() != QInternal::Printer) {
+ QMacCGContext ctx(pdev);
+ d->hd = CGContextRetain(ctx);
+ if (d->hd) {
+ d->saveGraphicsState();
+ d->orig_xform = CGContextGetCTM(d->hd);
+ if (d->shading) {
+ CGShadingRelease(d->shading);
+ d->shading = nullptr;
+ }
+ d->setClip(nullptr); //clear the context's clipping
}
- d->setClip(nullptr); //clear the context's clipping
}
setActive(true);
diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp
index 77340387d8..8963f2ad17 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.cpp
+++ b/src/plugins/platforms/windows/qwindowsintegration.cpp
@@ -343,7 +343,9 @@ QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) cons
QWindowsWindowData requested;
requested.flags = window->flags();
- requested.geometry = QHighDpi::toNativePixels(window->geometry(), window);
+ requested.geometry = window->isTopLevel()
+ ? QHighDpi::toNativePixels(window->geometry(), window)
+ : QHighDpi::toNativeLocalPosition(window->geometry(), window);
// Apply custom margins (see QWindowsWindow::setCustomMargins())).
const QVariant customMarginsV = window->property("_q_windowsCustomMargins");
if (customMarginsV.isValid())
diff --git a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp
index 53562c87dd..d6a5b29a71 100644
--- a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp
+++ b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp
@@ -424,8 +424,12 @@ bool QWindowsSystemTrayIcon::winEvent(const MSG &message, long *result)
if (screen) {
emit contextMenuRequested(globalPos, screen);
emit activated(Context);
- if (m_menu)
+ if (m_menu) {
+ // Set the foreground window to the controlling window so that clicking outside
+ // of the menu or window will cause the menu to close
+ SetForegroundWindow(m_hwnd);
m_menu->trackPopupMenu(message.hwnd, globalPos.x(), globalPos.y());
+ }
}
}
break;
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index e635463951..3dfffa6de6 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -1954,10 +1954,8 @@ void QWindowsWindow::checkForScreenChanged(ScreenChangeMode mode)
qCDebug(lcQpaWindows).noquote().nospace() << __FUNCTION__
<< ' ' << window() << " \"" << (currentScreen ? currentScreen->name() : QString())
<< "\"->\"" << newScreen->name() << '"';
- if (mode == FromGeometryChange)
- setFlag(SynchronousGeometryChangeEvent);
updateFullFrameMargins();
- QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
+ QWindowSystemInterface::handleWindowScreenChanged<QWindowSystemInterface::SynchronousDelivery>(window(), newScreen->screen());
}
void QWindowsWindow::handleGeometryChange()
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 71ec47b053..5be04a984a 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -274,7 +274,9 @@ void QXcbWindow::create()
QXcbScreen *currentScreen = xcbScreen();
QXcbScreen *platformScreen = parent() ? parentScreen() : initialScreen();
- QRect rect = QHighDpi::toNativePixels(window()->geometry(), platformScreen);
+ QRect rect = parent()
+ ? QHighDpi::toNativeLocalPosition(window()->geometry(), platformScreen)
+ : QHighDpi::toNativePixels(window()->geometry(), platformScreen);
if (type == Qt::Desktop) {
m_window = platformScreen->root();
diff --git a/src/tools/uic/python/pythonwriteimports.cpp b/src/tools/uic/python/pythonwriteimports.cpp
index d33b4c6210..95e039e6f0 100644
--- a/src/tools/uic/python/pythonwriteimports.cpp
+++ b/src/tools/uic/python/pythonwriteimports.cpp
@@ -131,6 +131,8 @@ void WriteImports::acceptCustomWidget(DomCustomWidget *node)
output << "import " << className << '\n';
} else { // When we do have elementHeader, we know it's a relative import.
QString modulePath = node->elementHeader()->text();
+ // Replace the '/' by '.'
+ modulePath.replace(QLatin1Char('/'), QLatin1Char('.'));
// '.h' is added by default on headers for <customwidget>
if (modulePath.endsWith(QLatin1String(".h")))
modulePath.chop(2);
diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp
index cae776159d..23292062cb 100644
--- a/src/widgets/widgets/qmenu.cpp
+++ b/src/widgets/widgets/qmenu.cpp
@@ -1473,6 +1473,9 @@ void QMenuPrivate::_q_actionTriggered()
}
}
activateCausedStack(list, action, QAction::Trigger, false);
+ // if a widget action fires, we need to hide the menu explicitly
+ if (qobject_cast<QWidgetAction*>(action))
+ hideUpToMenuBar();
}
}
}
@@ -1640,10 +1643,8 @@ void QMenu::initStyleOption(QStyleOptionMenuItem *option, const QAction *action)
Widgets can be inserted into menus with the QWidgetAction class.
Instances of this class are used to hold widgets, and are inserted
- into menus with the addAction() overload that takes a QAction.
-
- Conversely, actions can be added to widgets with the addAction(),
- addActions() and insertAction() functions.
+ into menus with the addAction() overload that takes a QAction. If the
+ QWidgetAction fires the triggered() signal, the menu will close.
\warning To make QMenu visible on the screen, exec() or popup() should be
used instead of show().
diff --git a/tests/auto/corelib/kernel/qdeadlinetimer/tst_qdeadlinetimer.cpp b/tests/auto/corelib/kernel/qdeadlinetimer/tst_qdeadlinetimer.cpp
index 35c5e7cb75..db53c3f20c 100644
--- a/tests/auto/corelib/kernel/qdeadlinetimer/tst_qdeadlinetimer.cpp
+++ b/tests/auto/corelib/kernel/qdeadlinetimer/tst_qdeadlinetimer.cpp
@@ -573,12 +573,32 @@ void tst_QDeadlineTimer::stdchrono()
QCOMPARE(deadline.remainingTimeAsDuration(), nanoseconds::zero());
+ /*
+ Call QTest::qSleep, and return true if the time actually slept is
+ within \a deviationPercent percent of the requested sleep time.
+ Otherwise, return false, in which case the test should to abort.
+ */
+ auto sleepHelper = [](int ms, int deviationPercent = 10) -> bool {
+ auto before = steady_clock::now();
+ QTest::qSleep(ms);
+ auto after = steady_clock::now();
+ auto diff = duration_cast<milliseconds>(after - before).count();
+ bool inRange = qAbs(diff - ms) < ms * deviationPercent/100.0;
+ if (!inRange)
+ qWarning() << "sleeping" << diff << "instead of" << ms << inRange;
+ return inRange;
+ };
+
auto steady_before = steady_clock::now();
auto system_before = system_clock::now();
- QTest::qSleep(minResolution);
+ if (!sleepHelper(minResolution))
+ QSKIP("Slept too long");
auto now = QDeadlineTimer::current(timerType);
- QTest::qSleep(minResolution);
+ auto steady_reference = steady_clock::now();
+ auto system_reference = system_clock::now();
+ if (!sleepHelper(minResolution))
+ QSKIP("Slept too long");
auto sampling_start = steady_clock::now();
auto steady_deadline = now.deadline<steady_clock>();
@@ -599,35 +619,33 @@ void tst_QDeadlineTimer::stdchrono()
}
{
- auto diff = duration_cast<milliseconds>(steady_after - steady_deadline);
- QVERIFY2(diff.count() > minResolution/2, QByteArray::number(qint64(diff.count())));
- QVERIFY2(diff.count() < 3*minResolution/2, QByteArray::number(qint64(diff.count())));
+ auto reference = duration_cast<milliseconds>(steady_after - steady_reference).count();
+ auto diff = duration_cast<milliseconds>(steady_after - steady_deadline).count();
+ QVERIFY2(diff > reference * 0.9 && diff < reference*1.1, QByteArray::number(qint64(diff)));
QDeadlineTimer dt_after(steady_after, timerType);
QVERIFY2(now < dt_after,
("now = " + QLocale().toString(now.deadlineNSecs()) +
"; after = " + QLocale().toString(dt_after.deadlineNSecs())).toLatin1());
- diff = duration_cast<milliseconds>(steady_deadline - steady_before);
- QVERIFY2(diff.count() > minResolution/2, QByteArray::number(qint64(diff.count())));
- QVERIFY2(diff.count() < 3*minResolution/2, QByteArray::number(qint64(diff.count())));
+ reference = duration_cast<milliseconds>(steady_reference - steady_before).count();
+ diff = duration_cast<milliseconds>(steady_deadline - steady_before).count();
+ QVERIFY2(diff > reference * 0.9 && diff < reference*1.1, QByteArray::number(qint64(diff)));
QDeadlineTimer dt_before(steady_before, timerType);
QVERIFY2(now > dt_before,
("now = " + QLocale().toString(now.deadlineNSecs()) +
"; before = " + QLocale().toString(dt_before.deadlineNSecs())).toLatin1());
}
{
- auto diff = duration_cast<milliseconds>(system_after - system_deadline);
- QVERIFY2(diff.count() > minResolution/2, QByteArray::number(qint64(diff.count())));
- QVERIFY2(diff.count() < 3*minResolution/2, QByteArray::number(qint64(diff.count())));
- QDeadlineTimer dt_after(system_after, timerType);
+ auto reference = duration_cast<milliseconds>(system_after - system_reference).count();
+ auto diff = duration_cast<milliseconds>(system_after - system_deadline).count();
+ QVERIFY2(diff > reference * 0.9 && diff < reference*1.1, QByteArray::number(qint64(diff))); QDeadlineTimer dt_after(system_after, timerType);
QVERIFY2(now < dt_after,
("now = " + QLocale().toString(now.deadlineNSecs()) +
"; after = " + QLocale().toString(dt_after.deadlineNSecs())).toLatin1());
- diff = duration_cast<milliseconds>(system_deadline - system_before);
- QVERIFY2(diff.count() > minResolution/2, QByteArray::number(qint64(diff.count())));
- QVERIFY2(diff.count() < 3*minResolution/2, QByteArray::number(qint64(diff.count())));
- QDeadlineTimer dt_before(system_before, timerType);
+ reference = duration_cast<milliseconds>(system_reference - system_before).count();
+ diff = duration_cast<milliseconds>(steady_deadline - steady_before).count();
+ QVERIFY2(diff > reference * 0.9 && diff < reference*1.1, QByteArray::number(qint64(diff))); QDeadlineTimer dt_before(system_before, timerType);
QVERIFY2(now > dt_before,
("now = " + QLocale().toString(now.deadlineNSecs()) +
"; before = " + QLocale().toString(dt_before.deadlineNSecs())).toLatin1());
diff --git a/tests/auto/corelib/kernel/qelapsedtimer/tst_qelapsedtimer.cpp b/tests/auto/corelib/kernel/qelapsedtimer/tst_qelapsedtimer.cpp
index 4ee3ca361f..bfc4f2ca36 100644
--- a/tests/auto/corelib/kernel/qelapsedtimer/tst_qelapsedtimer.cpp
+++ b/tests/auto/corelib/kernel/qelapsedtimer/tst_qelapsedtimer.cpp
@@ -48,6 +48,7 @@ private Q_SLOTS:
void validity();
void basics();
void elapsed();
+ void msecsTo();
};
void tst_QElapsedTimer::statics()
@@ -108,30 +109,42 @@ void tst_QElapsedTimer::elapsed()
t1.start();
QTest::qSleep(2*minResolution);
- QElapsedTimer t2;
- t2.start();
-
- QVERIFY(t1 != t2);
- QVERIFY(!(t1 == t2));
- QVERIFY(t1 < t2);
- QVERIFY(t1.msecsTo(t2) > 0);
- QVERIFY(t1.nsecsElapsed() > 0);
- QVERIFY(t1.elapsed() > 0);
+ auto nsecs = t1.nsecsElapsed();
+ auto msecs = t1.elapsed();
+ QVERIFY(nsecs > 0);
+ QVERIFY(msecs > 0);
// the number of elapsed nanoseconds and milliseconds should match
- QVERIFY(t1.nsecsElapsed() - t1.elapsed() * 1000000 < 1000000);
+ QVERIFY(nsecs - msecs * 1000000 < 1000000);
+
+ if (msecs > 8 * minResolution)
+ QSKIP("Sampling timer took too long, aborting test");
+
QVERIFY(t1.hasExpired(minResolution));
QVERIFY(!t1.hasExpired(8*minResolution));
- QVERIFY(!t2.hasExpired(minResolution));
-
QVERIFY(!t1.hasExpired(-1));
- QVERIFY(!t2.hasExpired(-1));
qint64 elapsed = t1.restart();
- QVERIFY(elapsed > minResolution);
- QVERIFY(elapsed < 3*minResolution);
- qint64 diff = t2.msecsTo(t1);
- QVERIFY(diff < minResolution);
+ QVERIFY(elapsed >= msecs);
+ QVERIFY(elapsed < msecs + 3*minResolution);
+}
+
+void tst_QElapsedTimer::msecsTo()
+{
+ QElapsedTimer t1;
+ t1.start();
+ QTest::qSleep(minResolution);
+ QElapsedTimer t2;
+ t2.start();
+
+ QVERIFY(t1 != t2);
+ QVERIFY(!(t1 == t2));
+ QVERIFY(t1 < t2);
+
+ auto diff = t1.msecsTo(t2);
+ QVERIFY2(diff > 0, QString("difference t1 and t2 is %1").arg(diff).toLatin1());
+ diff = t2.msecsTo(t1);
+ QVERIFY2(diff < 0, QString("difference t2 and t1 is %1").arg(diff).toLatin1());
}
QTEST_MAIN(tst_QElapsedTimer);
diff --git a/tests/auto/corelib/text/qstring/tst_qstring.cpp b/tests/auto/corelib/text/qstring/tst_qstring.cpp
index 2c02fb2264..65f88c0e4d 100644
--- a/tests/auto/corelib/text/qstring/tst_qstring.cpp
+++ b/tests/auto/corelib/text/qstring/tst_qstring.cpp
@@ -5803,6 +5803,8 @@ void tst_QString::split(const QString &string, const QString &sep, QStringList r
QVERIFY(list == result);
}
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
list = str.split(sep, QString::KeepEmptyParts);
QVERIFY(list == result);
list = str.split(rx, QString::KeepEmptyParts);
@@ -5825,6 +5827,7 @@ void tst_QString::split(const QString &string, const QString &sep, QStringList r
list = str.split(sep.at(0), QString::SkipEmptyParts);
QVERIFY(list == result);
}
+QT_WARNING_POP
}
void tst_QString::split()
diff --git a/tests/auto/corelib/tools/qhash/tst_qhash.cpp b/tests/auto/corelib/tools/qhash/tst_qhash.cpp
index 4052eff0ae..2a18f8d3e6 100644
--- a/tests/auto/corelib/tools/qhash/tst_qhash.cpp
+++ b/tests/auto/corelib/tools/qhash/tst_qhash.cpp
@@ -1115,6 +1115,12 @@ void tst_QHash::keyValueIterator()
entry_type pair(it.key(), it.value());
QCOMPARE(*key_value_it, pair);
+ QCOMPARE(key_value_it->first, pair.first);
+ QCOMPARE(key_value_it->second, pair.second);
+ QCOMPARE(&(*key_value_it).first, &it.key());
+ QCOMPARE(&key_value_it->first, &it.key());
+ QCOMPARE(&(*key_value_it).second, &it.value());
+ QCOMPARE(&key_value_it->second, &it.value());
++key_value_it;
++it;
}
diff --git a/tests/auto/corelib/tools/qmap/tst_qmap.cpp b/tests/auto/corelib/tools/qmap/tst_qmap.cpp
index 1638ebc992..9f0524c9e0 100644
--- a/tests/auto/corelib/tools/qmap/tst_qmap.cpp
+++ b/tests/auto/corelib/tools/qmap/tst_qmap.cpp
@@ -881,6 +881,12 @@ void tst_QMap::keyValueIterator()
entry_type pair(it.key(), it.value());
QCOMPARE(*key_value_it, pair);
+ QCOMPARE(key_value_it->first, pair.first);
+ QCOMPARE(key_value_it->second, pair.second);
+ QCOMPARE(&(*key_value_it).first, &it.key());
+ QCOMPARE(&key_value_it->first, &it.key());
+ QCOMPARE(&(*key_value_it).second, &it.value());
+ QCOMPARE(&key_value_it->second, &it.value());
++key_value_it;
++it;
}
diff --git a/tests/auto/gui/rhi/qshader/tst_qshader.cpp b/tests/auto/gui/rhi/qshader/tst_qshader.cpp
index ab7115b74a..378d1e85e7 100644
--- a/tests/auto/gui/rhi/qshader/tst_qshader.cpp
+++ b/tests/auto/gui/rhi/qshader/tst_qshader.cpp
@@ -368,7 +368,7 @@ void tst_QShader::serializeShaderDesc()
QBuffer buf(&data);
QDataStream ds(&buf);
QVERIFY(buf.open(QIODevice::ReadOnly));
- QShaderDescription desc2 = QShaderDescription::deserialize(&ds);
+ QShaderDescription desc2 = QShaderDescription::deserialize(&ds, QShaderPrivate::QSB_VERSION);
QVERIFY(!desc2.isValid());
}
}
@@ -400,7 +400,7 @@ void tst_QShader::serializeShaderDesc()
QBuffer buf(&data);
QDataStream ds(&buf);
QVERIFY(buf.open(QIODevice::ReadOnly));
- QShaderDescription desc2 = QShaderDescription::deserialize(&ds);
+ QShaderDescription desc2 = QShaderDescription::deserialize(&ds, QShaderPrivate::QSB_VERSION);
QVERIFY(desc2.isValid());
QCOMPARE(desc, desc2);
}
diff --git a/tests/auto/gui/text/qtextmarkdownimporter/data/fuzz20450.md b/tests/auto/gui/text/qtextmarkdownimporter/data/fuzz20450.md
new file mode 100644
index 0000000000..d7005cb01e
--- /dev/null
+++ b/tests/auto/gui/text/qtextmarkdownimporter/data/fuzz20450.md
@@ -0,0 +1,5 @@
+<t>
+*
+
+
+* \ No newline at end of file
diff --git a/tests/auto/gui/text/qtextmarkdownimporter/data/fuzz20580.md b/tests/auto/gui/text/qtextmarkdownimporter/data/fuzz20580.md
new file mode 100644
index 0000000000..22006f5876
--- /dev/null
+++ b/tests/auto/gui/text/qtextmarkdownimporter/data/fuzz20580.md
@@ -0,0 +1 @@
+| --:| <?`?><?|` \ No newline at end of file
diff --git a/tests/auto/gui/text/qtextmarkdownimporter/qtextmarkdownimporter.pro b/tests/auto/gui/text/qtextmarkdownimporter/qtextmarkdownimporter.pro
index 7b7fb61244..f3818efbf7 100644
--- a/tests/auto/gui/text/qtextmarkdownimporter/qtextmarkdownimporter.pro
+++ b/tests/auto/gui/text/qtextmarkdownimporter/qtextmarkdownimporter.pro
@@ -5,5 +5,7 @@ SOURCES += tst_qtextmarkdownimporter.cpp
TESTDATA += \
data/thematicBreaks.md \
data/headingBulletsContinuations.md \
+ data/fuzz20450.md \
+ data/fuzz20580.md \
DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/gui/text/qtextmarkdownimporter/tst_qtextmarkdownimporter.cpp b/tests/auto/gui/text/qtextmarkdownimporter/tst_qtextmarkdownimporter.cpp
index 39a1370f6f..5eb04af696 100644
--- a/tests/auto/gui/text/qtextmarkdownimporter/tst_qtextmarkdownimporter.cpp
+++ b/tests/auto/gui/text/qtextmarkdownimporter/tst_qtextmarkdownimporter.cpp
@@ -57,6 +57,8 @@ private slots:
void lists();
void avoidBlankLineAtBeginning_data();
void avoidBlankLineAtBeginning();
+ void pathological_data();
+ void pathological();
};
void tst_QTextMarkdownImporter::headingBulletsContinuations()
@@ -256,5 +258,27 @@ void tst_QTextMarkdownImporter::avoidBlankLineAtBeginning() // QTBUG-81060
QCOMPARE(i, expectedNumberOfParagraphs);
}
+void tst_QTextMarkdownImporter::pathological_data()
+{
+ QTest::addColumn<QString>("warning");
+ QTest::newRow("fuzz20450") << "attempted to insert into a list that no longer exists";
+ QTest::newRow("fuzz20580") << "";
+}
+
+void tst_QTextMarkdownImporter::pathological() // avoid crashing on crazy input
+{
+ QFETCH(QString, warning);
+ QString filename = QLatin1String("data/") + QTest::currentDataTag() + QLatin1String(".md");
+ QFile f(QFINDTESTDATA(filename));
+ QVERIFY(f.open(QFile::ReadOnly));
+#ifdef QT_NO_DEBUG
+ Q_UNUSED(warning)
+#else
+ if (!warning.isEmpty())
+ QTest::ignoreMessage(QtWarningMsg, warning.toLatin1());
+#endif
+ QTextDocument().setMarkdown(f.readAll());
+}
+
QTEST_MAIN(tst_QTextMarkdownImporter)
#include "tst_qtextmarkdownimporter.moc"
diff --git a/tests/auto/network/access/http2/tst_http2.cpp b/tests/auto/network/access/http2/tst_http2.cpp
index 904cfd52b0..1ca60655a6 100644
--- a/tests/auto/network/access/http2/tst_http2.cpp
+++ b/tests/auto/network/access/http2/tst_http2.cpp
@@ -513,7 +513,7 @@ void tst_Http2::goaway()
replies[i] = manager->get(request);
QCOMPARE(replies[i]->error(), QNetworkReply::NoError);
void (QNetworkReply::*errorSignal)(QNetworkReply::NetworkError) =
- &QNetworkReply::error;
+ &QNetworkReply::errorOccurred;
connect(replies[i], errorSignal, this, &tst_Http2::replyFinishedWithError);
// Since we're using self-signed certificates, ignore SSL errors:
replies[i]->ignoreSslErrors();
diff --git a/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp b/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp
index 57fa5a613c..e8d4c773f0 100644
--- a/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp
+++ b/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp
@@ -1005,10 +1005,8 @@ void tst_QHttpNetworkConnection::overlappingCloseAndWrite()
for (int i = 0; i < 10; ++i) {
QNetworkRequest request(url);
QNetworkReply *reply = accessManager.get(request);
- // Not using Qt5 connection syntax here because of overly baroque syntax to discern between
- // different error() methods.
- QObject::connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
- &server, SLOT(onReply(QNetworkReply::NetworkError)));
+ QObject::connect(reply, &QNetworkReply::errorOccurred,
+ &server, &TestTcpServer::onReply);
}
QTRY_COMPARE(server.errorCodeReports, 10);
diff --git a/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp b/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp
index 752655ee94..b5ded86d58 100644
--- a/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp
+++ b/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp
@@ -87,7 +87,7 @@ void tst_QNetworkAccessManager::networkAccessible()
// When network is not accessible, all requests fail
QNetworkReply *reply = manager.get(QNetworkRequest(QUrl("http://www.example.org")));
QSignalSpy finishedSpy(reply, &QNetworkReply::finished);
- QSignalSpy errorSpy(reply, QOverload<QNetworkReply::NetworkError>::of(&QNetworkReply::error));
+ QSignalSpy errorSpy(reply, &QNetworkReply::errorOccurred);
QVERIFY(finishedSpy.wait());
QCOMPARE(reply->isFinished(), true);
QCOMPARE(reply->errorString(), QStringLiteral("Network access is disabled."));
diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
index 5d46002a7c..430f9b7575 100644
--- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
+++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
@@ -1381,7 +1381,7 @@ QString tst_QNetworkReply::runMultipartRequest(const QNetworkRequest &request,
// the code below is copied from tst_QNetworkReply::runSimpleRequest, see below
reply->setParent(this);
connect(reply, SIGNAL(finished()), SLOT(finished()));
- connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(gotError()));
+ connect(reply, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), SLOT(gotError()));
multiPart->setParent(reply.data());
returnCode = Timeout;
@@ -1441,7 +1441,7 @@ QString tst_QNetworkReply::runSimpleRequest(QNetworkAccessManager::Operation op,
code = Failure;
} else {
connect(reply, SIGNAL(finished()), SLOT(finished()));
- connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(gotError()));
+ connect(reply, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), SLOT(gotError()));
int count = 0;
loop = new QEventLoop;
@@ -1476,7 +1476,7 @@ QString tst_QNetworkReply::runCustomRequest(const QNetworkRequest &request,
reply.reset(manager.sendCustomRequest(request, verb, data));
reply->setParent(this);
connect(reply, SIGNAL(finished()), SLOT(finished()));
- connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(gotError()));
+ connect(reply, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), SLOT(gotError()));
returnCode = Timeout;
loop = new QEventLoop;
@@ -1513,7 +1513,7 @@ int tst_QNetworkReply::waitForFinish(QNetworkReplyPtr &reply)
int count = 0;
connect(reply, SIGNAL(finished()), SLOT(finished()));
- connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(gotError()));
+ connect(reply, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), SLOT(gotError()));
returnCode = Success;
loop = new QEventLoop;
QSignalSpy spy(reply.data(), SIGNAL(downloadProgress(qint64,qint64)));
@@ -1901,7 +1901,7 @@ void tst_QNetworkReply::getFromFtpAfterError()
QNetworkRequest invalidRequest(QUrl("ftp://" + QtNetworkSettings::ftpServerName() + "/qtest/invalid.txt"));
QNetworkReplyPtr invalidReply;
invalidReply.reset(manager.get(invalidRequest));
- QSignalSpy spy(invalidReply.data(), SIGNAL(error(QNetworkReply::NetworkError)));
+ QSignalSpy spy(invalidReply.data(), SIGNAL(errorOccurred(QNetworkReply::NetworkError)));
QVERIFY(spy.wait());
QCOMPARE(invalidReply->error(), QNetworkReply::ContentNotFoundError);
@@ -3927,7 +3927,7 @@ void tst_QNetworkReply::ioGetFromHttpBrokenServer()
QNetworkRequest request(QUrl("http://localhost:" + QString::number(server.serverPort())));
QNetworkReplyPtr reply(manager.get(request));
- QSignalSpy spy(reply.data(), SIGNAL(error(QNetworkReply::NetworkError)));
+ QSignalSpy spy(reply.data(), SIGNAL(errorOccurred(QNetworkReply::NetworkError)));
QCOMPARE(waitForFinish(reply), int(Failure));
@@ -5475,7 +5475,7 @@ void tst_QNetworkReply::rateControl()
QNetworkRequest request("debugpipe://localhost:" + QString::number(sender.serverPort()));
QNetworkReplyPtr reply(manager.get(request));
reply->setReadBufferSize(32768);
- QSignalSpy errorSpy(reply.data(), SIGNAL(error(QNetworkReply::NetworkError)));
+ QSignalSpy errorSpy(reply.data(), SIGNAL(errorOccurred(QNetworkReply::NetworkError)));
RateControlledReader reader(sender, reply.data(), rate, 20);
@@ -5889,7 +5889,7 @@ void tst_QNetworkReply::nestedEventLoops()
QNetworkReplyPtr reply(manager.get(request));
QSignalSpy finishedspy(reply.data(), SIGNAL(finished()));
- QSignalSpy errorspy(reply.data(), SIGNAL(error(QNetworkReply::NetworkError)));
+ QSignalSpy errorspy(reply.data(), SIGNAL(errorOccurred(QNetworkReply::NetworkError)));
connect(reply, SIGNAL(finished()), SLOT(nestedEventLoops_slot()));
QTestEventLoop::instance().enterLoop(20);
@@ -6122,7 +6122,7 @@ void tst_QNetworkReply::authorizationError()
QCOMPARE(reply->error(), QNetworkReply::NoError);
- QSignalSpy errorSpy(reply.data(), SIGNAL(error(QNetworkReply::NetworkError)));
+ QSignalSpy errorSpy(reply.data(), SIGNAL(errorOccurred(QNetworkReply::NetworkError)));
QSignalSpy finishedSpy(reply.data(), SIGNAL(finished()));
// now run the request:
QCOMPARE(waitForFinish(reply), int(Failure));
@@ -7078,7 +7078,7 @@ void tst_QNetworkReply::qtbug4121unknownAuthentication()
QSignalSpy authSpy(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)));
QSignalSpy finishedSpy(&manager, SIGNAL(finished(QNetworkReply*)));
- QSignalSpy errorSpy(reply.data(), SIGNAL(error(QNetworkReply::NetworkError)));
+ QSignalSpy errorSpy(reply.data(), SIGNAL(errorOccurred(QNetworkReply::NetworkError)));
connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()), Qt::QueuedConnection);
QTestEventLoop::instance().enterLoop(10);
@@ -7399,7 +7399,7 @@ void tst_QNetworkReply::httpWithNoCredentialUsage()
request.setAttribute(QNetworkRequest::AuthenticationReuseAttribute, QNetworkRequest::Manual);
QNetworkReplyPtr reply(manager.get(request));
- QSignalSpy errorSpy(reply.data(), SIGNAL(error(QNetworkReply::NetworkError)));
+ QSignalSpy errorSpy(reply.data(), SIGNAL(errorOccurred(QNetworkReply::NetworkError)));
connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()), Qt::QueuedConnection);
QTestEventLoop::instance().enterLoop(10);
@@ -8115,7 +8115,7 @@ void tst_QNetworkReply::emitErrorForAllReplies() // QTBUG-36890
QNetworkRequest request(urls.at(a));
QNetworkReply *reply = manager.get(request);
replies.append(reply);
- QSignalSpy *errorSpy = new QSignalSpy(reply, SIGNAL(error(QNetworkReply::NetworkError)));
+ QSignalSpy *errorSpy = new QSignalSpy(reply, SIGNAL(errorOccurred(QNetworkReply::NetworkError)));
errorSpies.append(errorSpy);
QSignalSpy *finishedSpy = new QSignalSpy(reply, SIGNAL(finished()));
finishedSpies.append(finishedSpy);
@@ -8517,7 +8517,7 @@ void tst_QNetworkReply::ioHttpChangeMaxRedirects()
QNetworkReplyPtr reply(manager.get(request));
QSignalSpy redSpy(reply.data(), SIGNAL(redirected(QUrl)));
- QSignalSpy spy(reply.data(), SIGNAL(error(QNetworkReply::NetworkError)));
+ QSignalSpy spy(reply.data(), SIGNAL(errorOccurred(QNetworkReply::NetworkError)));
QCOMPARE(waitForFinish(reply), int(Failure));
@@ -8581,7 +8581,7 @@ void tst_QNetworkReply::ioHttpRedirectErrors()
QTimer watchDog;
watchDog.setSingleShot(true);
- reply->connect(reply.data(), QOverload<QNetworkReply::NetworkError>().of(&QNetworkReply::error),
+ reply->connect(reply.data(), &QNetworkReply::errorOccurred,
[&eventLoop](QNetworkReply::NetworkError){
eventLoop.exit(Failure);
});
@@ -8747,7 +8747,7 @@ void tst_QNetworkReply::ioHttpRedirectPolicyErrors()
if (ssl)
reply->ignoreSslErrors();
- QSignalSpy spy(reply.data(), SIGNAL(error(QNetworkReply::NetworkError)));
+ QSignalSpy spy(reply.data(), SIGNAL(errorOccurred(QNetworkReply::NetworkError)));
QCOMPARE(waitForFinish(reply), int(Failure));
QCOMPARE(spy.count(), 1);
@@ -9397,7 +9397,7 @@ void tst_QNetworkReply::getWithTimeout()
QNetworkRequest request(QUrl("http://localhost:" + QString::number(server.serverPort())));
QNetworkReplyPtr reply(manager.get(request));
- QSignalSpy spy(reply.data(), SIGNAL(error(QNetworkReply::NetworkError)));
+ QSignalSpy spy(reply.data(), SIGNAL(errorOccurred(QNetworkReply::NetworkError)));
QCOMPARE(waitForFinish(reply), int(Success));
@@ -9408,7 +9408,7 @@ void tst_QNetworkReply::getWithTimeout()
server.stopTransfer = true;
QNetworkReplyPtr reply2(manager.get(request));
- QSignalSpy spy2(reply2.data(), SIGNAL(error(QNetworkReply::NetworkError)));
+ QSignalSpy spy2(reply2.data(), SIGNAL(errorOccurred(QNetworkReply::NetworkError)));
QCOMPARE(waitForFinish(reply2), int(Failure));
@@ -9419,7 +9419,7 @@ void tst_QNetworkReply::getWithTimeout()
manager.setTransferTimeout(1000);
QNetworkReplyPtr reply3(manager.get(request));
- QSignalSpy spy3(reply3.data(), SIGNAL(error(QNetworkReply::NetworkError)));
+ QSignalSpy spy3(reply3.data(), SIGNAL(errorOccurred(QNetworkReply::NetworkError)));
QCOMPARE(waitForFinish(reply3), int(Failure));
@@ -9437,7 +9437,7 @@ void tst_QNetworkReply::postWithTimeout()
request.setRawHeader("Content-Type", "application/octet-stream");
QByteArray postData("Just some nonsense");
QNetworkReplyPtr reply(manager.post(request, postData));
- QSignalSpy spy(reply.data(), SIGNAL(error(QNetworkReply::NetworkError)));
+ QSignalSpy spy(reply.data(), SIGNAL(errorOccurred(QNetworkReply::NetworkError)));
QCOMPARE(waitForFinish(reply), int(Success));
@@ -9448,7 +9448,7 @@ void tst_QNetworkReply::postWithTimeout()
server.stopTransfer = true;
QNetworkReplyPtr reply2(manager.post(request, postData));
- QSignalSpy spy2(reply2.data(), SIGNAL(error(QNetworkReply::NetworkError)));
+ QSignalSpy spy2(reply2.data(), SIGNAL(errorOccurred(QNetworkReply::NetworkError)));
QCOMPARE(waitForFinish(reply2), int(Failure));
@@ -9459,7 +9459,7 @@ void tst_QNetworkReply::postWithTimeout()
manager.setTransferTimeout(1000);
QNetworkReplyPtr reply3(manager.post(request, postData));
- QSignalSpy spy3(reply3.data(), SIGNAL(error(QNetworkReply::NetworkError)));
+ QSignalSpy spy3(reply3.data(), SIGNAL(errorOccurred(QNetworkReply::NetworkError)));
QCOMPARE(waitForFinish(reply3), int(Failure));
diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
index 769836ff62..157c07f922 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
@@ -4568,7 +4568,9 @@ void tst_QGraphicsView::task255529_transformationAnchorMouseAndViewportMargins()
view.show();
qApp->setActiveWindow(&view);
QVERIFY(QTest::qWaitForWindowExposed(&view));
- QVERIFY(QTest::qWaitForWindowActive(&view));
+ const bool isActiveWindow = QTest::qWaitForWindowActive(&view);
+ if (!isActiveWindow)
+ QSKIP("Window activation failed, skipping test", Abort);
// This is highly unstable (observed to pass on Windows and some Linux configurations).
#ifndef Q_OS_MAC
for (int i = 0; i < 4; ++i) {
diff --git a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp
index 8ad4324c9e..a89b3231ad 100644
--- a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp
+++ b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp
@@ -116,6 +116,7 @@ private slots:
void QTBUG20403_nested_popup_on_shortcut_trigger();
void QTBUG47515_widgetActionEnterLeave();
void QTBUG8122_widgetActionCrashOnClose();
+ void widgetActionTriggerClosesMenu();
void QTBUG_10735_crashWithDialog();
#ifdef Q_OS_MAC
@@ -1407,6 +1408,84 @@ void tst_QMenu::QTBUG8122_widgetActionCrashOnClose()
QTRY_VERIFY(menu->isHidden());
}
+/*!
+ Test that a QWidgetAction that fires closes the menus that it is in.
+*/
+void tst_QMenu::widgetActionTriggerClosesMenu()
+{
+ class ButtonAction : public QWidgetAction
+ {
+ public:
+ ButtonAction()
+ : QWidgetAction(nullptr)
+ {}
+
+ void click()
+ {
+ if (pushButton)
+ pushButton->click();
+ }
+
+ protected:
+ QWidget *createWidget(QWidget *parent)
+ {
+ QPushButton *button = new QPushButton(QLatin1String("Button"), parent);
+ connect(button, &QPushButton::clicked, this, &QAction::trigger);
+
+ if (!pushButton)
+ pushButton = button;
+ return button;
+ }
+
+ private:
+ QPointer<QPushButton> pushButton;
+ };
+
+ QMenu menu;
+ QMenu submenu;
+
+ int menuTriggeredCount = 0;
+ int menuAboutToHideCount = 0;
+ QAction *actionTriggered = nullptr;
+
+ connect(&menu, &QMenu::triggered, this, [&](QAction *action){
+ ++menuTriggeredCount;
+ actionTriggered = action;
+ });
+ connect (&menu, &QMenu::aboutToHide, this, [&](){
+ ++menuAboutToHideCount;
+ });
+
+ QAction regularAction(QLatin1String("Action"));
+ ButtonAction widgetAction;
+
+ submenu.addAction(&regularAction);
+ submenu.addAction(&widgetAction);
+
+ menu.addMenu(&submenu);
+ menu.addAction(&regularAction);
+ menu.addAction(&widgetAction);
+
+ menu.popup(QPoint(200,200));
+ submenu.popup(QPoint(250,250));
+ if (!QTest::qWaitForWindowExposed(&menu) || !QTest::qWaitForWindowExposed(&submenu))
+ QSKIP("Failed to show menus, aborting test");
+
+ regularAction.trigger();
+ QVERIFY(menu.isVisible());
+ QVERIFY(submenu.isVisible());
+ QCOMPARE(menuTriggeredCount, 1);
+ QCOMPARE(actionTriggered, &regularAction);
+ menuTriggeredCount = 0;
+ actionTriggered = nullptr;
+
+ widgetAction.click();
+ QVERIFY(!menu.isVisible());
+ QVERIFY(!submenu.isVisible());
+ QCOMPARE(menuTriggeredCount, 1);
+ QCOMPARE(menuAboutToHideCount, 1);
+ QCOMPARE(actionTriggered, &widgetAction);
+}
class MyMenu : public QMenu
{
diff --git a/util/locale_database/cldr2qlocalexml.py b/util/locale_database/cldr2qlocalexml.py
index fdb0a34037..7f98e29d47 100755
--- a/util/locale_database/cldr2qlocalexml.py
+++ b/util/locale_database/cldr2qlocalexml.py
@@ -61,7 +61,7 @@ import enumdata
import xpathlite
from xpathlite import DraftResolution, findAlias, findEntry, findTagsInFile
from dateconverter import convert_date
-from localexml import Locale
+from qlocalexml import Locale
# TODO: make calendars a command-line option
calendars = ['gregorian', 'persian', 'islamic'] # 'hebrew'
@@ -335,8 +335,8 @@ def _generateLocaleInfo(path, language_code, script_code, country_code, variant_
endonym = findEntryDef(path, "localeDisplayNames/languages/language[type=%s_%s]" % (language_code, country_code))
if not endonym:
endonym = findEntryDef(path, "localeDisplayNames/languages/language[type=%s]" % (language_code))
- result['language_endonym'] = endonym
- result['country_endonym'] = findEntryDef(path, "localeDisplayNames/territories/territory[type=%s]" % (country_code))
+ result['languageEndonym'] = endonym
+ result['countryEndonym'] = findEntryDef(path, "localeDisplayNames/territories/territory[type=%s]" % (country_code))
currency_format = get_number_in_system(path, "numbers/currencyFormats/currencyFormatLength/currencyFormat/pattern", numbering_system)
currency_format = parse_number_format(currency_format, result)
diff --git a/util/locale_database/localexml.py b/util/locale_database/qlocalexml.py
index 85ecb2d6ca..b4fbe86be5 100644
--- a/util/locale_database/localexml.py
+++ b/util/locale_database/qlocalexml.py
@@ -169,7 +169,7 @@ class Locale:
for key in ('decimal', 'group', 'zero', 'list', 'percent', 'minus', 'plus', 'exp'):
print inner + "<%s>" % key + get(key) + "</%s>" % key
- for key in ('language_endonym', 'country_endonym',
+ for key in ('languageEndonym', 'countryEndonym',
'quotationStart', 'quotationEnd',
'alternateQuotationStart', 'alternateQuotationEnd',
'listPatternPartStart', 'listPatternPartMiddle',
@@ -187,8 +187,7 @@ class Locale:
'_'.join((k, cal))
for k in self.propsMonthDay('months')
for cal in calendars):
- ent = camelCase(key.split('_')) if key.endswith('_endonym') else key
- print inner + "<%s>%s</%s>" % (ent, escape(get(key)).encode('utf-8'), ent)
+ print inner + "<%s>%s</%s>" % (key, escape(get(key)).encode('utf-8'), key)
for key in ('currencyDigits', 'currencyRounding'):
print inner + "<%s>%d</%s>" % (key, get(key), key)
@@ -262,9 +261,9 @@ class Locale:
quantifiers=('k', 'M', 'G', 'T', 'P', 'E')):
"""Returns an object representing the C locale."""
return cls(dict(cls.__monthNames(calendars)),
- language='C', language_code='0', language_endonym='',
+ language='C', language_code='0', languageEndonym='',
script='AnyScript', script_code='0',
- country='AnyCountry', country_code='0', country_endonym='',
+ country='AnyCountry', country_code='0', countryEndonym='',
decimal='.', group=',', list=';', percent='%',
zero='0', minus='-', plus='+', exp='e',
quotationStart='"', quotationEnd='"',
diff --git a/util/locale_database/qlocalexml2cpp.py b/util/locale_database/qlocalexml2cpp.py
index bb9f138c18..3dde298f47 100755
--- a/util/locale_database/qlocalexml2cpp.py
+++ b/util/locale_database/qlocalexml2cpp.py
@@ -40,7 +40,7 @@ import datetime
import xml.dom.minidom
from enumdata import language_aliases, country_aliases, script_aliases
-from localexml import Locale
+from qlocalexml import Locale
# TODO: Make calendars a command-line parameter
# map { CLDR name: Qt file name }
@@ -373,7 +373,7 @@ def main():
if len(sys.argv) != 3:
usage()
- localexml = sys.argv[1]
+ qlocalexml = sys.argv[1]
qtsrcdir = sys.argv[2]
if not (os.path.isdir(qtsrcdir)
@@ -390,7 +390,7 @@ def main():
s = qlocaledata_file.readline()
data_temp_file.write(GENERATED_BLOCK_START)
- doc = xml.dom.minidom.parse(localexml)
+ doc = xml.dom.minidom.parse(qlocalexml)
language_map = loadMap(doc, 'language')
script_map = loadMap(doc, 'script')
country_map = loadMap(doc, 'country')