summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/libjpeg/COPYRIGHT.txt2
-rw-r--r--src/3rdparty/libjpeg/ChangeLog.md43
-rw-r--r--src/3rdparty/libjpeg/qt_attribution.json4
-rw-r--r--src/3rdparty/libjpeg/src/jconfig.h4
-rw-r--r--src/3rdparty/libjpeg/src/jconfigint.h2
-rw-r--r--src/3rdparty/libpng/ANNOUNCE26
-rw-r--r--src/3rdparty/libpng/CHANGES6
-rw-r--r--src/3rdparty/libpng/README2
-rw-r--r--src/3rdparty/libpng/libpng-manual.txt2
-rw-r--r--src/3rdparty/libpng/png.c4
-rw-r--r--src/3rdparty/libpng/png.h14
-rw-r--r--src/3rdparty/libpng/pngconf.h2
-rw-r--r--src/3rdparty/libpng/pnglibconf.h2
-rw-r--r--src/3rdparty/libpng/pngread.c2
-rw-r--r--src/3rdparty/libpng/qt_attribution.json4
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtWindow.java11
-rw-r--r--src/corelib/CMakeLists.txt17
-rw-r--r--src/corelib/Qt6CoreMacros.cmake15
-rw-r--r--src/corelib/animation/qabstractanimation.cpp1
-rw-r--r--src/corelib/configure.cmake11
-rw-r--r--src/corelib/doc/src/cmake/cmake-configure-variables.qdoc5
-rw-r--r--src/corelib/doc/src/external-resources.qdoc5
-rw-r--r--src/corelib/global/qcompilerdetection.h2
-rw-r--r--src/corelib/global/qoperatingsystemversion.cpp6
-rw-r--r--src/corelib/global/qoperatingsystemversion.h1
-rw-r--r--src/corelib/global/qttranslation.qdoc2
-rw-r--r--src/corelib/io/qfsfileengine.cpp6
-rw-r--r--src/corelib/io/qiooperation_p.h20
-rw-r--r--src/corelib/io/qioring_p.h6
-rw-r--r--src/corelib/io/qioring_win.cpp104
-rw-r--r--src/corelib/io/qrandomaccessasyncfile.cpp25
-rw-r--r--src/corelib/io/qrandomaccessasyncfile_darwin.mm103
-rw-r--r--src/corelib/io/qrandomaccessasyncfile_p_p.h241
-rw-r--r--src/corelib/io/qrandomaccessasyncfile_qioring.cpp61
-rw-r--r--src/corelib/io/qrandomaccessasyncfile_threadpool.cpp79
-rw-r--r--src/corelib/io/qwindowspipereader.cpp5
-rw-r--r--src/corelib/itemmodels/qrangemodel_impl.h18
-rw-r--r--src/corelib/itemmodels/qrangemodeladapter.h232
-rw-r--r--src/corelib/itemmodels/qrangemodeladapter.qdoc61
-rw-r--r--src/corelib/kernel/qassociativeiterable.h2
-rw-r--r--src/corelib/kernel/qcore_mac.mm32
-rw-r--r--src/corelib/kernel/qcore_mac_p.h17
-rw-r--r--src/corelib/kernel/qeventdispatcher_cf.mm1
-rw-r--r--src/corelib/kernel/qiterable.h6
-rw-r--r--src/corelib/kernel/qmetaassociation.h6
-rw-r--r--src/corelib/kernel/qmetacontainer.h9
-rw-r--r--src/corelib/kernel/qmetasequence.cpp40
-rw-r--r--src/corelib/kernel/qmetasequence.h29
-rw-r--r--src/corelib/kernel/qpermissions.cpp2
-rw-r--r--src/corelib/kernel/qproperty.cpp20
-rw-r--r--src/corelib/kernel/qsequentialiterable.h3
-rw-r--r--src/corelib/kernel/qtranslator.cpp4
-rw-r--r--src/corelib/kernel/qvariant.h10
-rw-r--r--src/corelib/platform/windows/qbstr_p.h3
-rw-r--r--src/corelib/platform/windows/qcomobject_p.h1
-rw-r--r--src/corelib/platform/windows/qcomptr_p.h1
-rw-r--r--src/corelib/platform/windows/qcomvariant_p.h1
-rw-r--r--src/corelib/platform/windows/qfactorycacheregistration.cpp1
-rw-r--r--src/corelib/platform/windows/qfactorycacheregistration_p.h1
-rw-r--r--src/corelib/platform/windows/qt_winrtbase_p.h1
-rw-r--r--src/corelib/serialization/qcborvalue.cpp1
-rw-r--r--src/corelib/serialization/qdatastream.cpp1
-rw-r--r--src/corelib/serialization/qdatastream.h5
-rw-r--r--src/corelib/serialization/qxmlstream.cpp6
-rw-r--r--src/corelib/text/qlocale.cpp1
-rw-r--r--src/corelib/text/qstringconverter.cpp4
-rw-r--r--src/corelib/thread/qfuture_impl.h9
-rw-r--r--src/corelib/thread/qfutureinterface.h4
-rw-r--r--src/corelib/thread/qreadwritelock.cpp8
-rw-r--r--src/corelib/time/qdatetimeparser.cpp1
-rw-r--r--src/corelib/tools/qarraydata.cpp2
-rw-r--r--src/corelib/tools/qeasingcurve.cpp14
-rw-r--r--src/gui/accessible/qaccessiblecache.cpp10
-rw-r--r--src/gui/doc/images/coordinatesystem-transformations.pngbin59180 -> 0 bytes
-rw-r--r--src/gui/doc/images/coordinatesystem-transformations.svg148
-rw-r--r--src/gui/doc/qtgui.qdocconf3
-rw-r--r--src/gui/doc/src/coordsys.qdoc2
-rw-r--r--src/gui/doc/src/external-resources.qdoc1
-rw-r--r--src/gui/itemmodels/qfileinfogatherer.cpp6
-rw-r--r--src/gui/kernel/qguiapplication.cpp6
-rw-r--r--src/gui/kernel/qplatformintegrationfactory.cpp1
-rw-r--r--src/gui/kernel/qplatformthemefactory.cpp1
-rw-r--r--src/gui/kernel/qsurface.cpp5
-rw-r--r--src/gui/math3d/qmatrix4x4.cpp19
-rw-r--r--src/gui/math3d/qmatrix4x4.h10
-rw-r--r--src/gui/opengl/platform/egl/qeglplatformcontext.cpp15
-rw-r--r--src/gui/opengl/qopenglfunctions.cpp6
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp1
-rw-r--r--src/gui/painting/qpainterpath.h2
-rw-r--r--src/gui/painting/qpdf.cpp1
-rw-r--r--src/gui/painting/qstroker.cpp6
-rw-r--r--src/gui/platform/unix/dbusmenu/qdbusplatformmenu.cpp1
-rw-r--r--src/gui/rhi/qrhivulkan.cpp104
-rw-r--r--src/gui/rhi/qrhivulkan_p.h6
-rw-r--r--src/gui/text/qfont.cpp33
-rw-r--r--src/gui/text/qfontengine.cpp7
-rw-r--r--src/gui/text/qtextdocument.cpp5
-rw-r--r--src/gui/text/qtextdocument_p.cpp1
-rw-r--r--src/gui/text/qtexttable.cpp4
-rw-r--r--src/gui/text/windows/qwindowsfontdatabase.cpp4
-rw-r--r--src/gui/text/windows/qwindowsfontdatabase_p.h4
-rw-r--r--src/gui/util/qlayoutpolicy.cpp5
-rw-r--r--src/network/access/qbytedatabuffer_p.h2
-rw-r--r--src/network/access/qformdatabuilder.cpp1
-rw-r--r--src/network/access/qformdatabuilder.h1
-rw-r--r--src/network/access/qhttp2connection.cpp77
-rw-r--r--src/network/access/qhttp2connection_p.h24
-rw-r--r--src/network/access/qnetworkaccesscache.cpp17
-rw-r--r--src/network/access/qnetworkaccesscache_p.h4
-rw-r--r--src/network/access/qnetworkcookie.cpp1
-rw-r--r--src/plugins/platforms/cocoa/qcocoaglcontext.mm21
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm25
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.cpp20
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp2
-rw-r--r--src/plugins/sqldrivers/.cmake.conf2
-rw-r--r--src/plugins/styles/modernwindows/qwindows11style.cpp59
-rw-r--r--src/plugins/styles/modernwindows/qwindows11style_p.h3
-rw-r--r--src/plugins/styles/modernwindows/qwindowsvistastyle.cpp5
-rw-r--r--src/plugins/tls/openssl/qtlsbackend_openssl.cpp9
-rw-r--r--src/testlib/doc/src/qt-webpages.qdoc4
-rw-r--r--src/tools/androidtestrunner/main.cpp59
-rw-r--r--src/tools/configure.cmake2
-rw-r--r--src/widgets/CMakeLists.txt2
-rw-r--r--src/widgets/accessible/qaccessiblecolorwell.cpp5
-rw-r--r--src/widgets/dialogs/qcolordialog.cpp15
-rw-r--r--src/widgets/doc/src/external-resources.qdoc6
-rw-r--r--src/widgets/kernel/qtooltip.cpp75
-rw-r--r--src/widgets/kernel/qtooltip_p.h74
-rw-r--r--src/widgets/kernel/qwidget.cpp6
-rw-r--r--src/widgets/styles/qcommonstyle.cpp9
-rw-r--r--src/widgets/styles/qstylesheetstyle.cpp12
-rw-r--r--src/xml/doc/src/external-resources.qdoc11
132 files changed, 1643 insertions, 729 deletions
diff --git a/src/3rdparty/libjpeg/COPYRIGHT.txt b/src/3rdparty/libjpeg/COPYRIGHT.txt
index f5eae868466..ce9d95bfebc 100644
--- a/src/3rdparty/libjpeg/COPYRIGHT.txt
+++ b/src/3rdparty/libjpeg/COPYRIGHT.txt
@@ -1,4 +1,4 @@
-Copyright (C) 2009-2025 D. R. Commander
+Copyright (C) 2009-2024 D. R. Commander
Copyright (C) 2015, 2020 Google, Inc.
Copyright (C) 2019-2020 Arm Limited
Copyright (C) 2015-2016, 2018 Matthieu Darbois
diff --git a/src/3rdparty/libjpeg/ChangeLog.md b/src/3rdparty/libjpeg/ChangeLog.md
index 4bdbf53dd34..17390d80bd0 100644
--- a/src/3rdparty/libjpeg/ChangeLog.md
+++ b/src/3rdparty/libjpeg/ChangeLog.md
@@ -1,3 +1,34 @@
+3.1.3
+=====
+
+### Significant changes relative to 3.1.2:
+
+1. Hardened the TurboJPEG API against hypothetical applications that may
+erroneously call `tj*Compress*()` or `tj*Transform()` with a reused JPEG
+destination buffer pointer while specifying a destination buffer size of 0.
+
+2. Hardened the TurboJPEG API against hypothetical applications that may
+erroneously set `TJPARAM_LOSSLESS` or `TJPARAM_COLORSPACE` prior to calling
+`tj3EncodeYUV*8()` or `tj3CompressFromYUV*8()`. `tj3EncodeYUV*8()` and
+`tj3CompressFromYUV*8()` now ignore `TJPARAM_LOSSLESS` and
+`TJPARAM_COLORSPACE`.
+
+3. Hardened the TurboJPEG Java API against hypothetical applications that may
+erroneously pass huge X or Y offsets to one of the compression, YUV encoding,
+decompression, or YUV decoding methods, leading to signed integer overflow in
+the JNI wrapper's buffer size checks that rendered those checks ineffective.
+
+4. Fixed an issue in the TurboJPEG Java API whereby
+`TJCompressor.getSourceBuf()` sometimes returned the buffer from a previous
+invocation of `TJCompressor.loadSourceImage()` if the target data precision was
+changed before the most recent invocation.
+
+5. Fixed an issue in the PPM reader that caused incorrect pixels to be
+generated when using `tj3LoadImage*()` or `TJCompressor.loadSourceImage()` to
+load a PBMPLUS (PPM/PGM) file into a CMYK buffer with a different data
+precision than that of the file.
+
+
3.1.2
=====
@@ -962,9 +993,9 @@ storage.
64-bit libjpeg-turbo SDK for Visual C++ were installed on the same system, only
one of them could be uninstalled.
-2. Fixed a signed integer overflow and subsequent segfault that occurred when
-attempting to decompress images with more than 715827882 pixels using the
-64-bit C version of TJBench.
+2. Fixed a signed integer overflow and subsequent segfault (CVE-2019-2201) that
+occurred when attempting to decompress images with more than 715827882 pixels
+using the 64-bit C version of TJBench.
3. Fixed out-of-bounds write in `tjDecompressToYUV2()` and
`tjDecompressToYUVPlanes()` (sometimes manifesting as a double free) that
@@ -1016,9 +1047,9 @@ regardless of whether a 4:2:2 JPEG image is rotated or transposed prior to
decompression (in the frequency domain) or after decompression (in the spatial
domain), the final image will be similar.
-4. Fixed an integer overflow and subsequent segfault that occurred when
-attempting to compress or decompress images with more than 1 billion pixels
-using the TurboJPEG API.
+4. Fixed an integer overflow and subsequent segfault (CVE-2019-2201) that
+occurred when attempting to compress or decompress images with more than 1
+billion pixels using the TurboJPEG API.
5. Fixed a regression introduced by 2.0 beta1[15] whereby attempting to
generate a progressive JPEG image on an SSE2-capable CPU using a scan script
diff --git a/src/3rdparty/libjpeg/qt_attribution.json b/src/3rdparty/libjpeg/qt_attribution.json
index fe38aec1f68..5ac811a12b4 100644
--- a/src/3rdparty/libjpeg/qt_attribution.json
+++ b/src/3rdparty/libjpeg/qt_attribution.json
@@ -7,8 +7,8 @@
"Description": "The Independent JPEG Group's JPEG software",
"Homepage": "http://libjpeg-turbo.virtualgl.org/",
- "Version": "3.1.2",
- "DownloadLocation": "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/3.1.2/libjpeg-turbo-3.1.2.tar.gz",
+ "Version": "3.1.3",
+ "DownloadLocation": "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/3.1.3/libjpeg-turbo-3.1.3.tar.gz",
"PURL": "pkg:github/libjpeg-turbo/libjpeg-turbo@$<VERSION>",
"CPE": "cpe:2.3:a:libjpeg-turbo:libjpeg-turbo:$<VERSION>:*:*:*:*:*:*:*",
diff --git a/src/3rdparty/libjpeg/src/jconfig.h b/src/3rdparty/libjpeg/src/jconfig.h
index e81574b9a48..85a1509fb68 100644
--- a/src/3rdparty/libjpeg/src/jconfig.h
+++ b/src/3rdparty/libjpeg/src/jconfig.h
@@ -2,9 +2,9 @@
#define JPEG_LIB_VERSION 80
-#define LIBJPEG_TURBO_VERSION 3.0.3
+#define LIBJPEG_TURBO_VERSION 3.1.3
-#define LIBJPEG_TURBO_VERSION_NUMBER 3000003
+#define LIBJPEG_TURBO_VERSION_NUMBER 3001003
#define C_ARITH_CODING_SUPPORTED 1
diff --git a/src/3rdparty/libjpeg/src/jconfigint.h b/src/3rdparty/libjpeg/src/jconfigint.h
index 6e7dbd75a1e..6d5f9633928 100644
--- a/src/3rdparty/libjpeg/src/jconfigint.h
+++ b/src/3rdparty/libjpeg/src/jconfigint.h
@@ -10,7 +10,7 @@
#define PACKAGE_NAME "libjpeg-turbo"
-#define VERSION "3.0.3"
+#define VERSION "3.1.3"
#if SIZE_MAX == 0xffffffff
#define SIZEOF_SIZE_T 4
diff --git a/src/3rdparty/libpng/ANNOUNCE b/src/3rdparty/libpng/ANNOUNCE
index 10dee70d834..e9a94e05de3 100644
--- a/src/3rdparty/libpng/ANNOUNCE
+++ b/src/3rdparty/libpng/ANNOUNCE
@@ -1,4 +1,4 @@
-libpng 1.6.52 - December 3, 2025
+libpng 1.6.53 - December 5, 2025
================================
This is a public release of libpng, intended for use in production code.
@@ -9,10 +9,10 @@ Files available for download
Source files:
- * libpng-1.6.52.tar.xz (LZMA-compressed, recommended)
- * libpng-1.6.52.tar.gz (deflate-compressed)
- * lpng1652.7z (LZMA-compressed)
- * lpng1652.zip (deflate-compressed)
+ * libpng-1.6.53.tar.xz (LZMA-compressed, recommended)
+ * libpng-1.6.53.tar.gz (deflate-compressed)
+ * lpng1653.7z (LZMA-compressed)
+ * lpng1653.zip (deflate-compressed)
Other information:
@@ -22,18 +22,14 @@ Other information:
* TRADEMARK.md
-Changes from version 1.6.51 to version 1.6.52
+Changes from version 1.6.52 to version 1.6.53
---------------------------------------------
- * Fixed CVE-2025-66293 (high severity):
- Out-of-bounds read in `png_image_read_composite`.
- (Reported by flyfish101 <[email protected]>.)
- * Fixed the Paeth filter handling in the RISC-V RVV implementation.
- (Reported by Filip Wasil; fixed by Liang Junzhao.)
- * Improved the performance of the RISC-V RVV implementation.
- (Contributed by Liang Junzhao.)
- * Added allocation failure fuzzing to oss-fuzz.
- (Contributed by Philippe Antoine.)
+ * Fixed a build failure on RISC-V RVV caused by a misspelled intrinsic.
+ (Contributed by Alexander Smorkalov.)
+ * Fixed a build failure with CMake 4.1 or newer, on Windows, when using
+ Visual C++ without MASM installed.
+ (Reported by Andrew Tribick; fixed by Luis Caro Campos.)
Send comments/corrections/commendations to png-mng-implement at lists.sf.net.
diff --git a/src/3rdparty/libpng/CHANGES b/src/3rdparty/libpng/CHANGES
index f8ad74bbdf3..ea43101538a 100644
--- a/src/3rdparty/libpng/CHANGES
+++ b/src/3rdparty/libpng/CHANGES
@@ -6315,6 +6315,12 @@ Version 1.6.52 [December 3, 2025]
Added allocation failure fuzzing to oss-fuzz.
(Contributed by Philippe Antoine.)
+Version 1.6.53 [December 5, 2025]
+ Fixed a build failure on RISC-V RVV caused by a misspelled intrinsic.
+ (Contributed by Alexander Smorkalov.)
+ Fixed a build failure with CMake 4.1 or newer, on Windows, when using
+ Visual C++ without MASM installed.
+
Send comments/corrections/commendations to png-mng-implement at lists.sf.net.
Subscription is required; visit
https://lists.sourceforge.net/lists/listinfo/png-mng-implement
diff --git a/src/3rdparty/libpng/README b/src/3rdparty/libpng/README
index 87e5f8b177e..4041ad86eb3 100644
--- a/src/3rdparty/libpng/README
+++ b/src/3rdparty/libpng/README
@@ -1,4 +1,4 @@
-README for libpng version 1.6.52
+README for libpng version 1.6.53
================================
See the note about version numbers near the top of `png.h`.
diff --git a/src/3rdparty/libpng/libpng-manual.txt b/src/3rdparty/libpng/libpng-manual.txt
index f284d987ba6..750025cfdad 100644
--- a/src/3rdparty/libpng/libpng-manual.txt
+++ b/src/3rdparty/libpng/libpng-manual.txt
@@ -9,7 +9,7 @@ libpng-manual.txt - A description on how to use and modify libpng
Based on:
- libpng version 1.6.36, December 2018, through 1.6.52 - December 2025
+ libpng version 1.6.36, December 2018, through 1.6.53 - December 2025
Updated and distributed by Cosmin Truta
Copyright (c) 2018-2025 Cosmin Truta
diff --git a/src/3rdparty/libpng/png.c b/src/3rdparty/libpng/png.c
index 11b65d1f13e..85b49496520 100644
--- a/src/3rdparty/libpng/png.c
+++ b/src/3rdparty/libpng/png.c
@@ -13,7 +13,7 @@
#include "pngpriv.h"
/* Generate a compiler error if there is an old png.h in the search path. */
-typedef png_libpng_version_1_6_52 Your_png_h_is_not_version_1_6_52;
+typedef png_libpng_version_1_6_53 Your_png_h_is_not_version_1_6_53;
/* Sanity check the chunks definitions - PNG_KNOWN_CHUNKS from pngpriv.h and the
* corresponding macro definitions. This causes a compile time failure if
@@ -817,7 +817,7 @@ png_get_copyright(png_const_structrp png_ptr)
return PNG_STRING_COPYRIGHT
#else
return PNG_STRING_NEWLINE \
- "libpng version 1.6.52" PNG_STRING_NEWLINE \
+ "libpng version 1.6.53" PNG_STRING_NEWLINE \
"Copyright (c) 2018-2025 Cosmin Truta" PNG_STRING_NEWLINE \
"Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson" \
PNG_STRING_NEWLINE \
diff --git a/src/3rdparty/libpng/png.h b/src/3rdparty/libpng/png.h
index bceb9aa45d7..bdcd243dea2 100644
--- a/src/3rdparty/libpng/png.h
+++ b/src/3rdparty/libpng/png.h
@@ -1,6 +1,6 @@
/* png.h - header file for PNG reference library
*
- * libpng version 1.6.52
+ * libpng version 1.6.53
*
* Copyright (c) 2018-2025 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
@@ -14,7 +14,7 @@
* libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger
* libpng versions 0.97, January 1998, through 1.6.35, July 2018:
* Glenn Randers-Pehrson
- * libpng versions 1.6.36, December 2018, through 1.6.52, December 2025:
+ * libpng versions 1.6.36, December 2018, through 1.6.53, December 2025:
* Cosmin Truta
* See also "Contributing Authors", below.
*/
@@ -238,7 +238,7 @@
* ...
* 1.5.30 15 10530 15.so.15.30[.0]
* ...
- * 1.6.52 16 10651 16.so.16.52[.0]
+ * 1.6.53 16 10651 16.so.16.53[.0]
*
* Henceforth the source version will match the shared-library major and
* minor numbers; the shared-library major version number will be used for
@@ -274,7 +274,7 @@
*/
/* Version information for png.h - this should match the version in png.c */
-#define PNG_LIBPNG_VER_STRING "1.6.52"
+#define PNG_LIBPNG_VER_STRING "1.6.53"
#define PNG_HEADER_VERSION_STRING " libpng version " PNG_LIBPNG_VER_STRING "\n"
/* The versions of shared library builds should stay in sync, going forward */
@@ -285,7 +285,7 @@
/* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */
#define PNG_LIBPNG_VER_MAJOR 1
#define PNG_LIBPNG_VER_MINOR 6
-#define PNG_LIBPNG_VER_RELEASE 52
+#define PNG_LIBPNG_VER_RELEASE 53
/* This should be zero for a public release, or non-zero for a
* development version.
@@ -316,7 +316,7 @@
* From version 1.0.1 it is:
* XXYYZZ, where XX=major, YY=minor, ZZ=release
*/
-#define PNG_LIBPNG_VER 10652 /* 1.6.52 */
+#define PNG_LIBPNG_VER 10653 /* 1.6.53 */
/* Library configuration: these options cannot be changed after
* the library has been built.
@@ -426,7 +426,7 @@ extern "C" {
/* This triggers a compiler error in png.c, if png.c and png.h
* do not agree upon the version number.
*/
-typedef char* png_libpng_version_1_6_52;
+typedef char* png_libpng_version_1_6_53;
/* Basic control structions. Read libpng-manual.txt or libpng.3 for more info.
*
diff --git a/src/3rdparty/libpng/pngconf.h b/src/3rdparty/libpng/pngconf.h
index 76b5c20bdff..f4ff19209c6 100644
--- a/src/3rdparty/libpng/pngconf.h
+++ b/src/3rdparty/libpng/pngconf.h
@@ -1,6 +1,6 @@
/* pngconf.h - machine-configurable file for libpng
*
- * libpng version 1.6.52
+ * libpng version 1.6.53
*
* Copyright (c) 2018-2025 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson
diff --git a/src/3rdparty/libpng/pnglibconf.h b/src/3rdparty/libpng/pnglibconf.h
index f4a993441f7..27fa87045b3 100644
--- a/src/3rdparty/libpng/pnglibconf.h
+++ b/src/3rdparty/libpng/pnglibconf.h
@@ -1,6 +1,6 @@
/* pnglibconf.h - library build configuration */
-/* libpng version 1.6.52 */
+/* libpng version 1.6.53 */
/* Copyright (c) 2018-2025 Cosmin Truta */
/* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson */
diff --git a/src/3rdparty/libpng/pngread.c b/src/3rdparty/libpng/pngread.c
index f8ca2b7e31d..13a93deedcb 100644
--- a/src/3rdparty/libpng/pngread.c
+++ b/src/3rdparty/libpng/pngread.c
@@ -3278,7 +3278,7 @@ png_image_read_composite(png_voidp argument)
/* Clamp to the valid range to defend against
* unforeseen cases where the data might be sRGB
* instead of linear premultiplied.
- * (Belt-and-suspenders for GitHub Issue #764.)
+ * (Belt-and-suspenders for CVE-2025-66293.)
*/
if (component > 255*65535)
component = 255*65535;
diff --git a/src/3rdparty/libpng/qt_attribution.json b/src/3rdparty/libpng/qt_attribution.json
index 1f942f8f564..132e5e8d4cd 100644
--- a/src/3rdparty/libpng/qt_attribution.json
+++ b/src/3rdparty/libpng/qt_attribution.json
@@ -7,8 +7,8 @@
"Description": "libpng is the official PNG reference library.",
"Homepage": "http://www.libpng.org/pub/png/libpng.html",
- "Version": "1.6.52",
- "DownloadLocation": "https://download.sourceforge.net/libpng/libpng-1.6.52.tar.xz",
+ "Version": "1.6.53",
+ "DownloadLocation": "https://download.sourceforge.net/libpng/libpng-1.6.53.tar.xz",
"PURL": "pkg:github/pnggroup/libpng@v$<VERSION>",
"CPE": "cpe:2.3:a:libpng:libpng:$<VERSION>:*:*:*:*:*:*:*",
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtWindow.java b/src/android/jar/src/org/qtproject/qt/android/QtWindow.java
index f0d304f9e7f..c63cd1a77e3 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtWindow.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtWindow.java
@@ -32,6 +32,7 @@ class QtWindow extends QtLayout implements QtSurfaceInterface {
private QtWindow m_parentWindow;
private GestureDetector m_gestureDetector;
private final QtEditText m_editText;
+ private boolean m_editTextFocusInitialized = false;
private final QtInputConnection.QtInputConnectionListener m_inputConnectionListener;
private boolean m_firstSafeMarginsDelivered = false;
private int m_actionBarHeight = -1;
@@ -62,6 +63,8 @@ class QtWindow extends QtLayout implements QtSurfaceInterface {
if (!isForeignWindow && context instanceof Activity) {
// TODO QTBUG-122552 - Service keyboard input not implemented
m_editText = new QtEditText(context, listener);
+ m_editText.setFocusable(false);
+ m_editText.setFocusableInTouchMode(false);
m_editText.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
@@ -242,6 +245,14 @@ class QtWindow extends QtLayout implements QtSurfaceInterface {
@Override
public boolean onTouchEvent(MotionEvent event)
{
+ // Enable focus for the edit text on first touch event to avoid
+ // early QtInputConnection callbacks from blocking the UI thread.
+ if (!m_editTextFocusInitialized) {
+ m_editTextFocusInitialized = true;
+ m_editText.setFocusable(true);
+ m_editText.setFocusableInTouchMode(true);
+ }
+
windowFocusChanged(true, getId());
if (m_editText != null && m_inputConnectionListener != null)
m_inputConnectionListener.onEditTextChanged(m_editText);
diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt
index ea8cf7b9c8e..539ad753ca6 100644
--- a/src/corelib/CMakeLists.txt
+++ b/src/corelib/CMakeLists.txt
@@ -590,17 +590,14 @@ if(QT_FEATURE_async_io)
DEFINES
QT_RANDOMACCESSASYNCFILE_QIORING
)
- elseif(QT_FEATURE_thread AND QT_FEATURE_future)
- # TODO: This should become the last (fallback) condition later.
- # We migth also want to rewrite it so that it does not depend on
- # QT_FEATURE_future.
- qt_internal_extend_target(Core
- SOURCES
- io/qrandomaccessasyncfile_threadpool.cpp
- DEFINES
- QT_RANDOMACCESSASYNCFILE_THREAD
- )
endif()
+ # This is the fallback condition that should be always available.
+ # TODO: try to rewrite it so that it does not depend on
+ # QT_FEATURE_future.
+ qt_internal_extend_target(Core
+ SOURCES
+ io/qrandomaccessasyncfile_threadpool.cpp
+ )
endif()
# This needs to be done before one below adds kernel32 because the symbols we use
diff --git a/src/corelib/Qt6CoreMacros.cmake b/src/corelib/Qt6CoreMacros.cmake
index b69d0285de2..c1f9aee0180 100644
--- a/src/corelib/Qt6CoreMacros.cmake
+++ b/src/corelib/Qt6CoreMacros.cmake
@@ -3677,21 +3677,6 @@ macro(qt6_standard_project_setup)
if(NOT DEFINED QT_I18N_SOURCE_LANGUAGE)
set(QT_I18N_SOURCE_LANGUAGE ${__qt_sps_arg_I18N_SOURCE_LANGUAGE})
endif()
-
- if(CMAKE_GENERATOR STREQUAL "Xcode")
- # Ensure we always use device SDK for Xcode for single-arch Qt builds
- set(qt_osx_arch_count 0)
- if(QT_OSX_ARCHITECTURES)
- list(LENGTH QT_OSX_ARCHITECTURES qt_osx_arch_count)
- endif()
- if(NOT qt_osx_arch_count GREATER 1 AND "${CMAKE_OSX_SYSROOT}" MATCHES "^[a-z]+simulator$")
- # Xcode expects the base SDK to be the device SDK
- set(simulator_sysroot "${CMAKE_OSX_SYSROOT}")
- string(REGEX REPLACE "simulator" "os" CMAKE_OSX_SYSROOT "${CMAKE_OSX_SYSROOT}")
- set(CMAKE_OSX_SYSROOT "${CMAKE_OSX_SYSROOT}" CACHE STRING "" FORCE)
- set(CMAKE_XCODE_ATTRIBUTE_SUPPORTED_PLATFORMS "${simulator_sysroot}")
- endif()
- endif()
endif()
endmacro()
diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp
index c3e1ba4010f..8a343b15eeb 100644
--- a/src/corelib/animation/qabstractanimation.cpp
+++ b/src/corelib/animation/qabstractanimation.cpp
@@ -858,6 +858,7 @@ qint64 QAnimationDriver::elapsed() const
*/
/*!
+ \internal
The default animation driver just spins the timer...
*/
QDefaultAnimationDriver::QDefaultAnimationDriver(QUnifiedTimer *timer)
diff --git a/src/corelib/configure.cmake b/src/corelib/configure.cmake
index 7216f2920fe..7274b51cc0a 100644
--- a/src/corelib/configure.cmake
+++ b/src/corelib/configure.cmake
@@ -620,6 +620,10 @@ int main(void)
HRESULT hr = CreateIoRing(IORING_VERSION_3, flags, 1, 1, &ioRingHandle);
if (hr == IORING_E_SUBMISSION_QUEUE_FULL) // not valid, but test that this #define exists
return 0;
+ IORING_HANDLE_REF ref(HANDLE(nullptr));
+ IORING_BUFFER_REF bufRef(nullptr);
+ // The newest API addition that we require:
+ BuildIoRingWriteFile(ioRingHandle, ref, bufRef, -1, 0, FILE_WRITE_FLAGS_NONE, 0, IOSQE_FLAGS_NONE);
/* END TEST: */
return 0;
}
@@ -806,7 +810,7 @@ qt_feature("winsdkicu" PRIVATE
CONDITION TEST_winsdkicu
DISABLE QT_FEATURE_icu
)
-qt_feature("windows_ioring" PRIVATE
+qt_feature("windows-ioring" PRIVATE
LABEL "Windows I/O Ring"
AUTODETECT WIN32 AND CMAKE_HOST_SYSTEM_VERSION VERSION_GREATER_EQUAL 10.0.22000
CONDITION TEST_windows_ioring
@@ -1278,14 +1282,13 @@ qt_feature("permissions" PUBLIC
)
qt_feature("openssl-hash" PRIVATE
LABEL "OpenSSL based cryptographic hash"
- AUTODETECT OFF
CONDITION QT_FEATURE_openssl_linked AND QT_FEATURE_opensslv30
PURPOSE "Uses OpenSSL based implementation of cryptographic hash algorithms."
)
qt_feature("async-io" PRIVATE
LABEL "Async File I/O"
PURPOSE "Provides support for asynchronous file I/O."
- CONDITION (QT_FEATURE_thread AND QT_FEATURE_future) OR APPLE
+ CONDITION QT_FEATURE_thread AND QT_FEATURE_future
)
qt_configure_add_summary_section(NAME "Qt Core")
@@ -1298,7 +1301,7 @@ qt_configure_add_summary_entry(ARGS "glib")
qt_configure_add_summary_entry(ARGS "icu")
qt_configure_add_summary_entry(ARGS "jemalloc")
qt_configure_add_summary_entry(ARGS "liburing")
-qt_configure_add_summary_entry(ARGS "windows_ioring")
+qt_configure_add_summary_entry(ARGS "windows-ioring")
qt_configure_add_summary_entry(ARGS "timezone_tzdb")
qt_configure_add_summary_entry(ARGS "system-libb2")
qt_configure_add_summary_entry(ARGS "mimetype-database")
diff --git a/src/corelib/doc/src/cmake/cmake-configure-variables.qdoc b/src/corelib/doc/src/cmake/cmake-configure-variables.qdoc
index 0a0dc0b3c50..b8e5e038a33 100644
--- a/src/corelib/doc/src/cmake/cmake-configure-variables.qdoc
+++ b/src/corelib/doc/src/cmake/cmake-configure-variables.qdoc
@@ -133,7 +133,6 @@ use, for example, library files referenced from a Qt installation.
\summary {Forces or disables release package signing regardless of the build type.}
\cmakevariablesince 6.7
-\preliminarycmakevariable
\cmakevariableandroidonly
When set to \c Release, the \c --release flag is passed to the \c
@@ -143,6 +142,10 @@ effectively disables release package signing even in Release or RelWithDebInfo
builds. When not set, the default behavior is to use release package signing in
build types other than Debug.
+This variable is not supposed to be set in CMake project files. Rather set it
+when configuring your project on the command line or in the CMake settings of
+your IDE.
+
\sa {androiddeployqt}
*/
diff --git a/src/corelib/doc/src/external-resources.qdoc b/src/corelib/doc/src/external-resources.qdoc
index 2232b49bf23..5d357c65496 100644
--- a/src/corelib/doc/src/external-resources.qdoc
+++ b/src/corelib/doc/src/external-resources.qdoc
@@ -28,11 +28,6 @@
*/
/*!
- \externalpage https://marcmutz.wordpress.com/effective-qt/containers/#containers-qlist
- \title Pros and Cons of Using QList
-*/
-
-/*!
\externalpage https://marcmutz.wordpress.com/effective-qt/containers/
\title Understand the Qt Containers
*/
diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h
index 0b42af7686c..b2d79cca603 100644
--- a/src/corelib/global/qcompilerdetection.h
+++ b/src/corelib/global/qcompilerdetection.h
@@ -1404,7 +1404,7 @@ static_assert(!std::is_convertible_v<std::nullptr_t, bool>,
#if defined(__cplusplus)
#ifdef __cpp_constinit
-# if defined(Q_CC_MSVC) && !defined(Q_CC_CLANG)
+# if defined(Q_CC_MSVC) && _MSC_VER < 1940 && !defined(Q_CC_CLANG)
// https://developercommunity.visualstudio.com/t/C:-constinit-for-an-optional-fails-if-/1406069
# define Q_CONSTINIT
# else
diff --git a/src/corelib/global/qoperatingsystemversion.cpp b/src/corelib/global/qoperatingsystemversion.cpp
index d27a71526d8..32364fa8eb4 100644
--- a/src/corelib/global/qoperatingsystemversion.cpp
+++ b/src/corelib/global/qoperatingsystemversion.cpp
@@ -486,6 +486,12 @@ const QOperatingSystemVersionBase QOperatingSystemVersion::Windows11_22H2;
*/
/*!
+ \variable QOperatingSystemVersion::Windows11_25H2
+ \brief a version corresponding to Windows 11 Version 25H2 (version 10.0.26200).
+ \since 6.11
+ */
+
+/*!
\variable QOperatingSystemVersion::OSXMavericks
\brief a version corresponding to OS X Mavericks (version 10.9).
\since 5.9
diff --git a/src/corelib/global/qoperatingsystemversion.h b/src/corelib/global/qoperatingsystemversion.h
index 75801a7ddcf..99866692f8c 100644
--- a/src/corelib/global/qoperatingsystemversion.h
+++ b/src/corelib/global/qoperatingsystemversion.h
@@ -148,6 +148,7 @@ public:
static constexpr QOperatingSystemVersionBase Android14 { QOperatingSystemVersionBase::Android, 14, 0 };
static constexpr QOperatingSystemVersionBase Windows11_23H2 { QOperatingSystemVersionBase::Windows, 10, 0, 22631 };
static constexpr QOperatingSystemVersionBase Windows11_24H2 { QOperatingSystemVersionBase::Windows, 10, 0, 26100 };
+ static constexpr QOperatingSystemVersionBase Windows11_25H2 { QOperatingSystemVersionBase::Windows, 10, 0, 26200 };
#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED) && !defined(Q_QDOC)
};
diff --git a/src/corelib/global/qttranslation.qdoc b/src/corelib/global/qttranslation.qdoc
index 191b3777db6..c8b3764614e 100644
--- a/src/corelib/global/qttranslation.qdoc
+++ b/src/corelib/global/qttranslation.qdoc
@@ -179,7 +179,7 @@
\fn QString qTrId(const char *id, int n = -1)
\relates <QtTranslation>
\reentrant
- \since 6.9
+ \since 6.11
\brief The qTrId function is an alias for qtTrId.
diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp
index 0771c15584b..d3c398f0860 100644
--- a/src/corelib/io/qfsfileengine.cpp
+++ b/src/corelib/io/qfsfileengine.cpp
@@ -249,6 +249,12 @@ bool QFSFileEngine::open(QIODevice::OpenMode openMode, FILE *fh, QFile::FileHand
}
/*!
+ \class QFSFileEnginePrivate
+ \inmodule QtCore
+ \internal
+*/
+
+/*!
Opens the file handle \a fh using the open mode \a flags.
*/
bool QFSFileEnginePrivate::openFh(QIODevice::OpenMode openMode, FILE *fh)
diff --git a/src/corelib/io/qiooperation_p.h b/src/corelib/io/qiooperation_p.h
index 56845167ede..1486719a7e8 100644
--- a/src/corelib/io/qiooperation_p.h
+++ b/src/corelib/io/qiooperation_p.h
@@ -72,6 +72,9 @@ protected:
Q_DECLARE_PRIVATE(QIOOperation)
friend class QRandomAccessAsyncFilePrivate;
+ friend class QRandomAccessAsyncFileBackend;
+ friend class QRandomAccessAsyncFileNativeBackend;
+ friend class QRandomAccessAsyncFileThreadPoolBackend;
};
class Q_CORE_EXPORT QIOReadWriteOperationBase : public QIOOperation
@@ -86,6 +89,11 @@ protected:
QIOReadWriteOperationBase() = delete;
Q_DISABLE_COPY_MOVE(QIOReadWriteOperationBase)
explicit QIOReadWriteOperationBase(QIOOperationPrivate &dd, QObject *parent = nullptr);
+
+ friend class QRandomAccessAsyncFilePrivate;
+ friend class QRandomAccessAsyncFileBackend;
+ friend class QRandomAccessAsyncFileNativeBackend;
+ friend class QRandomAccessAsyncFileThreadPoolBackend;
};
class Q_CORE_EXPORT QIOReadOperation : public QIOReadWriteOperationBase
@@ -101,6 +109,9 @@ protected:
explicit QIOReadOperation(QIOOperationPrivate &dd, QObject *parent = nullptr);
friend class QRandomAccessAsyncFilePrivate;
+ friend class QRandomAccessAsyncFileBackend;
+ friend class QRandomAccessAsyncFileNativeBackend;
+ friend class QRandomAccessAsyncFileThreadPoolBackend;
};
class Q_CORE_EXPORT QIOWriteOperation : public QIOReadWriteOperationBase
@@ -116,6 +127,9 @@ protected:
explicit QIOWriteOperation(QIOOperationPrivate &dd, QObject *parent = nullptr);
friend class QRandomAccessAsyncFilePrivate;
+ friend class QRandomAccessAsyncFileBackend;
+ friend class QRandomAccessAsyncFileNativeBackend;
+ friend class QRandomAccessAsyncFileThreadPoolBackend;
};
class Q_CORE_EXPORT QIOVectoredReadOperation : public QIOReadWriteOperationBase
@@ -131,6 +145,9 @@ protected:
explicit QIOVectoredReadOperation(QIOOperationPrivate &dd, QObject *parent = nullptr);
friend class QRandomAccessAsyncFilePrivate;
+ friend class QRandomAccessAsyncFileBackend;
+ friend class QRandomAccessAsyncFileNativeBackend;
+ friend class QRandomAccessAsyncFileThreadPoolBackend;
};
class Q_CORE_EXPORT QIOVectoredWriteOperation : public QIOReadWriteOperationBase
@@ -146,6 +163,9 @@ protected:
explicit QIOVectoredWriteOperation(QIOOperationPrivate &dd, QObject *parent = nullptr);
friend class QRandomAccessAsyncFilePrivate;
+ friend class QRandomAccessAsyncFileBackend;
+ friend class QRandomAccessAsyncFileNativeBackend;
+ friend class QRandomAccessAsyncFileThreadPoolBackend;
};
QT_END_NAMESPACE
diff --git a/src/corelib/io/qioring_p.h b/src/corelib/io/qioring_p.h
index 0db832bc6bf..8fdaf48f8f6 100644
--- a/src/corelib/io/qioring_p.h
+++ b/src/corelib/io/qioring_p.h
@@ -91,6 +91,10 @@ enum class Operation : quint8 {
// clang-format on
Q_ENUM_NS(Operation);
#undef DEFINE_ENTRY
+
+#ifdef Q_OS_WIN
+struct IORingApiTable;
+#endif
}; // namespace QtPrivate
template <QtPrivate::Operation Op>
@@ -221,9 +225,11 @@ private:
std::optional<QWinEventNotifier> notifier;
HIORING ioRingHandle = nullptr;
HANDLE eventHandle = INVALID_HANDLE_VALUE;
+ const QtPrivate::IORingApiTable *apiTable;
bool initialized = false;
bool queueWasFull = false;
+
[[nodiscard]]
RequestPrepResult prepareRequest(GenericRequestType &request);
QIORing::ReadWriteStatus handleReadCompletion(
diff --git a/src/corelib/io/qioring_win.cpp b/src/corelib/io/qioring_win.cpp
index 42c51f428d6..b2f188486d0 100644
--- a/src/corelib/io/qioring_win.cpp
+++ b/src/corelib/io/qioring_win.cpp
@@ -24,6 +24,59 @@ static_assert(sizeof(qsizetype) > sizeof(UINT32),
using namespace Qt::StringLiterals;
+namespace QtPrivate {
+#define FOREACH_WIN_IORING_FUNCTION(Fn) \
+ Fn(BuildIoRingReadFile) \
+ Fn(BuildIoRingWriteFile) \
+ Fn(BuildIoRingFlushFile) \
+ Fn(BuildIoRingCancelRequest) \
+ Fn(QueryIoRingCapabilities) \
+ Fn(CreateIoRing) \
+ Fn(GetIoRingInfo) \
+ Fn(SubmitIoRing) \
+ Fn(CloseIoRing) \
+ Fn(PopIoRingCompletion) \
+ Fn(SetIoRingCompletionEvent) \
+ /**/
+struct IORingApiTable
+{
+#define DefineIORingFunction(Name) \
+ using Name##Fn = decltype(&::Name); \
+ Name##Fn Name = nullptr;
+
+ FOREACH_WIN_IORING_FUNCTION(DefineIORingFunction)
+
+#undef DefineIORingFunction
+};
+
+static const IORingApiTable *getApiTable()
+{
+ static const IORingApiTable apiTable = []() {
+ IORingApiTable apiTable;
+ const HMODULE kernel32 = GetModuleHandleW(L"kernel32.dll");
+ if (Q_UNLIKELY(!kernel32)) // how would this happen
+ return apiTable;
+
+#define ResolveFunction(Name) \
+ apiTable.Name = IORingApiTable::Name##Fn(QFunctionPointer(GetProcAddress(kernel32, #Name)));
+
+ FOREACH_WIN_IORING_FUNCTION(ResolveFunction)
+
+#undef ResolveFunction
+ return apiTable;
+ }();
+
+#define TEST_TABLE_OK(X) \
+ apiTable.X && /* chain */
+#define BOOL_CHAIN(...) (__VA_ARGS__ true)
+ const bool success = BOOL_CHAIN(FOREACH_WIN_IORING_FUNCTION(TEST_TABLE_OK));
+#undef BOOL_CHAIN
+#undef TEST_TABLE_OK
+
+ return success ? std::addressof(apiTable) : nullptr;
+}
+} // namespace QtPrivate
+
static HRESULT buildReadOperation(HIORING ioRingHandle, qintptr fd, QSpan<std::byte> destination,
quint64 offset, quintptr userData)
{
@@ -32,8 +85,10 @@ static HRESULT buildReadOperation(HIORING ioRingHandle, qintptr fd, QSpan<std::b
const IORING_BUFFER_REF bufferRef(destination.data());
const auto maxSize = q26::saturate_cast<UINT32>(destination.size());
Q_ASSERT(maxSize == destination.size());
- return BuildIoRingReadFile(ioRingHandle, fileRef, bufferRef, maxSize, offset, userData,
- IOSQE_FLAGS_NONE);
+ const auto *apiTable = QtPrivate::getApiTable();
+ Q_ASSERT(apiTable); // If we got this far it needs to be here
+ return apiTable->BuildIoRingReadFile(ioRingHandle, fileRef, bufferRef, maxSize, offset,
+ userData, IOSQE_FLAGS_NONE);
}
static HRESULT buildWriteOperation(HIORING ioRingHandle, qintptr fd, QSpan<const std::byte> source,
@@ -44,16 +99,18 @@ static HRESULT buildWriteOperation(HIORING ioRingHandle, qintptr fd, QSpan<const
const IORING_BUFFER_REF bufferRef(const_cast<std::byte *>(source.data()));
const auto maxSize = q26::saturate_cast<UINT32>(source.size());
Q_ASSERT(maxSize == source.size());
+ const auto *apiTable = QtPrivate::getApiTable();
+ Q_ASSERT(apiTable); // If we got this far it needs to be here
// @todo: FILE_WRITE_FLAGS can be set to write-through, could be used for Unbuffered mode.
- return BuildIoRingWriteFile(ioRingHandle, fileRef, bufferRef, maxSize, offset,
- FILE_WRITE_FLAGS_NONE, userData, IOSQE_FLAGS_NONE);
+ return apiTable->BuildIoRingWriteFile(ioRingHandle, fileRef, bufferRef, maxSize, offset,
+ FILE_WRITE_FLAGS_NONE, userData, IOSQE_FLAGS_NONE);
}
QIORing::~QIORing()
{
if (initialized) {
CloseHandle(eventHandle);
- CloseIoRing(ioRingHandle);
+ apiTable->CloseIoRing(ioRingHandle);
}
}
@@ -62,8 +119,13 @@ bool QIORing::initializeIORing()
if (initialized)
return true;
+ if (apiTable = QtPrivate::getApiTable(); !apiTable) {
+ qCWarning(lcQIORing, "Failed to retrieve API table");
+ return false;
+ }
+
IORING_CAPABILITIES capabilities;
- QueryIoRingCapabilities(&capabilities);
+ apiTable->QueryIoRingCapabilities(&capabilities);
if (capabilities.MaxVersion < IORING_VERSION_3) // 3 adds write, flush and drain
return false;
if ((capabilities.FeatureFlags & IORING_FEATURE_SET_COMPLETION_EVENT) == 0)
@@ -75,7 +137,8 @@ bool QIORing::initializeIORing()
IORING_CREATE_FLAGS flags;
memset(&flags, 0, sizeof(flags));
- HRESULT hr = CreateIoRing(IORING_VERSION_3, flags, sqEntries, cqEntries, &ioRingHandle);
+ HRESULT hr = apiTable->CreateIoRing(IORING_VERSION_3, flags, sqEntries, cqEntries,
+ &ioRingHandle);
if (FAILED(hr)) {
qErrnoWarning(hr, "failed to initialize QIORing");
return false;
@@ -83,7 +146,7 @@ bool QIORing::initializeIORing()
auto earlyExitCleanup = qScopeGuard([this]() {
if (eventHandle != INVALID_HANDLE_VALUE)
CloseHandle(eventHandle);
- CloseIoRing(ioRingHandle);
+ apiTable->CloseIoRing(ioRingHandle);
});
eventHandle = CreateEvent(nullptr, TRUE, FALSE, nullptr);
if (eventHandle == INVALID_HANDLE_VALUE) {
@@ -91,13 +154,13 @@ bool QIORing::initializeIORing()
return false;
}
notifier.emplace(eventHandle);
- hr = SetIoRingCompletionEvent(ioRingHandle, eventHandle);
+ hr = apiTable->SetIoRingCompletionEvent(ioRingHandle, eventHandle);
if (FAILED(hr)) {
qErrnoWarning(hr, "Failed to assign the event handle to QIORing");
return false;
}
IORING_INFO info;
- if (SUCCEEDED(GetIoRingInfo(ioRingHandle, &info))) {
+ if (SUCCEEDED(apiTable->GetIoRingInfo(ioRingHandle, &info))) {
sqEntries = info.SubmissionQueueSize;
cqEntries = info.CompletionQueueSize;
qCDebug(lcQIORing) << "QIORing configured with capacity for" << sqEntries
@@ -274,7 +337,7 @@ void QIORing::completionReady()
{
ResetEvent(eventHandle);
IORING_CQE entry;
- while (PopIoRingCompletion(ioRingHandle, &entry) == S_OK) {
+ while (apiTable->PopIoRingCompletion(ioRingHandle, &entry) == S_OK) {
// NOLINTNEXTLINE(performance-no-int-to-ptr)
auto *request = reinterpret_cast<GenericRequestType *>(entry.UserData);
if (!addrItMap.contains(request)) {
@@ -458,7 +521,8 @@ void QIORing::submitRequests()
const bool shouldTryWait = std::exchange(queueWasFull, false);
const auto submitToRing = [this, &shouldTryWait] {
quint32 submittedEntries = 0;
- HRESULT hr = SubmitIoRing(ioRingHandle, shouldTryWait ? 1 : 0, 1, &submittedEntries);
+ HRESULT hr = apiTable->SubmitIoRing(ioRingHandle, shouldTryWait ? 1 : 0, 1,
+ &submittedEntries);
qCDebug(lcQIORing) << "Submitted" << submittedEntries << "requests";
unstagedRequests -= submittedEntries;
if (FAILED(hr)) {
@@ -558,9 +622,9 @@ auto QIORing::prepareRequest(GenericRequestType &request) -> RequestPrepResult
auto *closeRequest = request.requestData<Operation::Close>();
// NOLINTNEXTLINE(performance-no-int-to-ptr)
const IORING_HANDLE_REF fileRef(HANDLE(closeRequest->fd));
- hr = BuildIoRingFlushFile(ioRingHandle, fileRef, FILE_FLUSH_MIN_METADATA,
- quintptr(std::addressof(request)),
- IOSQE_FLAGS_DRAIN_PRECEDING_OPS);
+ hr = apiTable->BuildIoRingFlushFile(ioRingHandle, fileRef, FILE_FLUSH_MIN_METADATA,
+ quintptr(std::addressof(request)),
+ IOSQE_FLAGS_DRAIN_PRECEDING_OPS);
break;
}
case Operation::Read: {
@@ -645,9 +709,9 @@ auto QIORing::prepareRequest(GenericRequestType &request) -> RequestPrepResult
auto *flushRequest = request.requestData<Operation::Flush>();
// NOLINTNEXTLINE(performance-no-int-to-ptr)
const IORING_HANDLE_REF fileRef(HANDLE(flushRequest->fd));
- hr = BuildIoRingFlushFile(ioRingHandle, fileRef, FILE_FLUSH_DEFAULT,
- quintptr(std::addressof(request)),
- IOSQE_FLAGS_DRAIN_PRECEDING_OPS);
+ hr = apiTable->BuildIoRingFlushFile(ioRingHandle, fileRef, FILE_FLUSH_DEFAULT,
+ quintptr(std::addressof(request)),
+ IOSQE_FLAGS_DRAIN_PRECEDING_OPS);
break;
}
case QtPrivate::Operation::Stat: {
@@ -703,8 +767,8 @@ auto QIORing::prepareRequest(GenericRequestType &request) -> RequestPrepResult
}
// NOLINTNEXTLINE(performance-no-int-to-ptr)
const IORING_HANDLE_REF fileRef((HANDLE(fd)));
- hr = BuildIoRingCancelRequest(ioRingHandle, fileRef, quintptr(otherOperation),
- quintptr(std::addressof(request)));
+ hr = apiTable->BuildIoRingCancelRequest(ioRingHandle, fileRef, quintptr(otherOperation),
+ quintptr(std::addressof(request)));
break;
}
case Operation::NumOperations:
diff --git a/src/corelib/io/qrandomaccessasyncfile.cpp b/src/corelib/io/qrandomaccessasyncfile.cpp
index c544585de9d..34e216efe27 100644
--- a/src/corelib/io/qrandomaccessasyncfile.cpp
+++ b/src/corelib/io/qrandomaccessasyncfile.cpp
@@ -7,6 +7,31 @@
QT_BEGIN_NAMESPACE
+QRandomAccessAsyncFileBackend::QRandomAccessAsyncFileBackend(QRandomAccessAsyncFile *owner)
+ : m_owner(owner)
+{
+}
+QRandomAccessAsyncFileBackend::~QRandomAccessAsyncFileBackend() = default;
+QRandomAccessAsyncFilePrivate::QRandomAccessAsyncFilePrivate() = default;
+QRandomAccessAsyncFilePrivate::~QRandomAccessAsyncFilePrivate() = default;
+
+void QRandomAccessAsyncFilePrivate::init()
+{
+ Q_Q(QRandomAccessAsyncFile);
+
+#if defined(QT_RANDOMACCESSASYNCFILE_QIORING) || defined(Q_OS_DARWIN)
+ m_backend = std::make_unique<QRandomAccessAsyncFileNativeBackend>(q);
+#endif
+ if (!m_backend || !m_backend->init()) {
+#if QT_CONFIG(thread) && QT_CONFIG(future)
+ m_backend = std::make_unique<QRandomAccessAsyncFileThreadPoolBackend>(q);
+ [[maybe_unused]]
+ bool result = m_backend->init();
+ Q_ASSERT(result); // it always succeeds
+#endif
+ }
+}
+
QRandomAccessAsyncFile::QRandomAccessAsyncFile(QObject *parent)
: QObject{*new QRandomAccessAsyncFilePrivate, parent}
{
diff --git a/src/corelib/io/qrandomaccessasyncfile_darwin.mm b/src/corelib/io/qrandomaccessasyncfile_darwin.mm
index 7231d12fe7d..80c1affa642 100644
--- a/src/corelib/io/qrandomaccessasyncfile_darwin.mm
+++ b/src/corelib/io/qrandomaccessasyncfile_darwin.mm
@@ -27,14 +27,14 @@ static bool isBarrierOperation(QIOOperation::Type type)
// only!
template <typename Operation, typename ...Args>
Operation *
-QRandomAccessAsyncFilePrivate::addOperation(QIOOperation::Type type, qint64 offset, Args &&...args)
+QRandomAccessAsyncFileNativeBackend::addOperation(QIOOperation::Type type, qint64 offset, Args &&...args)
{
auto dataStorage = new QtPrivate::QIOOperationDataStorage(std::forward<Args>(args)...);
auto *priv = new QIOOperationPrivate(dataStorage);
priv->offset = offset;
priv->type = type;
- Operation *op = new Operation(*priv, q_ptr);
+ Operation *op = new Operation(*priv, m_owner);
auto opId = getNextId();
m_operations.push_back(OperationInfo(opId, op));
startOperationsUntilBarrier();
@@ -42,19 +42,20 @@ QRandomAccessAsyncFilePrivate::addOperation(QIOOperation::Type type, qint64 offs
return op;
}
-QRandomAccessAsyncFilePrivate::QRandomAccessAsyncFilePrivate()
- : QObjectPrivate()
+QRandomAccessAsyncFileNativeBackend::QRandomAccessAsyncFileNativeBackend(QRandomAccessAsyncFile *owner)
+ : QRandomAccessAsyncFileBackend(owner)
{
}
-QRandomAccessAsyncFilePrivate::~QRandomAccessAsyncFilePrivate()
+QRandomAccessAsyncFileNativeBackend::~QRandomAccessAsyncFileNativeBackend()
= default;
-void QRandomAccessAsyncFilePrivate::init()
+bool QRandomAccessAsyncFileNativeBackend::init()
{
+ return true;
}
-void QRandomAccessAsyncFilePrivate::cancelAndWait(QIOOperation *op)
+void QRandomAccessAsyncFileNativeBackend::cancelAndWait(QIOOperation *op)
{
auto it = std::find_if(m_operations.cbegin(), m_operations.cend(),
[op](const auto &opInfo) {
@@ -87,7 +88,7 @@ void QRandomAccessAsyncFilePrivate::cancelAndWait(QIOOperation *op)
startOperationsUntilBarrier();
}
-void QRandomAccessAsyncFilePrivate::close()
+void QRandomAccessAsyncFileNativeBackend::close()
{
if (m_fileState == FileState::Closed)
return;
@@ -95,10 +96,8 @@ void QRandomAccessAsyncFilePrivate::close()
// cancel all operations
m_mutex.lock();
m_opToCancel = kAllOperationIds;
- m_numChannelsToClose = m_ioChannel ? 1 : 0;
for (const auto &op : m_operations) {
if (op.channel) {
- ++m_numChannelsToClose;
closeIoChannel(op.channel);
}
}
@@ -127,7 +126,7 @@ void QRandomAccessAsyncFilePrivate::close()
m_fileState = FileState::Closed;
}
-qint64 QRandomAccessAsyncFilePrivate::size() const
+qint64 QRandomAccessAsyncFileNativeBackend::size() const
{
if (m_fileState != FileState::Opened)
return -1;
@@ -140,7 +139,7 @@ qint64 QRandomAccessAsyncFilePrivate::size() const
}
QIOOperation *
-QRandomAccessAsyncFilePrivate::open(const QString &path, QIODeviceBase::OpenMode mode)
+QRandomAccessAsyncFileNativeBackend::open(const QString &path, QIODeviceBase::OpenMode mode)
{
if (m_fileState == FileState::Closed) {
m_filePath = path;
@@ -153,44 +152,44 @@ QRandomAccessAsyncFilePrivate::open(const QString &path, QIODeviceBase::OpenMode
return addOperation<QIOOperation>(QIOOperation::Type::Open, 0);
}
-QIOOperation *QRandomAccessAsyncFilePrivate::flush()
+QIOOperation *QRandomAccessAsyncFileNativeBackend::flush()
{
return addOperation<QIOOperation>(QIOOperation::Type::Flush, 0);
}
-QIOReadOperation *QRandomAccessAsyncFilePrivate::read(qint64 offset, qint64 maxSize)
+QIOReadOperation *QRandomAccessAsyncFileNativeBackend::read(qint64 offset, qint64 maxSize)
{
QByteArray array(maxSize, Qt::Uninitialized);
return addOperation<QIOReadOperation>(QIOOperation::Type::Read, offset, std::move(array));
}
-QIOWriteOperation *QRandomAccessAsyncFilePrivate::write(qint64 offset, const QByteArray &data)
+QIOWriteOperation *QRandomAccessAsyncFileNativeBackend::write(qint64 offset, const QByteArray &data)
{
QByteArray copy = data;
return write(offset, std::move(copy));
}
-QIOWriteOperation *QRandomAccessAsyncFilePrivate::write(qint64 offset, QByteArray &&data)
+QIOWriteOperation *QRandomAccessAsyncFileNativeBackend::write(qint64 offset, QByteArray &&data)
{
return addOperation<QIOWriteOperation>(QIOOperation::Type::Write, offset, std::move(data));
}
QIOVectoredReadOperation *
-QRandomAccessAsyncFilePrivate::readInto(qint64 offset, QSpan<std::byte> buffer)
+QRandomAccessAsyncFileNativeBackend::readInto(qint64 offset, QSpan<std::byte> buffer)
{
return addOperation<QIOVectoredReadOperation>(QIOOperation::Type::Read, offset,
QSpan<const QSpan<std::byte>>{buffer});
}
QIOVectoredWriteOperation *
-QRandomAccessAsyncFilePrivate::writeFrom(qint64 offset, QSpan<const std::byte> buffer)
+QRandomAccessAsyncFileNativeBackend::writeFrom(qint64 offset, QSpan<const std::byte> buffer)
{
return addOperation<QIOVectoredWriteOperation>(QIOOperation::Type::Write, offset,
QSpan<const QSpan<const std::byte>>{buffer});
}
QIOVectoredReadOperation *
-QRandomAccessAsyncFilePrivate::readInto(qint64 offset, QSpan<const QSpan<std::byte>> buffers)
+QRandomAccessAsyncFileNativeBackend::readInto(qint64 offset, QSpan<const QSpan<std::byte>> buffers)
{
// GCD implementation does not have vectored read. Spawning several read
// operations (each with an updated offset), is not ideal, because some
@@ -204,32 +203,40 @@ QRandomAccessAsyncFilePrivate::readInto(qint64 offset, QSpan<const QSpan<std::by
}
QIOVectoredWriteOperation *
-QRandomAccessAsyncFilePrivate::writeFrom(qint64 offset, QSpan<const QSpan<const std::byte>> buffers)
+QRandomAccessAsyncFileNativeBackend::writeFrom(qint64 offset, QSpan<const QSpan<const std::byte>> buffers)
{
return addOperation<QIOVectoredWriteOperation>(QIOOperation::Type::Write, offset, buffers);
}
-void QRandomAccessAsyncFilePrivate::notifyIfOperationsAreCompleted()
+void QRandomAccessAsyncFileNativeBackend::notifyIfOperationsAreCompleted()
{
QMutexLocker locker(&m_mutex);
+ --m_numChannelsToClose;
if (m_opToCancel == kAllOperationIds) {
- --m_numChannelsToClose;
if (m_numChannelsToClose == 0 && m_runningOps.isEmpty())
m_cancellationCondition.wakeOne();
}
}
-dispatch_io_t QRandomAccessAsyncFilePrivate::createMainChannel(int fd)
+dispatch_io_t QRandomAccessAsyncFileNativeBackend::createMainChannel(int fd)
{
auto sharedThis = this;
- return dispatch_io_create(DISPATCH_IO_RANDOM, fd,
- dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0),
- ^(int /*error*/) {
- sharedThis->notifyIfOperationsAreCompleted();
- });
+ auto channel =
+ dispatch_io_create(DISPATCH_IO_RANDOM, fd,
+ dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0),
+ ^(int /*error*/) {
+ // main I/O channel uses kInvalidOperationId
+ // as its identifier
+ sharedThis->notifyIfOperationsAreCompleted();
+ });
+ if (channel) {
+ QMutexLocker locker(&m_mutex);
+ ++m_numChannelsToClose;
+ }
+ return channel;
}
-dispatch_io_t QRandomAccessAsyncFilePrivate::duplicateIoChannel(OperationId opId)
+dispatch_io_t QRandomAccessAsyncFileNativeBackend::duplicateIoChannel(OperationId opId)
{
if (!m_ioChannel)
return nullptr;
@@ -247,17 +254,18 @@ dispatch_io_t QRandomAccessAsyncFilePrivate::duplicateIoChannel(OperationId opId
if (channel) {
QMutexLocker locker(&m_mutex);
m_runningOps.insert(opId);
+ ++m_numChannelsToClose;
}
return channel;
}
-void QRandomAccessAsyncFilePrivate::closeIoChannel(dispatch_io_t channel)
+void QRandomAccessAsyncFileNativeBackend::closeIoChannel(dispatch_io_t channel)
{
if (channel)
dispatch_io_close(channel, DISPATCH_IO_STOP);
}
-void QRandomAccessAsyncFilePrivate::releaseIoChannel(dispatch_io_t channel)
+void QRandomAccessAsyncFileNativeBackend::releaseIoChannel(dispatch_io_t channel)
{
if (channel) {
dispatch_release(channel);
@@ -265,7 +273,7 @@ void QRandomAccessAsyncFilePrivate::releaseIoChannel(dispatch_io_t channel)
}
}
-void QRandomAccessAsyncFilePrivate::handleOperationComplete(const OperationResult &opResult)
+void QRandomAccessAsyncFileNativeBackend::handleOperationComplete(const OperationResult &opResult)
{
// try to start next operations on return
auto onReturn = qScopeGuard([this] {
@@ -372,15 +380,15 @@ void QRandomAccessAsyncFilePrivate::handleOperationComplete(const OperationResul
}
}
-void QRandomAccessAsyncFilePrivate::queueCompletion(OperationId opId, int error)
+void QRandomAccessAsyncFileNativeBackend::queueCompletion(OperationId opId, int error)
{
const OperationResult res = { opId, 0LL, error };
- QMetaObject::invokeMethod(q_ptr, [this, res] {
+ QMetaObject::invokeMethod(m_owner, [this, res] {
handleOperationComplete(res);
}, Qt::QueuedConnection);
}
-void QRandomAccessAsyncFilePrivate::startOperationsUntilBarrier()
+void QRandomAccessAsyncFileNativeBackend::startOperationsUntilBarrier()
{
// starts all operations until barrier, or a barrier operation if it's the
// first one
@@ -414,7 +422,7 @@ void QRandomAccessAsyncFilePrivate::startOperationsUntilBarrier()
}
}
-void QRandomAccessAsyncFilePrivate::executeRead(OperationInfo &opInfo)
+void QRandomAccessAsyncFileNativeBackend::executeRead(OperationInfo &opInfo)
{
opInfo.channel = duplicateIoChannel(opInfo.opId);
if (!opInfo.channel) {
@@ -445,7 +453,7 @@ void QRandomAccessAsyncFilePrivate::executeRead(OperationInfo &opInfo)
}
}
-void QRandomAccessAsyncFilePrivate::executeWrite(OperationInfo &opInfo)
+void QRandomAccessAsyncFileNativeBackend::executeWrite(OperationInfo &opInfo)
{
opInfo.channel = duplicateIoChannel(opInfo.opId);
if (!opInfo.channel) {
@@ -494,7 +502,7 @@ void QRandomAccessAsyncFilePrivate::executeWrite(OperationInfo &opInfo)
}
}
-void QRandomAccessAsyncFilePrivate::executeFlush(OperationInfo &opInfo)
+void QRandomAccessAsyncFileNativeBackend::executeFlush(OperationInfo &opInfo)
{
opInfo.channel = duplicateIoChannel(opInfo.opId);
if (!opInfo.channel) {
@@ -523,7 +531,7 @@ void QRandomAccessAsyncFilePrivate::executeFlush(OperationInfo &opInfo)
}
}
} else {
- auto context = sharedThis->q_ptr;
+ auto context = sharedThis->m_owner;
const OperationResult res = { opId, 0LL, err };
QMetaObject::invokeMethod(context, [sharedThis](const OperationResult &r) {
sharedThis->handleOperationComplete(r);
@@ -555,7 +563,7 @@ static inline int openModeToOpenFlags(QIODevice::OpenMode mode)
return oflags;
}
-void QRandomAccessAsyncFilePrivate::executeOpen(OperationInfo &opInfo)
+void QRandomAccessAsyncFileNativeBackend::executeOpen(OperationInfo &opInfo)
{
if (m_fileState != FileState::OpenPending) {
queueCompletion(opInfo.opId, EINVAL);
@@ -593,9 +601,10 @@ void QRandomAccessAsyncFilePrivate::executeOpen(OperationInfo &opInfo)
// So we need to notify the condition variable in
// both cases.
Q_ASSERT(sharedThis->m_runningOps.isEmpty());
+ Q_ASSERT(sharedThis->m_numChannelsToClose == 0);
sharedThis->m_cancellationCondition.wakeOne();
} else {
- auto context = sharedThis->q_ptr;
+ auto context = sharedThis->m_owner;
const OperationResult res = { opId, qint64(fd), err };
QMetaObject::invokeMethod(context,
[sharedThis](const OperationResult &r) {
@@ -605,7 +614,7 @@ void QRandomAccessAsyncFilePrivate::executeOpen(OperationInfo &opInfo)
});
}
-void QRandomAccessAsyncFilePrivate::readOneBuffer(OperationId opId, qsizetype bufferIdx,
+void QRandomAccessAsyncFileNativeBackend::readOneBuffer(OperationId opId, qsizetype bufferIdx,
qint64 alreadyRead)
{
// we need to lookup the operation again, because it could have beed removed
@@ -642,7 +651,7 @@ void QRandomAccessAsyncFilePrivate::readOneBuffer(OperationId opId, qsizetype bu
readBuffers.size(), alreadyRead);
}
-void QRandomAccessAsyncFilePrivate::readOneBufferHelper(OperationId opId, dispatch_io_t channel,
+void QRandomAccessAsyncFileNativeBackend::readOneBufferHelper(OperationId opId, dispatch_io_t channel,
qint64 offset, void *bytesPtr,
qint64 maxSize, qsizetype currentBufferIdx,
qsizetype totalBuffers, qint64 alreadyRead)
@@ -690,7 +699,7 @@ void QRandomAccessAsyncFilePrivate::readOneBufferHelper(OperationId opId, dispat
}
} else {
sharedThis->m_runningOps.remove(opId);
- auto context = sharedThis->q_ptr;
+ auto context = sharedThis->m_owner;
// if error, or last buffer, or read less than expected,
// report operation completion
qint64 totalRead = qint64(readFromBuffer) + alreadyRead;
@@ -713,7 +722,7 @@ void QRandomAccessAsyncFilePrivate::readOneBufferHelper(OperationId opId, dispat
});
}
-void QRandomAccessAsyncFilePrivate::writeHelper(OperationId opId, dispatch_io_t channel,
+void QRandomAccessAsyncFileNativeBackend::writeHelper(OperationId opId, dispatch_io_t channel,
qint64 offset, dispatch_data_t dataToWrite,
qint64 dataSize)
{
@@ -752,7 +761,7 @@ void QRandomAccessAsyncFilePrivate::writeHelper(OperationId opId, dispatch_io_t
const size_t written = dataSize - toBeWritten;
[dataToWrite release];
- auto context = sharedThis->q_ptr;
+ auto context = sharedThis->m_owner;
const OperationResult res = { opId, qint64(written), error };
QMetaObject::invokeMethod(context,
[sharedThis](const OperationResult &r) {
@@ -762,7 +771,7 @@ void QRandomAccessAsyncFilePrivate::writeHelper(OperationId opId, dispatch_io_t
});
}
-QRandomAccessAsyncFilePrivate::OperationId QRandomAccessAsyncFilePrivate::getNextId()
+QRandomAccessAsyncFileNativeBackend::OperationId QRandomAccessAsyncFileNativeBackend::getNextId()
{
// never return reserved values
static OperationId opId = kInvalidOperationId;
diff --git a/src/corelib/io/qrandomaccessasyncfile_p_p.h b/src/corelib/io/qrandomaccessasyncfile_p_p.h
index 11ad788c884..2eb53058780 100644
--- a/src/corelib/io/qrandomaccessasyncfile_p_p.h
+++ b/src/corelib/io/qrandomaccessasyncfile_p_p.h
@@ -22,7 +22,7 @@
#include <QtCore/qstring.h>
-#ifdef QT_RANDOMACCESSASYNCFILE_THREAD
+#if QT_CONFIG(future) && QT_CONFIG(thread)
#include <QtCore/private/qfsfileengine_p.h>
@@ -30,7 +30,7 @@
#include <QtCore/qmutex.h>
#include <QtCore/qqueue.h>
-#endif // QT_RANDOMACCESSASYNCFILE_THREAD
+#endif // future && thread
#ifdef Q_OS_DARWIN
@@ -50,41 +50,36 @@
QT_BEGIN_NAMESPACE
-class QRandomAccessAsyncFilePrivate : public QObjectPrivate
+class QRandomAccessAsyncFileBackend
{
- Q_DECLARE_PUBLIC(QRandomAccessAsyncFile)
- Q_DISABLE_COPY_MOVE(QRandomAccessAsyncFilePrivate)
+ Q_DISABLE_COPY_MOVE(QRandomAccessAsyncFileBackend)
public:
- QRandomAccessAsyncFilePrivate();
- ~QRandomAccessAsyncFilePrivate() override;
-
- static QRandomAccessAsyncFilePrivate *get(QRandomAccessAsyncFile *file)
- { return file->d_func(); }
+ explicit QRandomAccessAsyncFileBackend(QRandomAccessAsyncFile *owner);
+ virtual ~QRandomAccessAsyncFileBackend();
- void init();
- void cancelAndWait(QIOOperation *op);
+ virtual bool init() = 0;
+ virtual void cancelAndWait(QIOOperation *op) = 0;
- void close();
- qint64 size() const;
+ virtual void close() = 0;
+ virtual qint64 size() const = 0;
- [[nodiscard]] QIOOperation *open(const QString &path, QIODeviceBase::OpenMode mode);
- [[nodiscard]] QIOOperation *flush();
+ [[nodiscard]] virtual QIOOperation *open(const QString &path, QIODeviceBase::OpenMode mode) = 0;
+ [[nodiscard]] virtual QIOOperation *flush() = 0;
- [[nodiscard]] QIOReadOperation *read(qint64 offset, qint64 maxSize);
- [[nodiscard]] QIOWriteOperation *write(qint64 offset, const QByteArray &data);
- [[nodiscard]] QIOWriteOperation *write(qint64 offset, QByteArray &&data);
+ [[nodiscard]] virtual QIOReadOperation *read(qint64 offset, qint64 maxSize) = 0;
+ [[nodiscard]] virtual QIOWriteOperation *write(qint64 offset, const QByteArray &data) = 0;
+ [[nodiscard]] virtual QIOWriteOperation *write(qint64 offset, QByteArray &&data) = 0;
- [[nodiscard]] QIOVectoredReadOperation *
- readInto(qint64 offset, QSpan<std::byte> buffer);
- [[nodiscard]] QIOVectoredWriteOperation *
- writeFrom(qint64 offset, QSpan<const std::byte> buffer);
-
- [[nodiscard]] QIOVectoredReadOperation *
- readInto(qint64 offset, QSpan<const QSpan<std::byte>> buffers);
- [[nodiscard]] QIOVectoredWriteOperation *
- writeFrom(qint64 offset, QSpan<const QSpan<const std::byte>> buffers);
+ [[nodiscard]] virtual QIOVectoredReadOperation *
+ readInto(qint64 offset, QSpan<std::byte> buffer) = 0;
+ [[nodiscard]] virtual QIOVectoredWriteOperation *
+ writeFrom(qint64 offset, QSpan<const std::byte> buffer) = 0;
-private:
+ [[nodiscard]] virtual QIOVectoredReadOperation *
+ readInto(qint64 offset, QSpan<const QSpan<std::byte>> buffers) = 0;
+ [[nodiscard]] virtual QIOVectoredWriteOperation *
+ writeFrom(qint64 offset, QSpan<const QSpan<const std::byte>> buffers) = 0;
+protected:
// common for all backends
enum class FileState : quint8
{
@@ -94,32 +89,131 @@ private:
};
QString m_filePath;
+ QRandomAccessAsyncFile *m_owner = nullptr;
QIODeviceBase::OpenMode m_openMode;
FileState m_fileState = FileState::Closed;
+};
-#ifdef QT_RANDOMACCESSASYNCFILE_THREAD
+class QRandomAccessAsyncFilePrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QRandomAccessAsyncFile)
+ Q_DISABLE_COPY_MOVE(QRandomAccessAsyncFilePrivate)
public:
- struct OperationResult
+ QRandomAccessAsyncFilePrivate();
+ ~QRandomAccessAsyncFilePrivate() override;
+
+ static QRandomAccessAsyncFilePrivate *get(QRandomAccessAsyncFile *file)
+ { return file->d_func(); }
+
+ void init();
+ void cancelAndWait(QIOOperation *op)
{
- qint64 bytesProcessed; // either read or written
- QIOOperation::Error error;
- };
+ checkValid();
+ m_backend->cancelAndWait(op);
+ }
+
+ void close()
+ {
+ checkValid();
+ m_backend->close();
+ }
+ qint64 size() const
+ {
+ checkValid();
+ return m_backend->size();
+ }
+
+ [[nodiscard]] QIOOperation *open(const QString &path, QIODeviceBase::OpenMode mode)
+ {
+ checkValid();
+ return m_backend->open(path, mode);
+ }
+ [[nodiscard]] QIOOperation *flush()
+ {
+ checkValid();
+ return m_backend->flush();
+ }
+
+ [[nodiscard]] QIOReadOperation *read(qint64 offset, qint64 maxSize)
+ {
+ checkValid();
+ return m_backend->read(offset, maxSize);
+ }
+ [[nodiscard]] QIOWriteOperation *write(qint64 offset, const QByteArray &data)
+ {
+ checkValid();
+ return m_backend->write(offset, data);
+ }
+ [[nodiscard]] QIOWriteOperation *write(qint64 offset, QByteArray &&data)
+ {
+ checkValid();
+ return m_backend->write(offset, std::move(data));
+ }
+
+ [[nodiscard]] QIOVectoredReadOperation *readInto(qint64 offset, QSpan<std::byte> buffer)
+ {
+ checkValid();
+ return m_backend->readInto(offset, buffer);
+ }
+ [[nodiscard]] QIOVectoredWriteOperation *writeFrom(qint64 offset, QSpan<const std::byte> buffer)
+ {
+ checkValid();
+ return m_backend->writeFrom(offset, buffer);
+ }
+
+ [[nodiscard]] QIOVectoredReadOperation *readInto(qint64 offset,
+ QSpan<const QSpan<std::byte>> buffers)
+ {
+ checkValid();
+ return m_backend->readInto(offset, buffers);
+ }
+ [[nodiscard]] QIOVectoredWriteOperation *writeFrom(qint64 offset,
+ QSpan<const QSpan<const std::byte>> buffers)
+ {
+ checkValid();
+ return m_backend->writeFrom(offset, buffers);
+ }
private:
- mutable QBasicMutex m_engineMutex;
- std::unique_ptr<QFSFileEngine> m_engine;
- QFutureWatcher<OperationResult> m_watcher;
+ void checkValid() const { Q_ASSERT(m_backend); }
+ std::unique_ptr<QRandomAccessAsyncFileBackend> m_backend;
- QQueue<QPointer<QIOOperation>> m_operations;
- QPointer<QIOOperation> m_currentOperation;
- qsizetype numProcessedBuffers = 0;
+};
- void executeNextOperation();
- void processBufferAt(qsizetype idx);
- void processFlush();
- void processOpen();
- void operationComplete();
-#elif defined(QT_RANDOMACCESSASYNCFILE_QIORING)
+
+#if defined(QT_RANDOMACCESSASYNCFILE_QIORING) || defined(Q_OS_DARWIN)
+class QRandomAccessAsyncFileNativeBackend final : public QRandomAccessAsyncFileBackend
+{
+ Q_DISABLE_COPY_MOVE(QRandomAccessAsyncFileNativeBackend)
+public:
+ explicit QRandomAccessAsyncFileNativeBackend(QRandomAccessAsyncFile *owner);
+ ~QRandomAccessAsyncFileNativeBackend();
+
+ bool init() override;
+ void cancelAndWait(QIOOperation *op) override;
+
+ void close() override;
+ qint64 size() const override;
+
+ [[nodiscard]] QIOOperation *open(const QString &path, QIODeviceBase::OpenMode mode) override;
+ [[nodiscard]] QIOOperation *flush() override;
+
+ [[nodiscard]] QIOReadOperation *read(qint64 offset, qint64 maxSize) override;
+ [[nodiscard]] QIOWriteOperation *write(qint64 offset, const QByteArray &data) override;
+ [[nodiscard]] QIOWriteOperation *write(qint64 offset, QByteArray &&data) override;
+
+ [[nodiscard]] QIOVectoredReadOperation *
+ readInto(qint64 offset, QSpan<std::byte> buffer) override;
+ [[nodiscard]] QIOVectoredWriteOperation *
+ writeFrom(qint64 offset, QSpan<const std::byte> buffer) override;
+
+ [[nodiscard]] QIOVectoredReadOperation *
+ readInto(qint64 offset, QSpan<const QSpan<std::byte>> buffers) override;
+ [[nodiscard]] QIOVectoredWriteOperation *
+ writeFrom(qint64 offset, QSpan<const QSpan<const std::byte>> buffers) override;
+
+private:
+#if defined(QT_RANDOMACCESSASYNCFILE_QIORING)
void queueCompletion(QIOOperationPrivate *priv, QIOOperation::Error error);
void startReadIntoSingle(QIOOperation *op, const QSpan<std::byte> &to);
void startWriteFromSingle(QIOOperation *op, const QSpan<const std::byte> &from);
@@ -210,6 +304,61 @@ private:
dispatch_data_t dataToWrite, qint64 dataSize);
#endif
};
+#endif // QIORing || macOS
+
+#if QT_CONFIG(future) && QT_CONFIG(thread)
+class QRandomAccessAsyncFileThreadPoolBackend : public QRandomAccessAsyncFileBackend
+{
+ Q_DISABLE_COPY_MOVE(QRandomAccessAsyncFileThreadPoolBackend)
+public:
+ explicit QRandomAccessAsyncFileThreadPoolBackend(QRandomAccessAsyncFile *owner);
+ ~QRandomAccessAsyncFileThreadPoolBackend();
+
+ bool init() override;
+ void cancelAndWait(QIOOperation *op) override;
+
+ void close() override;
+ qint64 size() const override;
+
+ [[nodiscard]] QIOOperation *open(const QString &path, QIODeviceBase::OpenMode mode) override;
+ [[nodiscard]] QIOOperation *flush() override;
+
+ [[nodiscard]] QIOReadOperation *read(qint64 offset, qint64 maxSize) override;
+ [[nodiscard]] QIOWriteOperation *write(qint64 offset, const QByteArray &data) override;
+ [[nodiscard]] QIOWriteOperation *write(qint64 offset, QByteArray &&data) override;
+
+ [[nodiscard]] QIOVectoredReadOperation *
+ readInto(qint64 offset, QSpan<std::byte> buffer) override;
+ [[nodiscard]] QIOVectoredWriteOperation *
+ writeFrom(qint64 offset, QSpan<const std::byte> buffer) override;
+
+ [[nodiscard]] QIOVectoredReadOperation *
+ readInto(qint64 offset, QSpan<const QSpan<std::byte>> buffers) override;
+ [[nodiscard]] QIOVectoredWriteOperation *
+ writeFrom(qint64 offset, QSpan<const QSpan<const std::byte>> buffers) override;
+
+ struct OperationResult
+ {
+ qint64 bytesProcessed; // either read or written
+ QIOOperation::Error error;
+ };
+private:
+
+ mutable QBasicMutex m_engineMutex;
+ std::unique_ptr<QFSFileEngine> m_engine;
+ QFutureWatcher<OperationResult> m_watcher;
+
+ QQueue<QPointer<QIOOperation>> m_operations;
+ QPointer<QIOOperation> m_currentOperation;
+ qsizetype numProcessedBuffers = 0;
+
+ void executeNextOperation();
+ void processBufferAt(qsizetype idx);
+ void processFlush();
+ void processOpen();
+ void operationComplete();
+};
+#endif // future && thread
QT_END_NAMESPACE
diff --git a/src/corelib/io/qrandomaccessasyncfile_qioring.cpp b/src/corelib/io/qrandomaccessasyncfile_qioring.cpp
index c9783ea2856..8e1145325d8 100644
--- a/src/corelib/io/qrandomaccessasyncfile_qioring.cpp
+++ b/src/corelib/io/qrandomaccessasyncfile_qioring.cpp
@@ -18,18 +18,21 @@ QT_BEGIN_NAMESPACE
Q_STATIC_LOGGING_CATEGORY(lcQRandomAccessIORing, "qt.core.qrandomaccessasyncfile.ioring",
QtCriticalMsg);
-QRandomAccessAsyncFilePrivate::QRandomAccessAsyncFilePrivate() = default;
+QRandomAccessAsyncFileNativeBackend::QRandomAccessAsyncFileNativeBackend(QRandomAccessAsyncFile *owner)
+ : QRandomAccessAsyncFileBackend(owner)
+{}
-QRandomAccessAsyncFilePrivate::~QRandomAccessAsyncFilePrivate() = default;
+QRandomAccessAsyncFileNativeBackend::~QRandomAccessAsyncFileNativeBackend() = default;
-void QRandomAccessAsyncFilePrivate::init()
+bool QRandomAccessAsyncFileNativeBackend::init()
{
m_ioring = QIORing::sharedInstance();
if (!m_ioring)
- qCCritical(lcQRandomAccessIORing, "QRandomAccessAsyncFile: ioring failed to initialize");
+ qCWarning(lcQRandomAccessIORing, "QRandomAccessAsyncFile: ioring failed to initialize");
+ return m_ioring != nullptr;
}
-QIORing::RequestHandle QRandomAccessAsyncFilePrivate::cancel(QIORing::RequestHandle handle)
+QIORing::RequestHandle QRandomAccessAsyncFileNativeBackend::cancel(QIORing::RequestHandle handle)
{
if (handle) {
QIORingRequest<QIORing::Operation::Cancel> cancelRequest;
@@ -39,7 +42,7 @@ QIORing::RequestHandle QRandomAccessAsyncFilePrivate::cancel(QIORing::RequestHan
return nullptr;
}
-void QRandomAccessAsyncFilePrivate::cancelAndWait(QIOOperation *op)
+void QRandomAccessAsyncFileNativeBackend::cancelAndWait(QIOOperation *op)
{
auto *opHandle = m_opHandleMap.value(op);
if (auto *handle = cancel(opHandle)) {
@@ -48,7 +51,7 @@ void QRandomAccessAsyncFilePrivate::cancelAndWait(QIOOperation *op)
}
}
-void QRandomAccessAsyncFilePrivate::queueCompletion(QIOOperationPrivate *priv, QIOOperation::Error error)
+void QRandomAccessAsyncFileNativeBackend::queueCompletion(QIOOperationPrivate *priv, QIOOperation::Error error)
{
// Remove the handle now in case the user cancels or deletes the io-operation
// before operationComplete is called - the null-handle will protect from
@@ -61,14 +64,14 @@ void QRandomAccessAsyncFilePrivate::queueCompletion(QIOOperationPrivate *priv, Q
}, Qt::QueuedConnection);
}
-QIOOperation *QRandomAccessAsyncFilePrivate::open(const QString &path, QIODeviceBase::OpenMode mode)
+QIOOperation *QRandomAccessAsyncFileNativeBackend::open(const QString &path, QIODeviceBase::OpenMode mode)
{
auto *dataStorage = new QtPrivate::QIOOperationDataStorage();
auto *priv = new QIOOperationPrivate(dataStorage);
priv->type = QIOOperation::Type::Open;
- auto *op = new QIOOperation(*priv, q_ptr);
+ auto *op = new QIOOperation(*priv, m_owner);
if (m_fileState != FileState::Closed) {
queueCompletion(priv, QIOOperation::Error::Open);
return op;
@@ -115,7 +118,7 @@ QIOOperation *QRandomAccessAsyncFilePrivate::open(const QString &path, QIODevice
return op;
}
-void QRandomAccessAsyncFilePrivate::close()
+void QRandomAccessAsyncFileNativeBackend::close()
{
// all the operations should be aborted
const auto ops = std::exchange(m_operations, {});
@@ -123,7 +126,7 @@ void QRandomAccessAsyncFilePrivate::close()
// Request to cancel all of the in-flight operations:
for (const auto &op : ops) {
if (op) {
- op->d_func()->error = QIOOperation::Error::Aborted;
+ QIOOperationPrivate::get(op)->error = QIOOperation::Error::Aborted;
if (auto *opHandle = m_opHandleMap.value(op)) {
tasksToAwait.append(cancel(opHandle));
tasksToAwait.append(opHandle);
@@ -142,7 +145,7 @@ void QRandomAccessAsyncFilePrivate::close()
m_fd = -1;
}
-qint64 QRandomAccessAsyncFilePrivate::size() const
+qint64 QRandomAccessAsyncFileNativeBackend::size() const
{
QIORingRequest<QIORing::Operation::Stat> statRequest;
statRequest.fd = m_fd;
@@ -161,14 +164,14 @@ qint64 QRandomAccessAsyncFilePrivate::size() const
return finalSize;
}
-QIOOperation *QRandomAccessAsyncFilePrivate::flush()
+QIOOperation *QRandomAccessAsyncFileNativeBackend::flush()
{
auto *dataStorage = new QtPrivate::QIOOperationDataStorage();
auto *priv = new QIOOperationPrivate(dataStorage);
priv->type = QIOOperation::Type::Flush;
- auto *op = new QIOOperation(*priv, q_ptr);
+ auto *op = new QIOOperation(*priv, m_owner);
m_operations.append(op);
QIORingRequest<QIORing::Operation::Flush> flushRequest;
@@ -192,7 +195,7 @@ QIOOperation *QRandomAccessAsyncFilePrivate::flush()
return op;
}
-void QRandomAccessAsyncFilePrivate::startReadIntoSingle(QIOOperation *op,
+void QRandomAccessAsyncFileNativeBackend::startReadIntoSingle(QIOOperation *op,
const QSpan<std::byte> &to)
{
QIORingRequest<QIORing::Operation::Read> readRequest;
@@ -231,7 +234,7 @@ void QRandomAccessAsyncFilePrivate::startReadIntoSingle(QIOOperation *op,
m_opHandleMap.insert(priv->q_func(), m_ioring->queueRequest(std::move(readRequest)));
}
-QIOReadOperation *QRandomAccessAsyncFilePrivate::read(qint64 offset, qint64 maxSize)
+QIOReadOperation *QRandomAccessAsyncFileNativeBackend::read(qint64 offset, qint64 maxSize)
{
QByteArray array;
array.resizeForOverwrite(maxSize);
@@ -241,7 +244,7 @@ QIOReadOperation *QRandomAccessAsyncFilePrivate::read(qint64 offset, qint64 maxS
priv->offset = offset;
priv->type = QIOOperation::Type::Read;
- auto *op = new QIOReadOperation(*priv, q_ptr);
+ auto *op = new QIOReadOperation(*priv, m_owner);
m_operations.append(op);
startReadIntoSingle(op, as_writable_bytes(QSpan(dataStorage->getByteArray())));
@@ -249,12 +252,12 @@ QIOReadOperation *QRandomAccessAsyncFilePrivate::read(qint64 offset, qint64 maxS
return op;
}
-QIOWriteOperation *QRandomAccessAsyncFilePrivate::write(qint64 offset, const QByteArray &data)
+QIOWriteOperation *QRandomAccessAsyncFileNativeBackend::write(qint64 offset, const QByteArray &data)
{
return write(offset, QByteArray(data));
}
-void QRandomAccessAsyncFilePrivate::startWriteFromSingle(QIOOperation *op,
+void QRandomAccessAsyncFileNativeBackend::startWriteFromSingle(QIOOperation *op,
const QSpan<const std::byte> &from)
{
QIORingRequest<QIORing::Operation::Write> writeRequest;
@@ -288,7 +291,7 @@ void QRandomAccessAsyncFilePrivate::startWriteFromSingle(QIOOperation *op,
m_opHandleMap.insert(priv->q_func(), m_ioring->queueRequest(std::move(writeRequest)));
}
-QIOWriteOperation *QRandomAccessAsyncFilePrivate::write(qint64 offset, QByteArray &&data)
+QIOWriteOperation *QRandomAccessAsyncFileNativeBackend::write(qint64 offset, QByteArray &&data)
{
auto *dataStorage = new QtPrivate::QIOOperationDataStorage(std::move(data));
@@ -296,7 +299,7 @@ QIOWriteOperation *QRandomAccessAsyncFilePrivate::write(qint64 offset, QByteArra
priv->offset = offset;
priv->type = QIOOperation::Type::Write;
- auto *op = new QIOWriteOperation(*priv, q_ptr);
+ auto *op = new QIOWriteOperation(*priv, m_owner);
m_operations.append(op);
startWriteFromSingle(op, as_bytes(QSpan(dataStorage->getByteArray())));
@@ -304,7 +307,7 @@ QIOWriteOperation *QRandomAccessAsyncFilePrivate::write(qint64 offset, QByteArra
return op;
}
-QIOVectoredReadOperation *QRandomAccessAsyncFilePrivate::readInto(qint64 offset,
+QIOVectoredReadOperation *QRandomAccessAsyncFileNativeBackend::readInto(qint64 offset,
QSpan<std::byte> buffer)
{
auto *dataStorage = new QtPrivate::QIOOperationDataStorage(
@@ -314,7 +317,7 @@ QIOVectoredReadOperation *QRandomAccessAsyncFilePrivate::readInto(qint64 offset,
priv->offset = offset;
priv->type = QIOOperation::Type::Read;
- auto *op = new QIOVectoredReadOperation(*priv, q_ptr);
+ auto *op = new QIOVectoredReadOperation(*priv, m_owner);
m_operations.append(op);
startReadIntoSingle(op, dataStorage->getReadSpans().first());
@@ -322,7 +325,7 @@ QIOVectoredReadOperation *QRandomAccessAsyncFilePrivate::readInto(qint64 offset,
return op;
}
-QIOVectoredWriteOperation *QRandomAccessAsyncFilePrivate::writeFrom(qint64 offset,
+QIOVectoredWriteOperation *QRandomAccessAsyncFileNativeBackend::writeFrom(qint64 offset,
QSpan<const std::byte> buffer)
{
auto *dataStorage = new QtPrivate::QIOOperationDataStorage(
@@ -332,7 +335,7 @@ QIOVectoredWriteOperation *QRandomAccessAsyncFilePrivate::writeFrom(qint64 offse
priv->offset = offset;
priv->type = QIOOperation::Type::Write;
- auto *op = new QIOVectoredWriteOperation(*priv, q_ptr);
+ auto *op = new QIOVectoredWriteOperation(*priv, m_owner);
m_operations.append(op);
startWriteFromSingle(op, dataStorage->getWriteSpans().first());
@@ -341,7 +344,7 @@ QIOVectoredWriteOperation *QRandomAccessAsyncFilePrivate::writeFrom(qint64 offse
}
QIOVectoredReadOperation *
-QRandomAccessAsyncFilePrivate::readInto(qint64 offset, QSpan<const QSpan<std::byte>> buffers)
+QRandomAccessAsyncFileNativeBackend::readInto(qint64 offset, QSpan<const QSpan<std::byte>> buffers)
{
if (!QIORing::supportsOperation(QtPrivate::Operation::VectoredRead))
return nullptr;
@@ -351,7 +354,7 @@ QRandomAccessAsyncFilePrivate::readInto(qint64 offset, QSpan<const QSpan<std::by
priv->offset = offset;
priv->type = QIOOperation::Type::Read;
- auto *op = new QIOVectoredReadOperation(*priv, q_ptr);
+ auto *op = new QIOVectoredReadOperation(*priv, m_owner);
if (priv->offset < 0) { // The QIORing offset is unsigned, so error out now
queueCompletion(priv, QIOOperation::Error::IncorrectOffset);
return op;
@@ -393,7 +396,7 @@ QRandomAccessAsyncFilePrivate::readInto(qint64 offset, QSpan<const QSpan<std::by
}
QIOVectoredWriteOperation *
-QRandomAccessAsyncFilePrivate::writeFrom(qint64 offset, QSpan<const QSpan<const std::byte>> buffers)
+QRandomAccessAsyncFileNativeBackend::writeFrom(qint64 offset, QSpan<const QSpan<const std::byte>> buffers)
{
if (!QIORing::supportsOperation(QtPrivate::Operation::VectoredWrite))
return nullptr;
@@ -403,7 +406,7 @@ QRandomAccessAsyncFilePrivate::writeFrom(qint64 offset, QSpan<const QSpan<const
priv->offset = offset;
priv->type = QIOOperation::Type::Write;
- auto *op = new QIOVectoredWriteOperation(*priv, q_ptr);
+ auto *op = new QIOVectoredWriteOperation(*priv, m_owner);
if (priv->offset < 0) { // The QIORing offset is unsigned, so error out now
queueCompletion(priv, QIOOperation::Error::IncorrectOffset);
return op;
diff --git a/src/corelib/io/qrandomaccessasyncfile_threadpool.cpp b/src/corelib/io/qrandomaccessasyncfile_threadpool.cpp
index 4ebcf554655..774fbadc5ad 100644
--- a/src/corelib/io/qrandomaccessasyncfile_threadpool.cpp
+++ b/src/corelib/io/qrandomaccessasyncfile_threadpool.cpp
@@ -64,28 +64,29 @@ static SharedThreadPool asyncFileThreadPool;
} // anonymous namespace
-QRandomAccessAsyncFilePrivate::QRandomAccessAsyncFilePrivate() :
- QObjectPrivate()
+QRandomAccessAsyncFileThreadPoolBackend::QRandomAccessAsyncFileThreadPoolBackend(QRandomAccessAsyncFile *owner) :
+ QRandomAccessAsyncFileBackend(owner)
{
asyncFileThreadPool.ref();
}
-QRandomAccessAsyncFilePrivate::~QRandomAccessAsyncFilePrivate()
+QRandomAccessAsyncFileThreadPoolBackend::~QRandomAccessAsyncFileThreadPoolBackend()
{
asyncFileThreadPool.deref();
}
-void QRandomAccessAsyncFilePrivate::init()
+bool QRandomAccessAsyncFileThreadPoolBackend::init()
{
- QObject::connect(&m_watcher, &QFutureWatcherBase::finished, q_ptr, [this]{
+ QObject::connect(&m_watcher, &QFutureWatcherBase::finished, m_owner, [this]{
operationComplete();
});
- QObject::connect(&m_watcher, &QFutureWatcherBase::canceled, q_ptr, [this]{
+ QObject::connect(&m_watcher, &QFutureWatcherBase::canceled, m_owner, [this]{
operationComplete();
});
+ return true;
}
-void QRandomAccessAsyncFilePrivate::cancelAndWait(QIOOperation *op)
+void QRandomAccessAsyncFileThreadPoolBackend::cancelAndWait(QIOOperation *op)
{
if (op == m_currentOperation) {
m_currentOperation = nullptr; // to discard the result
@@ -97,7 +98,7 @@ void QRandomAccessAsyncFilePrivate::cancelAndWait(QIOOperation *op)
}
QIOOperation *
-QRandomAccessAsyncFilePrivate::open(const QString &path, QIODeviceBase::OpenMode mode)
+QRandomAccessAsyncFileThreadPoolBackend::open(const QString &path, QIODeviceBase::OpenMode mode)
{
// We generate the command in any case. But if the file is already opened,
// it will finish with an error
@@ -112,14 +113,14 @@ QRandomAccessAsyncFilePrivate::open(const QString &path, QIODeviceBase::OpenMode
auto *priv = new QIOOperationPrivate(dataStorage);
priv->type = QIOOperation::Type::Open;
- auto *op = new QIOOperation(*priv, q_ptr);
+ auto *op = new QIOOperation(*priv, m_owner);
m_operations.append(op);
executeNextOperation();
return op;
}
-void QRandomAccessAsyncFilePrivate::close()
+void QRandomAccessAsyncFileThreadPoolBackend::close()
{
// all the operations should be aborted
for (const auto &op : std::as_const(m_operations)) {
@@ -148,7 +149,7 @@ void QRandomAccessAsyncFilePrivate::close()
m_fileState = FileState::Closed;
}
-qint64 QRandomAccessAsyncFilePrivate::size() const
+qint64 QRandomAccessAsyncFileThreadPoolBackend::size() const
{
QMutexLocker locker(&m_engineMutex);
if (m_engine)
@@ -156,20 +157,20 @@ qint64 QRandomAccessAsyncFilePrivate::size() const
return -1;
}
-QIOOperation *QRandomAccessAsyncFilePrivate::flush()
+QIOOperation *QRandomAccessAsyncFileThreadPoolBackend::flush()
{
auto *dataStorage = new QtPrivate::QIOOperationDataStorage();
auto *priv = new QIOOperationPrivate(dataStorage);
priv->type = QIOOperation::Type::Flush;
- auto *op = new QIOOperation(*priv, q_ptr);
+ auto *op = new QIOOperation(*priv, m_owner);
m_operations.append(op);
executeNextOperation();
return op;
}
-QIOReadOperation *QRandomAccessAsyncFilePrivate::read(qint64 offset, qint64 maxSize)
+QIOReadOperation *QRandomAccessAsyncFileThreadPoolBackend::read(qint64 offset, qint64 maxSize)
{
QByteArray array;
array.resizeForOverwrite(maxSize);
@@ -179,14 +180,14 @@ QIOReadOperation *QRandomAccessAsyncFilePrivate::read(qint64 offset, qint64 maxS
priv->offset = offset;
priv->type = QIOOperation::Type::Read;
- auto *op = new QIOReadOperation(*priv, q_ptr);
+ auto *op = new QIOReadOperation(*priv, m_owner);
m_operations.append(op);
executeNextOperation();
return op;
}
QIOWriteOperation *
-QRandomAccessAsyncFilePrivate::write(qint64 offset, const QByteArray &data)
+QRandomAccessAsyncFileThreadPoolBackend::write(qint64 offset, const QByteArray &data)
{
auto *dataStorage = new QtPrivate::QIOOperationDataStorage(data);
@@ -194,14 +195,14 @@ QRandomAccessAsyncFilePrivate::write(qint64 offset, const QByteArray &data)
priv->offset = offset;
priv->type = QIOOperation::Type::Write;
- auto *op = new QIOWriteOperation(*priv, q_ptr);
+ auto *op = new QIOWriteOperation(*priv, m_owner);
m_operations.append(op);
executeNextOperation();
return op;
}
QIOWriteOperation *
-QRandomAccessAsyncFilePrivate::write(qint64 offset, QByteArray &&data)
+QRandomAccessAsyncFileThreadPoolBackend::write(qint64 offset, QByteArray &&data)
{
auto *dataStorage = new QtPrivate::QIOOperationDataStorage(std::move(data));
@@ -209,14 +210,14 @@ QRandomAccessAsyncFilePrivate::write(qint64 offset, QByteArray &&data)
priv->offset = offset;
priv->type = QIOOperation::Type::Write;
- auto *op = new QIOWriteOperation(*priv, q_ptr);
+ auto *op = new QIOWriteOperation(*priv, m_owner);
m_operations.append(op);
executeNextOperation();
return op;
}
QIOVectoredReadOperation *
-QRandomAccessAsyncFilePrivate::readInto(qint64 offset, QSpan<std::byte> buffer)
+QRandomAccessAsyncFileThreadPoolBackend::readInto(qint64 offset, QSpan<std::byte> buffer)
{
auto *dataStorage =
new QtPrivate::QIOOperationDataStorage(QSpan<const QSpan<std::byte>>{buffer});
@@ -225,14 +226,14 @@ QRandomAccessAsyncFilePrivate::readInto(qint64 offset, QSpan<std::byte> buffer)
priv->offset = offset;
priv->type = QIOOperation::Type::Read;
- auto *op = new QIOVectoredReadOperation(*priv, q_ptr);
+ auto *op = new QIOVectoredReadOperation(*priv, m_owner);
m_operations.append(op);
executeNextOperation();
return op;
}
QIOVectoredWriteOperation *
-QRandomAccessAsyncFilePrivate::writeFrom(qint64 offset, QSpan<const std::byte> buffer)
+QRandomAccessAsyncFileThreadPoolBackend::writeFrom(qint64 offset, QSpan<const std::byte> buffer)
{
auto *dataStorage =
new QtPrivate::QIOOperationDataStorage(QSpan<const QSpan<const std::byte>>{buffer});
@@ -241,14 +242,14 @@ QRandomAccessAsyncFilePrivate::writeFrom(qint64 offset, QSpan<const std::byte> b
priv->offset = offset;
priv->type = QIOOperation::Type::Write;
- auto *op = new QIOVectoredWriteOperation(*priv, q_ptr);
+ auto *op = new QIOVectoredWriteOperation(*priv, m_owner);
m_operations.append(op);
executeNextOperation();
return op;
}
QIOVectoredReadOperation *
-QRandomAccessAsyncFilePrivate::readInto(qint64 offset, QSpan<const QSpan<std::byte>> buffers)
+QRandomAccessAsyncFileThreadPoolBackend::readInto(qint64 offset, QSpan<const QSpan<std::byte>> buffers)
{
auto *dataStorage = new QtPrivate::QIOOperationDataStorage(buffers);
@@ -256,14 +257,14 @@ QRandomAccessAsyncFilePrivate::readInto(qint64 offset, QSpan<const QSpan<std::by
priv->offset = offset;
priv->type = QIOOperation::Type::Read;
- auto *op = new QIOVectoredReadOperation(*priv, q_ptr);
+ auto *op = new QIOVectoredReadOperation(*priv, m_owner);
m_operations.append(op);
executeNextOperation();
return op;
}
QIOVectoredWriteOperation *
-QRandomAccessAsyncFilePrivate::writeFrom(qint64 offset, QSpan<const QSpan<const std::byte>> buffers)
+QRandomAccessAsyncFileThreadPoolBackend::writeFrom(qint64 offset, QSpan<const QSpan<const std::byte>> buffers)
{
auto *dataStorage = new QtPrivate::QIOOperationDataStorage(buffers);
@@ -271,16 +272,16 @@ QRandomAccessAsyncFilePrivate::writeFrom(qint64 offset, QSpan<const QSpan<const
priv->offset = offset;
priv->type = QIOOperation::Type::Write;
- auto *op = new QIOVectoredWriteOperation(*priv, q_ptr);
+ auto *op = new QIOVectoredWriteOperation(*priv, m_owner);
m_operations.append(op);
executeNextOperation();
return op;
}
-static QRandomAccessAsyncFilePrivate::OperationResult
+static QRandomAccessAsyncFileThreadPoolBackend::OperationResult
executeRead(QFSFileEngine *engine, QBasicMutex *mutex, qint64 offset, char *buffer, qint64 maxSize)
{
- QRandomAccessAsyncFilePrivate::OperationResult result{0, QIOOperation::Error::None};
+ QRandomAccessAsyncFileThreadPoolBackend::OperationResult result{0, QIOOperation::Error::None};
QMutexLocker locker(mutex);
if (engine) {
@@ -299,11 +300,11 @@ executeRead(QFSFileEngine *engine, QBasicMutex *mutex, qint64 offset, char *buff
return result;
}
-static QRandomAccessAsyncFilePrivate::OperationResult
+static QRandomAccessAsyncFileThreadPoolBackend::OperationResult
executeWrite(QFSFileEngine *engine, QBasicMutex *mutex, qint64 offset,
const char *buffer, qint64 size)
{
- QRandomAccessAsyncFilePrivate::OperationResult result{0, QIOOperation::Error::None};
+ QRandomAccessAsyncFileThreadPoolBackend::OperationResult result{0, QIOOperation::Error::None};
QMutexLocker locker(mutex);
if (engine) {
@@ -322,7 +323,7 @@ executeWrite(QFSFileEngine *engine, QBasicMutex *mutex, qint64 offset,
return result;
}
-void QRandomAccessAsyncFilePrivate::executeNextOperation()
+void QRandomAccessAsyncFileThreadPoolBackend::executeNextOperation()
{
if (m_currentOperation.isNull()) {
// start next
@@ -351,7 +352,7 @@ void QRandomAccessAsyncFilePrivate::executeNextOperation()
}
}
-void QRandomAccessAsyncFilePrivate::processBufferAt(qsizetype idx)
+void QRandomAccessAsyncFileThreadPoolBackend::processBufferAt(qsizetype idx)
{
Q_ASSERT(!m_currentOperation.isNull());
auto *priv = QIOOperationPrivate::get(m_currentOperation.get());
@@ -417,7 +418,7 @@ void QRandomAccessAsyncFilePrivate::processBufferAt(qsizetype idx)
}
}
-void QRandomAccessAsyncFilePrivate::processFlush()
+void QRandomAccessAsyncFileThreadPoolBackend::processFlush()
{
Q_ASSERT(!m_currentOperation.isNull());
auto *priv = QIOOperationPrivate::get(m_currentOperation.get());
@@ -427,7 +428,7 @@ void QRandomAccessAsyncFilePrivate::processFlush()
QBasicMutex *mutexPtr = &m_engineMutex;
auto op = [engine = m_engine.get(), mutexPtr] {
QMutexLocker locker(mutexPtr);
- QRandomAccessAsyncFilePrivate::OperationResult result{0, QIOOperation::Error::None};
+ QRandomAccessAsyncFileThreadPoolBackend::OperationResult result{0, QIOOperation::Error::None};
if (engine) {
if (!engine->flush())
result.error = QIOOperation::Error::Flush;
@@ -442,7 +443,7 @@ void QRandomAccessAsyncFilePrivate::processFlush()
m_watcher.setFuture(f);
}
-void QRandomAccessAsyncFilePrivate::processOpen()
+void QRandomAccessAsyncFileThreadPoolBackend::processOpen()
{
Q_ASSERT(!m_currentOperation.isNull());
auto *priv = QIOOperationPrivate::get(m_currentOperation.get());
@@ -457,7 +458,7 @@ void QRandomAccessAsyncFilePrivate::processOpen()
m_engineMutex.unlock();
QBasicMutex *mutexPtr = &m_engineMutex;
auto op = [engine = m_engine.get(), mutexPtr, mode = m_openMode] {
- QRandomAccessAsyncFilePrivate::OperationResult result{0, QIOOperation::Error::None};
+ QRandomAccessAsyncFileThreadPoolBackend::OperationResult result{0, QIOOperation::Error::None};
QMutexLocker locker(mutexPtr);
const bool res =
engine && engine->open(mode | QIODeviceBase::Unbuffered, std::nullopt);
@@ -468,13 +469,13 @@ void QRandomAccessAsyncFilePrivate::processOpen()
f = QtFuture::makeReadyVoidFuture().then(asyncFileThreadPool(), op);
} else {
f = QtFuture::makeReadyVoidFuture().then(asyncFileThreadPool(), [] {
- return QRandomAccessAsyncFilePrivate::OperationResult{0, QIOOperation::Error::Open};
+ return QRandomAccessAsyncFileThreadPoolBackend::OperationResult{0, QIOOperation::Error::Open};
});
}
m_watcher.setFuture(f);
}
-void QRandomAccessAsyncFilePrivate::operationComplete()
+void QRandomAccessAsyncFileThreadPoolBackend::operationComplete()
{
// TODO: if one of the buffers was read/written with an error,
// stop processing immediately
diff --git a/src/corelib/io/qwindowspipereader.cpp b/src/corelib/io/qwindowspipereader.cpp
index 456a209af37..6edf4395887 100644
--- a/src/corelib/io/qwindowspipereader.cpp
+++ b/src/corelib/io/qwindowspipereader.cpp
@@ -14,6 +14,11 @@ using namespace Qt::StringLiterals;
static const DWORD minReadBufferSize = 4096;
+/*!
+ \class QWindowsPipeReader
+ \inmodule QtCore
+ \internal
+*/
QWindowsPipeReader::QWindowsPipeReader(QObject *parent)
: QObject(parent),
handle(INVALID_HANDLE_VALUE),
diff --git a/src/corelib/itemmodels/qrangemodel_impl.h b/src/corelib/itemmodels/qrangemodel_impl.h
index f6b08099fe7..7eca3094a66 100644
--- a/src/corelib/itemmodels/qrangemodel_impl.h
+++ b/src/corelib/itemmodels/qrangemodel_impl.h
@@ -239,17 +239,15 @@ namespace QRangeModelDetails
: std::true_type
{};
- // we use std::rotate in moveRows/Columns, which requires std::swap and the
- // iterators to be at least a forward iterator
- template <typename It, typename = void>
- struct test_rotate : std::false_type {};
-
+ // we use std::rotate in moveRows/Columns, which requires the values (which
+ // might be const if we only get a const iterator) to be swappable, and the
+ // iterator type to be at least a forward iterator
template <typename It>
- struct test_rotate<It, std::void_t<decltype(std::swap(*std::declval<It>(),
- *std::declval<It>()))>>
- : std::is_base_of<std::forward_iterator_tag,
- typename std::iterator_traits<It>::iterator_category>
- {};
+ using test_rotate = std::conjunction<
+ std::is_swappable<decltype(*std::declval<It>())>,
+ std::is_base_of<std::forward_iterator_tag,
+ typename std::iterator_traits<It>::iterator_category>
+ >;
template <typename C, typename = void>
struct test_splice : std::false_type {};
diff --git a/src/corelib/itemmodels/qrangemodeladapter.h b/src/corelib/itemmodels/qrangemodeladapter.h
index bd3342e6185..0234c402248 100644
--- a/src/corelib/itemmodels/qrangemodeladapter.h
+++ b/src/corelib/itemmodels/qrangemodeladapter.h
@@ -19,13 +19,11 @@ class QT_TECH_PREVIEW_API QRangeModelAdapter
#ifdef Q_QDOC
using range_type = Range;
- using const_row_reference = typename std::iterator_traits<Range>::const_reference;
- using row_reference = typename std::iterator_traits<Range>::reference;
#else
using range_type = QRangeModelDetails::wrapped_t<Range>;
+#endif
using const_row_reference = typename Impl::const_row_reference;
using row_reference = typename Impl::row_reference;
-#endif
using range_features = typename QRangeModelDetails::range_traits<range_type>;
using row_type = std::remove_reference_t<row_reference>;
using row_features = QRangeModelDetails::range_traits<typename Impl::wrapped_row_type>;
@@ -78,16 +76,22 @@ class QT_TECH_PREVIEW_API QRangeModelAdapter
template <typename C>
using if_compatible_row_range = std::enable_if_t<is_compatible_row_range<C>, bool>;
template <typename Data>
- static constexpr bool is_compatible_data = true;
- // std::is_convertible_v<Data, decltype(*std::begin(std::declval<const_row_reference>()))>;
+ static constexpr bool is_compatible_data = std::is_convertible_v<Data, data_type>;
template <typename Data>
using if_compatible_data = std::enable_if_t<is_compatible_data<Data>, bool>;
template <typename C>
static constexpr bool is_compatible_data_range = is_compatible_data<
+ typename QRangeModelDetails::data_type<
+ typename QRangeModelDetails::row_traits<
decltype(*std::begin(std::declval<C&>()))
- >;
+ >::item_type
+ >::type
+ >;
template <typename C>
- using if_compatible_data_range = std::enable_if_t<is_compatible_data_range<C>, bool>;
+ using if_compatible_column_data = std::enable_if_t<is_compatible_data<C>
+ || is_compatible_data_range<C>, bool>;
+ template <typename C>
+ using if_compatible_column_range = std::enable_if_t<is_compatible_data_range<C>, bool>;
template <typename R>
using if_assignable_range = std::enable_if_t<std::is_assignable_v<range_type, R>, bool>;
@@ -141,6 +145,7 @@ public:
}
DataReference(const DataReference &other) = default;
+ DataReference(DataReference &&other) = default;
// reference (not std::reference_wrapper) semantics
DataReference &operator=(const DataReference &other)
@@ -149,29 +154,23 @@ public:
return *this;
}
+ DataReference &operator=(DataReference &&other)
+ {
+ *this = other.get();
+ return *this;
+ }
+
~DataReference() = default;
DataReference &operator=(const value_type &value)
{
- constexpr Qt::ItemDataRole dataRole = Qt::RangeModelAdapterRole;
+ assign(value);
+ return *this;
+ }
- if (m_index.isValid()) {
- auto model = const_cast<QAbstractItemModel *>(m_index.model());
- [[maybe_unused]] bool couldWrite = false;
- if constexpr (std::is_same_v<q20::remove_cvref_t<value_type>, QVariant>)
- couldWrite = model->setData(m_index, value, dataRole);
- else
- couldWrite = model->setData(m_index, QVariant::fromValue(value), dataRole);
-#ifndef QT_NO_DEBUG
- if (!couldWrite) {
- qWarning() << "Writing value of type" << QMetaType::fromType<value_type>().name()
- << "to role" << dataRole << "at index" << m_index
- << "of the model failed";
- }
- } else {
- qCritical("Data reference for invalid index, can't write to model");
-#endif
- }
+ DataReference &operator=(value_type &&value)
+ {
+ assign(std::move(value));
return *this;
}
@@ -196,6 +195,33 @@ public:
private:
QModelIndex m_index;
+ template <typename Value>
+ void assign(Value &&value)
+ {
+ constexpr Qt::ItemDataRole dataRole = Qt::RangeModelAdapterRole;
+
+ if (m_index.isValid()) {
+ auto model = const_cast<QAbstractItemModel *>(m_index.model());
+ [[maybe_unused]] bool couldWrite = false;
+ if constexpr (std::is_same_v<q20::remove_cvref_t<Value>, QVariant>) {
+ couldWrite = model->setData(m_index, value, dataRole);
+ } else {
+ couldWrite = model->setData(m_index,
+ QVariant::fromValue(std::forward<Value>(value)),
+ dataRole);
+ }
+#ifndef QT_NO_DEBUG
+ if (!couldWrite) {
+ qWarning() << "Writing value of type"
+ << QMetaType::fromType<q20::remove_cvref_t<Value>>().name()
+ << "to role" << dataRole << "at index" << m_index << "failed";
+ }
+ } else {
+ qCritical("Data reference for invalid index, can't write to model");
+#endif
+ }
+ }
+
friend inline bool comparesEqual(const DataReference &lhs, const DataReference &rhs)
{
return lhs.m_index == rhs.m_index
@@ -1020,60 +1046,55 @@ public:
template <typename NewRange = range_type, if_assignable_range<NewRange> = true>
void setRange(NewRange &&newRange)
{
- using namespace QRangeModelDetails;
-
- auto *impl = storage.implementation();
- const QModelIndex root = storage.root();
- const qsizetype newLastRow = qsizetype(Impl::size(refTo(newRange))) - 1;
- auto *oldRange = impl->childRange(root);
- const qsizetype oldLastRow = qsizetype(Impl::size(oldRange)) - 1;
-
- if (!root.isValid()) {
- impl->beginResetModel();
- impl->deleteOwnedRows();
- } else if constexpr (is_tree<Impl>) {
- if (oldLastRow > 0) {
- impl->beginRemoveRows(root, 0, model()->rowCount(root) - 1);
- impl->deleteRemovedRows(refTo(oldRange));
- impl->endRemoveRows();
- }
- if (newLastRow > 0)
- impl->beginInsertRows(root, 0, newLastRow);
- } else {
- Q_ASSERT_X(false, "QRangeModelAdapter::setRange",
- "Internal error: The root index in a table or list must be invalid.");
- }
- refTo(oldRange) = std::forward<NewRange>(newRange);
- if (!root.isValid()) {
- impl->endResetModel();
- } else if constexpr (is_tree<Impl>) {
- if (newLastRow > 0) {
- Q_ASSERT(model()->hasChildren(root));
- // if it was moved, then newRange is now likely to be empty. Get
- // the inserted row.
- impl->setParentRow(refTo(impl->childRange(storage.root())),
- pointerTo(impl->rowData(root)));
- impl->endInsertRows();
- }
- }
- if constexpr (Impl::itemsAreQObjects) {
- if (model()->autoConnectPolicy() == QRangeModel::AutoConnectPolicy::Full) {
- const auto begin = QRangeModelDetails::begin(refTo(oldRange));
- const auto end = QRangeModelDetails::end(refTo(oldRange));
- int rowIndex = 0;
- for (auto it = begin; it != end; ++it, ++rowIndex)
- impl->autoConnectPropertiesInRow(*it, rowIndex, root);
- }
- }
+ setRangeImpl(qsizetype(Impl::size(QRangeModelDetails::refTo(newRange))) - 1,
+ [&newRange](auto &oldRange) {
+ oldRange = std::forward<NewRange>(newRange);
+ });
}
- template <typename NewRange = range_type, if_assignable_range<NewRange> = true>
+ template <typename NewRange = range_type, if_assignable_range<NewRange> = true,
+ unless_adapter<NewRange> = true>
QRangeModelAdapter &operator=(NewRange &&newRange)
{
setRange(std::forward<NewRange>(newRange));
return *this;
}
+ template <typename Row, if_assignable_range<std::initializer_list<Row>> = true>
+ void setRange(std::initializer_list<Row> newRange)
+ {
+ setRangeImpl(qsizetype(newRange.size() - 1), [&newRange](auto &oldRange) {
+ oldRange = newRange;
+ });
+ }
+
+ template <typename Row, if_assignable_range<std::initializer_list<Row>> = true>
+ QRangeModelAdapter &operator=(std::initializer_list<Row> newRange)
+ {
+ setRange(newRange);
+ return *this;
+ }
+
+ template <typename Row, if_assignable_range<std::initializer_list<Row>> = true>
+ void assign(std::initializer_list<Row> newRange)
+ {
+ setRange(newRange);
+ }
+
+ template <typename InputIterator, typename Sentinel, typename I = Impl, if_writable<I> = true>
+ void setRange(InputIterator first, Sentinel last)
+ {
+ setRangeImpl(qsizetype(std::distance(first, last) - 1), [first, last](auto &oldRange) {
+ oldRange.assign(first, last);
+ });
+ }
+
+ template <typename InputIterator, typename Sentinel, typename I = Impl, if_writable<I> = true>
+ void assign(InputIterator first, Sentinel last)
+ {
+ setRange(first, last);
+ }
+
// iterator API
ConstRowIterator cbegin() const
{
@@ -1245,12 +1266,12 @@ public:
decltype(auto) operator[](int row) const { return at(row); }
template <typename I = Impl, if_table<I> = true, if_writable<I> = true>
- decltype(auto) at(int row)
+ auto at(int row)
{
return RowReference{index(row, 0), this};
}
template <typename I = Impl, if_table<I> = true, if_writable<I> = true>
- decltype(auto) operator[](int row) { return at(row); }
+ auto operator[](int row) { return at(row); }
// at/operator[int, int] for table: returns value at row/column
template <typename I = Impl, unless_list<I> = true>
@@ -1428,15 +1449,15 @@ public:
return storage.m_model->insertColumn(before);
}
- template <typename D = row_type, typename I = Impl,
- if_canInsertColumns<I> = true, if_compatible_data<D> = true>
+ template <typename D, typename I = Impl,
+ if_canInsertColumns<I> = true, if_compatible_column_data<D> = true>
bool insertColumn(int before, D &&data)
{
return insertColumnImpl(before, storage.root(), std::forward<D>(data));
}
template <typename C, typename I = Impl,
- if_canInsertColumns<I> = true, if_compatible_data_range<C> = true>
+ if_canInsertColumns<I> = true, if_compatible_column_range<C> = true>
bool insertColumns(int before, C &&data)
{
return insertColumnsImpl(before, storage.root(), std::forward<C>(data));
@@ -1503,6 +1524,65 @@ private:
Q_EMIT storage.implementation()->dataChanged(topLeft, bottomRight, {});
}
+ void beginSetRangeImpl(Impl *impl, range_type *oldRange, qsizetype newLastRow)
+ {
+ const QModelIndex root = storage.root();
+ const qsizetype oldLastRow = qsizetype(Impl::size(oldRange)) - 1;
+
+ if (!root.isValid()) {
+ impl->beginResetModel();
+ impl->deleteOwnedRows();
+ } else if constexpr (is_tree<Impl>) {
+ if (oldLastRow > 0) {
+ impl->beginRemoveRows(root, 0, model()->rowCount(root) - 1);
+ impl->deleteRemovedRows(QRangeModelDetails::refTo(oldRange));
+ impl->endRemoveRows();
+ }
+ if (newLastRow > 0)
+ impl->beginInsertRows(root, 0, newLastRow);
+ } else {
+ Q_ASSERT_X(false, "QRangeModelAdapter::setRange",
+ "Internal error: The root index in a table or list must be invalid.");
+ }
+ }
+
+ void endSetRangeImpl(Impl *impl, qsizetype newLastRow)
+ {
+ const QModelIndex root = storage.root();
+ if (!root.isValid()) {
+ impl->endResetModel();
+ } else if constexpr (is_tree<Impl>) {
+ if (newLastRow > 0) {
+ Q_ASSERT(model()->hasChildren(root));
+ // if it was moved, then newRange is now likely to be empty. Get
+ // the inserted row.
+ impl->setParentRow(QRangeModelDetails::refTo(impl->childRange(root)),
+ QRangeModelDetails::pointerTo(impl->rowData(root)));
+ impl->endInsertRows();
+ }
+ }
+ }
+
+ template <typename Assigner>
+ void setRangeImpl(qsizetype newLastRow, Assigner &&assigner)
+ {
+ auto *impl = storage.implementation();
+ auto *oldRange = impl->childRange(storage.root());
+ beginSetRangeImpl(impl, oldRange, newLastRow);
+ assigner(QRangeModelDetails::refTo(oldRange));
+ endSetRangeImpl(impl, newLastRow);
+
+ if constexpr (Impl::itemsAreQObjects) {
+ if (model()->autoConnectPolicy() == QRangeModel::AutoConnectPolicy::Full) {
+ const auto begin = QRangeModelDetails::begin(QRangeModelDetails::refTo(oldRange));
+ const auto end = QRangeModelDetails::end(QRangeModelDetails::refTo(oldRange));
+ int rowIndex = 0;
+ for (auto it = begin; it != end; ++it, ++rowIndex)
+ impl->autoConnectPropertiesInRow(*it, rowIndex, storage.root());
+ }
+ }
+ }
+
template <typename P>
static auto setParentRow(P protocol, row_type &newRow, row_ptr parentRow)
-> decltype(protocol.setParentRow(std::declval<row_type&>(), std::declval<row_ptr>()))
diff --git a/src/corelib/itemmodels/qrangemodeladapter.qdoc b/src/corelib/itemmodels/qrangemodeladapter.qdoc
index 263bff0dd0c..88872589299 100644
--- a/src/corelib/itemmodels/qrangemodeladapter.qdoc
+++ b/src/corelib/itemmodels/qrangemodeladapter.qdoc
@@ -277,14 +277,6 @@
*/
/*!
- \typedef QRangeModelAdapter::const_row_reference
-*/
-
-/*!
- \typedef QRangeModelAdapter::row_reference
-*/
-
-/*!
\typedef QRangeModelAdapter::range_type
*/
@@ -329,16 +321,39 @@
/*!
\fn template <typename Range, typename Protocol, typename Model> template <typename NewRange, QRangeModelAdapter<Range, Protocol, Model>::if_assignable_range<NewRange>> void QRangeModelAdapter<Range, Protocol, Model>::setRange(NewRange &&newRange)
- \fn template <typename Range, typename Protocol, typename Model> template <typename NewRange, QRangeModelAdapter<Range, Protocol, Model>::if_assignable_range<NewRange>> QRangeModelAdapter &QRangeModelAdapter<Range, Protocol, Model>::operator=(NewRange &&newRange)
+ \fn template <typename Range, typename Protocol, typename Model> template <typename NewRange, QRangeModelAdapter<Range, Protocol, Model>::if_assignable_range<NewRange>, QRangeModelAdapter<Range, Protocol, Model>::unless_adapter<NewRange>> QRangeModelAdapter &QRangeModelAdapter<Range, Protocol, Model>::operator=(NewRange &&newRange)
+
+ Replaces the contents of the model with the rows in \a newRange, possibly
+ using move semantics.
- Assigns \a newRange to the stored range, possibly using move semantics.
This function makes the model() emit the \l{QAbstractItemModel::}{modelAboutToBeReset()}
and \l{QAbstractItemModel::}{modelReset()} signals.
\constraints \c Range is mutable, and \a newRange is of a type that can be
- assigned to \c Range.
+ assigned to \c Range, but not a QRangeModelAdapter.
+
+ \sa range(), at(), model(), assign()
+*/
+
+/*!
+ \fn template <typename Range, typename Protocol, typename Model> template <typename Row, QRangeModelAdapter<Range, Protocol, Model>::if_assignable_range<std::initializer_list<Row>>> void QRangeModelAdapter<Range, Protocol, Model>::setRange(std::initializer_list<Row> newRange)
+ \fn template <typename Range, typename Protocol, typename Model> template <typename Row, QRangeModelAdapter<Range, Protocol, Model>::if_assignable_range<std::initializer_list<Row>>> QRangeModelAdapter &QRangeModelAdapter<Range, Protocol, Model>::assign(std::initializer_list<Row> newRange)
+ \fn template <typename Range, typename Protocol, typename Model> template <typename Row, QRangeModelAdapter<Range, Protocol, Model>::if_assignable_range<std::initializer_list<Row>>> QRangeModelAdapter &QRangeModelAdapter<Range, Protocol, Model>::operator=(std::initializer_list<Row> newRange)
+
+ Replaces the contents of the model with the rows in \a newRange.
- \sa range(), at(), model()
+ \constraints \c Range is mutable, and \a newRange can be assigned to \c Range.
+
+ \sa range(), at, model()
+*/
+
+/*!
+ \fn template <typename Range, typename Protocol, typename Model> template <typename InputIterator, typename Sentinel, typename I = Impl, QRangeModelAdapter<Range, Protocol, Model>::if_writable<I>> void QRangeModelAdapter<Range, Protocol, Model>::setRange(InputIterator first, Sentinel last)
+ \fn template <typename Range, typename Protocol, typename Model> template <typename InputIterator, typename Sentinel, typename I = Impl, QRangeModelAdapter<Range, Protocol, Model>::if_writable<I>> void QRangeModelAdapter<Range, Protocol, Model>::assign(InputIterator first, Sentinel last)
+
+ Replaces the contents of the models with the rows in the range [\a first, \a last).
+
+ \sa range(), at, model()
*/
/*!
@@ -508,8 +523,8 @@
*/
/*!
- \fn template <typename Range, typename Protocol, typename Model> template <typename I, QRangeModelAdapter<Range, Protocol, Model>::unless_list<I>> QRangeModelAdapter<Range, Protocol, Model>::const_row_reference QRangeModelAdapter<Range, Protocol, Model>::at(int row) const
- \fn template <typename Range, typename Protocol, typename Model> template <typename I, QRangeModelAdapter<Range, Protocol, Model>::unless_list<I>> QRangeModelAdapter<Range, Protocol, Model>::const_row_reference QRangeModelAdapter<Range, Protocol, Model>::operator[](int row) const
+ \fn template <typename Range, typename Protocol, typename Model> template <typename I, QRangeModelAdapter<Range, Protocol, Model>::unless_list<I>> decltype(auto) QRangeModelAdapter<Range, Protocol, Model>::at(int row) const
+ \fn template <typename Range, typename Protocol, typename Model> template <typename I, QRangeModelAdapter<Range, Protocol, Model>::unless_list<I>> decltype(auto) QRangeModelAdapter<Range, Protocol, Model>::operator[](int row) const
\return a constant reference to the row at \a row, as stored in \c Range.
@@ -517,8 +532,8 @@
*/
/*!
- \fn template <typename Range, typename Protocol, typename Model> template <typename I, QRangeModelAdapter<Range, Protocol, Model>::if_table<I>, QRangeModelAdapter<Range, Protocol, Model>::if_writable<I>> QRangeModelAdapter<Range, Protocol, Model>::row_reference QRangeModelAdapter<Range, Protocol, Model>::at(int row)
- \fn template <typename Range, typename Protocol, typename Model> template <typename I, QRangeModelAdapter<Range, Protocol, Model>::if_table<I>, QRangeModelAdapter<Range, Protocol, Model>::if_writable<I>> QRangeModelAdapter<Range, Protocol, Model>::row_reference QRangeModelAdapter<Range, Protocol, Model>::operator[](int row)
+ \fn template <typename Range, typename Protocol, typename Model> template <typename I, QRangeModelAdapter<Range, Protocol, Model>::if_table<I>, QRangeModelAdapter<Range, Protocol, Model>::if_writable<I>> auto QRangeModelAdapter<Range, Protocol, Model>::at(int row)
+ \fn template <typename Range, typename Protocol, typename Model> template <typename I, QRangeModelAdapter<Range, Protocol, Model>::if_table<I>, QRangeModelAdapter<Range, Protocol, Model>::if_writable<I>> auto QRangeModelAdapter<Range, Protocol, Model>::operator[](int row)
\return a mutable reference to the row at \a row, as stored in \c Range.
@@ -574,6 +589,16 @@
*/
/*!
+ \fn template <typename Range, typename Protocol, typename Model> template <typename I, QRangeModelAdapter<Range, Protocol, Model>::if_tree<I>> decltype(auto) QRangeModelAdapter<Range, Protocol, Model>::at(QSpan<const int> path) const
+ \fn template <typename Range, typename Protocol, typename Model> template <typename I, QRangeModelAdapter<Range, Protocol, Model>::if_tree<I>> decltype(auto) QRangeModelAdapter<Range, Protocol, Model>::operator[](QSpan<const int> path) const
+
+ \return a constant reference to the row specified by \a path, as stored in
+ \c Range.
+
+ \constraints \c Range is a tree.
+*/
+
+/*!
\fn template <typename Range, typename Protocol, typename Model> template <typename I, QRangeModelAdapter<Range, Protocol, Model>::if_tree<I>, QRangeModelAdapter<Range, Protocol, Model>::if_writable<I>> auto QRangeModelAdapter<Range, Protocol, Model>::at(QSpan<const int> path)
\fn template <typename Range, typename Protocol, typename Model> template <typename I, QRangeModelAdapter<Range, Protocol, Model>::if_tree<I>, QRangeModelAdapter<Range, Protocol, Model>::if_writable<I>> auto QRangeModelAdapter<Range, Protocol, Model>::operator[](QSpan<const int> path)
@@ -810,7 +835,7 @@
*/
/*!
- \fn template <typename Range, typename Protocol, typename Model> template <typename D, typename I, QRangeModelAdapter<Range, Protocol, Model>::if_canInsertColumns<I>, QRangeModelAdapter<Range, Protocol, Model>::if_compatible_data<D>> bool QRangeModelAdapter<Range, Protocol, Model>::insertColumn(int before, D &&data)
+ \fn template <typename Range, typename Protocol, typename Model> template <typename D, typename I, QRangeModelAdapter<Range, Protocol, Model>::if_canInsertColumns<I>, QRangeModelAdapter<Range, Protocol, Model>::if_compatible_column_data<D>> bool QRangeModelAdapter<Range, Protocol, Model>::insertColumn(int before, D &&data)
\overload
Inserts a single column constructed from \a data before the column specified
@@ -838,7 +863,7 @@
*/
/*!
- \fn template <typename Range, typename Protocol, typename Model> template <typename C, typename I, QRangeModelAdapter<Range, Protocol, Model>::if_canInsertColumns<I>, QRangeModelAdapter<Range, Protocol, Model>::if_compatible_data_range<C>> bool QRangeModelAdapter<Range, Protocol, Model>::insertColumns(int before, C &&data)
+ \fn template <typename Range, typename Protocol, typename Model> template <typename C, typename I, QRangeModelAdapter<Range, Protocol, Model>::if_canInsertColumns<I>, QRangeModelAdapter<Range, Protocol, Model>::if_compatible_column_range<C>> bool QRangeModelAdapter<Range, Protocol, Model>::insertColumns(int before, C &&data)
Inserts columns constructed from the elements in \a data before the column
specified by \a before into all rows, and returns whether the insertion was
diff --git a/src/corelib/kernel/qassociativeiterable.h b/src/corelib/kernel/qassociativeiterable.h
index 39f66d45fa0..4f9bbf67bfb 100644
--- a/src/corelib/kernel/qassociativeiterable.h
+++ b/src/corelib/kernel/qassociativeiterable.h
@@ -156,10 +156,12 @@ inline QVariantRef<QAssociativeIterator>::operator QVariant() const
if (!metaType.isValid())
return m_pointer->key();
+ return [&] {
QVariant v(metaType);
metaAssociation.mappedAtIterator(m_pointer->constIterator(),
metaType == QMetaType::fromType<QVariant>() ? &v : v.data());
return v;
+ }();
}
template<>
diff --git a/src/corelib/kernel/qcore_mac.mm b/src/corelib/kernel/qcore_mac.mm
index 687fc7e85fa..f5f1f4a8cb8 100644
--- a/src/corelib/kernel/qcore_mac.mm
+++ b/src/corelib/kernel/qcore_mac.mm
@@ -22,6 +22,10 @@
#include <spawn.h>
#include <qdebug.h>
+#include <qpoint.h>
+#include <qsize.h>
+#include <qrect.h>
+#include <qmargins.h>
#include "qendian.h"
#include "qhash.h"
@@ -222,6 +226,34 @@ QDebug operator<<(QDebug dbg, CFStringRef stringRef)
return dbg;
}
+QDebug operator<<(QDebug dbg, CGPoint point)
+{
+ dbg << QPointF::fromCGPoint(point);
+ return dbg;
+}
+
+QDebug operator<<(QDebug dbg, CGSize size)
+{
+ dbg << QSizeF::fromCGSize(size);
+ return dbg;
+}
+
+QDebug operator<<(QDebug dbg, CGRect rect)
+{
+ dbg << QRectF::fromCGRect(rect);
+ return dbg;
+}
+
+#if defined(Q_OS_MACOS)
+QDebug operator<<(QDebug dbg, NSEdgeInsets insets)
+#else
+QDebug operator<<(QDebug dbg, UIEdgeInsets insets)
+#endif
+{
+ dbg << QMargins(insets.left, insets.top, insets.right, insets.bottom);
+ return dbg;
+}
+
// Prevents breaking the ODR in case we introduce support for more types
// later on, and lets the user override our default QDebug operators.
#define QT_DECLARE_WEAK_QDEBUG_OPERATOR_FOR_CF_TYPE(CFType) \
diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h
index 2c4b4c02c55..1e57ee01e1d 100644
--- a/src/corelib/kernel/qcore_mac_p.h
+++ b/src/corelib/kernel/qcore_mac_p.h
@@ -78,6 +78,15 @@ kern_return_t IOObjectRelease(io_object_t object);
Q_FORWARD_DECLARE_OBJC_CLASS(NSObject);
Q_FORWARD_DECLARE_OBJC_CLASS(NSString);
+struct CGPoint;
+struct CGSize;
+struct CGRect;
+#if defined(Q_OS_MACOS)
+struct NSEdgeInsets;
+#else
+struct UIEdgeInsets;
+#endif
+
// @compatibility_alias doesn't work with categories or their methods
#define QtExtras QT_MANGLE_NAMESPACE(QtExtras)
@@ -225,6 +234,14 @@ Q_AUTOTEST_EXPORT void qt_mac_ensureResponsible();
#ifndef QT_NO_DEBUG_STREAM
Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QMacAutoReleasePool *pool);
Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QCFString &string);
+Q_CORE_EXPORT QDebug operator<<(QDebug, CGPoint);
+Q_CORE_EXPORT QDebug operator<<(QDebug, CGSize);
+Q_CORE_EXPORT QDebug operator<<(QDebug, CGRect);
+#if defined(Q_OS_MACOS)
+Q_CORE_EXPORT QDebug operator<<(QDebug, NSEdgeInsets);
+#else
+Q_CORE_EXPORT QDebug operator<<(QDebug, UIEdgeInsets);
+#endif
#endif
Q_CORE_EXPORT bool qt_apple_isApplicationExtension();
diff --git a/src/corelib/kernel/qeventdispatcher_cf.mm b/src/corelib/kernel/qeventdispatcher_cf.mm
index 2dddf147f85..d57c057a21a 100644
--- a/src/corelib/kernel/qeventdispatcher_cf.mm
+++ b/src/corelib/kernel/qeventdispatcher_cf.mm
@@ -207,6 +207,7 @@ QEventLoop *QEventDispatcherCoreFoundation::currentEventLoop() const
}
/*!
+ \internal
Processes all pending events that match \a flags until there are no
more events to process. Returns \c true if pending events were handled;
otherwise returns \c false.
diff --git a/src/corelib/kernel/qiterable.h b/src/corelib/kernel/qiterable.h
index baab2897967..494cec73a3f 100644
--- a/src/corelib/kernel/qiterable.h
+++ b/src/corelib/kernel/qiterable.h
@@ -502,7 +502,10 @@ public:
if (m_metaContainer.hasSize())
return m_metaContainer.size(container);
- // ### Qt7: Return -1 here. We shouldn't second-guess the underlying container
+#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0)
+ // We shouldn't second-guess the underlying container, so we're not synthesizing a size.
+ return -1;
+#else
QtPrivate::warnSynthesizedAccess(
"size() called on an iterable without native size accessor. This is slow");
@@ -515,6 +518,7 @@ public:
m_metaContainer.destroyConstIterator(begin);
m_metaContainer.destroyConstIterator(end);
return size;
+#endif
}
void clear()
diff --git a/src/corelib/kernel/qmetaassociation.h b/src/corelib/kernel/qmetaassociation.h
index 6d8de13e90a..d481ae91079 100644
--- a/src/corelib/kernel/qmetaassociation.h
+++ b/src/corelib/kernel/qmetaassociation.h
@@ -25,8 +25,8 @@ public:
using reference = QVariant::Reference<AssociativeIterator>;
using pointer = QVariant::Pointer<AssociativeIterator>;
- static constexpr bool canNoexceptAssignQVariant = false;
- static constexpr bool canNoexceptConvertToQVariant = false;
+ static constexpr bool CanNoexceptAssignQVariant = false;
+ static constexpr bool CanNoexceptConvertToQVariant = false;
AssociativeIterator(QIterator &&it) : QIterator(std::move(it)) {}
@@ -51,7 +51,7 @@ public:
using reference = QVariant::ConstReference<AssociativeConstIterator>;
using pointer = QVariant::ConstPointer<AssociativeConstIterator>;
- static constexpr bool canNoexceptConvertToQVariant = false;
+ static constexpr bool CanNoexceptConvertToQVariant = false;
AssociativeConstIterator(QConstIterator &&it) : QConstIterator(std::move(it)) {}
diff --git a/src/corelib/kernel/qmetacontainer.h b/src/corelib/kernel/qmetacontainer.h
index c9d3a6bf9c6..66047afefd4 100644
--- a/src/corelib/kernel/qmetacontainer.h
+++ b/src/corelib/kernel/qmetacontainer.h
@@ -971,18 +971,11 @@ public:
Iterator mutableEnd();
QVariant at(qsizetype idx) const;
- void set(qsizetype idx, const QVariant &value);
+ void setAt(qsizetype idx, const QVariant &value);
void append(const QVariant &value);
void prepend(const QVariant &value);
void removeLast();
void removeFirst();
-
-#if QT_DEPRECATED_SINCE(6, 11)
- enum Position: quint8 { Unspecified, AtBegin, AtEnd };
- void addValue(const QVariant &value, Position position = Unspecified);
- void removeValue(Position position = Unspecified);
- QMetaType valueMetaType() const;
-#endif // QT_DEPRECATED_SINCE(6, 11)
};
#else
using Iterable = QtMetaContainerPrivate::Sequence;
diff --git a/src/corelib/kernel/qmetasequence.cpp b/src/corelib/kernel/qmetasequence.cpp
index 2a3a923d5ca..018dd610146 100644
--- a/src/corelib/kernel/qmetasequence.cpp
+++ b/src/corelib/kernel/qmetasequence.cpp
@@ -531,39 +531,6 @@ void QMetaSequence::valueAtConstIterator(const void *iterator, void *result) con
*/
/*!
- \enum QMetaSequence::Iterable::Position
- \deprecated [6.11] Use append(), prepend(), removeFirst(), or removeLast()
-
- Specifies the position at which an element shall be added to or removed from
- the iterable.
-
- \value AtBegin
- Add or remove at the beginning of the iterable.
- \value AtEnd
- Add or remove at the end of the iterable.
- \value Unspecified
- Add or remove at an unspecified position in the iterable.
- */
-
-/*!
- \fn void QMetaSequence::Iterable::addValue(const QVariant &value, Position position)
- \deprecated [6.11] Use append() or prepend()
- Adds \a value to the container, at \a position, if possible.
- */
-
-/*!
- \deprecated [6.11] Use removeFirst() or removeLast()
- \fn void QMetaSequence::Iterable::removeValue(Position position)
- Removes a value from the container, at \a position, if possible.
- */
-
-/*!
- \deprecated [6.11] Use QMetaSequence::valueMetaType()
- \fn QMetaType QMetaSequence::Iterable::valueMetaType() const
- Returns the meta type for values stored in the underlying container.
- */
-
-/*!
\fn QVariant QMetaSequence::Iterable::at(qsizetype idx) const
Returns the value at position \a idx in the container.
@@ -574,13 +541,8 @@ void QMetaSequence::valueAtConstIterator(const void *iterator, void *result) con
*/
/*!
- \fn void QMetaSequence::Iterable::set(qsizetype idx, const QVariant &value)
+ \fn void QMetaSequence::Iterable::setAt(qsizetype idx, const QVariant &value)
Sets the element at position \a idx in the container to \a value.
-
- \note If the underlying container does not provide a native way to assign
- an element at an index, this method will synthesize the assignment
- using iterators. This behavior is deprecated and will be removed in a
- future version of Qt.
*/
/*!
diff --git a/src/corelib/kernel/qmetasequence.h b/src/corelib/kernel/qmetasequence.h
index e8000439dba..f8052476d79 100644
--- a/src/corelib/kernel/qmetasequence.h
+++ b/src/corelib/kernel/qmetasequence.h
@@ -24,8 +24,8 @@ public:
using reference = QVariant::Reference<SequentialIterator>;
using pointer = QVariant::Pointer<SequentialIterator>;
- static constexpr bool canNoexceptAssignQVariant = false;
- static constexpr bool canNoexceptConvertToQVariant = false;
+ static constexpr bool CanNoexceptAssignQVariant = false;
+ static constexpr bool CanNoexceptConvertToQVariant = false;
SequentialIterator(QIterator &&it) : QIterator(std::move(it)) {}
@@ -41,7 +41,7 @@ public:
using reference = QVariant::ConstReference<SequentialConstIterator>;
using pointer = QVariant::ConstPointer<SequentialConstIterator>;
- static constexpr bool canNoexceptConvertToQVariant = false;
+ static constexpr bool CanNoexceptConvertToQVariant = false;
SequentialConstIterator(QConstIterator &&it) : QConstIterator(std::move(it)) {}
@@ -184,33 +184,23 @@ public:
return;
}
- // ### Qt7: Drop this code. We shouldn't second-guess the underlying container
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
+ // We shouldn't second-guess the underlying container.
QtPrivate::warnSynthesizedAccess(
"at() called on an iterable without native indexed accessors. This is slow");
void *it = meta.constBegin(m_iterable.constPointer());
meta.advanceConstIterator(it, idx);
meta.valueAtConstIterator(it, dataPtr);
meta.destroyConstIterator(it);
+#endif
});
}
- void set(qsizetype idx, const QVariant &value)
+ void setAt(qsizetype idx, const QVariant &value)
{
const QMetaSequence meta = metaContainer();
QtPrivate::QVariantTypeCoercer coercer;
- const void *dataPtr = coercer.coerce(value, meta.valueMetaType());
- if (meta.canSetValueAtIndex()) {
- meta.setValueAtIndex(mutableIterable(), idx, dataPtr);
- return;
- }
-
- // ### Qt7: Drop this code. We shouldn't second-guess the underlying container
- QtPrivate::warnSynthesizedAccess(
- "set() called on an iterable without native indexed accessors. This is slow");
- void *it = meta.begin(m_iterable.mutablePointer());
- meta.advanceIterator(it, idx);
- meta.setValueAtIterator(it, dataPtr);
- meta.destroyIterator(it);
+ meta.setValueAtIndex(mutableIterable(), idx, coercer.coerce(value, meta.valueMetaType()));
}
void append(const QVariant &value)
@@ -257,6 +247,9 @@ public:
QMetaType valueMetaType() const
Q_DECL_EQ_DELETE_X("Use QMetaSequence::valueMetaType() instead.");
+ void set(qsizetype idx, const QVariant &value)
+ Q_DECL_EQ_DELETE_X("Use setAt() instead.");
+
QT_WARNING_POP
#endif // QT_DEPRECATED_SINCE(6, 11)
};
diff --git a/src/corelib/kernel/qpermissions.cpp b/src/corelib/kernel/qpermissions.cpp
index 6767917e176..69383dafdd9 100644
--- a/src/corelib/kernel/qpermissions.cpp
+++ b/src/corelib/kernel/qpermissions.cpp
@@ -119,7 +119,7 @@ Q_LOGGING_CATEGORY(lcPermissions, "qt.permissions", QtWarningMsg);
To ensure the relevant permission backend is included with your
application, please \l {QT_ANDROID_PACKAGE_SOURCE_DIR}
{point the build system to your custom \c AndroidManifest.xml}
- or use \l {qt_add_android_permission()}.
+ or use \l {qt_add_android_permission}().
The relevant permission names are described in the documentation
for each permission type.
diff --git a/src/corelib/kernel/qproperty.cpp b/src/corelib/kernel/qproperty.cpp
index d538ed7b4e9..9141a8f8bad 100644
--- a/src/corelib/kernel/qproperty.cpp
+++ b/src/corelib/kernel/qproperty.cpp
@@ -402,6 +402,16 @@ QPropertyBindingPrivate::NotificationState QPropertyBindingPrivate::notifyNonRec
}
/*!
+ \class QUntypedPropertyBinding
+ \inmodule QtCore
+ \since 6.0
+ \ingroup tools
+ \brief Represents a type-erased property binding.
+
+ \sa QUntypedBindable
+*/
+
+/*!
Constructs a null QUntypedPropertyBinding.
\sa isNull()
@@ -409,8 +419,8 @@ QPropertyBindingPrivate::NotificationState QPropertyBindingPrivate::notifyNonRec
QUntypedPropertyBinding::QUntypedPropertyBinding() = default;
/*!
- \fn template<typename Functor>
- QUntypedPropertyBinding(QMetaType metaType, Functor &&f, const QPropertyBindingSourceLocation &location)
+ \fn template<typename Functor> QUntypedPropertyBinding(
+ QMetaType metaType, Functor &&f, const QPropertyBindingSourceLocation &location)
\internal
*/
@@ -448,7 +458,6 @@ QUntypedPropertyBinding::QUntypedPropertyBinding(const QUntypedPropertyBinding &
: d(other.d)
{
}
-
/*!
Copy-assigns \a other to this QUntypedPropertyBinding.
*/
@@ -1183,7 +1192,7 @@ QString QPropertyBindingError::description() const
\return \c true when the binding was successfully set.
- //! \sa QUntypedPropertyBinding::valueMetaType()
+ \sa QUntypedPropertyBinding::valueMetaType()
*/
/*!
@@ -1199,8 +1208,7 @@ QString QPropertyBindingError::description() const
Returns the metatype of the property from which the QUntypedBindable was created.
If the bindable is invalid, an invalid metatype will be returned.
- \sa isValid()
- //! \sa QUntypedPropertyBinding::valueMetaType()
+ \sa isValid(), QUntypedPropertyBinding::valueMetaType()
*/
/*!
diff --git a/src/corelib/kernel/qsequentialiterable.h b/src/corelib/kernel/qsequentialiterable.h
index 92252cb19dd..76908bdae4b 100644
--- a/src/corelib/kernel/qsequentialiterable.h
+++ b/src/corelib/kernel/qsequentialiterable.h
@@ -142,10 +142,13 @@ inline QVariantRef<QSequentialIterator>::operator QVariant() const
if (m_pointer == nullptr)
return QVariant();
const QMetaType metaType(m_pointer->metaContainer().valueMetaType());
+
+ return [&] {
QVariant v(metaType);
void *dataPtr = metaType == QMetaType::fromType<QVariant>() ? &v : v.data();
m_pointer->metaContainer().valueAtIterator(m_pointer->constIterator(), dataPtr);
return v;
+ }();
}
template<>
diff --git a/src/corelib/kernel/qtranslator.cpp b/src/corelib/kernel/qtranslator.cpp
index 9fdac89f775..6000edaa177 100644
--- a/src/corelib/kernel/qtranslator.cpp
+++ b/src/corelib/kernel/qtranslator.cpp
@@ -392,8 +392,8 @@ public:
translation files may contain misleading or malicious translations.
\sa QCoreApplication::installTranslator(), QCoreApplication::removeTranslator(),
- QObject::tr(), QCoreApplication::translate(), {I18N Example},
- {Hello tr() Example}, {Arrow Pad Example}, {Troll Print Example}
+ QObject::tr(), QCoreApplication::translate(),
+ {Localized Clock Example}, {Arrow Pad Example}, {Troll Print Example}
*/
/*!
diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h
index 82eec0693d6..19cd1fea7fb 100644
--- a/src/corelib/kernel/qvariant.h
+++ b/src/corelib/kernel/qvariant.h
@@ -263,7 +263,7 @@ public:
ConstReference &operator=(ConstReference &&value) = delete;
// To be specialized for each Referred
- operator QVariant() const noexcept(Referred::canNoexceptConvertToQVariant);
+ operator QVariant() const noexcept(Referred::CanNoexceptConvertToQVariant);
};
template<typename Referred>
@@ -288,18 +288,18 @@ public:
~Reference() = default;
Reference &operator=(const Reference &value)
- noexcept(Referred::canNoexceptAssignQVariant)
+ noexcept(Referred::CanNoexceptAssignQVariant)
{
return operator=(QVariant(value));
}
Reference &operator=(Reference &&value)
- noexcept(Referred::canNoexceptAssignQVariant)
+ noexcept(Referred::CanNoexceptAssignQVariant)
{
return operator=(QVariant(value));
}
- operator QVariant() const noexcept(Referred::canNoexceptConvertToQVariant)
+ operator QVariant() const noexcept(Referred::CanNoexceptConvertToQVariant)
{
return ConstReference(m_referred);
}
@@ -313,7 +313,7 @@ public:
}
// To be specialized for each Referred
- Reference &operator=(const QVariant &value) noexcept(Referred::canNoexceptAssignQVariant);
+ Reference &operator=(const QVariant &value) noexcept(Referred::CanNoexceptAssignQVariant);
};
template<typename Pointed>
diff --git a/src/corelib/platform/windows/qbstr_p.h b/src/corelib/platform/windows/qbstr_p.h
index 21eecfe2df7..32b1aace76f 100644
--- a/src/corelib/platform/windows/qbstr_p.h
+++ b/src/corelib/platform/windows/qbstr_p.h
@@ -1,5 +1,6 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:significant reason:default
#ifndef QBSTR_P_H
#define QBSTR_P_H
@@ -141,4 +142,4 @@ QT_END_NAMESPACE
#endif // Q_OS_WIN
-#endif // QCOMPTR_P_H
+#endif // QBSTR_P_H
diff --git a/src/corelib/platform/windows/qcomobject_p.h b/src/corelib/platform/windows/qcomobject_p.h
index bd6f81d1c28..b7a9c56555d 100644
--- a/src/corelib/platform/windows/qcomobject_p.h
+++ b/src/corelib/platform/windows/qcomobject_p.h
@@ -1,5 +1,6 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:significant reason:default
#ifndef QCOMOBJECT_P_H
#define QCOMOBJECT_P_H
diff --git a/src/corelib/platform/windows/qcomptr_p.h b/src/corelib/platform/windows/qcomptr_p.h
index 2a69e7b6038..e640528d3c2 100644
--- a/src/corelib/platform/windows/qcomptr_p.h
+++ b/src/corelib/platform/windows/qcomptr_p.h
@@ -1,5 +1,6 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:significant reason:default
#ifndef QCOMPTR_P_H
#define QCOMPTR_P_H
diff --git a/src/corelib/platform/windows/qcomvariant_p.h b/src/corelib/platform/windows/qcomvariant_p.h
index 34ce5f179ce..cc4ad104106 100644
--- a/src/corelib/platform/windows/qcomvariant_p.h
+++ b/src/corelib/platform/windows/qcomvariant_p.h
@@ -1,5 +1,6 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:significant reason:default
#ifndef QCOMVARIANT_P_H
#define QCOMVARIANT_P_H
diff --git a/src/corelib/platform/windows/qfactorycacheregistration.cpp b/src/corelib/platform/windows/qfactorycacheregistration.cpp
index 6bd69c66d14..04c81b7b665 100644
--- a/src/corelib/platform/windows/qfactorycacheregistration.cpp
+++ b/src/corelib/platform/windows/qfactorycacheregistration.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:significant reason:default
#include "qfactorycacheregistration_p.h"
diff --git a/src/corelib/platform/windows/qfactorycacheregistration_p.h b/src/corelib/platform/windows/qfactorycacheregistration_p.h
index d0b19b995b4..f6e7d9eb064 100644
--- a/src/corelib/platform/windows/qfactorycacheregistration_p.h
+++ b/src/corelib/platform/windows/qfactorycacheregistration_p.h
@@ -1,5 +1,6 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:significant reason:default
#ifndef QFACTORYCACHEREGISTRATION_P_H
#define QFACTORYCACHEREGISTRATION_P_H
diff --git a/src/corelib/platform/windows/qt_winrtbase_p.h b/src/corelib/platform/windows/qt_winrtbase_p.h
index 79c2bdf6b1c..69a602a59e0 100644
--- a/src/corelib/platform/windows/qt_winrtbase_p.h
+++ b/src/corelib/platform/windows/qt_winrtbase_p.h
@@ -1,5 +1,6 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:significant reason:default
#ifndef QT_WINRTBASE_P_H
#define QT_WINRTBASE_P_H
diff --git a/src/corelib/serialization/qcborvalue.cpp b/src/corelib/serialization/qcborvalue.cpp
index 13d74e591d5..0aeb2b07f47 100644
--- a/src/corelib/serialization/qcborvalue.cpp
+++ b/src/corelib/serialization/qcborvalue.cpp
@@ -975,6 +975,7 @@ QCborContainerPrivate *QCborContainerPrivate::detach(QCborContainerPrivate *d, q
}
/*!
+ \internal
Prepare for an insertion at position \a index
Detaches and ensures there are at least index entries in the array, padding
diff --git a/src/corelib/serialization/qdatastream.cpp b/src/corelib/serialization/qdatastream.cpp
index ae3bed5b751..fd2f7faeee5 100644
--- a/src/corelib/serialization/qdatastream.cpp
+++ b/src/corelib/serialization/qdatastream.cpp
@@ -552,6 +552,7 @@ void QDataStream::setByteOrder(ByteOrder bo)
\value Qt_6_9
\value Qt_6_10
\value Qt_6_11
+ \value Qt_6_12
\omitvalue Qt_DefaultCompiledVersion
\sa setVersion(), version()
diff --git a/src/corelib/serialization/qdatastream.h b/src/corelib/serialization/qdatastream.h
index 04373fe9c8a..d6fcf17efcd 100644
--- a/src/corelib/serialization/qdatastream.h
+++ b/src/corelib/serialization/qdatastream.h
@@ -96,8 +96,9 @@ public:
Qt_6_9 = Qt_6_7,
Qt_6_10 = 23,
Qt_6_11 = 24,
- Qt_DefaultCompiledVersion = Qt_6_11
-#if QT_VERSION >= QT_VERSION_CHECK(6, 12, 0)
+ Qt_6_12 = Qt_6_11,
+ Qt_DefaultCompiledVersion = Qt_6_12
+#if QT_VERSION >= QT_VERSION_CHECK(6, 13, 0)
#error Add the datastream version for this Qt version and update Qt_DefaultCompiledVersion
#endif
};
diff --git a/src/corelib/serialization/qxmlstream.cpp b/src/corelib/serialization/qxmlstream.cpp
index 9cd90fa9d65..ff70289013a 100644
--- a/src/corelib/serialization/qxmlstream.cpp
+++ b/src/corelib/serialization/qxmlstream.cpp
@@ -3678,7 +3678,7 @@ void QXmlStreamWriter::setStopWritingOnError(bool stop)
The error status is never reset. Writes happening after the error
occurred may be ignored, even if the error condition is cleared.
- \sa error(), errorString(), raiseError(const QString &message),
+ \sa error(), errorString(), raiseError()
*/
bool QXmlStreamWriter::hasError() const
{
@@ -3692,7 +3692,7 @@ bool QXmlStreamWriter::hasError() const
QXmlStreamWriter::Error::None.
\since 6.10
- \sa errorString(), raiseError(const QString &message), hasError()
+ \sa errorString(), raiseError(), hasError()
*/
QXmlStreamWriter::Error QXmlStreamWriter::error() const
{
@@ -3708,7 +3708,7 @@ QXmlStreamWriter::Error QXmlStreamWriter::error() const
a null string.
\since 6.10
- \sa error(), raiseError(const QString &message), hasError()
+ \sa error(), raiseError(), hasError()
*/
QString QXmlStreamWriter::errorString() const
{
diff --git a/src/corelib/text/qlocale.cpp b/src/corelib/text/qlocale.cpp
index fed09aee45e..18007cacae6 100644
--- a/src/corelib/text/qlocale.cpp
+++ b/src/corelib/text/qlocale.cpp
@@ -301,6 +301,7 @@ bool operator<(LikelyPair lhs, LikelyPair rhs)
} // anonymous namespace
/*!
+ \internal
Fill in blank fields of a locale ID.
An ID in which some fields are zero stands for any locale that agrees with
diff --git a/src/corelib/text/qstringconverter.cpp b/src/corelib/text/qstringconverter.cpp
index bf6e776ee0e..896142b4837 100644
--- a/src/corelib/text/qstringconverter.cpp
+++ b/src/corelib/text/qstringconverter.cpp
@@ -2739,7 +2739,7 @@ QStringList QStringConverter::availableCodecs()
May also provide data from residual content that was pending decoding.
When there is no residual data to account for, the return's \c error
- field will be set to \l {QCharConverter::FinalizeResult::Error::}
+ field will be set to \l {QStringConverter::FinalizeResultChar::error}
{NoError}.
If \a out is supplied and non-null, it must have space in which up to
@@ -2793,7 +2793,7 @@ auto QStringDecoder::finalize(char16_t *out, qsizetype maxlen) -> FinalizeResult
May also provide data from residual content that was pending decoding.
When there is no residual data to account for, the return's \c error
- field will be set to \l {QCharConverter::FinalizeResult::Error::}
+ field will be set to \l {QStringConverter::FinalizeResultChar::error}
{NoError}.
If \a out is supplied and non-null, it must have space in which up to
diff --git a/src/corelib/thread/qfuture_impl.h b/src/corelib/thread/qfuture_impl.h
index 371ee524d72..d6c185cd704 100644
--- a/src/corelib/thread/qfuture_impl.h
+++ b/src/corelib/thread/qfuture_impl.h
@@ -845,7 +845,7 @@ struct UnwrapHandler
using NestedType = typename QtPrivate::Future<ResultType>::type;
QFutureInterface<NestedType> promise(QFutureInterfaceBase::State::Pending);
- outer->then([promise](const QFuture<ResultType> &outerFuture) mutable {
+ auto chain = outer->then([promise](const QFuture<ResultType> &outerFuture) mutable {
// We use the .then([](QFuture<ResultType> outerFuture) {...}) version
// (where outerFuture == *outer), to propagate the exception if the
// outer future has failed.
@@ -883,6 +883,13 @@ struct UnwrapHandler
promise.reportCanceled();
promise.reportFinished();
});
+
+ // Inject the promise into the chain.
+ // We use a fake function as a continuation, since the promise is
+ // managed by the outer future
+ chain.d.setContinuation(ContinuationWrapper(std::move([](const QFutureInterfaceBase &) {})),
+ promise.d, QFutureInterfaceBase::ContinuationType::Then);
+
return promise.future();
}
};
diff --git a/src/corelib/thread/qfutureinterface.h b/src/corelib/thread/qfutureinterface.h
index 0b88013800e..ff17560d3a1 100644
--- a/src/corelib/thread/qfutureinterface.h
+++ b/src/corelib/thread/qfutureinterface.h
@@ -42,6 +42,8 @@ template<class Function, class ResultType>
class FailureHandler;
#endif
+struct UnwrapHandler;
+
#if QT_CORE_REMOVED_SINCE(6, 10)
void Q_CORE_EXPORT watchContinuationImpl(const QObject *context,
QtPrivate::QSlotObjectBase *slotObj,
@@ -187,6 +189,8 @@ private:
friend class QtPrivate::FailureHandler;
#endif
+ friend struct QtPrivate::UnwrapHandler;
+
#if QT_CORE_REMOVED_SINCE(6, 10)
friend Q_CORE_EXPORT void QtPrivate::watchContinuationImpl(
const QObject *context, QtPrivate::QSlotObjectBase *slotObj, QFutureInterfaceBase &fi);
diff --git a/src/corelib/thread/qreadwritelock.cpp b/src/corelib/thread/qreadwritelock.cpp
index 96e35dcb965..2a1af2315ca 100644
--- a/src/corelib/thread/qreadwritelock.cpp
+++ b/src/corelib/thread/qreadwritelock.cpp
@@ -234,14 +234,14 @@ QBasicReadWriteLock::contendedTryLockForRead(QDeadlineTimer timeout, void *dd)
return d->recursiveLockForRead(timeout);
auto lock = qt_unique_lock(d->mutex);
- if (d != d_ptr.loadRelaxed()) {
+ if (QReadWriteLockPrivate *dd = d_ptr.loadAcquire(); d != dd) {
// d_ptr has changed: this QReadWriteLock was unlocked before we had
// time to lock d->mutex.
// We are holding a lock to a mutex within a QReadWriteLockPrivate
// that is already released (or even is already re-used). That's ok
// because the QFreeList never frees them.
// Just unlock d->mutex (at the end of the scope) and retry.
- d = d_ptr.loadAcquire();
+ d = dd;
continue;
}
return d->lockForRead(lock, timeout);
@@ -340,11 +340,11 @@ QBasicReadWriteLock::contendedTryLockForWrite(QDeadlineTimer timeout, void *dd)
return d->recursiveLockForWrite(timeout);
auto lock = qt_unique_lock(d->mutex);
- if (d != d_ptr.loadRelaxed()) {
+ if (QReadWriteLockPrivate *dd = d_ptr.loadAcquire(); d != dd) {
// The mutex was unlocked before we had time to lock the mutex.
// We are holding to a mutex within a QReadWriteLockPrivate that is already released
// (or even is already re-used) but that's ok because the QFreeList never frees them.
- d = d_ptr.loadAcquire();
+ d = dd;
continue;
}
return d->lockForWrite(lock, timeout);
diff --git a/src/corelib/time/qdatetimeparser.cpp b/src/corelib/time/qdatetimeparser.cpp
index 10882738a39..05ba3d2beae 100644
--- a/src/corelib/time/qdatetimeparser.cpp
+++ b/src/corelib/time/qdatetimeparser.cpp
@@ -2389,6 +2389,7 @@ bool operator==(QDateTimeParser::SectionNode s1, QDateTimeParser::SectionNode s2
}
/*!
+ \internal
Sets \a cal as the calendar to use. The default is Gregorian.
*/
diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp
index 1c0371e463e..d173d824e88 100644
--- a/src/corelib/tools/qarraydata.cpp
+++ b/src/corelib/tools/qarraydata.cpp
@@ -162,7 +162,7 @@ allocateHelper(QArrayData **dptr, qsizetype objectSize, qsizetype alignment, qsi
QArrayData::AllocationOption option) noexcept
{
*dptr = nullptr;
- if (capacity == 0)
+ if (capacity <= 0)
return {};
const qsizetype headerSize = calculateHeaderSize(alignment);
diff --git a/src/corelib/tools/qeasingcurve.cpp b/src/corelib/tools/qeasingcurve.cpp
index de68a0042ac..1e647a83dc0 100644
--- a/src/corelib/tools/qeasingcurve.cpp
+++ b/src/corelib/tools/qeasingcurve.cpp
@@ -332,15 +332,13 @@ struct TCBPoint
qreal _c;
qreal _b;
- TCBPoint() {}
- TCBPoint(QPointF point, qreal t, qreal c, qreal b) : _point(point), _t(t), _c(c), _b(b) {}
- bool operator==(const TCBPoint &other) const
+ friend bool operator==(const TCBPoint &lhs, const TCBPoint &rhs) noexcept
{
- return _point == other._point &&
- qFuzzyCompare(_t, other._t) &&
- qFuzzyCompare(_c, other._c) &&
- qFuzzyCompare(_b, other._b);
+ return qFuzzyCompare(lhs._point, rhs._point)
+ && QtPrivate::fuzzyCompare(lhs._t, rhs._t)
+ && QtPrivate::fuzzyCompare(lhs._c, rhs._c)
+ && QtPrivate::fuzzyCompare(lhs._b, rhs._b);
}
};
Q_DECLARE_TYPEINFO(TCBPoint, Q_PRIMITIVE_TYPE);
@@ -1381,7 +1379,7 @@ void QEasingCurve::addTCBSegment(const QPointF &nextPoint, qreal t, qreal c, qre
if (!d_ptr->config)
d_ptr->config = curveToFunctionObject(d_ptr->type);
- d_ptr->config->_tcbPoints.append(TCBPoint(nextPoint, t, c, b));
+ d_ptr->config->_tcbPoints.append(TCBPoint{nextPoint, t, c, b});
if (nextPoint == QPointF(1.0, 1.0)) {
d_ptr->config->_bezierCurves = tcbToBezier(d_ptr->config->_tcbPoints);
diff --git a/src/gui/accessible/qaccessiblecache.cpp b/src/gui/accessible/qaccessiblecache.cpp
index 311b53aeaa3..b5dcdca6270 100644
--- a/src/gui/accessible/qaccessiblecache.cpp
+++ b/src/gui/accessible/qaccessiblecache.cpp
@@ -19,6 +19,7 @@ Q_STATIC_LOGGING_CATEGORY(lcAccessibilityCache, "qt.accessibility.cache");
*/
static QAccessibleCache *accessibleCache = nullptr;
+static bool inCacheDestructor = false;
static void cleanupAccessibleCache()
{
@@ -32,6 +33,8 @@ QAccessibleObjectDestroyedEvent::~QAccessibleObjectDestroyedEvent()
QAccessibleCache::~QAccessibleCache()
{
+ inCacheDestructor = true;
+
for (QAccessible::Id id: idToInterface.keys())
deleteInterface(id);
}
@@ -188,10 +191,9 @@ void QAccessibleCache::deleteInterface(QAccessible::Id id, QObject *obj)
return;
}
- // QObjects sends this from their destructor, but
- // the object less interfaces calls deleteInterface
- // directly
- if (!obj && !iface->object()) {
+ // QObjects send this from their destructors, but the interfaces
+ // with no associated object call deleteInterface directly.
+ if (!inCacheDestructor && !obj && !iface->object()) {
if (QGuiApplicationPrivate::is_app_running && !QGuiApplicationPrivate::is_app_closing && QAccessible::isActive()) {
QAccessibleObjectDestroyedEvent event(id);
QAccessible::updateAccessibility(&event);
diff --git a/src/gui/doc/images/coordinatesystem-transformations.png b/src/gui/doc/images/coordinatesystem-transformations.png
deleted file mode 100644
index 2736213c072..00000000000
--- a/src/gui/doc/images/coordinatesystem-transformations.png
+++ /dev/null
Binary files differ
diff --git a/src/gui/doc/images/coordinatesystem-transformations.svg b/src/gui/doc/images/coordinatesystem-transformations.svg
new file mode 100644
index 00000000000..a3bc17af3ef
--- /dev/null
+++ b/src/gui/doc/images/coordinatesystem-transformations.svg
@@ -0,0 +1,148 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg width="760" height="300"
+ viewBox="0 0 760 300"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.2" baseProfile="tiny">
+
+<style>
+ svg .line-style { stroke: black; fill: none; stroke-width: 2 }
+ svg .text-style { font: 14px arial; fill: black }
+ svg .mono-text-style { font: 14px monospace; fill: black }
+ svg .heading-style { font: 14px arial; fill: black; font-weight: bold }
+ svg .shape-style { stroke: none; fill: black }
+ svg .dash-style { stroke-dasharray: 4,3; stroke-dashoffset: 0; fill: none;
+ stroke: black }
+
+ svg .window-line-style { stroke: red; fill: none; stroke-width: 2 }
+ svg .window-text-style { font: 14px arial; fill: red }
+ svg .window-shape-style { stroke: none; fill: red }
+ svg .window-dash-style { stroke-dasharray: 4,3; stroke-dashoffset: 0; fill: none;
+ stroke: red }
+
+ svg.dark .line-style { stroke: #f2f2f2; fill: none; stroke-width: 2 }
+ svg.dark .text-style { font: 14px arial; fill: #f2f2f2 }
+ svg.dark .mono-text-style { font: 14px monospace; fill: #f2f2f2 }
+ svg.dark .heading-style { font: 14px arial; fill: #f2f2f2; font-weight: bold }
+ svg.dark .shape-style { stroke: none; fill: #f2f2f2 }
+ svg.dark .dash-style { stroke-dasharray: 4,3; stroke-dashoffset: 0; fill: none;
+ stroke: #f2f2f2 }
+ svg.dark .window-line-style { stroke: yellow; fill: none; stroke-width: 2 }
+ svg.dark .window-text-style { font: 14px arial; fill: yellow }
+ svg.dark .window-shape-style { stroke: none; fill: yellow }
+ svg.dark .window-dash-style { stroke-dasharray: 4,3; stroke-dashoffset: 0; fill: none;
+ stroke: yellow }
+
+ [data-theme="dark"] svg .line-style { stroke: #f2f2f2; fill: none; stroke-width: 2 }
+ [data-theme="dark"] svg .text-style { font: 14px arial; fill: #f2f2f2 }
+ [data-theme="dark"] svg .mono-text-style { font: 14px monospace; fill: #f2f2f2 }
+ [data-theme="dark"] svg .heading-style { font: 14px arial; fill: #f2f2f2; font-weight: bold }
+ [data-theme="dark"] svg .shape-style { stroke: none; fill: #f2f2f2 }
+ [data-theme="dark"] svg .dash-style { stroke-dasharray: 4,3; stroke-dashoffset: 0; fill: none;
+ stroke: #f2f2f2 }
+ [data-theme="dark"] svg .window-line-style { stroke: yellow; fill: none; stroke-width: 2 }
+ [data-theme="dark"] svg .window-text-style { font: 14px arial; fill: yellow }
+ [data-theme="dark"] svg .window-shape-style { stroke: none; fill: yellow }
+ [data-theme="dark"] svg .window-dash-style { stroke-dasharray: 4,3; stroke-dashoffset: 0; fill: none;
+ stroke: yellow }
+
+ [data-theme="light"] svg .line-style { stroke: black; fill: none; stroke-width: 2 }
+ [data-theme="light"] svg .text-style { font: 14px arial; fill: black }
+ [data-theme="light"] svg .mono-text-style { font: 14px monospace; fill: black }
+ [data-theme="light"] svg .heading-style { font: 14px arial; fill: black; font-weight: bold }
+ [data-theme="light"] svg .shape-style { stroke: none; fill: black }
+ [data-theme="light"] svg .dash-style { stroke-dasharray: 4,3; stroke-dashoffset: 0; fill: none;
+ stroke: black }
+ [data-theme="light"] svg .window-line-style { stroke: red; fill: none; stroke-width: 2 }
+ [data-theme="light"] svg .window-text-style { font: 14px arial; fill: red }
+ [data-theme="light"] svg .window-shape-style { stroke: none; fill: red }
+ [data-theme="light"] svg .window-dash-style { stroke-dasharray: 4,3; stroke-dashoffset: 0; fill: none;
+ stroke: red }
+</style>
+
+<text x="50" y="20" fill="black" font-size="14px" font-family="arial"
+ font-weight="bold"
+ class="heading-style">World coordinates</text>
+
+<g transform="translate(20, 30)">
+ <rect x="0" y="0" width="200" height="200" stroke="black" fill="none" stroke-dasharray="4,3" stroke-dashoffset="0"
+ class="dash-style" />
+
+ <path d="M5,5 L16,10 L10,16 L5,5" class="shape-style" />
+ <polyline points="5,5 20,20" stroke="black" stroke-width="2" fill="none" class="line-style" />
+ <text x="25" y="30" fill="black" font-size="14px" font-family="arial"
+ class="text-style">(0, 0)</text>
+
+ <path d="M195,195 L184,190 L190,184 L195,195" class="shape-style" />
+ <polyline points="195,195 180,180" stroke="black" stroke-width="2" fill="none" class="line-style" />
+ <text x="115" y="175" fill="black" font-size="14px" font-family="arial"
+ class="text-style">(100, 100)</text>
+
+ <polyline points="-3,-3 3,3" stroke="black" stroke-width="2" class="line-style" />
+ <polyline points="-3,3 3,-3" stroke="black" stroke-width="2" class="line-style" />
+</g>
+
+<g transform="translate(45,235)">
+ <path d="M 0,0 c 0,25 10,35 25,35" stroke="black" stroke-width="2" fill="none" class="line-style" />
+ <path d="M 25,30 l 10,5 l -10,5 z" class="shape-style" />
+ <text x="40" y="40" fill="black" font-size="14px" font-family="monospace"
+ class="mono-text-style">setWindow(-50, -50, 100, 100)</text>
+ <path d="M 290,35 c 15,0 25,-10 25,-35" stroke="black" stroke-width="2" fill="none" class="line-style" />
+ <path d="M 315,0 l 5,10 l -10,0 z" class="shape-style" />
+</g>
+
+<text x="300" y="20" fill="black" font-size="14px" font-family="arial"
+ font-weight="bold"
+ class="heading-style">"Window" coordinates</text>
+
+<g transform="translate(280, 30)">
+
+ <rect x="0" y="0" width="200" height="200" stroke="red" fill="none" stroke-dasharray="4,3" stroke-dashoffset="0"
+ class="window-dash-style" />
+
+ <path d="M5,5 L16,10 L10,16 L5,5" fill="red" class="window-shape-style" />
+ <polyline points="5,5 20,20" stroke="red" stroke-width="2" fill="none" class="window-line-style" />
+ <text x="25" y="30" fill="red" font-size="14px" font-family="arial"
+ class="window-text-style">(-50, -50)</text>
+
+ <path d="M195,195 L184,190 L190,184 L195,195" fill="red" class="window-shape-style" />
+ <polyline points="195,195 180,180" stroke="red" stroke-width="2" fill="none" class="window-line-style" />
+ <text x="130" y="175" fill="red" font-size="14px" font-family="arial"
+ class="window-text-style">(50, 50)</text>
+
+ <polyline points="97,97 103,103" stroke="red" stroke-width="2" class="window-line-style" />
+ <polyline points="97,103 103,97" stroke="red" stroke-width="2" class="window-line-style" />
+</g>
+
+<g transform="translate(395,235)">
+ <path d="M 0,0 c 0,25 10,35 25,35" stroke="black" stroke-width="2" fill="none" class="line-style" />
+ <path d="M 25,30 l 10,5 l -10,5 z" class="shape-style" />
+ <text x="40" y="40" fill="black" font-size="14px" font-family="monospace"
+ class="mono-text-style">setViewport(45, 25, 50, 50)</text>
+ <path d="M 270,35 c 15,0 25,-10 25,-35" stroke="black" stroke-width="2" fill="none" class="line-style" />
+ <path d="M 295,0 l 5,10 l -10,0 z" class="shape-style" />
+</g>
+
+<text x="570" y="20" fill="black" font-size="14px" font-family="arial"
+ font-weight="bold"
+ class="heading-style">Device coordinates</text>
+
+<g transform="translate(540, 30)">
+
+ <rect x="0" y="0" width="200" height="200" stroke="black" stroke-width="2" fill="none" class="line-style" />
+
+ <path d="M5,5 L16,10 L10,16 L5,5" class="shape-style" />
+ <polyline points="5,5 20,20" stroke="black" stroke-width="2" fill="none" class="line-style" />
+ <text x="25" y="30" fill="black" font-size="14px" font-family="arial"
+ class="text-style">(0, 0)</text>
+
+ <path d="M195,195 L184,190 L190,184 L195,195" class="shape-style" />
+ <polyline points="195,195 180,180" stroke="black" stroke-width="2" fill="none" class="line-style" />
+ <text x="115" y="175" fill="black" font-size="14px" font-family="arial"
+ class="text-style">(100, 100)</text>
+
+ <rect x="90" y="50" width="100" height="100" stroke="red" fill="none" stroke-dasharray="4,3" stroke-dashoffset="0"
+ class="window-dash-style" />
+ <polyline points="137,97 143,103" stroke="red" stroke-width="2" class="window-line-style" />
+ <polyline points="137,103 143,97" stroke="red" stroke-width="2" class="window-line-style" />
+</g>
+
+</svg>
diff --git a/src/gui/doc/qtgui.qdocconf b/src/gui/doc/qtgui.qdocconf
index 24d9d522735..8b7569c1296 100644
--- a/src/gui/doc/qtgui.qdocconf
+++ b/src/gui/doc/qtgui.qdocconf
@@ -50,7 +50,8 @@ depends += \
qtshadertools \
qttestlib \
qtplatformintegration \
- qthelp
+ qthelp \
+ qtquickcontrols
headerdirs += ..
diff --git a/src/gui/doc/src/coordsys.qdoc b/src/gui/doc/src/coordsys.qdoc
index 3dd064c19bc..22e14121af6 100644
--- a/src/gui/doc/src/coordsys.qdoc
+++ b/src/gui/doc/src/coordsys.qdoc
@@ -321,7 +321,7 @@
still transformed to the viewport using the same linear algebraic
approach.
- \image coordinatesystem-transformations.png {Illustration showing
+ \image coordinatesystem-transformations.svg {Illustration showing
how coordinates are mapped using viewport, "window" and
transformation matrix}
diff --git a/src/gui/doc/src/external-resources.qdoc b/src/gui/doc/src/external-resources.qdoc
index 0f356dd5046..14ed0817e62 100644
--- a/src/gui/doc/src/external-resources.qdoc
+++ b/src/gui/doc/src/external-resources.qdoc
@@ -36,6 +36,7 @@
\externalpage https://specifications.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html
\title Freedesktop Icon Naming Specification
*/
+
/*!
\externalpage https://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html#directory_layout
\title Icon Theme Specification - Directory Layout
diff --git a/src/gui/itemmodels/qfileinfogatherer.cpp b/src/gui/itemmodels/qfileinfogatherer.cpp
index b7ab3dbbc46..ea19db0d20f 100644
--- a/src/gui/itemmodels/qfileinfogatherer.cpp
+++ b/src/gui/itemmodels/qfileinfogatherer.cpp
@@ -46,6 +46,12 @@ static QString translateDriveName(const QFileInfo &drive)
}
/*!
+ \class QFileInfoGatherer
+ \inmodule QtGui
+ \internal
+*/
+
+/*!
Creates thread
*/
QFileInfoGatherer::QFileInfoGatherer(QObject *parent)
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index 741b089306e..e8df40f21b2 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -490,6 +490,12 @@ static QWindowGeometrySpecification windowGeometrySpecification = Q_WINDOW_GEOME
*/
/*!
+ \class QGuiApplicationPrivate
+ \inmodule QtGui
+ \internal
+*/
+
+/*!
Initializes the window system and constructs an application object with
\a argc command line arguments in \a argv.
diff --git a/src/gui/kernel/qplatformintegrationfactory.cpp b/src/gui/kernel/qplatformintegrationfactory.cpp
index d0a5e8871f8..d113e86090d 100644
--- a/src/gui/kernel/qplatformintegrationfactory.cpp
+++ b/src/gui/kernel/qplatformintegrationfactory.cpp
@@ -24,6 +24,7 @@ QPlatformIntegration *QPlatformIntegrationFactory::create(const QString &platfor
}
/*!
+ \internal
Returns the list of valid keys, i.e. the keys this factory can
create styles for.
diff --git a/src/gui/kernel/qplatformthemefactory.cpp b/src/gui/kernel/qplatformthemefactory.cpp
index beefa1c2942..3ac462598fd 100644
--- a/src/gui/kernel/qplatformthemefactory.cpp
+++ b/src/gui/kernel/qplatformthemefactory.cpp
@@ -31,6 +31,7 @@ QPlatformTheme *QPlatformThemeFactory::create(const QString& key, const QString
}
/*!
+ \internal
Returns the list of valid keys, i.e. the keys this factory can
create styles for.
diff --git a/src/gui/kernel/qsurface.cpp b/src/gui/kernel/qsurface.cpp
index e2bafa73988..f361ec86c2d 100644
--- a/src/gui/kernel/qsurface.cpp
+++ b/src/gui/kernel/qsurface.cpp
@@ -68,7 +68,10 @@ QT_IMPL_METATYPE_EXTERN_TAGGED(QSurface*, QSurface_ptr)
bool QSurface::supportsOpenGL() const
{
- return surfaceType() == OpenGLSurface;
+ static bool openGLOnRasterSurfaceSupported =
+ QGuiApplicationPrivate::instance()->platformIntegration()->hasCapability(QPlatformIntegration::OpenGLOnRasterSurface);
+ return surfaceType() == OpenGLSurface
+ || (surfaceType() == RasterSurface && openGLOnRasterSurfaceSupported);
}
/*!
diff --git a/src/gui/math3d/qmatrix4x4.cpp b/src/gui/math3d/qmatrix4x4.cpp
index 95b9524172f..ec6e696ba00 100644
--- a/src/gui/math3d/qmatrix4x4.cpp
+++ b/src/gui/math3d/qmatrix4x4.cpp
@@ -294,6 +294,7 @@ double QMatrix4x4::determinant() const
if ((flagBits & ~(Translation | Rotation2D | Rotation)) == Identity)
return 1.0;
+ Q_DECL_UNINITIALIZED
double mm[4][4];
copyToDoubles(m, mm);
if (flagBits < Rotation2D)
@@ -355,8 +356,10 @@ QMatrix4x4 QMatrix4x4::inverted(bool *invertible) const
*invertible = true;
return orthonormalInverse();
} else if (flagBits < Perspective) {
+ Q_DECL_UNINITIALIZED
QMatrix4x4 inv(Qt::Uninitialized);
+ Q_DECL_UNINITIALIZED
double mm[4][4];
copyToDoubles(m, mm);
@@ -391,8 +394,10 @@ QMatrix4x4 QMatrix4x4::inverted(bool *invertible) const
return inv;
}
+ Q_DECL_UNINITIALIZED
QMatrix4x4 inv(Qt::Uninitialized);
+ Q_DECL_UNINITIALIZED
double mm[4][4];
copyToDoubles(m, mm);
@@ -465,6 +470,7 @@ QMatrix3x3 QMatrix4x4::normalMatrix() const
return inv;
}
+ Q_DECL_UNINITIALIZED
double mm[4][4];
copyToDoubles(m, mm);
double det = matrixDet3(mm, 0, 1, 2, 0, 1, 2);
@@ -493,6 +499,7 @@ QMatrix3x3 QMatrix4x4::normalMatrix() const
*/
QMatrix4x4 QMatrix4x4::transposed() const
{
+ Q_DECL_UNINITIALIZED
QMatrix4x4 result(Qt::Uninitialized);
for (int row = 0; row < 4; ++row) {
for (int col = 0; col < 4; ++col) {
@@ -709,6 +716,7 @@ QMatrix4x4& QMatrix4x4::operator/=(float divisor)
*/
QMatrix4x4 operator/(const QMatrix4x4& matrix, float divisor)
{
+ Q_DECL_UNINITIALIZED
QMatrix4x4 m(Qt::Uninitialized);
m.m[0][0] = matrix.m[0][0] / divisor;
m.m[0][1] = matrix.m[0][1] / divisor;
@@ -1141,6 +1149,7 @@ void QMatrix4x4::rotate(float angle, float x, float y, float z)
z = float(double(z) / len);
}
float ic = 1.0f - c;
+ Q_DECL_UNINITIALIZED
QMatrix4x4 rot(Qt::Uninitialized);
rot.m[0][0] = x * x * ic + c;
rot.m[1][0] = x * y * ic - z * s;
@@ -1244,6 +1253,7 @@ void QMatrix4x4::projectedRotate(float angle, float x, float y, float z, float d
z = float(double(z) / len);
}
const float ic = 1.0f - c;
+ Q_DECL_UNINITIALIZED
QMatrix4x4 rot(Qt::Uninitialized);
rot.m[0][0] = x * x * ic + c;
rot.m[1][0] = x * y * ic - z * s;
@@ -1306,6 +1316,7 @@ void QMatrix4x4::rotate(const QQuaternion& quaternion)
// Algorithm from:
// http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q54
+ Q_DECL_UNINITIALIZED
QMatrix4x4 m(Qt::Uninitialized);
const float f2x = quaternion.x() + quaternion.x();
@@ -1393,6 +1404,7 @@ void QMatrix4x4::ortho(float left, float right, float bottom, float top, float n
const float width = right - left;
const float invheight = top - bottom;
const float clip = farPlane - nearPlane;
+ Q_DECL_UNINITIALIZED
QMatrix4x4 m(Qt::Uninitialized);
m.m[0][0] = 2.0f / width;
m.m[1][0] = 0.0f;
@@ -1431,6 +1443,7 @@ void QMatrix4x4::frustum(float left, float right, float bottom, float top, float
return;
// Construct the projection.
+ Q_DECL_UNINITIALIZED
QMatrix4x4 m(Qt::Uninitialized);
const float width = right - left;
const float invheight = top - bottom;
@@ -1474,6 +1487,7 @@ void QMatrix4x4::perspective(float verticalAngle, float aspectRatio, float nearP
return;
// Construct the projection.
+ Q_DECL_UNINITIALIZED
QMatrix4x4 m(Qt::Uninitialized);
const float radians = qDegreesToRadians(verticalAngle / 2.0f);
const float sine = std::sin(radians);
@@ -1524,6 +1538,7 @@ void QMatrix4x4::lookAt(const QVector3D& eye, const QVector3D& center, const QVe
QVector3D side = QVector3D::crossProduct(forward, up).normalized();
QVector3D upVector = QVector3D::crossProduct(side, forward);
+ Q_DECL_UNINITIALIZED
QMatrix4x4 m(Qt::Uninitialized);
m.m[0][0] = side.x();
m.m[1][0] = side.y();
@@ -1573,6 +1588,7 @@ void QMatrix4x4::viewport(float left, float bottom, float width, float height, f
const float w2 = width / 2.0f;
const float h2 = height / 2.0f;
+ Q_DECL_UNINITIALIZED
QMatrix4x4 m(Qt::Uninitialized);
m.m[0][0] = w2;
m.m[1][0] = 0.0f;
@@ -1871,6 +1887,7 @@ QRectF QMatrix4x4::mapRect(const QRectF& rect) const
// of just rotations and translations.
QMatrix4x4 QMatrix4x4::orthonormalInverse() const
{
+ Q_DECL_UNINITIALIZED
QMatrix4x4 result(Qt::Uninitialized);
result.m[0][0] = m[0][0];
@@ -1943,6 +1960,7 @@ void QMatrix4x4::optimize()
flagBits &= ~Scale;
} else {
// If the columns are orthonormal and form a right-handed system, then there is no scale.
+ Q_DECL_UNINITIALIZED
double mm[4][4];
copyToDoubles(m, mm);
double det = matrixDet2(mm, 0, 1, 0, 1);
@@ -1957,6 +1975,7 @@ void QMatrix4x4::optimize()
}
} else {
// If the columns are orthonormal and form a right-handed system, then there is no scale.
+ Q_DECL_UNINITIALIZED
double mm[4][4];
copyToDoubles(m, mm);
double det = matrixDet3(mm, 0, 1, 2, 0, 1, 2);
diff --git a/src/gui/math3d/qmatrix4x4.h b/src/gui/math3d/qmatrix4x4.h
index 94f9c12f19b..2a801905ce0 100644
--- a/src/gui/math3d/qmatrix4x4.h
+++ b/src/gui/math3d/qmatrix4x4.h
@@ -564,6 +564,7 @@ inline bool QMatrix4x4::operator!=(const QMatrix4x4& other) const
inline QMatrix4x4 operator+(const QMatrix4x4& m1, const QMatrix4x4& m2)
{
+ Q_DECL_UNINITIALIZED
QMatrix4x4 m(Qt::Uninitialized);
m.m[0][0] = m1.m[0][0] + m2.m[0][0];
m.m[0][1] = m1.m[0][1] + m2.m[0][1];
@@ -586,6 +587,7 @@ inline QMatrix4x4 operator+(const QMatrix4x4& m1, const QMatrix4x4& m2)
inline QMatrix4x4 operator-(const QMatrix4x4& m1, const QMatrix4x4& m2)
{
+ Q_DECL_UNINITIALIZED
QMatrix4x4 m(Qt::Uninitialized);
m.m[0][0] = m1.m[0][0] - m2.m[0][0];
m.m[0][1] = m1.m[0][1] - m2.m[0][1];
@@ -608,9 +610,11 @@ inline QMatrix4x4 operator-(const QMatrix4x4& m1, const QMatrix4x4& m2)
inline QMatrix4x4 operator*(const QMatrix4x4& m1, const QMatrix4x4& m2)
{
+ Q_DECL_UNINITIALIZED
+ QMatrix4x4 m(Qt::Uninitialized);
QMatrix4x4::Flags flagBits = m1.flagBits | m2.flagBits;
if (flagBits.toInt() < QMatrix4x4::Rotation2D) {
- QMatrix4x4 m(Qt::Uninitialized);
+ // Scale | Translation
m.m[0][0] = m1.m[0][0] * m2.m[0][0];
m.m[0][1] = 0.0f;
m.m[0][2] = 0.0f;
@@ -634,7 +638,6 @@ inline QMatrix4x4 operator*(const QMatrix4x4& m1, const QMatrix4x4& m2)
return m;
}
- QMatrix4x4 m(Qt::Uninitialized);
m.m[0][0] = m1.m[0][0] * m2.m[0][0]
+ m1.m[1][0] * m2.m[0][1]
+ m1.m[2][0] * m2.m[0][2]
@@ -855,6 +858,7 @@ inline QPointF operator*(const QMatrix4x4& matrix, const QPointF& point)
inline QMatrix4x4 operator-(const QMatrix4x4& matrix)
{
+ Q_DECL_UNINITIALIZED
QMatrix4x4 m(Qt::Uninitialized);
m.m[0][0] = -matrix.m[0][0];
m.m[0][1] = -matrix.m[0][1];
@@ -877,6 +881,7 @@ inline QMatrix4x4 operator-(const QMatrix4x4& matrix)
inline QMatrix4x4 operator*(float factor, const QMatrix4x4& matrix)
{
+ Q_DECL_UNINITIALIZED
QMatrix4x4 m(Qt::Uninitialized);
m.m[0][0] = matrix.m[0][0] * factor;
m.m[0][1] = matrix.m[0][1] * factor;
@@ -899,6 +904,7 @@ inline QMatrix4x4 operator*(float factor, const QMatrix4x4& matrix)
inline QMatrix4x4 operator*(const QMatrix4x4& matrix, float factor)
{
+ Q_DECL_UNINITIALIZED
QMatrix4x4 m(Qt::Uninitialized);
m.m[0][0] = matrix.m[0][0] * factor;
m.m[0][1] = matrix.m[0][1] * factor;
diff --git a/src/gui/opengl/platform/egl/qeglplatformcontext.cpp b/src/gui/opengl/platform/egl/qeglplatformcontext.cpp
index e56504833d1..350968b87d4 100644
--- a/src/gui/opengl/platform/egl/qeglplatformcontext.cpp
+++ b/src/gui/opengl/platform/egl/qeglplatformcontext.cpp
@@ -104,6 +104,14 @@ QT_BEGIN_NAMESPACE
#define GL_LOSE_CONTEXT_ON_RESET 0x8252
#endif
+// Constants from GL_EXT_robustness.
+#ifndef GL_RESET_NOTIFICATION_STRATEGY_EXT
+#define GL_RESET_NOTIFICATION_STRATEGY_EXT 0x8256
+#endif
+#ifndef GL_LOSE_CONTEXT_ON_RESET_EXT
+#define GL_LOSE_CONTEXT_ON_RESET_EXT 0x8252
+#endif
+
// Constants from EGL_NV_robustness_video_memory_purge
#ifndef EGL_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV
#define EGL_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV 0x334C
@@ -452,11 +460,16 @@ void QEGLPlatformContext::updateFormatFromGL()
}
}
}
- if (hasExtension("GL_ARB_robustness")) {
+ if (m_format.renderableType() == QSurfaceFormat::OpenGL && hasExtension("GL_ARB_robustness")) {
GLint value = 0;
glGetIntegerv(GL_RESET_NOTIFICATION_STRATEGY, &value);
if (value == GL_LOSE_CONTEXT_ON_RESET)
m_format.setOption(QSurfaceFormat::ResetNotification);
+ } else if (m_format.renderableType() == QSurfaceFormat::OpenGLES && hasExtension("GL_EXT_robustness")) {
+ GLint value = 0;
+ glGetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_EXT, &value);
+ if (value == GL_LOSE_CONTEXT_ON_RESET_EXT)
+ m_format.setOption(QSurfaceFormat::ResetNotification);
}
}
runGLChecks();
diff --git a/src/gui/opengl/qopenglfunctions.cpp b/src/gui/opengl/qopenglfunctions.cpp
index 6b45d26fb4c..cb927d7c296 100644
--- a/src/gui/opengl/qopenglfunctions.cpp
+++ b/src/gui/opengl/qopenglfunctions.cpp
@@ -192,6 +192,12 @@ QOpenGLFunctions::QOpenGLFunctions(QOpenGLContext *context)
qWarning("QOpenGLFunctions created with non-current context");
}
+/*!
+ \class QOpenGLExtensions
+ \inmodule QtGui
+ \internal
+*/
+
QOpenGLExtensions::QOpenGLExtensions()
{
}
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index 047be5f1c3d..8e815394849 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -2881,6 +2881,7 @@ bool QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs,
/*!
+ * \internal
* Returns \c true if the rectangle is completely within the current clip
* state of the paint engine.
*/
diff --git a/src/gui/painting/qpainterpath.h b/src/gui/painting/qpainterpath.h
index cc80641ded9..ab9e7fe312a 100644
--- a/src/gui/painting/qpainterpath.h
+++ b/src/gui/painting/qpainterpath.h
@@ -6,9 +6,11 @@
#include <QtGui/qtguiglobal.h>
#include <QtGui/qtransform.h>
+
#include <QtCore/qglobal.h>
#include <QtCore/qline.h>
#include <QtCore/qlist.h>
+#include <QtCore/qpoint.h>
#include <QtCore/qrect.h>
QT_BEGIN_NAMESPACE
diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp
index 908051a477c..b1ea3f240f1 100644
--- a/src/gui/painting/qpdf.cpp
+++ b/src/gui/painting/qpdf.cpp
@@ -3192,6 +3192,7 @@ static inline bool is_monochrome(const QList<QRgb> &colorTable)
}
/*!
+ * \internal
* Adds an image to the pdf and return the pdf-object id. Returns -1 if adding the image failed.
*/
int QPdfEnginePrivate::addImage(const QImage &img, bool *bitmap, bool lossless, qint64 serial_no)
diff --git a/src/gui/painting/qstroker.cpp b/src/gui/painting/qstroker.cpp
index 0d435c95048..08128c30a70 100644
--- a/src/gui/painting/qstroker.cpp
+++ b/src/gui/painting/qstroker.cpp
@@ -145,6 +145,11 @@ static inline qreal adapted_angle_on_x(const QLineF &line)
return QLineF(0, 0, 1, 0).angleTo(line);
}
+/*!
+ \class QStrokerOps
+ \inmodule QtGui
+ \internal
+*/
QStrokerOps::QStrokerOps()
: m_elements(0)
, m_curveThreshold(qt_real_to_fixed(0.25))
@@ -373,6 +378,7 @@ QStroker::LineJoinMode QStroker::joinModeForJoin(Qt::PenJoinStyle joinStyle)
/*!
+ \internal
This function is called to stroke the currently built up
subpath. The subpath is cleared when the function completes.
*/
diff --git a/src/gui/platform/unix/dbusmenu/qdbusplatformmenu.cpp b/src/gui/platform/unix/dbusmenu/qdbusplatformmenu.cpp
index fe050461260..00c3192e00a 100644
--- a/src/gui/platform/unix/dbusmenu/qdbusplatformmenu.cpp
+++ b/src/gui/platform/unix/dbusmenu/qdbusplatformmenu.cpp
@@ -48,6 +48,7 @@ void QDBusPlatformMenuItem::setIcon(const QIcon &icon)
}
/*!
+ \internal
Set a submenu under this menu item.
*/
void QDBusPlatformMenuItem::setMenu(QPlatformMenu *menu)
diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp
index 33e35ba6694..202e28263c2 100644
--- a/src/gui/rhi/qrhivulkan.cpp
+++ b/src/gui/rhi/qrhivulkan.cpp
@@ -682,6 +682,12 @@ bool QRhiVulkan::create(QRhi::Flags flags)
if (devExts.contains("VK_KHR_fragment_shading_rate"))
addToChain(&physDevFeaturesChainable, &fragmentShadingRateFeatures);
#endif
+#ifdef VK_EXT_device_fault
+ VkPhysicalDeviceFaultFeaturesEXT deviceFaultFeatures = {};
+ deviceFaultFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FAULT_FEATURES_EXT;
+ if (devExts.contains(VK_EXT_DEVICE_FAULT_EXTENSION_NAME))
+ addToChain(&physDevFeaturesChainable, &deviceFaultFeatures);
+#endif
#endif
// Vulkan >=1.2 headers at build time, >=1.2 implementation at run time
@@ -825,6 +831,13 @@ bool QRhiVulkan::create(QRhi::Flags flags)
requestedDevExts.append(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME);
#endif
+#ifdef VK_EXT_device_fault
+ if (devExts.contains(VK_EXT_DEVICE_FAULT_EXTENSION_NAME)) {
+ requestedDevExts.append(VK_EXT_DEVICE_FAULT_EXTENSION_NAME);
+ caps.deviceFault = true;
+ }
+#endif
+
for (const QByteArray &ext : requestedDeviceExtensions) {
if (!ext.isEmpty() && !requestedDevExts.contains(ext)) {
if (devExts.contains(ext)) {
@@ -910,6 +923,7 @@ bool QRhiVulkan::create(QRhi::Flags flags)
// Here we have no way to tell if the extensions got enabled or not.
// Pretend it's all there and supported. If getProcAddress fails, we'll
// handle that gracefully.
+ caps.deviceFault = true;
caps.vertexAttribDivisor = true;
caps.renderPass2KHR = true;
caps.depthStencilResolveKHR = true;
@@ -1126,6 +1140,12 @@ bool QRhiVulkan::create(QRhi::Flags flags)
}
#endif
+#ifdef VK_EXT_device_fault
+ if (caps.deviceFault) {
+ vkGetDeviceFaultInfoEXT = reinterpret_cast<PFN_vkGetDeviceFaultInfoEXT>(f->vkGetDeviceProcAddr(dev, "vkGetDeviceFaultInfoEXT"));
+ }
+#endif
+
deviceLost = false;
nativeHandlesStruct.physDev = physDev;
@@ -2643,6 +2663,7 @@ QRhi::FrameOpResult QRhiVulkan::beginFrame(QRhiSwapChain *swapChain, QRhi::Begin
} else {
if (err == VK_ERROR_DEVICE_LOST) {
qWarning("Device loss detected in vkAcquireNextImageKHR()");
+ printExtraErrorInfo(err);
deviceLost = true;
return QRhi::FrameOpDeviceLost;
}
@@ -2803,6 +2824,7 @@ QRhi::FrameOpResult QRhiVulkan::endFrame(QRhiSwapChain *swapChain, QRhi::EndFram
} else if (err != VK_SUBOPTIMAL_KHR) {
if (err == VK_ERROR_DEVICE_LOST) {
qWarning("Device loss detected in vkQueuePresentKHR()");
+ printExtraErrorInfo(err);
deviceLost = true;
return QRhi::FrameOpDeviceLost;
}
@@ -2862,6 +2884,7 @@ QRhi::FrameOpResult QRhiVulkan::startPrimaryCommandBuffer(VkCommandBuffer *cb)
if (err != VK_SUCCESS) {
if (err == VK_ERROR_DEVICE_LOST) {
qWarning("Device loss detected in vkAllocateCommandBuffers()");
+ printExtraErrorInfo(err);
deviceLost = true;
return QRhi::FrameOpDeviceLost;
}
@@ -2877,6 +2900,7 @@ QRhi::FrameOpResult QRhiVulkan::startPrimaryCommandBuffer(VkCommandBuffer *cb)
if (err != VK_SUCCESS) {
if (err == VK_ERROR_DEVICE_LOST) {
qWarning("Device loss detected in vkBeginCommandBuffer()");
+ printExtraErrorInfo(err);
deviceLost = true;
return QRhi::FrameOpDeviceLost;
}
@@ -2894,6 +2918,7 @@ QRhi::FrameOpResult QRhiVulkan::endAndSubmitPrimaryCommandBuffer(VkCommandBuffer
if (err != VK_SUCCESS) {
if (err == VK_ERROR_DEVICE_LOST) {
qWarning("Device loss detected in vkEndCommandBuffer()");
+ printExtraErrorInfo(err);
deviceLost = true;
return QRhi::FrameOpDeviceLost;
}
@@ -2930,6 +2955,7 @@ QRhi::FrameOpResult QRhiVulkan::endAndSubmitPrimaryCommandBuffer(VkCommandBuffer
if (err != VK_SUCCESS) {
if (err == VK_ERROR_DEVICE_LOST) {
qWarning("Device loss detected in vkQueueSubmit()");
+ printExtraErrorInfo(err);
deviceLost = true;
return QRhi::FrameOpDeviceLost;
}
@@ -2951,6 +2977,7 @@ QRhi::FrameOpResult QRhiVulkan::waitCommandCompletion(int frameSlot)
if (err != VK_SUCCESS) {
if (err == VK_ERROR_DEVICE_LOST) {
qWarning("Device loss detected in vkWaitForFences()");
+ printExtraErrorInfo(err);
deviceLost = true;
return QRhi::FrameOpDeviceLost;
}
@@ -4079,10 +4106,87 @@ void QRhiVulkan::prepareUploadSubres(QVkTexture *texD, int layer, int level,
void QRhiVulkan::printExtraErrorInfo(VkResult err)
{
+ if (err == VK_ERROR_DEVICE_LOST)
+ printDeviceLossErrorInfo();
if (err == VK_ERROR_OUT_OF_DEVICE_MEMORY)
qWarning() << "Out of device memory, current allocator statistics are" << statistics();
}
+void QRhiVulkan::printDeviceLossErrorInfo() const
+{
+#ifdef VK_EXT_device_fault
+ if (!dev || !caps.deviceFault || !vkGetDeviceFaultInfoEXT)
+ return;
+
+ VkDeviceFaultCountsEXT faultCounts{};
+ faultCounts.sType = VK_STRUCTURE_TYPE_DEVICE_FAULT_COUNTS_EXT;
+ faultCounts.pNext = nullptr;
+
+ VkResult result = vkGetDeviceFaultInfoEXT(dev, &faultCounts, nullptr);
+ if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
+ qWarning("vkGetDeviceFaultInfoEXT failed with %d", result);
+ return;
+ }
+ faultCounts.vendorBinarySize = 0;
+
+ QVarLengthArray<VkDeviceFaultAddressInfoEXT> addressInfos;
+ addressInfos.resize(faultCounts.addressInfoCount);
+
+ QVarLengthArray<VkDeviceFaultVendorInfoEXT> vendorInfos;
+ vendorInfos.resize(faultCounts.vendorInfoCount);
+
+ VkDeviceFaultInfoEXT info{};
+ info.sType = VK_STRUCTURE_TYPE_DEVICE_FAULT_INFO_EXT;
+ info.pNext = nullptr;
+ info.pAddressInfos = addressInfos.isEmpty() ? nullptr : addressInfos.data();
+ info.pVendorInfos = vendorInfos.isEmpty() ? nullptr : vendorInfos.data();
+ info.pVendorBinaryData = nullptr;
+
+ result = vkGetDeviceFaultInfoEXT(dev, &faultCounts, &info);
+ if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
+ qWarning("vkGetDeviceFaultInfoEXT failed with %d", result);
+ return;
+ }
+
+ const char *desc = info.description[0] ? info.description : "n/a";
+ qWarning("VK_ERROR_DEVICE_LOST (VK_EXT_device_fault): %u address infos, %u vendor infos, %llu bytes vendor binary: %s",
+ faultCounts.addressInfoCount,
+ faultCounts.vendorInfoCount,
+ (unsigned long long)faultCounts.vendorBinarySize,
+ desc);
+
+ for (uint32_t i = 0; i < faultCounts.addressInfoCount; ++i) {
+ const auto &a = addressInfos[i];
+ auto addressTypeString = [](const VkDeviceFaultAddressTypeEXT type) {
+ switch (type) {
+ case VK_DEVICE_FAULT_ADDRESS_TYPE_NONE_EXT: return "NONE";
+ case VK_DEVICE_FAULT_ADDRESS_TYPE_READ_INVALID_EXT: return "READ_INVALID";
+ case VK_DEVICE_FAULT_ADDRESS_TYPE_WRITE_INVALID_EXT: return "WRITE_INVALID";
+ case VK_DEVICE_FAULT_ADDRESS_TYPE_EXECUTE_INVALID_EXT: return "EXECUTE_INVALID";
+ case VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_UNKNOWN_EXT: return "INSTRUCTION_POINTER_UNKNOWN";
+ case VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_INVALID_EXT: return "INSTRUCTION_POINTER_INVALID";
+ case VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_FAULT_EXT: return "INSTRUCTION_POINTER_FAULT";
+ default: return "UNKNOWN";
+ };
+ };
+ qWarning(" AddressInfo[%02u]: type=%s addr=0x%llx precision=%llu",
+ i,
+ addressTypeString(a.addressType),
+ (unsigned long long)a.reportedAddress,
+ (unsigned long long)a.addressPrecision);
+ }
+
+ for (uint32_t i = 0; i < faultCounts.vendorInfoCount; ++i) {
+ const auto &v = vendorInfos[i];
+ qWarning(" VendorInfo[%02u]: code=%llu data=%llu desc=%s",
+ i,
+ (unsigned long long)v.vendorFaultCode,
+ (unsigned long long)v.vendorFaultData,
+ v.description);
+ }
+#endif // VK_EXT_device_fault
+}
+
void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdateBatch *resourceUpdates)
{
QRhiResourceUpdateBatchPrivate *ud = QRhiResourceUpdateBatchPrivate::get(resourceUpdates);
diff --git a/src/gui/rhi/qrhivulkan_p.h b/src/gui/rhi/qrhivulkan_p.h
index 21044545ad2..eb07d8be448 100644
--- a/src/gui/rhi/qrhivulkan_p.h
+++ b/src/gui/rhi/qrhivulkan_p.h
@@ -882,6 +882,7 @@ public:
void ensureCommandPoolForNewFrame();
double elapsedSecondsFromTimestamp(quint64 timestamp[2], bool *ok);
void printExtraErrorInfo(VkResult err);
+ void printDeviceLossErrorInfo() const;
QVulkanInstance *inst = nullptr;
QWindow *maybeWindow = nullptr;
@@ -942,11 +943,16 @@ public:
PFN_vkCreateRenderPass2KHR vkCreateRenderPass2KHR = nullptr;
#endif
+#ifdef VK_EXT_device_fault
+ PFN_vkGetDeviceFaultInfoEXT vkGetDeviceFaultInfoEXT = nullptr;
+#endif
+
struct {
bool compute = false;
bool depthClamp = false;
bool wideLines = false;
bool debugUtils = false;
+ bool deviceFault = false;
bool vertexAttribDivisor = false;
bool texture3DSliceAs2D = false;
bool tessellation = false;
diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp
index c144820fa24..ba49d538c2c 100644
--- a/src/gui/text/qfont.cpp
+++ b/src/gui/text/qfont.cpp
@@ -31,6 +31,7 @@
#include <QtCore/QMutexLocker>
#include <QtCore/QMutex>
+#include <algorithm>
#include <array>
// #define QFONTCACHE_DEBUG
@@ -1853,35 +1854,13 @@ bool QFont::operator<(const QFont &f) const
int f2attrs = (d->underline << 3) + (d->overline << 2) + (d->strikeOut<<1) + d->kerning;
if (f1attrs != f2attrs) return f1attrs < f2attrs;
- if (d->features.size() != f.d->features.size())
- return f.d->features.size() < d->features.size();
-
- {
- auto it = d->features.constBegin();
- auto jt = f.d->features.constBegin();
- for (; it != d->features.constEnd(); ++it, ++jt) {
- if (it.key() != jt.key())
- return jt.key() < it.key();
- if (it.value() != jt.value())
- return jt.value() < it.value();
- }
- }
-
- if (r1.variableAxisValues.size() != r2.variableAxisValues.size())
- return r1.variableAxisValues.size() < r2.variableAxisValues.size();
-
- {
- auto it = r1.variableAxisValues.constBegin();
- auto jt = r2.variableAxisValues.constBegin();
- for (; it != r1.variableAxisValues.constEnd(); ++it, ++jt) {
- if (it.key() != jt.key())
- return jt.key() < it.key();
- if (it.value() != jt.value())
- return jt.value() < it.value();
- }
+ if (d->features != f.d->features) {
+ return std::lexicographical_compare(f.d->features.keyValueBegin(), f.d->features.keyValueEnd(),
+ d->features.keyValueBegin(), d->features.keyValueEnd());
}
- return false;
+ return std::lexicographical_compare(r1.variableAxisValues.keyValueBegin(), r1.variableAxisValues.keyValueEnd(),
+ r2.variableAxisValues.keyValueBegin(), r2.variableAxisValues.keyValueEnd());
}
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
index d41296291f6..4df55d5b89c 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -402,7 +402,7 @@ bool QFontEngine::processHheaTable() const
const qreal unitsPerEm = emSquareSize().toReal();
// Bail out if values are too large for QFixed
- const auto limitForQFixed = qreal(std::numeric_limits<int>::max() / 64) / fontDef.pixelSize;
+ const auto limitForQFixed = qreal(std::numeric_limits<int>::max() >> 6) / fontDef.pixelSize;
if (ascent > limitForQFixed || descent > limitForQFixed || leading > limitForQFixed)
return false;
m_ascent = QFixed::fromReal(ascent * fontDef.pixelSize / unitsPerEm);
@@ -470,7 +470,7 @@ bool QFontEngine::processOS2Table() const
if (typoAscent == 0 && typoDescent == 0)
return false;
// Bail out if values are too large for QFixed
- const auto limitForQFixed = qreal(std::numeric_limits<int>::max() / 64) / fontDef.pixelSize;
+ const auto limitForQFixed = qreal(std::numeric_limits<int>::max() >> 6) / fontDef.pixelSize;
if (typoAscent > limitForQFixed || typoDescent > limitForQFixed
|| typoLineGap > limitForQFixed)
return false;
@@ -481,7 +481,7 @@ bool QFontEngine::processOS2Table() const
// Some fonts may have invalid OS/2 data. We detect this and bail out.
if (winAscent == 0 && winDescent == 0)
return false;
- const auto limitForQFixed = qreal(std::numeric_limits<int>::max() / 64) / fontDef.pixelSize;
+ const auto limitForQFixed = qreal(std::numeric_limits<int>::max() >> 6) / fontDef.pixelSize;
if (winAscent > limitForQFixed || winDescent > limitForQFixed)
return false;
m_ascent = QFixed::fromReal(winAscent * fontDef.pixelSize / unitsPerEm);
@@ -1059,6 +1059,7 @@ void QFontEngine::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metr
}
/*!
+ \internal
Returns \c true if the font table idetified by \a tag exists in the font;
returns \c false otherwise.
diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp
index 4f01d09fed1..d519cd5a5d3 100644
--- a/src/gui/text/qtextdocument.cpp
+++ b/src/gui/text/qtextdocument.cpp
@@ -2385,6 +2385,11 @@ static QString colorValue(QColor color)
return result;
}
+/*!
+ \class QTextHtmlExporter
+ \inmodule QtGui
+ \internal
+*/
QTextHtmlExporter::QTextHtmlExporter(const QTextDocument *_doc)
: doc(_doc), fragmentMarkers(false)
{
diff --git a/src/gui/text/qtextdocument_p.cpp b/src/gui/text/qtextdocument_p.cpp
index 227cbae2952..85a74d366ac 100644
--- a/src/gui/text/qtextdocument_p.cpp
+++ b/src/gui/text/qtextdocument_p.cpp
@@ -1006,6 +1006,7 @@ int QTextDocumentPrivate::undoRedo(bool undo)
}
/*!
+ \internal
Appends a custom undo \a item to the undo stack.
*/
void QTextDocumentPrivate::appendUndoItem(QAbstractUndoItem *item)
diff --git a/src/gui/text/qtexttable.cpp b/src/gui/text/qtexttable.cpp
index ff8644b5302..337228ff170 100644
--- a/src/gui/text/qtexttable.cpp
+++ b/src/gui/text/qtexttable.cpp
@@ -394,11 +394,9 @@ void QTextTablePrivate::fragmentRemoved(QChar type, uint fragment)
}
/*!
- /fn void QTextTablePrivate::update() const
-
+ \internal
This function is usually called when the table is "dirty".
It seems to update all kind of table information.
-
*/
void QTextTablePrivate::update() const
{
diff --git a/src/gui/text/windows/qwindowsfontdatabase.cpp b/src/gui/text/windows/qwindowsfontdatabase.cpp
index 93af1a9600b..0c6d9a31316 100644
--- a/src/gui/text/windows/qwindowsfontdatabase.cpp
+++ b/src/gui/text/windows/qwindowsfontdatabase.cpp
@@ -1113,17 +1113,21 @@ void QWindowsFontDatabase::removeApplicationFonts()
m_eudcFonts.clear();
}
+#if QT_CONFIG(directwrite)
QWindowsFontDatabase::FontHandle::FontHandle(IDWriteFontFace *face, const QString &name)
: fontFace(face), faceName(name)
{
fontFace->AddRef();
}
+#endif // !QT_NO_DIRECTWRITE
QWindowsFontDatabase::FontHandle::~FontHandle()
{
+#if QT_CONFIG(directwrite)
if (fontFace != nullptr)
fontFace->Release();
+#endif // !QT_NO_DIRECTWRITE
}
void QWindowsFontDatabase::releaseHandle(void *handle)
diff --git a/src/gui/text/windows/qwindowsfontdatabase_p.h b/src/gui/text/windows/qwindowsfontdatabase_p.h
index 92e3f04f968..856a5593722 100644
--- a/src/gui/text/windows/qwindowsfontdatabase_p.h
+++ b/src/gui/text/windows/qwindowsfontdatabase_p.h
@@ -78,10 +78,14 @@ public:
struct FontHandle {
FontHandle(const QString &name) : faceName(name) {}
+#if QT_CONFIG(directwrite)
FontHandle(IDWriteFontFace *face, const QString &name);
+#endif // !QT_NO_DIRECTWRITE
~FontHandle();
+#if QT_CONFIG(directwrite)
IDWriteFontFace *fontFace = nullptr;
+#endif // !QT_NO_DIRECTWRITE
QString faceName;
};
diff --git a/src/gui/util/qlayoutpolicy.cpp b/src/gui/util/qlayoutpolicy.cpp
index 4d81a426835..0c0651c1f39 100644
--- a/src/gui/util/qlayoutpolicy.cpp
+++ b/src/gui/util/qlayoutpolicy.cpp
@@ -8,6 +8,11 @@
QT_BEGIN_NAMESPACE
+/*!
+ \class QLayoutPolicy
+ \inmodule QtGui
+ \internal
+*/
void QLayoutPolicy::setControlType(ControlType type)
{
/*
diff --git a/src/network/access/qbytedatabuffer_p.h b/src/network/access/qbytedatabuffer_p.h
index a119093cf7e..036b562d06a 100644
--- a/src/network/access/qbytedatabuffer_p.h
+++ b/src/network/access/qbytedatabuffer_p.h
@@ -280,6 +280,8 @@ public:
}
return false;
}
+
+ const QByteArray &last() const { return buffers.last(); }
};
QT_END_NAMESPACE
diff --git a/src/network/access/qformdatabuilder.cpp b/src/network/access/qformdatabuilder.cpp
index 470e285c6ad..debefd24634 100644
--- a/src/network/access/qformdatabuilder.cpp
+++ b/src/network/access/qformdatabuilder.cpp
@@ -9,6 +9,7 @@
#include "QtCore/qmimedatabase.h"
#endif
+#include <variant>
#include <vector>
QT_BEGIN_NAMESPACE
diff --git a/src/network/access/qformdatabuilder.h b/src/network/access/qformdatabuilder.h
index 7d667aea21c..3992776161d 100644
--- a/src/network/access/qformdatabuilder.h
+++ b/src/network/access/qformdatabuilder.h
@@ -15,7 +15,6 @@
#include <QtCore/qstring.h>
#include <memory>
-#include <variant>
#ifndef Q_OS_WASM
QT_REQUIRE_CONFIG(http);
diff --git a/src/network/access/qhttp2connection.cpp b/src/network/access/qhttp2connection.cpp
index 2895e8335d2..c0b07ddd652 100644
--- a/src/network/access/qhttp2connection.cpp
+++ b/src/network/access/qhttp2connection.cpp
@@ -34,8 +34,38 @@ using namespace Http2;
\sa QHttp2Connection
*/
-QHttp2Stream::QHttp2Stream(QHttp2Connection *connection, quint32 streamID) noexcept
- : QObject(connection), m_streamID(streamID)
+/*!
+ \struct QHttp2Stream::Configuration
+ \inmodule QtNetwork
+ \internal
+
+ \brief Configuration options for a QHttp2Stream.
+
+ The Configuration struct holds options that control stream behavior.
+
+ \sa QHttp2Connection::createStream()
+*/
+
+/*!
+ \variable QHttp2Stream::Configuration::useDownloadBuffer
+
+ Controls whether incoming DATA frames, from QHttp2Stream::dataReceived(),
+ are buffered. The default is \c true.
+
+ You may disable buffering for client-initiated streams when the
+ application processes DATA immediately.
+
+ Buffering must remain enabled for pushed streams. A pushed stream can
+ receive DATA before the application becomes aware of them and the buffered
+ DATA is required to deliver the pushed response.
+
+ \sa QHttp2Stream::downloadBuffer(), QHttp2Stream::takeDownloadBuffer(),
+ QHttp2Configuration::serverPushEnabled(), QHttp2Stream::dataReceived()
+*/
+
+QHttp2Stream::QHttp2Stream(QHttp2Connection *connection, quint32 streamID,
+ Configuration configuration) noexcept
+ : QObject(connection), m_streamID(streamID), m_configuration(configuration)
{
Q_ASSERT(connection);
Q_ASSERT(streamID); // stream id 0 is reserved for connection control messages
@@ -213,6 +243,12 @@ QHttp2Stream::~QHttp2Stream() noexcept {
Returns the buffer containing the data received from the remote peer.
*/
+/*!
+ \fn QHttp2Stream::Configuration QHttp2Stream::configuration() const
+
+ Returns the configuration of this stream.
+*/
+
void QHttp2Stream::finishWithError(Http2::Http2Error errorCode, const QString &message)
{
qCDebug(qHttp2ConnectionLog, "[%p] stream %u finished with error: %ls (error code: %u)",
@@ -697,8 +733,14 @@ void QHttp2Stream::handleDATA(const Frame &inboundFrame)
inboundFrame.dataSize());
if (endStream)
transitionState(StateTransition::CloseRemote);
- emit dataReceived(fragment, endStream);
- m_downloadBuffer.append(std::move(fragment));
+ const auto shouldBuffer = m_configuration.useDownloadBuffer && !fragment.isEmpty();
+ if (shouldBuffer) {
+ // Only non-empty fragments get appended!
+ m_downloadBuffer.append(std::move(fragment));
+ emit dataReceived(m_downloadBuffer.last(), endStream);
+ } else {
+ emit dataReceived(fragment, endStream);
+ }
}
if (!endStream && m_recvWindow < connection->streamInitialReceiveWindowSize / 2) {
@@ -885,23 +927,35 @@ QHttp2Connection *QHttp2Connection::createDirectServerConnection(QIODevice *sock
}
/*!
- Creates a stream on this connection.
+ \fn QH2Expected<QHttp2Stream *, QHttp2Connection::CreateStreamError> QHttp2Connection::createStream()
+ Creates a stream on this connection, using the default QHttp2Stream::Configuration.
+
+//! [createStream]
Automatically picks the next available stream ID and returns a pointer to
the new stream, if possible. Otherwise returns an error.
\sa QHttp2Connection::CreateStreamError, QHttp2Stream
+//! [createStream]
+ \sa createStream(QHttp2Stream::Configuration)
+*/
+
+/*!
+ Creates a stream with \a configuration on this connection.
+
+ \include qhttp2connection.cpp createStream
*/
-QH2Expected<QHttp2Stream *, QHttp2Connection::CreateStreamError> QHttp2Connection::createStream()
+QH2Expected<QHttp2Stream *, QHttp2Connection::CreateStreamError>
+QHttp2Connection::createStream(QHttp2Stream::Configuration configuration)
{
Q_ASSERT(m_connectionType == Type::Client); // This overload is just for clients
if (m_nextStreamID > lastValidStreamID)
return { QHttp2Connection::CreateStreamError::StreamIdsExhausted };
- return createLocalStreamInternal();
+ return createLocalStreamInternal(configuration);
}
QH2Expected<QHttp2Stream *, QHttp2Connection::CreateStreamError>
-QHttp2Connection::createLocalStreamInternal()
+QHttp2Connection::createLocalStreamInternal(QHttp2Stream::Configuration conf)
{
if (m_goingAway)
return { QHttp2Connection::CreateStreamError::ReceivedGOAWAY };
@@ -909,7 +963,7 @@ QHttp2Connection::createLocalStreamInternal()
if (size_t(m_peerMaxConcurrentStreams) <= size_t(numActiveLocalStreams()))
return { QHttp2Connection::CreateStreamError::MaxConcurrentStreamsReached };
- if (QHttp2Stream *ptr = createStreamInternal_impl(streamID)) {
+ if (QHttp2Stream *ptr = createStreamInternal_impl(streamID, conf)) {
m_nextStreamID += 2;
return {ptr};
}
@@ -917,7 +971,8 @@ QHttp2Connection::createLocalStreamInternal()
return { QHttp2Connection::CreateStreamError::UnknownError };
}
-QHttp2Stream *QHttp2Connection::createStreamInternal_impl(quint32 streamID)
+QHttp2Stream *QHttp2Connection::createStreamInternal_impl(quint32 streamID,
+ QHttp2Stream::Configuration conf)
{
Q_ASSERT(streamID > m_lastIncomingStreamID || streamID >= m_nextStreamID);
@@ -930,7 +985,7 @@ QHttp2Stream *QHttp2Connection::createStreamInternal_impl(quint32 streamID)
if (!result.inserted)
return nullptr;
QPointer<QHttp2Stream> &stream = result.iterator.value();
- stream = new QHttp2Stream(this, streamID);
+ stream = new QHttp2Stream(this, streamID, conf);
stream->m_recvWindow = streamInitialReceiveWindowSize;
stream->m_sendWindow = streamInitialSendWindowSize;
diff --git a/src/network/access/qhttp2connection_p.h b/src/network/access/qhttp2connection_p.h
index f3f14145278..e2af7d7ab33 100644
--- a/src/network/access/qhttp2connection_p.h
+++ b/src/network/access/qhttp2connection_p.h
@@ -101,6 +101,11 @@ public:
Q_ENUM(State)
constexpr static quint8 DefaultPriority = 127;
+ struct Configuration
+ {
+ bool useDownloadBuffer = true;
+ };
+
~QHttp2Stream() noexcept;
// HTTP2 things
@@ -124,6 +129,8 @@ public:
QByteDataBuffer takeDownloadBuffer() noexcept { return std::exchange(m_downloadBuffer, {}); }
void clearDownloadBuffer() { m_downloadBuffer.clear(); }
+ Configuration configuration() const { return m_configuration; }
+
Q_SIGNALS:
void headersReceived(const HPack::HttpHeader &headers, bool endStream);
void headersUpdated();
@@ -154,7 +161,8 @@ private Q_SLOTS:
private:
friend class QHttp2Connection;
- QHttp2Stream(QHttp2Connection *connection, quint32 streamID) noexcept;
+ QHttp2Stream(QHttp2Connection *connection, quint32 streamID,
+ Configuration configuration) noexcept;
[[nodiscard]] QHttp2Connection *getConnection() const
{
@@ -201,6 +209,8 @@ private:
bool m_isReserved = false;
bool m_owningByteDevice = false;
+ const Configuration m_configuration;
+
friend tst_QHttp2Connection;
};
@@ -235,7 +245,12 @@ public:
createDirectServerConnection(QIODevice *socket, const QHttp2Configuration &config);
~QHttp2Connection();
- [[nodiscard]] QH2Expected<QHttp2Stream *, CreateStreamError> createStream();
+ [[nodiscard]] QH2Expected<QHttp2Stream *, CreateStreamError> createStream()
+ {
+ return createStream(QHttp2Stream::Configuration{});
+ }
+ [[nodiscard]] QH2Expected<QHttp2Stream *, CreateStreamError>
+ createStream(QHttp2Stream::Configuration config);
QHttp2Stream *getStream(quint32 streamId) const;
QHttp2Stream *promisedStream(const QUrl &streamKey) const
@@ -278,8 +293,9 @@ private:
friend class QHttp2Stream;
[[nodiscard]] QIODevice *getSocket() const { return qobject_cast<QIODevice *>(parent()); }
- QH2Expected<QHttp2Stream *, QHttp2Connection::CreateStreamError> createLocalStreamInternal();
- QHttp2Stream *createStreamInternal_impl(quint32 streamID);
+ QH2Expected<QHttp2Stream *, QHttp2Connection::CreateStreamError>
+ createLocalStreamInternal(QHttp2Stream::Configuration = {});
+ QHttp2Stream *createStreamInternal_impl(quint32 streamID, QHttp2Stream::Configuration = {});
bool isInvalidStream(quint32 streamID) noexcept;
bool streamWasResetLocally(quint32 streamID) noexcept;
diff --git a/src/network/access/qnetworkaccesscache.cpp b/src/network/access/qnetworkaccesscache.cpp
index bb1bdd87a8a..1f2bbd321cf 100644
--- a/src/network/access/qnetworkaccesscache.cpp
+++ b/src/network/access/qnetworkaccesscache.cpp
@@ -5,11 +5,6 @@
#include "qnetworkaccesscache_p.h"
#include "QtCore/qpointer.h"
#include "QtCore/qdeadlinetimer.h"
-#include "qnetworkaccessmanager_p.h"
-#include "qnetworkreply_p.h"
-#include "qnetworkrequest.h"
-
-#include <vector>
//#define DEBUG_ACCESSCACHE
@@ -181,18 +176,6 @@ void QNetworkAccessCache::updateTimer()
timer.start(interval + 10, this);
}
-bool QNetworkAccessCache::emitEntryReady(Node *node, QObject *target, const char *member)
-{
- if (!connect(this, SIGNAL(entryReady(QNetworkAccessCache::CacheableObject*)),
- target, member, Qt::QueuedConnection))
- return false;
-
- emit entryReady(node->object);
- disconnect(SIGNAL(entryReady(QNetworkAccessCache::CacheableObject*)));
-
- return true;
-}
-
void QNetworkAccessCache::timerEvent(QTimerEvent *)
{
while (firstExpiringNode && firstExpiringNode->timer.hasExpired()) {
diff --git a/src/network/access/qnetworkaccesscache_p.h b/src/network/access/qnetworkaccesscache_p.h
index 4d4ff325f98..5d7dc819461 100644
--- a/src/network/access/qnetworkaccesscache_p.h
+++ b/src/network/access/qnetworkaccesscache_p.h
@@ -69,9 +69,6 @@ public:
void releaseEntry(const QByteArray &key);
void removeEntry(const QByteArray &key);
-signals:
- void entryReady(QNetworkAccessCache::CacheableObject *);
-
protected:
void timerEvent(QTimerEvent *) override;
@@ -86,7 +83,6 @@ private:
void linkEntry(const QByteArray &key);
bool unlinkEntry(const QByteArray &key);
void updateTimer();
- bool emitEntryReady(Node *node, QObject *target, const char *member);
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QNetworkAccessCache::CacheableObject::Options)
diff --git a/src/network/access/qnetworkcookie.cpp b/src/network/access/qnetworkcookie.cpp
index c20cd43a2fd..6c44e42dbba 100644
--- a/src/network/access/qnetworkcookie.cpp
+++ b/src/network/access/qnetworkcookie.cpp
@@ -5,7 +5,6 @@
#include "qnetworkcookie.h"
#include "qnetworkcookie_p.h"
-#include "qnetworkrequest.h"
#include "qnetworkreply.h"
#include "QtCore/qbytearray.h"
#include "QtCore/qdatetime.h"
diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
index adad12a4242..be05249c1b8 100644
--- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm
+++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
@@ -265,19 +265,26 @@ void QCocoaGLContext::updateSurfaceFormat()
return value;
};
- int colorSize = pixelFormatAttribute(NSOpenGLPFAColorSize);
- colorSize /= 4; // The attribute includes the alpha component
- m_format.setRedBufferSize(colorSize);
- m_format.setGreenBufferSize(colorSize);
- m_format.setBlueBufferSize(colorSize);
+ // Resolve color channel bits from GL, rather than NSOpenGLPFAColorSize,
+ // as the latter is not specific enough (combines all channels).
+ GLint redBits, greenBits, blueBits;
+ glGetIntegerv(GL_RED_BITS, &redBits);
+ glGetIntegerv(GL_GREEN_BITS, &greenBits);
+ glGetIntegerv(GL_BLUE_BITS, &blueBits);
+ m_format.setRedBufferSize(redBits);
+ m_format.setGreenBufferSize(greenBits);
+ m_format.setBlueBufferSize(blueBits);
// Surfaces on macOS always have an alpha channel, but unless the user requested
// one via setAlphaBufferSize(), which triggered setting NSOpenGLCPSurfaceOpacity
// to make the surface non-opaque, we don't want to report back the actual alpha
// size, as that will make the user believe the alpha channel can be used for
// something useful, when in reality it can't, due to the surface being opaque.
- if (m_format.alphaBufferSize() > 0)
- m_format.setAlphaBufferSize(pixelFormatAttribute(NSOpenGLPFAAlphaSize));
+ if (m_format.alphaBufferSize() > 0) {
+ GLint alphaBits;
+ glGetIntegerv(GL_ALPHA_BITS, &alphaBits);
+ m_format.setAlphaBufferSize(alphaBits);
+ }
m_format.setDepthBufferSize(pixelFormatAttribute(NSOpenGLPFADepthSize));
m_format.setStencilBufferSize(pixelFormatAttribute(NSOpenGLPFAStencilSize));
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 0905ba3e644..1b34490e358 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -330,6 +330,13 @@ QMargins QCocoaWindow::safeAreaMargins() const
// merge them.
auto screenRect = m_view.window.screen.frame;
auto screenInsets = m_view.window.screen.safeAreaInsets;
+ auto screenSafeArea = QCocoaScreen::mapFromNative(NSMakeRect(
+ NSMinX(screenRect) + screenInsets.left,
+ NSMinY(screenRect) + screenInsets.bottom, // Non-flipped
+ NSWidth(screenRect) - screenInsets.left - screenInsets.right,
+ NSHeight(screenRect) - screenInsets.top - screenInsets.bottom
+ ));
+
auto screenRelativeViewBounds = QCocoaScreen::mapFromNative(
[m_view.window convertRectToScreen:
[m_view convertRect:m_view.bounds toView:nil]]
@@ -339,20 +346,10 @@ QMargins QCocoaWindow::safeAreaMargins() const
// Note that we do not want represent the area outside of the
// screen as being outside of the safe area.
QMarginsF screenSafeAreaMargins = {
- screenInsets.left ?
- qMax(0.0f, screenInsets.left - screenRelativeViewBounds.left())
- : 0.0f,
- screenInsets.top ?
- qMax(0.0f, screenInsets.top - screenRelativeViewBounds.top())
- : 0.0f,
- screenInsets.right ?
- qMax(0.0f, screenInsets.right
- - (screenRect.size.width - screenRelativeViewBounds.right()))
- : 0.0f,
- screenInsets.bottom ?
- qMax(0.0f, screenInsets.bottom
- - (screenRect.size.height - screenRelativeViewBounds.bottom()))
- : 0.0f
+ qMin(screenSafeArea.left() - screenRelativeViewBounds.left(), screenInsets.left),
+ qMin(screenSafeArea.top() - screenRelativeViewBounds.top(), screenInsets.top),
+ qMin(screenRelativeViewBounds.right() - screenSafeArea.right(), screenInsets.right),
+ qMin(screenRelativeViewBounds.bottom() - screenSafeArea.bottom(), screenInsets.bottom)
};
return (screenSafeAreaMargins | viewSafeAreaMargins).toMargins();
diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp
index 0236669d6fb..23bbe409caa 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.cpp
+++ b/src/plugins/platforms/windows/qwindowsscreen.cpp
@@ -450,6 +450,26 @@ QPixmap QWindowsScreen::grabWindow(WId window, int xIn, int yIn, int width, int
hwnd = GetDesktopWindow();
const QRect screenGeometry = geometry();
windowSize = screenGeometry.size();
+ // When dpi awareness is not set to PerMonitor, windows reports primary display or dummy
+ // DPI for all displays, so xIn and yIn and windowSize are calculated with a wrong DPI,
+ // so we need to recalculate them using the actual screen size we get from
+ // EnumDisplaySettings api.
+ const auto dpiAwareness = QWindowsContext::instance()->processDpiAwareness();
+ if (dpiAwareness != QtWindows::DpiAwareness::PerMonitor &&
+ dpiAwareness != QtWindows::DpiAwareness::PerMonitorVersion2) {
+ MONITORINFOEX info = {};
+ info.cbSize = sizeof(MONITORINFOEX);
+ if (GetMonitorInfo(handle(), &info)) {
+ DEVMODE dm = {};
+ dm.dmSize = sizeof(dm);
+ if (EnumDisplaySettings(info.szDevice, ENUM_CURRENT_SETTINGS, &dm)) {
+ qreal scale = static_cast<qreal>(dm.dmPelsWidth) / windowSize.width();
+ x = static_cast<int>(static_cast<qreal>(x) * scale);
+ y = static_cast<int>(static_cast<qreal>(y) * scale);
+ windowSize = QSize(dm.dmPelsWidth, dm.dmPelsHeight);
+ }
+ }
+ }
x += screenGeometry.x();
y += screenGeometry.y();
}
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index b77e985c965..2816982b1a8 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -1732,8 +1732,10 @@ void QWindowsWindow::destroyWindow()
m_surface = nullptr;
}
#endif
+ DestroyWindow(m_data.hwndTitlebar);
DestroyWindow(m_data.hwnd);
context->removeWindow(m_data.hwnd);
+ m_data.hwndTitlebar = nullptr;
m_data.hwnd = nullptr;
}
}
diff --git a/src/plugins/sqldrivers/.cmake.conf b/src/plugins/sqldrivers/.cmake.conf
index be788d10f8e..846c4f3b923 100644
--- a/src/plugins/sqldrivers/.cmake.conf
+++ b/src/plugins/sqldrivers/.cmake.conf
@@ -1 +1 @@
-set(QT_REPO_MODULE_VERSION "6.11.0")
+set(QT_REPO_MODULE_VERSION "6.12.0")
diff --git a/src/plugins/styles/modernwindows/qwindows11style.cpp b/src/plugins/styles/modernwindows/qwindows11style.cpp
index 7caa352afe4..e9b90d787bc 100644
--- a/src/plugins/styles/modernwindows/qwindows11style.cpp
+++ b/src/plugins/styles/modernwindows/qwindows11style.cpp
@@ -596,7 +596,7 @@ void QWindows11Style::drawComplexControl(ComplexControl control, const QStyleOpt
if (sub & SC_ComboBoxArrow) {
QRectF rect = proxy()->subControlRect(CC_ComboBox, option, SC_ComboBoxArrow, widget);
painter->setFont(d->assetFont);
- painter->setPen(controlTextColor(option));
+ painter->setPen(controlTextColor(option, true));
painter->drawText(rect, Qt::AlignCenter, fluentIcon(Icon::ChevronDownMed));
}
if (state & State_KeyboardFocusChange && hasFocus) {
@@ -887,7 +887,7 @@ void QWindows11Style::drawPrimitive(PrimitiveElement element, const QStyleOption
if (isOn) {
painter->setFont(d->assetFont);
- painter->setPen(controlTextColor(option, QPalette::Window));
+ painter->setPen(controlTextColor(option));
qreal clipWidth = 1.0;
const QString str = fluentIcon(Icon::AcceptMedium);
QFontMetrics fm(d->assetFont);
@@ -907,19 +907,24 @@ void QWindows11Style::drawPrimitive(PrimitiveElement element, const QStyleOption
QFont f(d->assetFont);
f.setPointSize(6);
painter->setFont(f);
- painter->setPen(controlTextColor(option, QPalette::Window));
+ painter->setPen(controlTextColor(option));
painter->drawText(rect, Qt::AlignCenter, fluentIcon(Icon::Dash12));
}
}
break;
case PE_IndicatorBranch: {
if (option->state & State_Children) {
+ const QStyleOptionViewItem *vopt = qstyleoption_cast<const QStyleOptionViewItem *>(option);
const bool isReverse = option->direction == Qt::RightToLeft;
const bool isOpen = option->state & QStyle::State_Open;
+ const QAbstractItemView *view = qobject_cast<const QAbstractItemView *>(widget);
QFont f(d->assetFont);
f.setPointSize(8);
painter->setFont(f);
- painter->setPen(option->palette.color(isOpen ? QPalette::Active : QPalette::Disabled,
+ if (view && view->alternatingRowColors() && vopt && vopt->state & State_Selected)
+ painter->setPen(winUI3Color(textOnAccentPrimary));
+ else
+ painter->setPen(option->palette.color(isOpen ? QPalette::Active : QPalette::Disabled,
QPalette::WindowText));
const auto ico = isOpen ? Icon::ChevronDownMed
: (isReverse ? Icon::ChevronLeftMed
@@ -1071,14 +1076,16 @@ void QWindows11Style::drawPrimitive(PrimitiveElement element, const QStyleOption
if (option->state & State_Selected && !highContrastTheme) {
// keep in sync with CE_ItemViewItem QListView indicator painting
- const auto col = option->palette.accent().color();
- painter->setBrush(col);
- painter->setPen(col);
- const auto xPos = isRtl ? rect.right() - 4.5f : rect.left() + 3.5f;
- const auto yOfs = rect.height() / 4.;
- QRectF r(QPointF(xPos, rect.y() + yOfs),
- QPointF(xPos + 1, rect.y() + rect.height() - yOfs));
- painter->drawRoundedRect(r, 1, 1);
+ if (!qobject_cast<const QTableView *>(widget)) {
+ const auto col = option->palette.accent().color();
+ painter->setBrush(col);
+ painter->setPen(col);
+ const auto xPos = isRtl ? rect.right() - 4.5f : rect.left() + 3.5f;
+ const auto yOfs = rect.height() / 4.;
+ QRectF r(QPointF(xPos, rect.y() + yOfs),
+ QPointF(xPos + 1, rect.y() + rect.height() - yOfs));
+ painter->drawRoundedRect(r, 1, 1);
+ }
}
const bool isTreeDecoration = vopt->features.testFlag(
@@ -1099,7 +1106,7 @@ void QWindows11Style::drawPrimitive(PrimitiveElement element, const QStyleOption
}
const QAbstractItemView *view = qobject_cast<const QAbstractItemView *>(widget);
- painter->setBrush(view->alternatingRowColors() ? vopt->palette.highlight() : WINUI3Colors[colorSchemeIndex][subtleHighlightColor]);
+ painter->setBrush(view->alternatingRowColors() && state & State_Selected ? calculateAccentColor(option) : WINUI3Colors[colorSchemeIndex][subtleHighlightColor]);
painter->setPen(Qt::NoPen);
if (isFirst) {
QPainterStateGuard psg(painter);
@@ -1207,7 +1214,7 @@ void QWindows11Style::drawControl(ControlElement element, const QStyleOption *op
case QStyle::CE_ComboBoxLabel:
#if QT_CONFIG(combobox)
if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
- painter->setPen(controlTextColor(option));
+ painter->setPen(controlTextColor(option, true));
QStyleOptionComboBox newOption = *cb;
newOption.rect.adjust(4,0,-4,0);
QCommonStyle::drawControl(element, &newOption, painter, widget);
@@ -1753,13 +1760,13 @@ void QWindows11Style::drawControl(ControlElement element, const QStyleOption *op
}
}
const bool highlightCurrent = vopt->state.testAnyFlags(State_Selected | State_MouseOver);
+ const QAbstractItemView *view = qobject_cast<const QAbstractItemView *>(widget);
if (highlightCurrent) {
if (highContrastTheme) {
painter->setBrush(vopt->palette.highlight());
} else {
- const QAbstractItemView *view = qobject_cast<const QAbstractItemView *>(widget);
- painter->setBrush(view && view->alternatingRowColors()
- ? vopt->palette.highlight()
+ painter->setBrush(view && view->alternatingRowColors() && vopt->state & State_Selected
+ ? calculateAccentColor(option)
: winUI3Color(subtleHighlightColor));
}
} else {
@@ -1815,8 +1822,13 @@ void QWindows11Style::drawControl(ControlElement element, const QStyleOption *op
vopt->icon.paint(painter, iconRect, vopt->decorationAlignment, mode, state);
}
- painter->setPen(highlightCurrent && highContrastTheme ? vopt->palette.base().color()
- : vopt->palette.text().color());
+ if (highlightCurrent && highContrastTheme) {
+ painter->setPen(vopt->palette.base().color());
+ } else if ((view && view->alternatingRowColors() && highlightCurrent && vopt->state & State_Selected)) {
+ painter->setPen(winUI3Color(textOnAccentPrimary));
+ } else {
+ painter->setPen(vopt->palette.text().color());
+ }
d->viewItemDrawText(painter, vopt, textRect);
// paint a vertical marker for QListView
@@ -2725,7 +2737,7 @@ QBrush QWindows11Style::inputFillBrush(const QStyleOption *option, const QWidget
return winUI3Color(fillControlDefault);
}
-QColor QWindows11Style::controlTextColor(const QStyleOption *option, QPalette::ColorRole role) const
+QColor QWindows11Style::controlTextColor(const QStyleOption *option, bool ignoreIsChecked) const
{
using namespace StyleOptionHelper;
static constexpr WINUI3Color colorEnums[2][4] = {
@@ -2738,12 +2750,9 @@ QColor QWindows11Style::controlTextColor(const QStyleOption *option, QPalette::C
if (option->palette.isBrushSet(QPalette::Current, QPalette::ButtonText))
return option->palette.buttonText().color();
- const int colorIndex = isChecked(option) ? 1 : 0;
+ const int colorIndex = !ignoreIsChecked && isChecked(option) ? 1 : 0;
const auto state = calcControlState(option);
- const auto alpha = winUI3Color(colorEnums[colorIndex][int(state)]);
- QColor col = option->palette.color(role);
- col.setAlpha(alpha.alpha());
- return col;
+ return winUI3Color(colorEnums[colorIndex][int(state)]);
}
void QWindows11Style::drawLineEditFrame(QPainter *p, const QRectF &rect, const QStyleOption *o, bool isEditable) const
diff --git a/src/plugins/styles/modernwindows/qwindows11style_p.h b/src/plugins/styles/modernwindows/qwindows11style_p.h
index 96c2c4136e0..9d0cdda3e33 100644
--- a/src/plugins/styles/modernwindows/qwindows11style_p.h
+++ b/src/plugins/styles/modernwindows/qwindows11style_p.h
@@ -104,8 +104,7 @@ private:
QBrush controlFillBrush(const QStyleOption *option, ControlType controlType) const;
QBrush inputFillBrush(const QStyleOption *option, const QWidget *widget) const;
// ControlType::ControlAlt can be mapped to QPalette directly
- QColor controlTextColor(const QStyleOption *option,
- QPalette::ColorRole role = QPalette::ButtonText) const;
+ QColor controlTextColor(const QStyleOption *option, bool ignoreIsChecked = false) const;
void drawLineEditFrame(QPainter *p, const QRectF &rect, const QStyleOption *o, bool isEditable = true) const;
inline QColor winUI3Color(enum WINUI3Color col) const;
diff --git a/src/plugins/styles/modernwindows/qwindowsvistastyle.cpp b/src/plugins/styles/modernwindows/qwindowsvistastyle.cpp
index 64ffba2d6f8..36b5d0f0143 100644
--- a/src/plugins/styles/modernwindows/qwindowsvistastyle.cpp
+++ b/src/plugins/styles/modernwindows/qwindowsvistastyle.cpp
@@ -16,6 +16,9 @@
#include <private/qapplication_p.h>
#include <private/qsystemlibrary_p.h>
#include <private/qwindowsthemecache_p.h>
+#if QT_CONFIG(tooltip)
+#include "private/qtooltip_p.h"
+#endif
#include "qdrawutil.h" // for now
#include <qbackingstore.h>
@@ -4676,7 +4679,7 @@ void QWindowsVistaStyle::polish(QWidget *widget)
widget->setPalette(pal);
} else
#endif // QT_CONFIG(commandlinkbutton)
- if (widget->inherits("QTipLabel")) {
+ if (qobject_cast<const QTipLabel *>(widget)) {
//note that since tooltips are not reused
//we do not have to care about unpolishing
widget->setContentsMargins(3, 0, 4, 0);
diff --git a/src/plugins/tls/openssl/qtlsbackend_openssl.cpp b/src/plugins/tls/openssl/qtlsbackend_openssl.cpp
index deb257be01c..d3b7d669ec7 100644
--- a/src/plugins/tls/openssl/qtlsbackend_openssl.cpp
+++ b/src/plugins/tls/openssl/qtlsbackend_openssl.cpp
@@ -407,8 +407,13 @@ QList<QSslCertificate> systemCaCertificates()
for (const QByteArray &directory : directories) {
for (const auto &dirEntry : QDirListing(QFile::decodeName(directory), flags)) {
// use canonical path here to not load the same certificate twice if symlinked
- if (hasMatchingExtension(dirEntry.fileName()))
- certFiles.insert(dirEntry.canonicalFilePath());
+ if (hasMatchingExtension(dirEntry.fileName())) {
+ QString canonicalPath = dirEntry.canonicalFilePath();
+ // skip broken symlinks to not end up adding "" to the list which will then
+ // just be rejected by `QSslCertificate::fromFile`
+ if (!canonicalPath.isEmpty())
+ certFiles.insert(canonicalPath);
+ }
}
}
for (const QString& file : std::as_const(certFiles))
diff --git a/src/testlib/doc/src/qt-webpages.qdoc b/src/testlib/doc/src/qt-webpages.qdoc
index 611f3795ba9..b32fd4f750f 100644
--- a/src/testlib/doc/src/qt-webpages.qdoc
+++ b/src/testlib/doc/src/qt-webpages.qdoc
@@ -15,7 +15,3 @@
\title Googletest Mocking (gMock) Framework
*/
-/*!
- \externalpage https://www.itk.org/Wiki/CMake_Testing_With_CTest
- \title CMake/Testing With CTest
-*/
diff --git a/src/tools/androidtestrunner/main.cpp b/src/tools/androidtestrunner/main.cpp
index b517d85c5fb..161d95db49c 100644
--- a/src/tools/androidtestrunner/main.cpp
+++ b/src/tools/androidtestrunner/main.cpp
@@ -28,7 +28,16 @@
using namespace Qt::StringLiterals;
-#define EXIT_ERROR -1
+
+// QTest-based test processes may exit with up to 127 for normal test failures
+static constexpr int HIGHEST_QTEST_EXITCODE = 127;
+// Something went wrong in androidtestrunner, in general
+static constexpr int EXIT_ERROR = 254;
+// More specific exit codes for failures in androidtestrunner:
+static constexpr int EXIT_NOEXITCODE = 253; // Failed to transfer exit code from device
+static constexpr int EXIT_ANR = 252; // Android ANR error (Application Not Responding)
+static constexpr int EXIT_NORESULTS = 251; // Failed to transfer result files from device
+
struct Options
{
@@ -71,6 +80,13 @@ struct TestInfo
static TestInfo g_testInfo;
+// QTest-based processes return 0 if all tests PASSed, or the number of FAILs up to 127.
+// Other exitcodes signify abnormal termination and are system-dependent.
+static bool isTestExitCodeNormal(const int ec)
+{
+ return (ec >= 0 && ec <= HIGHEST_QTEST_EXITCODE);
+}
+
static bool execCommand(const QString &program, const QStringList &args,
QByteArray *output = nullptr, bool verbose = false)
{
@@ -744,9 +760,9 @@ void printLogcatCrash(const QByteArray &logcat)
}
if (!crashLogcat.startsWith("********** Crash dump"))
- qDebug() << "********** Crash dump: **********";
+ qDebug() << "[androidtestrunner] ********** BEGIN crash dump **********";
qDebug().noquote() << crashLogcat.trimmed();
- qDebug() << "********** End crash dump **********";
+ qDebug() << "[androidtestrunner] ********** END crash dump **********";
}
void analyseLogcat(const QString &timeStamp, int *exitCode)
@@ -781,10 +797,13 @@ void analyseLogcat(const QString &timeStamp, int *exitCode)
// Check for ANRs
const bool anrOccurred = logcat.contains("ANR in %1"_L1.arg(g_options.package).toUtf8());
if (anrOccurred) {
- // Treat a found ANR as a test failure.
- *exitCode = *exitCode < 1 ? 1 : *exitCode;
- qCritical("An ANR has occurred while running the test %s. The logcat will include "
- "additional logs from the system_server process.",
+ // Rather improbable, but if the test managed to return a non-crash exitcode then overwrite
+ // it to signify that something blew up. Same if we didn't manage to collect an exit code.
+ // Preserve all other exitcodes, they might be useful crash information from the device.
+ if (isTestExitCodeNormal(*exitCode) || *exitCode == EXIT_NOEXITCODE)
+ *exitCode = EXIT_ANR;
+ qCritical("[androidtestrunner] An ANR has occurred while running the test '%s';"
+ " consult logcat for additional logs from the system_server process",
qPrintable(g_options.package));
}
@@ -818,13 +837,14 @@ void analyseLogcat(const QString &timeStamp, int *exitCode)
}
}
- // If we have a crash, attempt to print both logcat and the crash buffer which
- // includes the crash stacktrace that is not included in the default logcat.
- const bool testCrashed = *exitCode == EXIT_ERROR && !g_testInfo.isTestRunnerInterrupted.load();
+ // If we have an unpredictable exitcode, possibly a crash, attempt to print both logcat and the
+ // crash buffer which includes the crash stacktrace that is not included in the default logcat.
+ const bool testCrashed = ( !isTestExitCodeNormal(*exitCode)
+ && !g_testInfo.isTestRunnerInterrupted.load());
if (testCrashed) {
- qDebug() << "********** logcat dump **********";
+ qDebug() << "[androidtestrunner] ********** BEGIN logcat dump **********";
qDebug().noquote() << testLogcat.join(u'\n').trimmed();
- qDebug() << "********** End logcat dump **********";
+ qDebug() << "[androidtestrunner] ********** END logcat dump **********";
if (!crashLogcat.isEmpty())
printLogcatCrash(crashLogcat);
@@ -839,7 +859,7 @@ static QString getCurrentTimeString()
QStringList dateArgs = { "shell"_L1, "date"_L1, "+'%1'"_L1.arg(timeFormat) };
QByteArray output;
if (!execAdbCommand(dateArgs, &output, false)) {
- qWarning() << "Date/time adb command failed";
+ qWarning() << "[androidtestrunner] ERROR in command: adb shell date";
return {};
}
@@ -851,14 +871,15 @@ static int testExitCode()
QByteArray exitCodeOutput;
const QString exitCodeCmd = "cat files/qtest_last_exit_code 2> /dev/null"_L1;
if (!execAdbCommand({ "shell"_L1, runCommandAsUserArgs(exitCodeCmd) }, &exitCodeOutput, false)) {
- qCritical() << "Failed to retrieve the test exit code.";
- return EXIT_ERROR;
+ qCritical() << "[androidtestrunner] ERROR in command: adb shell cat files/qtest_last_exit_code";
+ return EXIT_NOEXITCODE;
}
+ qDebug() << "[androidtestrunner] Test exitcode: " << exitCodeOutput;
bool ok;
int exitCode = exitCodeOutput.toInt(&ok);
- return ok ? exitCode : EXIT_ERROR;
+ return ok ? exitCode : EXIT_NOEXITCODE;
}
static bool uninstallTestPackage()
@@ -899,7 +920,7 @@ void sigHandler(int signal)
// a main event loop. Since, there's no other alternative to do this,
// let's do the cleanup anyway.
if (!g_testInfo.isPackageInstalled.load())
- _exit(-1);
+ _exit(EXIT_ERROR);
g_testInfo.isTestRunnerInterrupted.store(true);
}
@@ -1031,7 +1052,9 @@ int main(int argc, char *argv[])
if (g_options.showLogcatOutput)
analyseLogcat(formattedStartTime, &exitCode);
- exitCode = pullResults() ? exitCode : EXIT_ERROR;
+ const bool pullRes = pullResults();
+ if (!pullRes && isTestExitCodeNormal(exitCode))
+ exitCode = EXIT_NORESULTS;
if (!uninstallTestPackage())
return EXIT_ERROR;
diff --git a/src/tools/configure.cmake b/src/tools/configure.cmake
index 27ea90b89ac..07e11dd935b 100644
--- a/src/tools/configure.cmake
+++ b/src/tools/configure.cmake
@@ -37,7 +37,7 @@ qt_feature("qmake" PRIVATE
QT_FEATURE_datestring AND QT_FEATURE_regularexpression AND QT_FEATURE_temporaryfile)
qt_feature("qtwaylandscanner" PRIVATE
- CONDITION TARGET Wayland::Scanner
+ CONDITION TARGET Wayland::Scanner AND NOT INTEGRITY AND NOT ANDROID AND NOT WASM AND NOT IOS AND NOT QNX AND NOT VXWORKS
)
qt_configure_add_summary_section(NAME "Core tools")
diff --git a/src/widgets/CMakeLists.txt b/src/widgets/CMakeLists.txt
index d43b6ec4fb2..c47e3bee13c 100644
--- a/src/widgets/CMakeLists.txt
+++ b/src/widgets/CMakeLists.txt
@@ -412,7 +412,7 @@ qt_internal_extend_target(Widgets CONDITION QT_FEATURE_shortcut
qt_internal_extend_target(Widgets CONDITION QT_FEATURE_tooltip
SOURCES
- kernel/qtooltip.cpp kernel/qtooltip.h
+ kernel/qtooltip.cpp kernel/qtooltip.h kernel/qtooltip_p.h
)
qt_internal_extend_target(Widgets CONDITION QT_FEATURE_whatsthis
diff --git a/src/widgets/accessible/qaccessiblecolorwell.cpp b/src/widgets/accessible/qaccessiblecolorwell.cpp
index ca08e511e9a..64fcd2a7fd1 100644
--- a/src/widgets/accessible/qaccessiblecolorwell.cpp
+++ b/src/widgets/accessible/qaccessiblecolorwell.cpp
@@ -3,6 +3,8 @@
#include "private/qaccessiblecolorwell_p.h"
+#include <QtCore/qcoreapplication.h>
+
QT_REQUIRE_CONFIG(accessibility);
#if QT_CONFIG(colordialog)
@@ -14,6 +16,7 @@ class QAccessibleColorWellItem : public QAccessibleInterface
{
QAccessibleColorWell *m_parent;
+ Q_DECLARE_TR_FUNCTIONS(QAccessibleColorWellItem)
public:
QAccessibleColorWellItem(QAccessibleColorWell *parent);
@@ -79,7 +82,7 @@ QString QAccessibleColorWellItem::text(QAccessible::Text t) const
if (t == QAccessible::Name) {
QRgb color = m_parent->colorWell()->rgbValues()[m_parent->indexOfChild(this)];
//: Color specified via its 3 RGB components (red, green, blue)
- return QObject::tr("RGB %1, %2, %3")
+ return tr("RGB %1, %2, %3")
.arg(QString::number(qRed(color)), QString::number(qGreen(color)),
QString::number(qBlue(color)));
}
diff --git a/src/widgets/dialogs/qcolordialog.cpp b/src/widgets/dialogs/qcolordialog.cpp
index d51c408ab5c..ce46170bba5 100644
--- a/src/widgets/dialogs/qcolordialog.cpp
+++ b/src/widgets/dialogs/qcolordialog.cpp
@@ -662,7 +662,7 @@ private:
int val2y(int val);
void setVal(int v);
- QPixmap *pix;
+ QPixmap pix;
};
@@ -682,14 +682,12 @@ QColorLuminancePicker::QColorLuminancePicker(QWidget* parent)
:QWidget(parent)
{
hue = 100; val = 100; sat = 100;
- pix = nullptr;
// setAttribute(WA_NoErase, true);
setFocusPolicy(Qt::StrongFocus);
}
QColorLuminancePicker::~QColorLuminancePicker()
{
- delete pix;
}
void QColorLuminancePicker::keyPressEvent(QKeyEvent *event)
@@ -725,7 +723,7 @@ void QColorLuminancePicker::setVal(int v)
if (val == v)
return;
val = qMax(0, qMin(v,255));
- delete pix; pix=nullptr;
+ pix = QPixmap();
repaint();
emit newHsv(hue, sat, val);
}
@@ -744,8 +742,7 @@ void QColorLuminancePicker::paintEvent(QPaintEvent *)
QRect r(0, foff, w, height() - 2*foff);
int wi = r.width() - 2;
int hi = r.height() - 2;
- if (!pix || pix->height() != hi || pix->width() != wi) {
- delete pix;
+ if (pix.isNull() || pix.height() != hi || pix.width() != wi) {
QImage img(wi, hi, QImage::Format_RGB32);
int y;
uint *pixel = (uint *) img.scanLine(0);
@@ -754,10 +751,10 @@ void QColorLuminancePicker::paintEvent(QPaintEvent *)
std::fill(pixel, end, QColor::fromHsv(hue, sat, y2val(y + coff)).rgb());
pixel = end;
}
- pix = new QPixmap(QPixmap::fromImage(img));
+ pix = QPixmap::fromImage(img);
}
QPainter p(this);
- p.drawPixmap(1, coff, *pix);
+ p.drawPixmap(1, coff, pix);
const QPalette &g = palette();
qDrawShadePanel(&p, r, g, true);
p.setPen(g.windowText().color());
@@ -773,7 +770,7 @@ void QColorLuminancePicker::setCol(int h, int s , int v)
val = v;
hue = h;
sat = s;
- delete pix; pix=nullptr;
+ pix = QPixmap();
repaint();
}
diff --git a/src/widgets/doc/src/external-resources.qdoc b/src/widgets/doc/src/external-resources.qdoc
index 96117546a29..0eccc3b19d4 100644
--- a/src/widgets/doc/src/external-resources.qdoc
+++ b/src/widgets/doc/src/external-resources.qdoc
@@ -1,12 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
-
-/*!
- \externalpage http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/index.html
- \title Apple Human Interface Guidelines
-*/
-
/*!
\externalpage https://rk.nvg.ntnu.no/sinclair/computers/zxspectrum/zxspectrum.htm
\title Sinclair Spectrum
diff --git a/src/widgets/kernel/qtooltip.cpp b/src/widgets/kernel/qtooltip.cpp
index fa17c94a23f..97332cd7d5d 100644
--- a/src/widgets/kernel/qtooltip.cpp
+++ b/src/widgets/kernel/qtooltip.cpp
@@ -6,15 +6,12 @@
#include <qapplication.h>
#include <qevent.h>
-#include <qpointer.h>
#include <qstyle.h>
#include <qstyleoption.h>
#include <qstylepainter.h>
#if QT_CONFIG(effects)
#include <private/qeffects_p.h>
#endif
-#include <qtextdocument.h>
-#include <qdebug.h>
#include <qpa/qplatformscreen.h>
#include <qpa/qplatformcursor.h>
#if QT_CONFIG(style_stylesheet)
@@ -23,12 +20,10 @@
#include <qpa/qplatformwindow.h>
#include <qpa/qplatformwindow_p.h>
-#include <qlabel.h>
#include <QtWidgets/private/qlabel_p.h>
#include <QtGui/private/qhighdpiscaling_p.h>
#include <qtooltip.h>
-
-#include <QtCore/qbasictimer.h>
+#include <QtWidgets/private/qtooltip_p.h>
QT_BEGIN_NAMESPACE
@@ -93,57 +88,6 @@ using namespace Qt::StringLiterals;
\sa QWidget::toolTip, QAction::toolTip
*/
-class QTipLabel : public QLabel
-{
- Q_OBJECT
-public:
- QTipLabel(const QString &text, const QPoint &pos, QWidget *w, int msecDisplayTime);
- ~QTipLabel();
- static QTipLabel *instance;
-
- void adjustTooltipScreen(const QPoint &pos);
- void updateSize(const QPoint &pos);
-
- bool eventFilter(QObject *, QEvent *) override;
-
- QBasicTimer hideTimer, expireTimer;
-
- bool fadingOut;
-
- void reuseTip(const QString &text, int msecDisplayTime, const QPoint &pos);
- void hideTip();
- void hideTipImmediately();
- void setTipRect(QWidget *w, const QRect &r);
- void restartExpireTimer(int msecDisplayTime);
- bool tipChanged(const QPoint &pos, const QString &text, QObject *o);
- void placeTip(const QPoint &pos, QWidget *w);
-
- static QScreen *getTipScreen(const QPoint &pos, QWidget *w);
-protected:
- void timerEvent(QTimerEvent *e) override;
- void paintEvent(QPaintEvent *e) override;
- void mouseMoveEvent(QMouseEvent *e) override;
- void resizeEvent(QResizeEvent *e) override;
-
-#if QT_CONFIG(style_stylesheet)
-public slots:
- /** \internal
- Cleanup the _q_stylesheet_parent property.
- */
- void styleSheetParentDestroyed() {
- setProperty("_q_stylesheet_parent", QVariant());
- styleSheetParent = nullptr;
- }
-
-private:
- QWidget *styleSheetParent;
-#endif
-
-private:
- QWidget *widget;
- QRect rect;
-};
-
QTipLabel *QTipLabel::instance = nullptr;
QTipLabel::QTipLabel(const QString &text, const QPoint &pos, QWidget *w, int msecDisplayTime)
@@ -152,6 +96,7 @@ QTipLabel::QTipLabel(const QString &text, const QPoint &pos, QWidget *w, int mse
, styleSheetParent(nullptr)
#endif
, widget(nullptr)
+ , fadingOut(false)
{
delete instance;
instance = this;
@@ -166,7 +111,6 @@ QTipLabel::QTipLabel(const QString &text, const QPoint &pos, QWidget *w, int mse
qApp->installEventFilter(this);
setWindowOpacity(style()->styleHint(QStyle::SH_ToolTipLabel_Opacity, nullptr, this) / 255.0);
setMouseTracking(true);
- fadingOut = false;
reuseTip(text, msecDisplayTime, pos);
}
@@ -240,10 +184,10 @@ void QTipLabel::resizeEvent(QResizeEvent *e)
void QTipLabel::mouseMoveEvent(QMouseEvent *e)
{
if (!rect.isNull()) {
- QPoint pos = e->globalPosition().toPoint();
+ QPointF pos = e->globalPosition();
if (widget)
pos = widget->mapFromGlobal(pos);
- if (!rect.contains(pos))
+ if (!rect.contains(pos.toPoint()))
hideTip();
}
QLabel::mouseMoveEvent(e);
@@ -433,6 +377,15 @@ bool QTipLabel::tipChanged(const QPoint &pos, const QString &text, QObject *o)
return false;
}
+/** \internal
+ Cleanup the _q_stylesheet_parent property.
+ */
+void QTipLabel::styleSheetParentDestroyed()
+{
+ setProperty("_q_stylesheet_parent", QVariant());
+ styleSheetParent = nullptr;
+}
+
/*!
Shows \a text as a tool tip, with the global position \a pos as
the point of interest. The tool tip will be shown with a platform
@@ -594,4 +547,4 @@ void QToolTip::setFont(const QFont &font)
QT_END_NAMESPACE
-#include "qtooltip.moc"
+#include "moc_qtooltip_p.cpp"
diff --git a/src/widgets/kernel/qtooltip_p.h b/src/widgets/kernel/qtooltip_p.h
new file mode 100644
index 00000000000..51faaf58c34
--- /dev/null
+++ b/src/widgets/kernel/qtooltip_p.h
@@ -0,0 +1,74 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:significant reason:default
+
+#ifndef QTOOLTIP_P_H
+#define QTOOLTIP_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of qlayout*.cpp, and qabstractlayout.cpp. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QLabel>
+#include <QString>
+#include <QRect>
+#include <QToolTip>
+
+QT_REQUIRE_CONFIG(tooltip);
+QT_BEGIN_NAMESPACE
+
+class Q_WIDGETS_EXPORT QTipLabel final : public QLabel
+{
+ Q_OBJECT
+public:
+ explicit QTipLabel(const QString &text, const QPoint &pos, QWidget *w, int msecDisplayTime);
+ ~QTipLabel() override;
+
+ void adjustTooltipScreen(const QPoint &pos);
+ void updateSize(const QPoint &pos);
+
+ bool eventFilter(QObject *, QEvent *) override;
+
+ void reuseTip(const QString &text, int msecDisplayTime, const QPoint &pos);
+ void hideTip();
+ void hideTipImmediately();
+ void setTipRect(QWidget *w, const QRect &r);
+ void restartExpireTimer(int msecDisplayTime);
+ bool tipChanged(const QPoint &pos, const QString &text, QObject *o);
+ void placeTip(const QPoint &pos, QWidget *w);
+
+ static QScreen *getTipScreen(const QPoint &pos, QWidget *w);
+protected:
+ void timerEvent(QTimerEvent *e) override;
+ void paintEvent(QPaintEvent *e) override;
+ void mouseMoveEvent(QMouseEvent *e) override;
+ void resizeEvent(QResizeEvent *e) override;
+
+#if QT_CONFIG(style_stylesheet)
+public Q_SLOTS:
+ void styleSheetParentDestroyed();
+
+private:
+ QWidget *styleSheetParent;
+#endif
+
+private:
+ friend class QToolTip;
+
+ static QTipLabel *instance;
+ QBasicTimer hideTimer, expireTimer;
+ QWidget *widget;
+ QRect rect;
+ bool fadingOut;
+};
+
+QT_END_NAMESPACE
+
+#endif // QTOOLTIP_P_H
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index 9499c88af12..bd2b5be11aa 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -32,7 +32,7 @@
#include "private/qwidgetwindow_p.h"
#include "qpainter.h"
#if QT_CONFIG(tooltip)
-#include "qtooltip.h"
+#include "private/qtooltip_p.h"
#endif
#if QT_CONFIG(whatsthis)
#include "qwhatsthis.h"
@@ -1435,7 +1435,9 @@ void QWidgetPrivate::createTLSysExtra()
if (extra->topextra->opacity != 255 && q->isWindow())
extra->topextra->window->setOpacity(qreal(extra->topextra->opacity) / qreal(255));
- const bool isTipLabel = q->inherits("QTipLabel");
+#if QT_CONFIG(tooltip)
+ const bool isTipLabel = qobject_cast<const QTipLabel *>(q) != nullptr;
+#endif
const bool isAlphaWidget = !isTipLabel && q->inherits("QAlphaWidget");
#ifdef Q_OS_WIN
// Pass on native parent handle for Widget embedded into Active X.
diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp
index 90c1cfb4b86..592b70ef8ba 100644
--- a/src/widgets/styles/qcommonstyle.cpp
+++ b/src/widgets/styles/qcommonstyle.cpp
@@ -1994,12 +1994,9 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
tr = proxy()->subElementRect(SE_TabBarTabText, opt, widget);
if (!tab->icon.isNull()) {
- QPixmap tabIcon = tab->icon.pixmap(tab->iconSize, QStyleHelper::getDpr(p),
- (tab->state & State_Enabled) ? QIcon::Normal
- : QIcon::Disabled,
- (tab->state & State_Selected) ? QIcon::On
- : QIcon::Off);
- p->drawPixmap(iconRect.x(), iconRect.y(), tabIcon);
+ const auto mode = (tab->state & State_Enabled) ? QIcon::Normal : QIcon::Disabled;
+ const auto state = (tab->state & State_Selected) ? QIcon::On : QIcon::Off;
+ tab->icon.paint(p, iconRect, Qt::AlignCenter, mode, state);
}
proxy()->drawItemText(p, tr, alignment, tab->palette, tab->state & State_Enabled, tab->text,
diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp
index 25b048db65e..e0fdd56e6d8 100644
--- a/src/widgets/styles/qstylesheetstyle.cpp
+++ b/src/widgets/styles/qstylesheetstyle.cpp
@@ -35,7 +35,7 @@
#include <qabstractscrollarea.h>
#include "private/qabstractscrollarea_p.h"
#if QT_CONFIG(tooltip)
-#include <qtooltip.h>
+#include "private/qtooltip_p.h"
#endif
#include <qshareddata.h>
#if QT_CONFIG(toolbutton)
@@ -950,7 +950,7 @@ QRenderRule::QRenderRule(const QList<Declaration> &declarations, const QObject *
hasFont = v.extractFont(&font, &adj);
#if QT_CONFIG(tooltip)
- if (object && qstrcmp(object->metaObject()->className(), "QTipLabel") == 0)
+ if (qobject_cast<const QTipLabel *>(object) != nullptr)
palette = QToolTip::palette();
#endif
@@ -1495,7 +1495,7 @@ bool QRenderRule::hasModification() const
static inline QObject *parentObject(const QObject *obj)
{
#if QT_CONFIG(tooltip)
- if (qobject_cast<const QLabel *>(obj) && qstrcmp(obj->metaObject()->className(), "QTipLabel") == 0) {
+ if (qobject_cast<const QTipLabel *>(obj) != nullptr) {
QObject *p = qvariant_cast<QObject *>(obj->property("_q_stylesheet_parent"));
if (p)
return p;
@@ -1515,7 +1515,7 @@ public:
return QStringList();
const QMetaObject *metaObject = OBJECT_PTR(node)->metaObject();
#if QT_CONFIG(tooltip)
- if (qstrcmp(metaObject->className(), "QTipLabel") == 0)
+ if (metaObject == &QTipLabel::staticMetaObject)
return QStringList("QToolTip"_L1);
#endif
QStringList result;
@@ -1581,7 +1581,7 @@ public:
return false;
const QMetaObject *metaObject = OBJECT_PTR(node)->metaObject();
#if QT_CONFIG(tooltip)
- if (qstrcmp(metaObject->className(), "QTipLabel") == 0)
+ if (metaObject == &QTipLabel::staticMetaObject)
return nodeName == "QToolTip"_L1;
#endif
do {
@@ -1747,7 +1747,7 @@ int QStyleSheetStyle::nativeFrameWidth(const QWidget *w)
}
#endif
- if (qstrcmp(w->metaObject()->className(), "QTipLabel") == 0)
+ if (w->metaObject() == &QTipLabel::staticMetaObject)
return base->pixelMetric(QStyle::PM_ToolTipLabelFrameWidth, nullptr, w);
return base->pixelMetric(QStyle::PM_DefaultFrameWidth, nullptr, w);
diff --git a/src/xml/doc/src/external-resources.qdoc b/src/xml/doc/src/external-resources.qdoc
index 89c30a84c47..89552477ae8 100644
--- a/src/xml/doc/src/external-resources.qdoc
+++ b/src/xml/doc/src/external-resources.qdoc
@@ -1,17 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
-
-/*!
- \externalpage http://www.w3.org/2000/xmlns/
- \title http://www.w3.org/2000/xmlns/
-*/
-
-/*!
- \externalpage http://www.saxproject.org/
- \title SAX2 Java interface
-*/
-
/*!
\externalpage http://www.w3.org/TR/DOM-Level-2-Core/
\title W3C DOM Level 2