summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmake/QtAndroidHelpers.cmake3
-rw-r--r--cmake/QtAutoDetectHelpers.cmake37
-rw-r--r--cmake/QtBaseConfigureTests.cmake30
-rw-r--r--cmake/QtCMakeVersionHelpers.cmake87
-rw-r--r--cmake/QtFeature.cmake8
-rw-r--r--cmake/QtPublicCMakeVersionHelpers.cmake36
-rw-r--r--cmake/QtToolchainHelpers.cmake7
-rw-r--r--coin/instructions/vxworks_testrunner.yaml96
-rw-r--r--examples/widgets/doc/src/draggableicons.qdoc1
-rw-r--r--examples/widgets/doc/src/draggabletext.qdoc1
-rw-r--r--examples/widgets/doc/src/dropsite.qdoc1
-rw-r--r--examples/widgets/doc/src/tablet.qdoc2
-rw-r--r--examples/widgets/gallery/main.cpp2
-rw-r--r--examples/widgets/gallery/widgetgallery.cpp168
-rw-r--r--examples/widgets/gallery/widgetgallery.h2
-rw-r--r--examples/widgets/gestures/imagegestures/doc/src/imagegestures.qdoc1
-rw-r--r--examples/widgets/touch/knobs/doc/src/touch-knobs.qdoc1
-rw-r--r--src/corelib/Qt6CoreMacros.cmake45
-rw-r--r--src/corelib/doc/src/qtcore.qdoc5
-rw-r--r--src/corelib/global/qalloc.h1
-rw-r--r--src/corelib/global/qassert.h19
-rw-r--r--src/corelib/global/qcompilerdetection.h4
-rw-r--r--src/corelib/global/qfloat16.h9
-rw-r--r--src/corelib/global/qnumeric.h2
-rw-r--r--src/corelib/io/qlockfile.cpp28
-rw-r--r--src/corelib/io/qlockfile_p.h12
-rw-r--r--src/corelib/io/qlockfile_unix.cpp5
-rw-r--r--src/corelib/io/qlockfile_win.cpp33
-rw-r--r--src/corelib/io/qrandomaccessasyncfile_p_p.h2
-rw-r--r--src/corelib/io/qrandomaccessasyncfile_threadpool.cpp4
-rw-r--r--src/corelib/kernel/qmetaobjectbuilder.cpp2
-rw-r--r--src/corelib/kernel/qobject.cpp43
-rw-r--r--src/corelib/kernel/qtimer.cpp27
-rw-r--r--src/corelib/kernel/qwinregistry.cpp4
-rw-r--r--src/corelib/platform/android/qandroidnativeinterface.cpp5
-rw-r--r--src/corelib/serialization/.gitignore1
-rwxr-xr-xsrc/corelib/serialization/make-xml-parser.sh1
-rw-r--r--src/corelib/serialization/qcborvalue.cpp24
-rw-r--r--src/corelib/serialization/qjsonparseerror.h4
-rw-r--r--src/corelib/serialization/qjsonparser.cpp4
-rw-r--r--src/corelib/text/qbytearray.h6
-rw-r--r--src/corelib/text/qchar.cpp77
-rw-r--r--src/corelib/text/qchar.h62
-rw-r--r--src/corelib/text/qcollator.cpp1
-rw-r--r--src/corelib/text/qcollator.h1
-rw-r--r--src/corelib/text/qcollator_icu.cpp1
-rw-r--r--src/corelib/text/qcollator_macx.cpp1
-rw-r--r--src/corelib/text/qcollator_p.h1
-rw-r--r--src/corelib/text/qcollator_posix.cpp1
-rw-r--r--src/corelib/text/qcollator_win.cpp1
-rw-r--r--src/corelib/text/qlocale.qdoc1
-rw-r--r--src/corelib/text/qstring.cpp4
-rw-r--r--src/corelib/text/qstring.h6
-rw-r--r--src/corelib/text/qtliterals.qdoc5
-rw-r--r--src/corelib/thread/qsemaphore.cpp20
-rw-r--r--src/corelib/time/qtimezoneprivate.cpp6
-rw-r--r--src/corelib/time/qtimezoneprivate_p.h4
-rw-r--r--src/corelib/tools/qarraydataops.h118
-rw-r--r--src/corelib/tools/qarraydatapointer.h95
-rw-r--r--src/corelib/tools/qcryptographichash.cpp38
-rw-r--r--src/corelib/tools/qhashfunctions.h4
-rw-r--r--src/corelib/tools/qlist.h13
-rw-r--r--src/corelib/tools/qshareddata.h323
-rw-r--r--src/gui/doc/images/plaintext-layout.pngbin46384 -> 0 bytes
-rw-r--r--src/gui/doc/images/plaintext-layout.webpbin0 -> 7714 bytes
-rw-r--r--src/gui/doc/src/qtgui.qdoc5
-rw-r--r--src/gui/doc/src/richtext.qdoc2
-rw-r--r--src/gui/image/qplatformpixmap.cpp1
-rw-r--r--src/gui/image/qplatformpixmap.h5
-rw-r--r--src/gui/kernel/qguiapplication.cpp9
-rw-r--r--src/gui/kernel/qkeysequence.cpp5
-rw-r--r--src/gui/kernel/qwindow.cpp6
-rw-r--r--src/gui/painting/qdrawhelper_avx2.cpp2
-rw-r--r--src/gui/painting/qpainterpath.cpp11
-rw-r--r--src/gui/painting/qstroker.cpp6
-rw-r--r--src/gui/platform/darwin/qappleiconengine.mm188
-rw-r--r--src/gui/platform/darwin/qapplekeymapper.mm153
-rw-r--r--src/gui/text/qtextdocumentfragment.cpp12
-rw-r--r--src/gui/text/qtextformat.cpp4
-rw-r--r--src/gui/util/qundostack.cpp12
-rw-r--r--src/gui/util/qundostack_p.h15
-rw-r--r--src/network/kernel/qhostaddress.cpp7
-rw-r--r--src/network/kernel/qhostaddress_p.h8
-rw-r--r--src/network/socket/qnativesocketengine_unix.cpp45
-rw-r--r--src/plugins/platforms/android/androidjniaccessibility.cpp13
-rw-r--r--src/plugins/platforms/android/qandroidplatformscreen.cpp2
-rw-r--r--src/plugins/platforms/android/qandroidplatformwindow.cpp39
-rw-r--r--src/plugins/platforms/android/qandroidplatformwindow.h5
-rw-r--r--src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm3
-rw-r--r--src/plugins/platforms/cocoa/qnsview_keys.mm3
-rw-r--r--src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosimagepickercontroller.h5
-rw-r--r--src/plugins/platforms/ios/qiosdocumentpickercontroller.h5
-rw-r--r--src/plugins/platforms/ios/qiosdocumentpickercontroller.mm13
-rw-r--r--src/plugins/platforms/ios/qiostextresponder.h5
-rw-r--r--src/plugins/platforms/ios/quiview.h5
-rw-r--r--src/plugins/platforms/wasm/qwasmaccessibility.cpp80
-rw-r--r--src/plugins/platforms/wasm/qwasmaccessibility.h2
-rw-r--r--src/plugins/platforms/wasm/qwasminputcontext.cpp4
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp6
-rw-r--r--src/plugins/styles/mac/qmacstyle_mac.mm5
-rw-r--r--src/plugins/styles/modernwindows/qwindows11style.cpp51
-rw-r--r--src/plugins/tls/schannel/qtls_schannel.cpp3
-rw-r--r--src/testinternal/QtRunCMakeTestWrappers.cmake14
-rw-r--r--src/testlib/qtest.h26
-rw-r--r--src/testlib/qtestcase.cpp13
-rw-r--r--src/testlib/qtestcase.h2
-rw-r--r--src/testlib/qtestregistry_p.h2
-rw-r--r--src/tools/androidtestrunner/main.cpp51
-rw-r--r--src/tools/macdeployqt/macdeployqt/main.cpp8
-rw-r--r--src/tools/macdeployqt/shared/shared.cpp1
-rw-r--r--src/widgets/doc/src/external-resources.qdoc2
-rw-r--r--src/widgets/doc/src/modelview.qdoc277
-rw-r--r--src/widgets/doc/src/qtwidgets-examples.qdoc12
-rw-r--r--src/widgets/doc/src/qtwidgets-toc.qdoc1
-rw-r--r--src/widgets/itemviews/qabstractitemview.cpp27
-rw-r--r--src/widgets/itemviews/qabstractitemview.h7
-rw-r--r--src/widgets/itemviews/qabstractitemview_p.h1
-rw-r--r--src/widgets/itemviews/qtreeview.cpp3
-rw-r--r--src/widgets/kernel/qapplication.cpp14
-rw-r--r--src/widgets/styles/qstylesheetstyle.cpp35
-rw-r--r--src/widgets/widgets/qmdisubwindow.cpp5
-rw-r--r--src/widgets/widgets/qmenu.cpp7
-rw-r--r--src/widgets/widgets/qmenu_p.h3
-rw-r--r--tests/auto/cmake/test_qt_add_ui_common/functions.cmake30
-rw-r--r--tests/auto/cmake/test_qt_add_ui_common/vs_generator_test/CMakeLists.txt6
-rw-r--r--tests/auto/corelib/global/qglobal/tst_qglobal.cpp13
-rw-r--r--tests/auto/corelib/io/qdirlisting/tst_qdirlisting.cpp63
-rw-r--r--tests/auto/corelib/io/qprocessenvironment/tst_qprocessenvironment.cpp2
-rw-r--r--tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp14
-rw-r--r--tests/auto/corelib/io/qsettings/tst_qsettings.cpp273
-rw-r--r--tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp23
-rw-r--r--tests/auto/corelib/kernel/qobject/tst_qobject.cpp6
-rw-r--r--tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp8
-rw-r--r--tests/auto/corelib/serialization/json/tst_qtjson.cpp22
-rw-r--r--tests/auto/corelib/thread/qfuture/tst_qfuture.cpp2
-rw-r--r--tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp8
-rw-r--r--tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp10
-rw-r--r--tests/auto/corelib/tools/qhash/tst_qhash.cpp2
-rw-r--r--tests/auto/corelib/tools/qlist/tst_qlist.cpp222
-rw-r--r--tests/auto/corelib/tools/qscopeguard/tst_qscopeguard.cpp8
-rw-r--r--tests/auto/gui/kernel/qsurfaceformat/tst_qsurfaceformat.cpp4
-rw-r--r--tests/auto/gui/painting/qpainter/tst_qpainter.cpp57
-rw-r--r--tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp26
-rw-r--r--tests/auto/gui/rhi/qrhi/tst_qrhi.cpp2
-rw-r--r--tests/auto/gui/rhi/qshader/tst_qshader.cpp5
-rw-r--r--tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp16
-rw-r--r--tests/auto/network/access/qnetworkreply_local/minihttpserver.h2
-rw-r--r--tests/auto/network/access/qnetworkreply_local/tst_qnetworkreply_local.cpp2
-rw-r--r--tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp67
-rw-r--r--tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp79
-rw-r--r--tests/auto/testlib/initmain/tst_initmain.cpp3
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp63
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp99
-rw-r--r--tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp14
-rw-r--r--tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp49
-rw-r--r--tests/benchmarks/corelib/time/qtimezone/tst_bench_qtimezone.cpp10
156 files changed, 2513 insertions, 1509 deletions
diff --git a/cmake/QtAndroidHelpers.cmake b/cmake/QtAndroidHelpers.cmake
index b473c2c331b..59a469b1683 100644
--- a/cmake/QtAndroidHelpers.cmake
+++ b/cmake/QtAndroidHelpers.cmake
@@ -442,8 +442,9 @@ function(qt_internal_create_source_jar)
add_dependencies(android_source_jars ${jar_target})
if(QT_WILL_INSTALL)
+ qt_path_join(destination "${INSTALL_DATADIR}" "android" "${module}")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${jar_name}-${PROJECT_VERSION}.jar"
- DESTINATION "${INSTALL_DATADIR}/android/${module}"
+ DESTINATION "${destination}"
COMPONENT _install_android_source_jar_${module}
EXCLUDE_FROM_ALL
)
diff --git a/cmake/QtAutoDetectHelpers.cmake b/cmake/QtAutoDetectHelpers.cmake
index fe6087748d6..6e6473da641 100644
--- a/cmake/QtAutoDetectHelpers.cmake
+++ b/cmake/QtAutoDetectHelpers.cmake
@@ -64,6 +64,41 @@ function(qt_auto_detect_wasm)
endif()
endfunction()
+# Handle assignment of CMAKE_POLICY_VERSION_MINIMUM for Android NDK cmake toolchain files shipped
+# with NDK < r28, to avoid deprecation warnings.
+#
+# NOTE: If updating the version, also update
+# qt_internal_get_android_qt_default_cmake_policy_version_minimum.
+#
+# Use a macro, to make propagation of the variable in the parent scope of the calling function
+# easier.
+macro(qt_auto_detect_set_android_cmake_policy_version_minimum is_android_detected)
+ if("${is_android_detected}"
+ AND CMAKE_VERSION VERSION_GREATER_EQUAL "4.0"
+ AND NOT QT_NO_SET_ANDROID_CMAKE_POLICY_VERSION_MINIMUM
+ )
+
+ if(QT_ANDROID_CMAKE_POLICY_VERSION_MINIMUM)
+ set(min_policy_version "${QT_ANDROID_CMAKE_POLICY_VERSION_MINIMUM}")
+ elseif(CMAKE_POLICY_VERSION_MINIMUM)
+ set(min_policy_version "${CMAKE_POLICY_VERSION_MINIMUM}")
+ else()
+ set(min_policy_version "3.10")
+ endif()
+
+ message(DEBUG
+ "Setting CMAKE_POLICY_VERSION_MINIMUM to ${min_policy_version} for Android builds.")
+
+ # Set the variable in the qtbase directory scope for easier reading.
+ set(CMAKE_POLICY_VERSION_MINIMUM "${min_policy_version}" PARENT_SCOPE)
+
+ # Also set the environment variable, otherwise any try_compile project that's started
+ # by CMake itself, rather than Qt (e.g. compiler detection), will not inherit the
+ # assignment.
+ set(ENV{CMAKE_POLICY_VERSION_MINIMUM} "${min_policy_version}")
+ endif()
+endmacro()
+
function(qt_auto_detect_android)
# Don't assume an Android build if we're requesting to build Java documentation on the host.
if(QT_BUILD_HOST_JAVA_DOCS)
@@ -154,6 +189,8 @@ function(qt_auto_detect_android)
elseif (QT_AUTODETECT_ANDROID)
message(STATUS "Android build detected")
endif()
+
+ qt_auto_detect_set_android_cmake_policy_version_minimum("${android_detected}")
endfunction()
function(qt_auto_detect_vcpkg)
diff --git a/cmake/QtBaseConfigureTests.cmake b/cmake/QtBaseConfigureTests.cmake
index fcc3b1a3f1c..da97e2b4f8b 100644
--- a/cmake/QtBaseConfigureTests.cmake
+++ b/cmake/QtBaseConfigureTests.cmake
@@ -306,6 +306,36 @@ function(qt_internal_print_cmake_host_and_target_info)
message(STATUS "CMAKE_SYSTEM_PROCESSOR: \"${CMAKE_SYSTEM_PROCESSOR}\"")
message(STATUS "CMAKE_CROSSCOMPILING: \"${CMAKE_CROSSCOMPILING}\"")
+
+ message(STATUS "CMAKE_CXX_COMPILER_ID: \"${CMAKE_CXX_COMPILER_ID}\"")
+ message(STATUS "CMAKE_CXX_COMPILER_VERSION: \"${CMAKE_CXX_COMPILER_VERSION}\"")
+
+ # The variables might not be defined depending on platform and CMake version.
+ if(CMAKE_CXX_COMPILER_TARGET)
+ message(STATUS "CMAKE_CXX_COMPILER_TARGET: \"${CMAKE_CXX_COMPILER_TARGET}\"")
+ endif()
+ if(CMAKE_CXX_COMPILER_ARCHITECTURE_ID)
+ message(STATUS
+ "CMAKE_CXX_COMPILER_ARCHITECTURE_ID: \"${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}\"")
+ endif()
+ if(CMAKE_CXX_COMPILER_FRONTEND_VARIANT)
+ message(STATUS
+ "CMAKE_CXX_COMPILER_FRONTEND_VARIANT: \"${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}\"")
+ endif()
+
+ if(CMAKE_CXX_COMPILER_LINKER_ID)
+ message(STATUS "CMAKE_CXX_COMPILER_LINKER_ID: \"${CMAKE_CXX_COMPILER_LINKER_ID}\"")
+ endif()
+
+ if(CMAKE_CXX_COMPILER_LINKER_VERSION)
+ message(STATUS
+ "CMAKE_CXX_COMPILER_LINKER_VERSION: \"${CMAKE_CXX_COMPILER_LINKER_VERSION}\"")
+ endif()
+
+ if(CMAKE_CXX_COMPILER_LINKER_FRONTEND_VARIANT)
+ message(STATUS "CMAKE_CXX_COMPILER_LINKER_FRONTEND_VARIANT: "
+ "\"${CMAKE_CXX_COMPILER_LINKER_FRONTEND_VARIANT}\"")
+ endif()
endfunction()
qt_internal_print_cmake_host_and_target_info()
diff --git a/cmake/QtCMakeVersionHelpers.cmake b/cmake/QtCMakeVersionHelpers.cmake
index 3a3ba0fc750..73b40b4a610 100644
--- a/cmake/QtCMakeVersionHelpers.cmake
+++ b/cmake/QtCMakeVersionHelpers.cmake
@@ -300,3 +300,90 @@ function(qt_internal_upgrade_cmake_policies)
qt_internal_get_max_new_policy_cmake_version(upper_version)
cmake_minimum_required(VERSION ${lower_version}...${upper_version})
endfunction()
+
+# Get which version to use for CMAKE_POLICY_VERSION_MINIMUM on Android.
+# Allow various overrides via QT_ANDROID_CMAKE_POLICY_VERSION_MINIMUM and reading an existing
+# CMAKE_POLICY_VERSION_MINIMUM.
+function(qt_internal_get_android_cmake_policy_version_minimum_value out_var)
+ if(QT_ANDROID_CMAKE_POLICY_VERSION_MINIMUM)
+ set(value "${QT_ANDROID_CMAKE_POLICY_VERSION_MINIMUM}")
+ elseif(CMAKE_POLICY_VERSION_MINIMUM)
+ set(value "${CMAKE_POLICY_VERSION_MINIMUM}")
+ else()
+ qt_internal_get_android_qt_default_cmake_policy_version_minimum(default_value)
+ set(value "${default_value}")
+ endif()
+
+ set(${out_var} "${value}" PARENT_SCOPE)
+endfunction()
+
+# NOTE: If updating the version, also update
+# qt_auto_detect_set_android_cmake_policy_version_minimum.
+function(qt_internal_get_android_qt_default_cmake_policy_version_minimum out_var)
+ set(${out_var} "3.10" PARENT_SCOPE)
+endfunction()
+
+# Handle assignment of CMAKE_POLICY_VERSION_MINIMUM for Android NDK cmake toolchain files shipped
+# with NDK < r28, to avoid deprecation warnings.
+# See https://github.com/android/ndk/issues/2100
+# and https://android.googlesource.com/platform/ndk/+/799e5a2d44cc2cc6c7d67f52f2d67957944b7680
+# The function is to get the appropriate var asisgnment for try_compile calls,
+# as well as writing it to the Qt generated toolchain file.
+# Various opt-outs and opt-ins are provided via QT_NO_SET_ANDROID_CMAKE_POLICY_VERSION_MINIMUM
+# and QT_ANDROID_CMAKE_POLICY_VERSION_MINIMUM.
+#
+# See also usage in qt_auto_detect_set_android_cmake_policy_version_minimum.
+function(qt_internal_get_android_cmake_policy_version_minimum_assignment out_var)
+ set(option_args "")
+ set(single_args
+ TYPE
+ )
+ set(multi_args "")
+
+ cmake_parse_arguments(PARSE_ARGV 1 arg
+ "${option_args}"
+ "${single_args}"
+ "${multi_args}"
+ )
+ _qt_internal_validate_all_args_are_parsed(arg)
+
+ set(value "")
+ if(CMAKE_VERSION VERSION_GREATER_EQUAL "4.0"
+ AND NOT QT_NO_SET_ANDROID_CMAKE_POLICY_VERSION_MINIMUM
+ )
+ qt_internal_get_android_cmake_policy_version_minimum_value(version)
+
+ if(arg_TYPE STREQUAL "COMMAND_LINE")
+ set(value "-DCMAKE_POLICY_VERSION_MINIMUM=${version}")
+
+ elseif(arg_TYPE STREQUAL "TOOLCHAIN_FILE_ASSIGNMENT")
+ set(value "
+# Avoid deprecation warnings in Android ndk cmake toolchain file < r28
+set(__qt_initially_configured_android_cmake_policy_version_minimum \"${version}\")
+if(CMAKE_VERSION VERSION_GREATER_EQUAL \"4.0\"
+ AND NOT QT_NO_SET_ANDROID_CMAKE_POLICY_VERSION_MINIMUM
+ )
+ if(QT_ANDROID_CMAKE_POLICY_VERSION_MINIMUM)
+ set(__qt_toolchain_cmake_policy_version_minimum
+ \"\${QT_ANDROID_CMAKE_POLICY_VERSION_MINIMUM}\")
+ elseif(CMAKE_POLICY_VERSION_MINIMUM)
+ set(__qt_toolchain_cmake_policy_version_minimum
+ \"\${CMAKE_POLICY_VERSION_MINIMUM}\")
+ else()
+ set(__qt_toolchain_cmake_policy_version_minimum
+ \"\${__qt_initially_configured_android_cmake_policy_version_minimum}\")
+ endif()
+ set(CMAKE_POLICY_VERSION_MINIMUM \"\${__qt_toolchain_cmake_policy_version_minimum}\")
+ message(DEBUG
+ \"Setting CMAKE_POLICY_VERSION_MINIMUM to \"
+ \"\${__qt_toolchain_cmake_policy_version_minimum}\ in toolchain file.\")
+endif()
+")
+ else()
+ message(FATAL_ERROR "Unknown TYPE value '${arg_TYPE}'. "
+ " Supported values are COMMAND_LINE and VAR_ASSIGNMENT.")
+ endif()
+ endif()
+
+ set(${out_var} "${value}" PARENT_SCOPE)
+endfunction()
diff --git a/cmake/QtFeature.cmake b/cmake/QtFeature.cmake
index e8ae3dd5163..de0323214c5 100644
--- a/cmake/QtFeature.cmake
+++ b/cmake/QtFeature.cmake
@@ -1737,6 +1737,14 @@ function(qt_get_platform_try_compile_vars out_var)
list(APPEND flags_cmd_line "-DCMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH:BOOL=OFF")
endif()
+ if(ANDROID)
+ qt_internal_get_android_cmake_policy_version_minimum_assignment(
+ android_cmake_policy_version_minimum TYPE COMMAND_LINE)
+ if(android_cmake_policy_version_minimum)
+ list(APPEND flags_cmd_line "${android_cmake_policy_version_minimum}")
+ endif()
+ endif()
+
set("${out_var}" "${flags_cmd_line}" PARENT_SCOPE)
endfunction()
diff --git a/cmake/QtPublicCMakeVersionHelpers.cmake b/cmake/QtPublicCMakeVersionHelpers.cmake
index 292d97c84e7..0207c087e1a 100644
--- a/cmake/QtPublicCMakeVersionHelpers.cmake
+++ b/cmake/QtPublicCMakeVersionHelpers.cmake
@@ -107,10 +107,9 @@ endfunction()
# Handle force-assignment of CMP0156 policy when using CMake 3.29+.
#
# For Apple-platforms we set it to NEW, to avoid duplicate linker issues when using -ObjC flag.
+# For Emscripten / WebAssembly we also set it to NEW, to avoid duplicate linker issues.
#
-# For non-Apple platforms we set it to OLD, because we haven't done the necessary testing to
-# see which platforms / linkers can handle the new deduplication behavior, without breaking the
-# various linking techniques that Qt uses for object library propagation.
+# For other platforms, we leave the policy value as-is, without showing any warnings.
function(__qt_internal_set_cmp0156)
# Exit early if not using CMake 3.29+
if(NOT POLICY CMP0156)
@@ -164,29 +163,32 @@ function(__qt_internal_set_cmp0156)
set(default_policy_value NEW)
set(unsupported_policy_value OLD)
else()
- # For non-Apple linkers, we keep the previous behavior of not deduplicating libraries,
- # because we haven't done the necessary testing to identify on which platforms
- # it is safe to deduplicate.
- set(default_policy_value OLD)
- set(unsupported_policy_value NEW)
+ # For other platforms we don't enforce any policy values and keep them as-is.
+ set(default_policy_value "")
+ set(unsupported_policy_value "")
endif()
# Force set the default policy value for the given platform, even if the policy value is
# the same or empty. That's because in the calling function scope, the value can be empty
# due to the cmake_minimum_required call in Qt6Config.cmake resetting the policy value.
- get_cmake_property(debug_message_shown _qt_internal_cmp0156_debug_message_shown)
- if(NOT debug_message_shown)
- message(DEBUG "Force setting the CMP0156 policy to '${default_policy_value}' "
- "for platform '${CMAKE_SYSTEM_NAME}'.")
- set_property(GLOBAL PROPERTY _qt_internal_cmp0156_debug_message_shown TRUE)
- endif()
+ if(default_policy_value)
+ get_cmake_property(debug_message_shown _qt_internal_cmp0156_debug_message_shown)
+ if(NOT debug_message_shown)
+ message(DEBUG "Force setting the CMP0156 policy to '${default_policy_value}' "
+ "for platform '${CMAKE_SYSTEM_NAME}'.")
+ set_property(GLOBAL PROPERTY _qt_internal_cmp0156_debug_message_shown TRUE)
+ endif()
- cmake_policy(SET CMP0156 "${default_policy_value}")
+ cmake_policy(SET CMP0156 "${default_policy_value}")
+ endif()
- # If the policy is explicitly set to a value other than the default, issue a warning.
+ # If the policy is explicitly set to a value other than the (non-empty) default, issue a
+ # warning.
# Don't show the warning if the policy is unset, which would be the default for most
# projects, because it's too much noise. Also don't show it for Qt builds.
- if("${policy_value}" STREQUAL "${unsupported_policy_value}" AND NOT QT_BUILDING_QT)
+ if(unsupported_policy_value
+ AND "${policy_value}" STREQUAL "${unsupported_policy_value}"
+ AND NOT QT_BUILDING_QT)
message(WARNING
"CMP0156 is set to '${policy_value}'. Qt forces the '${default_policy_value}'"
" behavior of this policy for the '${CMAKE_SYSTEM_NAME}' platform by default."
diff --git a/cmake/QtToolchainHelpers.cmake b/cmake/QtToolchainHelpers.cmake
index 9407fd0ebe5..348a3c25603 100644
--- a/cmake/QtToolchainHelpers.cmake
+++ b/cmake/QtToolchainHelpers.cmake
@@ -309,6 +309,13 @@ endif()")
" \"Please specify the toolchain file with -DQT_CHAINLOAD_TOOLCHAIN_FILE=<file>.\")")
list(APPEND init_platform " endif()")
list(APPEND init_platform "endif()")
+
+ qt_internal_get_android_cmake_policy_version_minimum_assignment(
+ android_cmake_policy_version_minimum TYPE TOOLCHAIN_FILE_ASSIGNMENT)
+ if(android_cmake_policy_version_minimum)
+ list(APPEND init_platform "${android_cmake_policy_version_minimum}")
+ endif()
+
elseif(EMSCRIPTEN)
list(APPEND init_platform
"include(\${CMAKE_CURRENT_LIST_DIR}/QtPublicWasmToolchainHelpers.cmake)
diff --git a/coin/instructions/vxworks_testrunner.yaml b/coin/instructions/vxworks_testrunner.yaml
index 6979b6807da..177a2ce7cf1 100644
--- a/coin/instructions/vxworks_testrunner.yaml
+++ b/coin/instructions/vxworks_testrunner.yaml
@@ -5,8 +5,41 @@ instructions:
fileMode: 493
fileContents: |
#!/bin/bash
+
+ # Seconds of serial silence before triggering an SSH probe; also the cadence for repeated probes
+ EMPTY_READ_GRACE=60
+
+ # Maximum time (s) with no output while waiting; exceeding this triggers a timeout failure
+ MAX_WAIT_TIME=700
+
quoted_args=`python3 -c 'import sys, shlex; print(shlex.join(sys.argv[2:]))' "$@"`
+ ssh_cmd() {
+ LD_LIBRARY_PATH=/usr/lib ssh -n -q -T \
+ -o BatchMode=yes -o ConnectTimeout=1 -o HostKeyAlgorithms=+ssh-rsa \
+ -o PreferredAuthentications=publickey \
+ -o NumberOfPasswordPrompts=0 \
+ ${VXWORKS_SSH} "$@" </dev/null
+ }
+
+ ssh_probe_status() {
+ # Returns one of: FINISHED | RUNNING | UNRESPONSIVE
+ local out
+ out="$(ssh_cmd 'cmd rtp list; exit' 2>&1 || true)"
+ # If we don't see the normal SSH epilogue ("Au revoir!"), treat as UNRESPONSIVE
+ # (system is probably under a heavy load)
+ if ! printf '%s\n' "$out" | /usr/bin/grep -q 'Au revoir!'; then
+ echo "UNRESPONSIVE"
+ return 0
+ fi
+ # Determine if our RTP is present; currently we match by 'tests' substring in 'rtp list' output
+ if printf '%s\n' "$out" | /usr/bin/grep -Fq "tests"; then
+ echo "RUNNING"
+ else
+ echo "FINISHED"
+ fi
+ }
+
testdir="$(dirname $1)"
testexecutable="$1"
echo RUNNING via serial: "$quoted_args"
@@ -33,8 +66,16 @@ instructions:
read -t 1 testline</tmp/guest.out
fi
- if [[ -z "$testline" ]]; then
- echo "Restarting stuck emulator"
+ probe0="$(ssh_probe_status)"
+
+ if [[ -z "$testline" || "$probe0" != "FINISHED" ]]; then
+ if [[ "$probe0" == "UNRESPONSIVE" ]]; then
+ echo "Restarting stuck emulator (SSH down)"
+ elif [[ "$probe0" == "RUNNING" ]]; then
+ echo "Restarting stuck emulator (RTP still running)"
+ else
+ echo "Restarting stuck emulator (serial down)"
+ fi
pkill qemu-system
rm /tmp/guest.in /tmp/guest.out
mkfifo /tmp/guest.in /tmp/guest.out
@@ -43,20 +84,57 @@ instructions:
/bin/bash /home/qt/work/coin_vxworks_vars.sh
sleep 1
else
- echo "Emulator responding"
+ echo "VxWorks is functional"
fi
- # Empty output
+ # Empty out any pending serial output to start clean
while read -t 1 line; do
echo $line
done < /tmp/guest.out
- echo "cmd cd $testdir" > /tmp/guest.in
- sleep 1
+ echo "cmd cd $testdir; echo done" > /tmp/guest.in
+
+ # Empty line before result of cd
+ read -t 1 line_cmd </tmp/guest.out
+
+ if read -t 1 cdline </tmp/guest.out; then
+ cdline_clean=$(printf '%s' "$cdline" | tr -d '\r')
+ if printf '%s' "$cdline_clean" | /usr/bin/grep -Eq 'error\s*='; then
+ printf 'entering %s: %s\n' "$testdir" "$cdline_clean"
+ exit 1
+ fi
+ fi
+
echo "</home/qt/work/vx.sh" > /tmp/guest.in
- while read -t 600 line; do
+ silent_seconds=0
+ last_probe_result="NONE"
+
+ while true; do
+ if ! read -t $EMPTY_READ_GRACE line; then
+ silent_seconds=$((silent_seconds + EMPTY_READ_GRACE))
+
+ probe="$(ssh_probe_status)"
+ last_probe_result="$probe"
+ if [[ "$probe" == "UNRESPONSIVE" ]]; then
+ echo "system is under heavy load after ${silent_seconds}s of silence (SSH unresponsive)"
+ elif [[ "$probe" == "FINISHED" ]]; then
+ echo "RTP finished after ${silent_seconds}s of silence, ending"
+ exit 0
+ fi
+ # RUNNING or UNRESPONSIVE - keep waiting
+ if (( silent_seconds >= MAX_WAIT_TIME )); then
+ echo "Timeout: no output for ${MAX_WAIT_TIME}s (last SSH probe: ${last_probe_result})"
+ exit 1
+ fi
+ continue
+ fi
+
+ # We received serial output
+ silent_seconds=0
+
echo "$line"
+
if echo "$line" | /usr/bin/grep -q "qtest_in_vxworks_complete"
then
read -t 1 line</tmp/guest.out
@@ -68,12 +146,12 @@ instructions:
# Handle crashes
if echo "$line" | /usr/bin/grep -qE "(SIGSEGV)|(SIGABRT)|(S_rtpLib_[A-Z_]+)"
then
- # Empty output pipe
+ # Drain the pipe for context, mark as crashed, and restart emulator next run.
while read -t 1 line; do
echo $line
done < /tmp/guest.out
echo "Test crashed"
- pkill qemu-system # Kill emulator to force restart on next test start
+ pkill qemu-system
exit 1
fi
done < /tmp/guest.out
diff --git a/examples/widgets/doc/src/draggableicons.qdoc b/examples/widgets/doc/src/draggableicons.qdoc
index 0f1feacb7fb..3cf9b9b7266 100644
--- a/examples/widgets/doc/src/draggableicons.qdoc
+++ b/examples/widgets/doc/src/draggableicons.qdoc
@@ -4,6 +4,7 @@
/*!
\example draganddrop/draggableicons
\title Draggable Icons Example
+ \ingroup examples-user-input
\examplecategory {User Interface Components}
\brief The Draggable Icons example shows how to drag and drop image data between widgets
diff --git a/examples/widgets/doc/src/draggabletext.qdoc b/examples/widgets/doc/src/draggabletext.qdoc
index 3609ed5a1a1..f34e166ed89 100644
--- a/examples/widgets/doc/src/draggabletext.qdoc
+++ b/examples/widgets/doc/src/draggabletext.qdoc
@@ -4,6 +4,7 @@
/*!
\example draganddrop/draggabletext
\title Draggable Text Example
+ \ingroup examples-user-input
\examplecategory {User Interface Components}
\brief Illustrates how to drag and drop text between widgets.
diff --git a/examples/widgets/doc/src/dropsite.qdoc b/examples/widgets/doc/src/dropsite.qdoc
index 4c38ffc50d3..baa7b22fa8a 100644
--- a/examples/widgets/doc/src/dropsite.qdoc
+++ b/examples/widgets/doc/src/dropsite.qdoc
@@ -4,6 +4,7 @@
/*!
\example draganddrop/dropsite
\title Drop Site Example
+ \ingroup examples-user-input
\examplecategory {User Interface Components}
\brief The example shows how to distinguish the various MIME formats available
diff --git a/examples/widgets/doc/src/tablet.qdoc b/examples/widgets/doc/src/tablet.qdoc
index a18eb3249e7..f1238238df9 100644
--- a/examples/widgets/doc/src/tablet.qdoc
+++ b/examples/widgets/doc/src/tablet.qdoc
@@ -5,7 +5,7 @@
\example widgets/tablet
\title Tablet Example
\examplecategory {User Interface Components}
- \ingroup examples-widgets
+ \ingroup examples-user-input
\brief This example shows how to use a Wacom tablet in Qt applications.
\image tabletexample.png {Application displaying a drawing area}
diff --git a/examples/widgets/gallery/main.cpp b/examples/widgets/gallery/main.cpp
index 95fffbdd3c1..b85706e1015 100644
--- a/examples/widgets/gallery/main.cpp
+++ b/examples/widgets/gallery/main.cpp
@@ -9,7 +9,7 @@
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
- app.styleHints()->setColorScheme(Qt::ColorScheme::Dark);
+ QGuiApplication::styleHints()->setColorScheme(Qt::ColorScheme::Dark);
WidgetGallery gallery;
gallery.show();
return QCoreApplication::exec();
diff --git a/examples/widgets/gallery/widgetgallery.cpp b/examples/widgets/gallery/widgetgallery.cpp
index deef6b42181..e2ffec50e81 100644
--- a/examples/widgets/gallery/widgetgallery.cpp
+++ b/examples/widgets/gallery/widgetgallery.cpp
@@ -13,10 +13,10 @@
#include <QFileSystemModel>
#include <QGridLayout>
#include <QGroupBox>
-#include <QMenu>
#include <QLabel>
#include <QLineEdit>
#include <QListWidget>
+#include <QMenu>
#include <QPlainTextEdit>
#include <QProgressBar>
#include <QPushButton>
@@ -26,26 +26,30 @@
#include <QSpinBox>
#include <QStandardItemModel>
#include <QStyle>
-#include <QStyleHints>
#include <QStyleFactory>
-#include <QTextBrowser>
-#include <QTreeView>
+#include <QStyleHints>
#include <QTableWidget>
+#include <QTextBrowser>
#include <QTextEdit>
#include <QToolBox>
#include <QToolButton>
+#include <QTreeView>
-#include <QIcon>
#include <QDesktopServices>
+#include <QIcon>
#include <QScreen>
#include <QWindow>
+#include <QAnyStringView>
#include <QDebug>
#include <QLibraryInfo>
+#include <QStringView>
#include <QSysInfo>
#include <QTextStream>
#include <QTimer>
+using namespace Qt::StringLiterals;
+
static inline QString className(const QObject *o)
{
return QString::fromUtf8(o->metaObject()->className());
@@ -56,7 +60,7 @@ static inline void setClassNameToolTip(QWidget *w)
w->setToolTip(className(w));
}
-static QString helpUrl(const QString &page)
+static QString helpUrl(QStringView page)
{
QString result;
QTextStream(&result) << "https://doc.qt.io/qt-" << QT_VERSION_MAJOR
@@ -76,23 +80,23 @@ static void launchHelp(const QWidget *w)
static void launchModuleHelp()
{
- QDesktopServices::openUrl(helpUrl(QLatin1String("qtwidgets-index")));
+ QDesktopServices::openUrl(helpUrl(u"qtwidgets-index"));
}
template <class Widget>
-Widget *createWidget(const char *name, QWidget *parent = nullptr)
+Widget *createWidget(QAnyStringView name, QWidget *parent = nullptr)
{
- auto result = new Widget(parent);
- result->setObjectName(QLatin1String(name));
+ auto *result = new Widget(parent);
+ result->setObjectName(name);
setClassNameToolTip(result);
return result;
}
template <class Widget, class Parameter>
-Widget *createWidget1(const Parameter &p1, const char *name, QWidget *parent = nullptr)
+Widget *createWidget1(const Parameter &p1, QAnyStringView name, QWidget *parent = nullptr)
{
- auto result = new Widget(p1, parent);
- result->setObjectName(QLatin1String(name));
+ auto *result = new Widget(p1, parent);
+ result->setObjectName(name);
setClassNameToolTip(result);
return result;
}
@@ -108,9 +112,9 @@ static QString highDpiScaleFactorRoundingPolicy()
{
QString result;
QDebug(&result) << QGuiApplication::highDpiScaleFactorRoundingPolicy();
- if (result.endsWith(QLatin1Char(')')))
+ if (result.endsWith(u')'))
result.chop(1);
- const int lastSep = result.lastIndexOf(QLatin1String("::"));
+ const auto lastSep = result.lastIndexOf("::"_L1);
if (lastSep != -1)
result.remove(0, lastSep + 2);
return result;
@@ -122,10 +126,10 @@ WidgetGallery::WidgetGallery(QWidget *parent)
{
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
- auto styleComboBox = createWidget<QComboBox>("styleComboBox");
+ auto *styleComboBox = createWidget<QComboBox>("styleComboBox");
const QString defaultStyleName = QApplication::style()->objectName();
QStringList styleNames = QStyleFactory::keys();
- for (int i = 1, size = styleNames.size(); i < size; ++i) {
+ for (qsizetype i = 1, size = styleNames.size(); i < size; ++i) {
if (defaultStyleName.compare(styleNames.at(i), Qt::CaseInsensitive) == 0) {
styleNames.swapItemsAt(0, i);
break;
@@ -133,16 +137,16 @@ WidgetGallery::WidgetGallery(QWidget *parent)
}
styleComboBox->addItems(styleNames);
- auto styleLabel = createWidget1<QLabel>(tr("&Style:"), "styleLabel");
+ auto *styleLabel = createWidget1<QLabel>(tr("&Style:"), "styleLabel");
styleLabel->setBuddy(styleComboBox);
- auto colorSchemeComboBox = createWidget<QComboBox>("colorSchemeComboBox");
+ auto *colorSchemeComboBox = createWidget<QComboBox>("colorSchemeComboBox");
colorSchemeComboBox->addItem(tr("Auto"));
colorSchemeComboBox->addItem(tr("Light"));
colorSchemeComboBox->addItem(tr("Dark"));
colorSchemeComboBox->setCurrentIndex(static_cast<int>(qApp->styleHints()->colorScheme()));
- auto colorSchemeLabel = createWidget1<QLabel>(tr("&Color Scheme:"), "colorSchemeLabel");
+ auto *colorSchemeLabel = createWidget1<QLabel>(tr("&Color Scheme:"), "colorSchemeLabel");
colorSchemeLabel->setBuddy(colorSchemeComboBox);
connect(colorSchemeComboBox, &QComboBox::currentIndexChanged, this, [](int index){
@@ -150,15 +154,16 @@ WidgetGallery::WidgetGallery(QWidget *parent)
});
const QKeySequence helpKeySequence(QKeySequence::HelpContents);
- auto helpLabel = createWidget1<QLabel>(tr("Press <kbd>%1</kbd> over a widget to see Documentation")
- .arg(helpKeySequence.toString(QKeySequence::NativeText)), "helpLabel");
+ const QString helpText = tr("Press <kbd>%1</kbd> over a widget to see Documentation")
+ .arg(helpKeySequence.toString(QKeySequence::NativeText));
+ auto *helpLabel = createWidget1<QLabel>(helpText, "helpLabel");
- auto disableWidgetsCheckBox = createWidget1<QCheckBox>(tr("&Disable widgets"), "disableWidgetsCheckBox");
+ auto *disableWidgetsCheckBox = createWidget1<QCheckBox>(tr("&Disable widgets"), "disableWidgetsCheckBox");
- auto buttonsGroupBox = createButtonsGroupBox();
- auto itemViewTabWidget = createItemViewTabWidget();
- auto simpleInputWidgetsGroupBox = createSimpleInputWidgetsGroupBox();
- auto textToolBox = createTextToolBox();
+ auto *buttonsGroupBox = createButtonsGroupBox();
+ auto *itemViewTabWidget = createItemViewTabWidget();
+ auto *simpleInputWidgetsGroupBox = createSimpleInputWidgetsGroupBox();
+ auto *textToolBox = createTextToolBox();
connect(styleComboBox, &QComboBox::textActivated,
this, &WidgetGallery::changeStyle);
@@ -171,8 +176,8 @@ WidgetGallery::WidgetGallery(QWidget *parent)
connect(disableWidgetsCheckBox, &QCheckBox::toggled,
simpleInputWidgetsGroupBox, &QWidget::setDisabled);
- auto topLayout = new QHBoxLayout;
- auto appearanceLayout = new QGridLayout;
+ auto *topLayout = new QHBoxLayout;
+ auto *appearanceLayout = new QGridLayout;
appearanceLayout->addWidget(styleLabel, 0, 0);
appearanceLayout->addWidget(styleComboBox, 0, 1);
appearanceLayout->addWidget(colorSchemeLabel, 1, 0);
@@ -183,12 +188,12 @@ WidgetGallery::WidgetGallery(QWidget *parent)
topLayout->addStretch(1);
topLayout->addWidget(disableWidgetsCheckBox);
- auto dialogButtonBox = createWidget1<QDialogButtonBox>(QDialogButtonBox::Help | QDialogButtonBox::Close,
- "dialogButtonBox");
+ auto *dialogButtonBox = createWidget1<QDialogButtonBox>(
+ QDialogButtonBox::Help | QDialogButtonBox::Close, "dialogButtonBox");
connect(dialogButtonBox, &QDialogButtonBox::helpRequested, this, launchModuleHelp);
connect(dialogButtonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
- auto mainLayout = new QGridLayout(this);
+ auto *mainLayout = new QGridLayout(this);
mainLayout->addLayout(topLayout, 0, 0, 1, 2);
mainLayout->addWidget(buttonsGroupBox, 1, 0);
mainLayout->addWidget(simpleInputWidgetsGroupBox, 1, 1);
@@ -225,38 +230,38 @@ void WidgetGallery::advanceProgressBar()
QGroupBox *WidgetGallery::createButtonsGroupBox()
{
- auto result = createWidget1<QGroupBox>(tr("Buttons"), "buttonsGroupBox");
+ auto *result = createWidget1<QGroupBox>(tr("Buttons"), "buttonsGroupBox");
- auto defaultPushButton = createWidget1<QPushButton>(tr("Default Push Button"), "defaultPushButton");
+ auto *defaultPushButton = createWidget1<QPushButton>(tr("Default Push Button"), "defaultPushButton");
defaultPushButton->setDefault(true);
- auto togglePushButton = createWidget1<QPushButton>(tr("Toggle Push Button"), "togglePushButton");
+ auto *togglePushButton = createWidget1<QPushButton>(tr("Toggle Push Button"), "togglePushButton");
togglePushButton->setCheckable(true);
togglePushButton->setChecked(true);
- auto flatPushButton = createWidget1<QPushButton>(tr("Flat Push Button"), "flatPushButton");
+ auto *flatPushButton = createWidget1<QPushButton>(tr("Flat Push Button"), "flatPushButton");
flatPushButton->setFlat(true);
- auto toolButton = createWidget<QToolButton>("toolButton");
+ auto *toolButton = createWidget<QToolButton>("toolButton");
toolButton->setText(tr("Tool Button"));
- auto menuToolButton = createWidget<QToolButton>("menuButton");
+ auto *menuToolButton = createWidget<QToolButton>("menuButton");
menuToolButton->setText(tr("Menu Button"));
- auto toolMenu = new QMenu(menuToolButton);
+ auto *toolMenu = new QMenu(menuToolButton);
menuToolButton->setPopupMode(QToolButton::InstantPopup);
toolMenu->addAction("Option");
toolMenu->addSeparator();
- auto action = toolMenu->addAction("Checkable Option");
+ auto *action = toolMenu->addAction("Checkable Option");
action->setCheckable(true);
menuToolButton->setMenu(toolMenu);
- auto toolLayout = new QHBoxLayout;
+ auto *toolLayout = new QHBoxLayout;
toolLayout->addWidget(toolButton);
toolLayout->addWidget(menuToolButton);
- auto commandLinkButton = createWidget1<QCommandLinkButton>(tr("Command Link Button"), "commandLinkButton");
+ auto *commandLinkButton = createWidget1<QCommandLinkButton>(tr("Command Link Button"), "commandLinkButton");
commandLinkButton->setDescription(tr("Description"));
- auto buttonLayout = new QVBoxLayout;
+ auto *buttonLayout = new QVBoxLayout;
buttonLayout->addWidget(defaultPushButton);
buttonLayout->addWidget(togglePushButton);
buttonLayout->addWidget(flatPushButton);
@@ -264,23 +269,23 @@ QGroupBox *WidgetGallery::createButtonsGroupBox()
buttonLayout->addWidget(commandLinkButton);
buttonLayout->addStretch(1);
- auto radioButton1 = createWidget1<QRadioButton>(tr("Radio button 1"), "radioButton1");
- auto radioButton2 = createWidget1<QRadioButton>(tr("Radio button 2"), "radioButton2");
- auto radioButton3 = createWidget1<QRadioButton>(tr("Radio button 3"), "radioButton3");
+ auto *radioButton1 = createWidget1<QRadioButton>(tr("Radio button 1"), "radioButton1");
+ auto *radioButton2 = createWidget1<QRadioButton>(tr("Radio button 2"), "radioButton2");
+ auto *radioButton3 = createWidget1<QRadioButton>(tr("Radio button 3"), "radioButton3");
radioButton1->setChecked(true);
- auto checkBox = createWidget1<QCheckBox>(tr("Tri-state check box"), "checkBox");
+ auto *checkBox = createWidget1<QCheckBox>(tr("Tri-state check box"), "checkBox");
checkBox->setTristate(true);
checkBox->setCheckState(Qt::PartiallyChecked);
- auto checkableLayout = new QVBoxLayout;
+ auto *checkableLayout = new QVBoxLayout;
checkableLayout->addWidget(radioButton1);
checkableLayout->addWidget(radioButton2);
checkableLayout->addWidget(radioButton3);
checkableLayout->addWidget(checkBox);
checkableLayout->addStretch(1);
- auto mainLayout = new QHBoxLayout(result);
+ auto *mainLayout = new QHBoxLayout(result);
mainLayout->addLayout(buttonLayout);
mainLayout->addLayout(checkableLayout);
mainLayout->addStretch();
@@ -289,8 +294,8 @@ QGroupBox *WidgetGallery::createButtonsGroupBox()
static QWidget *embedIntoHBoxLayout(QWidget *w, int margin = 5)
{
- auto result = new QWidget;
- auto layout = new QHBoxLayout(result);
+ auto *result = new QWidget;
+ auto *layout = new QHBoxLayout(result);
layout->setContentsMargins(margin, margin, margin, margin);
layout->addWidget(w);
return result;
@@ -298,7 +303,7 @@ static QWidget *embedIntoHBoxLayout(QWidget *w, int margin = 5)
QToolBox *WidgetGallery::createTextToolBox()
{
- auto result = createWidget<QToolBox>("toolBox");
+ auto *result = createWidget<QToolBox>("toolBox");
const QString plainText = tr("Twinkle, twinkle, little star,\n"
"How I wonder what you are.\n"
@@ -307,13 +312,13 @@ QToolBox *WidgetGallery::createTextToolBox()
"Twinkle, twinkle, little star,\n"
"How I wonder what you are!\n");
// Create centered/italic HTML rich text
- QString richText = QLatin1String("<html><head/><body><i>");
- for (const auto &line : QStringView{ plainText }.split(QLatin1Char('\n')))
- richText += QString::fromLatin1("<center>%1</center>").arg(line);
- richText += QLatin1String("</i></body></html>");
+ QString richText = "<html><head/><body><i>"_L1;
+ for (const auto &line : QStringView{ plainText }.split(u'\n'))
+ richText += "<center>"_L1 + line + "</center>"_L1;
+ richText += "</i></body></html>"_L1;
- auto textEdit = createWidget1<QTextEdit>(richText, "textEdit");
- auto plainTextEdit = createWidget1<QPlainTextEdit>(plainText, "plainTextEdit");
+ auto *textEdit = createWidget1<QTextEdit>(richText, "textEdit");
+ auto *plainTextEdit = createWidget1<QPlainTextEdit>(plainText, "plainTextEdit");
systemInfoTextBrowser = createWidget<QTextBrowser>("systemInfoTextBrowser");
@@ -325,28 +330,28 @@ QToolBox *WidgetGallery::createTextToolBox()
QTabWidget *WidgetGallery::createItemViewTabWidget()
{
- auto result = createWidget<QTabWidget>("bottomLeftTabWidget");
+ auto *result = createWidget<QTabWidget>("bottomLeftTabWidget");
result->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Ignored);
- auto treeView = createWidget<QTreeView>("treeView");
- auto fileSystemModel = new QFileSystemModel(treeView);
+ auto *treeView = createWidget<QTreeView>("treeView");
+ auto *fileSystemModel = new QFileSystemModel(treeView);
fileSystemModel->setRootPath(QDir::rootPath());
treeView->setModel(fileSystemModel);
- auto tableWidget = createWidget<QTableWidget>("tableWidget");
+ auto *tableWidget = createWidget<QTableWidget>("tableWidget");
tableWidget->setRowCount(10);
tableWidget->setColumnCount(10);
- auto listModel = new QStandardItemModel(0, 1, result);
- listModel->appendRow(new QStandardItem(QIcon(QLatin1String(":/qt-project.org/styles/commonstyle/images/diropen-128.png")),
+ auto *listModel = new QStandardItemModel(0, 1, result);
+ listModel->appendRow(new QStandardItem(QIcon(":/qt-project.org/styles/commonstyle/images/diropen-128.png"_L1),
tr("Directory")));
- listModel->appendRow(new QStandardItem(QIcon(QLatin1String(":/qt-project.org/styles/commonstyle/images/computer-32.png")),
+ listModel->appendRow(new QStandardItem(QIcon(":/qt-project.org/styles/commonstyle/images/computer-32.png"_L1),
tr("Computer")));
- auto listView = createWidget<QListView>("listView");
+ auto *listView = createWidget<QListView>("listView");
listView->setModel(listModel);
- auto iconModeListView = createWidget<QListView>("iconModeListView");
+ auto *iconModeListView = createWidget<QListView>("iconModeListView");
iconModeListView->setViewMode(QListView::IconMode);
iconModeListView->setModel(listModel);
@@ -359,34 +364,34 @@ QTabWidget *WidgetGallery::createItemViewTabWidget()
QGroupBox *WidgetGallery::createSimpleInputWidgetsGroupBox()
{
- auto result = createWidget1<QGroupBox>(tr("Simple Input Widgets"), "bottomRightGroupBox");
+ auto *result = createWidget1<QGroupBox>(tr("Simple Input Widgets"), "bottomRightGroupBox");
result->setCheckable(true);
result->setChecked(true);
- auto lineEdit = createWidget1<QLineEdit>("s3cRe7", "lineEdit");
+ auto *lineEdit = createWidget1<QLineEdit>("s3cRe7", "lineEdit");
lineEdit->setClearButtonEnabled(true);
lineEdit->setEchoMode(QLineEdit::Password);
- auto spinBox = createWidget<QSpinBox>("spinBox", result);
+ auto *spinBox = createWidget<QSpinBox>("spinBox", result);
spinBox->setValue(50);
- auto dateTimeEdit = createWidget<QDateTimeEdit>("dateTimeEdit", result);
+ auto *dateTimeEdit = createWidget<QDateTimeEdit>("dateTimeEdit", result);
dateTimeEdit->setDateTime(QDateTime::currentDateTime());
- auto slider = createWidget<QSlider>("slider", result);
+ auto *slider = createWidget<QSlider>("slider", result);
slider->setOrientation(Qt::Horizontal);
slider->setValue(40);
- auto scrollBar = createWidget<QScrollBar>("scrollBar", result);
+ auto *scrollBar = createWidget<QScrollBar>("scrollBar", result);
scrollBar->setOrientation(Qt::Horizontal);
setClassNameToolTip(scrollBar);
scrollBar->setValue(60);
- auto dial = createWidget<QDial>("dial", result);
+ auto *dial = createWidget<QDial>("dial", result);
dial->setValue(30);
dial->setNotchesVisible(true);
- auto layout = new QGridLayout(result);
+ auto *layout = new QGridLayout(result);
layout->addWidget(lineEdit, 0, 0, 1, 2);
layout->addWidget(spinBox, 1, 0, 1, 2);
layout->addWidget(dateTimeEdit, 2, 0, 1, 2);
@@ -399,11 +404,11 @@ QGroupBox *WidgetGallery::createSimpleInputWidgetsGroupBox()
QProgressBar *WidgetGallery::createProgressBar()
{
- auto result = createWidget<QProgressBar>("progressBar");
+ auto *result = createWidget<QProgressBar>("progressBar");
result->setRange(0, 10000);
result->setValue(0);
- auto timer = new QTimer(this);
+ auto *timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, &WidgetGallery::advanceProgressBar);
timer->start(1000);
return result;
@@ -414,11 +419,12 @@ void WidgetGallery::updateSystemInfo()
QString systemInfo;
QTextStream str(&systemInfo);
str << "<html><head/><body><h3>Build</h3><p>" << QLibraryInfo::build() << "</p>"
- << "<h3>Operating System</h3><p>" << QSysInfo::prettyProductName() << "</p>"
+ << "<h3>Operating System</h3><p>\"" << QSysInfo::prettyProductName() << "\" / "
+ << QGuiApplication::platformName() << "</p>"
<< "<h3>Screens</h3><p>High DPI scale factor rounding policy: "
<< highDpiScaleFactorRoundingPolicy() << "</p><ol>";
const auto screens = QGuiApplication::screens();
- for (auto screen : screens) {
+ for (const auto *screen : screens) {
const bool current = screen == this->screen();
str << "<li>";
if (current)
@@ -437,9 +443,9 @@ void WidgetGallery::updateSystemInfo()
void WidgetGallery::helpOnCurrentWidget()
{
// Skip over internal widgets
- for (auto w = QApplication::widgetAt(QCursor::pos(screen())); w; w = w->parentWidget()) {
+ for (const auto *w = QApplication::widgetAt(QCursor::pos(screen())); w; w = w->parentWidget()) {
const QString name = w->objectName();
- if (!name.isEmpty() && !name.startsWith(QLatin1String("qt_"))) {
+ if (!name.isEmpty() && !name.startsWith("qt_"_L1)) {
launchHelp(w);
break;
}
diff --git a/examples/widgets/gallery/widgetgallery.h b/examples/widgets/gallery/widgetgallery.h
index c96437a4667..f220847a0cd 100644
--- a/examples/widgets/gallery/widgetgallery.h
+++ b/examples/widgets/gallery/widgetgallery.h
@@ -37,7 +37,7 @@ private:
QProgressBar *createProgressBar();
QProgressBar *progressBar;
- QTextBrowser *systemInfoTextBrowser;
+ QTextBrowser *systemInfoTextBrowser{};
};
#endif // WIDGETGALLERY_H
diff --git a/examples/widgets/gestures/imagegestures/doc/src/imagegestures.qdoc b/examples/widgets/gestures/imagegestures/doc/src/imagegestures.qdoc
index 03b31edabc5..63ca14787b6 100644
--- a/examples/widgets/gestures/imagegestures/doc/src/imagegestures.qdoc
+++ b/examples/widgets/gestures/imagegestures/doc/src/imagegestures.qdoc
@@ -5,6 +5,7 @@
\example gestures/imagegestures
\title Image Gestures Example
\examplecategory {User Interface Components}
+ \ingroup examples-user-input
\brief Demonstrates the use of simple gestures in a widget.
This example shows how to enable gestures for a widget and use gesture input
diff --git a/examples/widgets/touch/knobs/doc/src/touch-knobs.qdoc b/examples/widgets/touch/knobs/doc/src/touch-knobs.qdoc
index d229f54f5c7..38bd2016cab 100644
--- a/examples/widgets/touch/knobs/doc/src/touch-knobs.qdoc
+++ b/examples/widgets/touch/knobs/doc/src/touch-knobs.qdoc
@@ -6,6 +6,7 @@
\title Touch Knobs Example
\examplecategory {User Interface Components}
\ingroup touchinputexamples
+ \ingroup examples-user-input
\brief Shows how to create custom controls that accept touch input.
The Touch Knobs example shows how to create custom controls that
diff --git a/src/corelib/Qt6CoreMacros.cmake b/src/corelib/Qt6CoreMacros.cmake
index 82179cfd89a..8aad11dfca7 100644
--- a/src/corelib/Qt6CoreMacros.cmake
+++ b/src/corelib/Qt6CoreMacros.cmake
@@ -1157,6 +1157,18 @@ function(_qt_internal_assign_to_internal_targets_folder target)
endif()
endfunction()
+# Returns the metatypes build dir where the Qt build system places module metatypes json files and
+# other supporting metatypes files like ${target}_json_file_list.txt.
+# The path is usually the target's BINARY_DIR + "/meta_types"
+function(_qt_internal_get_metatypes_build_dir out_var target)
+ get_target_property(target_binary_dir "${target}" BINARY_DIR)
+ set(out_dir "${target_binary_dir}/meta_types")
+ set(${out_var} "${out_dir}" PARENT_SCOPE)
+endfunction()
+
+# The AUTOGEN build dir is the location where all the generated .cpp files are placed, as well
+# as the moc_predefs.h, timestamp file and deps files.
+# E.g. ${CMAKE_CURRENT_BINARY_DIR}/${target}_autogen/moc_predefs.h
function(_qt_internal_get_target_autogen_build_dir target out_var)
get_property(target_autogen_build_dir TARGET ${target} PROPERTY AUTOGEN_BUILD_DIR)
if(target_autogen_build_dir)
@@ -1167,6 +1179,14 @@ function(_qt_internal_get_target_autogen_build_dir target out_var)
endif()
endfunction()
+# The AUTOGEN info dir is the location where AutogenInfo.json and ParseCache.txt files are placed.
+# E.g. ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${target}_autogen.dir/ParseCache.txt
+function(_qt_internal_get_target_autogen_info_dir target out_var)
+ get_target_property(target_binary_dir ${target} BINARY_DIR)
+ set(autogen_info_dir "${target_binary_dir}/CMakeFiles/${target}_autogen.dir")
+ set(${out_var} "${autogen_info_dir}" PARENT_SCOPE)
+endfunction()
+
function(_qt_internal_should_install_metatypes target)
set(args_option
INTERNAL_INSTALL
@@ -1354,12 +1374,14 @@ function(qt6_extract_metatypes target)
return()
endif()
- get_target_property(target_binary_dir ${target} BINARY_DIR)
- set(type_list_file "${target_binary_dir}/meta_types/${target}_json_file_list.txt")
- set(type_list_file_manual "${target_binary_dir}/meta_types/${target}_json_file_list_manual.txt")
+ _qt_internal_get_metatypes_build_dir(metatypes_dir "${target}")
+
+ set(type_list_file "${metatypes_dir}/${target}_json_file_list.txt")
+ set(type_list_file_manual "${metatypes_dir}/${target}_json_file_list_manual.txt")
set(target_autogen_build_dir "")
_qt_internal_get_target_autogen_build_dir(${target} target_autogen_build_dir)
+ _qt_internal_get_target_autogen_info_dir(${target} target_autogen_info_dir)
get_target_property(uses_automoc ${target} AUTOMOC)
set(automoc_args)
@@ -1373,21 +1395,18 @@ function(qt6_extract_metatypes target)
get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(NOT is_multi_config)
- set(cmake_autogen_cache_file
- "${target_binary_dir}/CMakeFiles/${target}_autogen.dir/ParseCache.txt")
+ set(cmake_autogen_cache_file "${target_autogen_info_dir}/ParseCache.txt")
set(multi_config_args
--cmake-autogen-include-dir-path "${target_autogen_build_dir}/include"
)
else()
- set(cmake_autogen_cache_file
- "${target_binary_dir}/CMakeFiles/${target}_autogen.dir/ParseCache_$<CONFIG>.txt")
+ set(cmake_autogen_cache_file "${target_autogen_info_dir}/ParseCache_$<CONFIG>.txt")
set(multi_config_args
--cmake-autogen-include-dir-path "${target_autogen_build_dir}/include_$<CONFIG>"
"--cmake-multi-config")
endif()
- set(cmake_autogen_info_file
- "${target_binary_dir}/CMakeFiles/${target}_autogen.dir/AutogenInfo.json")
+ set(cmake_autogen_info_file "${target_autogen_info_dir}/AutogenInfo.json")
set (use_dep_files FALSE)
if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.17") # Requires automoc changes present only in 3.17
@@ -1502,11 +1521,11 @@ function(qt6_extract_metatypes target)
string(TOLOWER ${target} target_lowercase)
set(metatypes_file_name "qt6${target_lowercase}_metatypes.json")
- set(metatypes_file "${target_binary_dir}/meta_types/${metatypes_file_name}")
- set(metatypes_file_gen "${target_binary_dir}/meta_types/${metatypes_file_name}.gen")
+ set(metatypes_file "${metatypes_dir}/${metatypes_file_name}")
+ set(metatypes_file_gen "${metatypes_dir}/${metatypes_file_name}.gen")
set(metatypes_dep_file_name "qt6${target_lowercase}_metatypes_dep.txt")
- set(metatypes_dep_file "${target_binary_dir}/meta_types/${metatypes_dep_file_name}")
+ set(metatypes_dep_file "${metatypes_dir}/${metatypes_dep_file_name}")
# Due to generated source file dependency rules being tied to the directory
# scope in which they are created it is not possible for other targets which
@@ -1517,7 +1536,7 @@ function(qt6_extract_metatypes target)
# file is then replaced with the contents of the generated file during
# build.
if (NOT EXISTS ${metatypes_file})
- file(MAKE_DIRECTORY "${target_binary_dir}/meta_types")
+ file(MAKE_DIRECTORY "${metatypes_dir}")
file(TOUCH ${metatypes_file})
endif()
diff --git a/src/corelib/doc/src/qtcore.qdoc b/src/corelib/doc/src/qtcore.qdoc
index ea65d68da58..ec5fa564639 100644
--- a/src/corelib/doc/src/qtcore.qdoc
+++ b/src/corelib/doc/src/qtcore.qdoc
@@ -19,8 +19,7 @@
\module QtCorePrivate
\title Qt Core Private C++ Classes
\qtvariable core-private
- \qtcmakepackage Core
- \qtcmaketargetitem CorePrivate
+ \qtcmakepackage CorePrivate
\preliminary
\brief Provides private core functionality.
@@ -28,7 +27,7 @@
private Qt Core APIs:
\badcode
- find_package(Qt6 REQUIRED COMPONENTS Core)
+ find_package(Qt6 REQUIRED COMPONENTS CorePrivate)
target_link_libraries(mytarget PRIVATE Qt6::CorePrivate)
\endcode
*/
diff --git a/src/corelib/global/qalloc.h b/src/corelib/global/qalloc.h
index 9d40f4261d3..a05c09ac63c 100644
--- a/src/corelib/global/qalloc.h
+++ b/src/corelib/global/qalloc.h
@@ -21,6 +21,7 @@
#include <QtCore/qtypeinfo.h>
#include <cstddef>
+#include <cstdlib>
QT_BEGIN_NAMESPACE
diff --git a/src/corelib/global/qassert.h b/src/corelib/global/qassert.h
index d1d306fd3ed..05210acb2d4 100644
--- a/src/corelib/global/qassert.h
+++ b/src/corelib/global/qassert.h
@@ -100,6 +100,25 @@ inline bool qt_assume_is_deprecated(bool cond) noexcept { return cond; }
Q_ASSUME_IMPL(valueOfExpression);\
}(qt_assume_is_deprecated(Expr))
+
+#if __has_builtin(__builtin_assume)
+// Clang has this intrinsic and won't warn about its use in C++20 mode
+# define Q_PRESUME_IMPL(assumption) __builtin_assume(assumption)
+#elif __has_cpp_attribute(assume)
+// GCC has implemented this attribute and allows its use in C++20 mode
+# define Q_PRESUME_IMPL(assumption) [[assume(assumption)]]
+#elif defined(Q_CC_MSVC)
+# define Q_PRESUME_IMPL(assumption) __assume(assumption)
+#else
+# define Q_PRESUME_IMPL(assumption) (void)0
+#endif
+
+#define Q_PRESUME(assumption) \
+ [&] { \
+ Q_ASSERT(assumption); \
+ Q_PRESUME_IMPL(assumption); \
+ }()
+
// Don't use these in C++ mode, use static_assert directly.
// These are here only to keep old code compiling.
# define Q_STATIC_ASSERT(Condition) static_assert(bool(Condition), #Condition)
diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h
index 700c59ab3c7..df55baf3120 100644
--- a/src/corelib/global/qcompilerdetection.h
+++ b/src/corelib/global/qcompilerdetection.h
@@ -1443,6 +1443,10 @@ QT_WARNING_DISABLE_MSVC(4706) /* assignment within conditional expression */
QT_WARNING_DISABLE_MSVC(4355) /* 'this' : used in base member initializer list */
QT_WARNING_DISABLE_MSVC(4710) /* function not inlined */
QT_WARNING_DISABLE_MSVC(4530) /* C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc */
+# elif defined(Q_CC_CLANG_ONLY)
+# if Q_CC_CLANG >= 2100
+ QT_WARNING_DISABLE_CLANG("-Wcharacter-conversion") /* until https://github.com/llvm/llvm-project/issues/163719 is fixed */
+# endif
# elif defined(Q_CC_BOR)
# pragma option -w-inl
# pragma option -w-aus
diff --git a/src/corelib/global/qfloat16.h b/src/corelib/global/qfloat16.h
index 01106abf34d..cb8514105a0 100644
--- a/src/corelib/global/qfloat16.h
+++ b/src/corelib/global/qfloat16.h
@@ -354,15 +354,15 @@ inline int qIntCast(qfloat16 f) noexcept
{ return int(static_cast<qfloat16::NearestFloat>(f)); }
#if !defined(Q_QDOC) && !QFLOAT16_IS_NATIVE
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_CLANG("-Wc99-extensions")
-QT_WARNING_DISABLE_GCC("-Wold-style-cast")
inline qfloat16::qfloat16(float f) noexcept
{
#if defined(QT_COMPILER_SUPPORTS_F16C) && defined(__F16C__)
__m128 packsingle = _mm_set_ss(f);
+ QT_WARNING_PUSH
+ QT_WARNING_DISABLE_GCC("-Wold-style-cast") // _mm_cvtps_ph() may be a macro using C-style casts
__m128i packhalf = _mm_cvtps_ph(packsingle, 0);
- b16 = _mm_extract_epi16(packhalf, 0);
+ QT_WARNING_POP
+ b16 = quint16(_mm_extract_epi16(packhalf, 0));
#elif defined (__ARM_FP16_FORMAT_IEEE)
__fp16 f16 = __fp16(f);
memcpy(&b16, &f16, sizeof(quint16));
@@ -393,7 +393,6 @@ inline qfloat16::qfloat16(float f) noexcept
b16 = quint16(base + (mantissa >> shift));
#endif
}
-QT_WARNING_POP
inline qfloat16::operator float() const noexcept
{
diff --git a/src/corelib/global/qnumeric.h b/src/corelib/global/qnumeric.h
index 723a462bae1..6caf3510f8a 100644
--- a/src/corelib/global/qnumeric.h
+++ b/src/corelib/global/qnumeric.h
@@ -27,6 +27,8 @@
# include <QtCore/qstdlibdetection.h>
# if defined(Q_CC_GNU_ONLY) && (defined(Q_STL_LIBCPP) || Q_CC_GNU_ONLY < 1500)
// broken - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121811
+# elif defined(Q_OS_FREEBSD) && __FreeBSD_version <= 1500000
+// broken - https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=290299
# else
# include <stdckdint.h>
# endif
diff --git a/src/corelib/io/qlockfile.cpp b/src/corelib/io/qlockfile.cpp
index 908db7b9d38..47229c8e6a1 100644
--- a/src/corelib/io/qlockfile.cpp
+++ b/src/corelib/io/qlockfile.cpp
@@ -24,19 +24,6 @@ QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals;
-namespace {
-struct LockFileInfo
-{
- qint64 pid;
- QString appname;
- QString hostname;
- QByteArray hostid;
- QByteArray bootid;
-};
-}
-
-static bool getLockInfo_helper(const QString &fileName, LockFileInfo *info);
-
static QString machineName()
{
#ifdef Q_OS_WIN
@@ -364,8 +351,8 @@ bool QLockFile::tryLock(std::chrono::milliseconds timeout)
bool QLockFile::getLockInfo(qint64 *pid, QString *hostname, QString *appname) const
{
Q_D(const QLockFile);
- LockFileInfo info;
- if (!getLockInfo_helper(d->fileName, &info))
+ QLockFilePrivate::LockFileInfo info;
+ if (!QLockFilePrivate::getLockInfo_helper(d->fileName, &info))
return false;
if (pid)
*pid = info.pid;
@@ -399,11 +386,16 @@ QByteArray QLockFilePrivate::lockFileContents() const
% QSysInfo::bootUniqueId() % '\n';
}
-static bool getLockInfo_helper(const QString &fileName, LockFileInfo *info)
+bool QLockFilePrivate::getLockInfo_helper(const QString &fileName, LockFileInfo *info)
{
- QFile reader(fileName);
- if (!reader.open(QIODevice::ReadOnly | QIODevice::Text))
+ int fd = openNewFileDescriptor(fileName);
+ if (fd < 0)
+ return false;
+ QFile reader;
+ if (!reader.open(fd, QFile::ReadOnly | QFile::Text, QFile::AutoCloseHandle)) {
+ QT_CLOSE(fd);
return false;
+ }
QByteArray pidLine = reader.readLine();
pidLine.chop(1);
diff --git a/src/corelib/io/qlockfile_p.h b/src/corelib/io/qlockfile_p.h
index 2a7ebe1926d..ea9b29e9f57 100644
--- a/src/corelib/io/qlockfile_p.h
+++ b/src/corelib/io/qlockfile_p.h
@@ -25,6 +25,15 @@ QT_BEGIN_NAMESPACE
class QLockFilePrivate
{
public:
+ struct LockFileInfo
+ {
+ qint64 pid;
+ QString appname;
+ QString hostname;
+ QByteArray hostid;
+ QByteArray bootid;
+ };
+
explicit QLockFilePrivate(const QString &fn);
~QLockFilePrivate();
@@ -41,6 +50,9 @@ public:
QString fileName;
+ static bool getLockInfo_helper(const QString &fileName, LockFileInfo *info);
+ static int openNewFileDescriptor(const QString &fileName);
+
#ifdef Q_OS_WIN
Qt::HANDLE fileHandle;
#else
diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp
index 87faac8b33d..34276373a1f 100644
--- a/src/corelib/io/qlockfile_unix.cpp
+++ b/src/corelib/io/qlockfile_unix.cpp
@@ -285,6 +285,11 @@ QString QLockFilePrivate::processNameByPid(qint64 pid)
#endif
}
+int QLockFilePrivate::openNewFileDescriptor(const QString &fileName)
+{
+ return QT_OPEN(fileName.toLocal8Bit().constData(), QT_OPEN_RDONLY);
+}
+
void QLockFile::unlock()
{
Q_D(QLockFile);
diff --git a/src/corelib/io/qlockfile_win.cpp b/src/corelib/io/qlockfile_win.cpp
index 12a668def0f..ef5d49fb20e 100644
--- a/src/corelib/io/qlockfile_win.cpp
+++ b/src/corelib/io/qlockfile_win.cpp
@@ -16,6 +16,8 @@
#include <qt_windows.h>
#include <psapi.h>
+#include <io.h>
+#include <fcntl.h>
QT_BEGIN_NAMESPACE
@@ -53,9 +55,10 @@ QLockFile::LockError QLockFilePrivate::tryLock_sys()
const QFileSystemEntry fileEntry(fileName);
// When writing, allow others to read.
// When reading, QFile will allow others to read and write, all good.
- // Adding FILE_SHARE_DELETE would allow forceful deletion of stale files,
- // but Windows doesn't allow recreating it while this handle is open anyway,
- // so this would only create confusion (can't lock, but no lock file to read from).
+ // ### Open the file with DELETE permission and use
+ // SetFileInformationByHandle to delete the file without needing to close
+ // the handle first, to avoid someone opening the handle again without the
+ // FILE_SHARE_DELETE flag in-between closure and deletion.
const DWORD dwShareMode = FILE_SHARE_READ;
SECURITY_ATTRIBUTES securityAtts = { sizeof(SECURITY_ATTRIBUTES), NULL, FALSE };
HANDLE fh = CreateFile((const wchar_t*)fileEntry.nativeFilePath().utf16(),
@@ -142,6 +145,30 @@ QString QLockFilePrivate::processNameByPid(qint64 pid)
return name;
}
+int QLockFilePrivate::openNewFileDescriptor(const QString &fileName)
+{
+ // We currently open with FILE_SHARE_DELETE, which would allow deletion to
+ // be requested even while other processes have the file open. We mostly
+ // want to do this so we can later open the file with the DELETE permission
+ // to delete the file using SetFileInformationByHandle, avoiding the need
+ // to close the handle first, where e.g. search indexer or antivirus may
+ // see their chance to open the file before we can delete it.
+ // We can't make this change immediately because currently-deployed
+ // applications will not be using FILE_SHARE_DELETE, so they would suddenly
+ // be unable to read the lockfile information.
+ HANDLE handle = CreateFile(reinterpret_cast<const wchar_t *>(fileName.utf16()), GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
+ if (handle == INVALID_HANDLE_VALUE)
+ return -1;
+ int fd = _open_osfhandle(intptr_t(handle), _O_RDONLY);
+ if (fd == -1) {
+ CloseHandle(handle);
+ return -1;
+ }
+ return fd;
+}
+
void QLockFile::unlock()
{
Q_D(QLockFile);
diff --git a/src/corelib/io/qrandomaccessasyncfile_p_p.h b/src/corelib/io/qrandomaccessasyncfile_p_p.h
index 7b10edc6728..ef996c37f07 100644
--- a/src/corelib/io/qrandomaccessasyncfile_p_p.h
+++ b/src/corelib/io/qrandomaccessasyncfile_p_p.h
@@ -39,7 +39,7 @@ class QRandomAccessAsyncFilePrivate : public QObjectPrivate
Q_DECLARE_PUBLIC(QRandomAccessAsyncFile)
Q_DISABLE_COPY_MOVE(QRandomAccessAsyncFilePrivate)
public:
- QRandomAccessAsyncFilePrivate(decltype(QObjectPrivateVersion) version = QObjectPrivateVersion);
+ QRandomAccessAsyncFilePrivate();
~QRandomAccessAsyncFilePrivate() override;
static QRandomAccessAsyncFilePrivate *get(QRandomAccessAsyncFile *file)
diff --git a/src/corelib/io/qrandomaccessasyncfile_threadpool.cpp b/src/corelib/io/qrandomaccessasyncfile_threadpool.cpp
index 42d38cc3adb..4ebcf554655 100644
--- a/src/corelib/io/qrandomaccessasyncfile_threadpool.cpp
+++ b/src/corelib/io/qrandomaccessasyncfile_threadpool.cpp
@@ -64,8 +64,8 @@ static SharedThreadPool asyncFileThreadPool;
} // anonymous namespace
-QRandomAccessAsyncFilePrivate::QRandomAccessAsyncFilePrivate(decltype(QObjectPrivateVersion) version) :
- QObjectPrivate(version)
+QRandomAccessAsyncFilePrivate::QRandomAccessAsyncFilePrivate() :
+ QObjectPrivate()
{
asyncFileThreadPool.ref();
}
diff --git a/src/corelib/kernel/qmetaobjectbuilder.cpp b/src/corelib/kernel/qmetaobjectbuilder.cpp
index a2719f97da7..6065bf2baea 100644
--- a/src/corelib/kernel/qmetaobjectbuilder.cpp
+++ b/src/corelib/kernel/qmetaobjectbuilder.cpp
@@ -1339,7 +1339,7 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
[[maybe_unused]] int flags = prop.flags;
- if (isBuiltinType(prop.type))
+ if (!isBuiltinType(prop.type))
flags |= EnumOrFlag;
if constexpr (mode == Construct) {
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index fe510898429..02c9f00f301 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -1894,8 +1894,8 @@ int QObject::startTimer(int interval, Qt::TimerType timerType)
A timer event will occur every \a interval until killTimer()
is called. If \a interval is equal to \c{std::chrono::duration::zero()},
- then the timer event occurs once every time there are no more window
- system events to process.
+ then the timer event occurs once every time control returns to the event
+ loop, that is, there are no more native window system events to process.
\include timers-common.qdocinc negative-intervals-not-allowed
@@ -2715,6 +2715,20 @@ static void err_info_about_objects(const char *func, const QObject *sender, cons
qCWarning(lcConnect, "QObject::%s: (receiver name: '%s')", func, b.toLocal8Bit().data());
}
+Q_DECL_COLD_FUNCTION
+static void connectWarning(const QObject *sender,
+ const QMetaObject *senderMetaObject,
+ const QObject *receiver,
+ const char *message)
+{
+ const char *senderString = sender ? sender->metaObject()->className()
+ : senderMetaObject ? senderMetaObject->className()
+ : "Unknown";
+ const char *receiverString = receiver ? receiver->metaObject()->className()
+ : "Unknown";
+ qCWarning(lcConnect, "QObject::connect(%s, %s): %s", senderString, receiverString, message);
+}
+
/*!
Returns a pointer to the object that sent the signal, if called in
a slot activated by a signal; otherwise it returns \nullptr. The pointer
@@ -4105,8 +4119,9 @@ QMetaObject::Connection QMetaObject::connectImpl(const QObject *sender, const QM
{
QtPrivate::SlotObjUniquePtr slotObj(slotObjRaw);
+ const QMetaObject *senderMetaObject = sender->metaObject();
if (!signal.isValid() || signal.methodType() != QMetaMethod::Signal) {
- qCWarning(lcConnect, "QObject::connect: invalid signal parameter");
+ connectWarning(sender, senderMetaObject, receiver, "invalid signal parameter");
return QMetaObject::Connection();
}
@@ -4116,7 +4131,6 @@ QMetaObject::Connection QMetaObject::connectImpl(const QObject *sender, const QM
QMetaObjectPrivate::memberIndexes(sender, signal, &signal_index, &dummy);
}
- const QMetaObject *senderMetaObject = sender->metaObject();
if (signal_index == -1) {
qCWarning(lcConnect, "QObject::connect: Can't find signal %s on instance of class %s",
signal.methodSignature().constData(), senderMetaObject->className());
@@ -5433,7 +5447,7 @@ QMetaObject::Connection QObject::connectImpl(const QObject *sender, void **signa
{
QtPrivate::SlotObjUniquePtr slotObj(slotObjRaw);
if (!signal) {
- qCWarning(lcConnect, "QObject::connect: invalid nullptr parameter");
+ connectWarning(sender, senderMetaObject, receiver, "invalid nullptr parameter");
return QMetaObject::Connection();
}
@@ -5445,26 +5459,13 @@ QMetaObject::Connection QObject::connectImpl(const QObject *sender, void **signa
break;
}
if (!senderMetaObject) {
- qCWarning(lcConnect, "QObject::connect: signal not found in %s", sender->metaObject()->className());
+ connectWarning(sender, senderMetaObject, receiver, "signal not found");
return QMetaObject::Connection(nullptr);
}
signal_index += QMetaObjectPrivate::signalOffset(senderMetaObject);
return QObjectPrivate::connectImpl(sender, signal_index, receiver, slot, slotObj.release(), type, types, senderMetaObject);
}
-static void connectWarning(const QObject *sender,
- const QMetaObject *senderMetaObject,
- const QObject *receiver,
- const char *message)
-{
- const char *senderString = sender ? sender->metaObject()->className()
- : senderMetaObject ? senderMetaObject->className()
- : "Unknown";
- const char *receiverString = receiver ? receiver->metaObject()->className()
- : "Unknown";
- qCWarning(lcConnect, "QObject::connect(%s, %s): %s", senderString, receiverString, message);
-}
-
/*!
\internal
@@ -5495,7 +5496,7 @@ QMetaObject::Connection QObjectPrivate::connectImpl(const QObject *sender, int s
QOrderedMutexLocker locker(signalSlotLock(sender),
signalSlotLock(receiver));
- if (type & Qt::UniqueConnection && slot) {
+ if (type & Qt::UniqueConnection) {
QObjectPrivate::ConnectionData *connections = QObjectPrivate::get(s)->connections.loadRelaxed();
if (connections && connections->signalVectorCount() > signal_index) {
const QObjectPrivate::Connection *c2 = connections->signalVector.loadRelaxed()->at(signal_index).first.loadRelaxed();
@@ -5683,7 +5684,7 @@ QMetaObject::Connection QObjectPrivate::connect(const QObject *sender, int signa
{
QtPrivate::SlotObjUniquePtr slotObj(slotObjRaw);
if (!sender) {
- qCWarning(lcConnect, "QObject::connect: invalid nullptr parameter");
+ connectWarning(sender, nullptr, receiver, "invalid nullptr parameter");
return QMetaObject::Connection();
}
const QMetaObject *senderMetaObject = sender->metaObject();
diff --git a/src/corelib/kernel/qtimer.cpp b/src/corelib/kernel/qtimer.cpp
index afc6bab8559..319ae8bc24e 100644
--- a/src/corelib/kernel/qtimer.cpp
+++ b/src/corelib/kernel/qtimer.cpp
@@ -15,6 +15,8 @@
#include "qproperty_p.h"
#include "qthread.h"
+#include <q26numeric.h> // for q26::staturate_cast
+
using namespace std::chrono_literals;
QT_BEGIN_NAMESPACE
@@ -248,19 +250,21 @@ void QTimer::start(int msec)
start(msec * 1ms);
}
-static std::chrono::milliseconds
+static int
checkInterval(const char *caller, std::chrono::milliseconds interval)
{
- constexpr auto maxInterval = INT_MAX * 1ms;
if (interval < 0ms) {
qWarning("%s: negative intervals aren't allowed; the interval will be set to 1ms.", caller);
- interval = 1ms;
- } else if (interval > maxInterval) {
+ return 1;
+ }
+
+ const auto msec = interval.count();
+ int ret = q26::saturate_cast<int>(msec);
+ if (ret != msec) {
qWarning("%s: interval exceeds maximum allowed interval, it will be clamped to "
"INT_MAX ms (about 24 days).", caller);
- interval = maxInterval;
}
- return interval;
+ return ret;
}
/*!
@@ -288,8 +292,7 @@ void QTimer::start(std::chrono::milliseconds interval)
{
Q_D(QTimer);
- interval = checkInterval("QTimer::start", interval);
- const int msec = interval.count();
+ const int msec = checkInterval("QTimer::start", interval);
const bool intervalChanged = msec != d->inter;
d->inter.setValue(msec);
start();
@@ -656,8 +659,7 @@ void QTimer::setInterval(std::chrono::milliseconds interval)
{
Q_D(QTimer);
- interval = checkInterval("QTimer::setInterval", interval);
- const int msec = interval.count();
+ const int msec = checkInterval("QTimer::setInterval", interval);
d->inter.removeBindingUnlessInWrapper();
const bool intervalChanged = msec != d->inter.valueBypassingBindings();
d->inter.setValueBypassingBindings(msec);
@@ -705,7 +707,10 @@ int QTimer::remainingTime() const
if (d->isActive()) {
using namespace std::chrono;
auto remaining = QAbstractEventDispatcher::instance()->remainingTime(d->id);
- return ceil<milliseconds>(remaining).count();
+ const auto msec = ceil<milliseconds>(remaining).count();
+ const int ret = q26::saturate_cast<int>(msec);
+ Q_ASSERT(ret == msec); // cannot overflow because the interval is clamped before it's set
+ return ret;
}
return -1;
diff --git a/src/corelib/kernel/qwinregistry.cpp b/src/corelib/kernel/qwinregistry.cpp
index fb315cacb7e..37bf3f99ae1 100644
--- a/src/corelib/kernel/qwinregistry.cpp
+++ b/src/corelib/kernel/qwinregistry.cpp
@@ -191,7 +191,9 @@ QVariant QWinRegistryKey::value(const QString &subKey) const
// Otherwise, the resulting string (which may be empty) is returned.
QString QWinRegistryKey::stringValue(const wchar_t *subKey) const
{
- return value<QString>(subKey).value_or(QString());
+ if (auto v = value<QString>(subKey))
+ return std::move(*v);
+ return QString();
}
QString QWinRegistryKey::stringValue(const QString &subKey) const
diff --git a/src/corelib/platform/android/qandroidnativeinterface.cpp b/src/corelib/platform/android/qandroidnativeinterface.cpp
index 680725dc6a1..5771d28f3a9 100644
--- a/src/corelib/platform/android/qandroidnativeinterface.cpp
+++ b/src/corelib/platform/android/qandroidnativeinterface.cpp
@@ -48,8 +48,9 @@ QT_DEFINE_NATIVE_INTERFACE(QAndroidApplication);
/*!
\fn QJniObject QNativeInterface::QAndroidApplication::context()
- Returns the Android context as a \c QJniObject. The context is an \c Activity
- if the most recently started activity object is valid. Otherwise, the context is a \c Service.
+ Returns the Android context as a \c QtJniTypes::Context. The context
+ is an \c Activity if the most recently started activity object is valid.
+ Otherwise, the context is a \c Service.
\since 6.2
*/
diff --git a/src/corelib/serialization/.gitignore b/src/corelib/serialization/.gitignore
index 89f9ac04aac..8261c031991 100644
--- a/src/corelib/serialization/.gitignore
+++ b/src/corelib/serialization/.gitignore
@@ -1 +1,2 @@
+# Qt-Security score:insignificant reason:gitignore
out/
diff --git a/src/corelib/serialization/make-xml-parser.sh b/src/corelib/serialization/make-xml-parser.sh
index 18898337003..4174949154c 100755
--- a/src/corelib/serialization/make-xml-parser.sh
+++ b/src/corelib/serialization/make-xml-parser.sh
@@ -1,6 +1,7 @@
#!/bin/sh
# Copyright (C) 2016 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+# Qt-Security score:insignificant reason:build-tool-containing-no-compiled-source
me=$(dirname $0)
mkdir -p $me/out
diff --git a/src/corelib/serialization/qcborvalue.cpp b/src/corelib/serialization/qcborvalue.cpp
index f905b97a164..13d74e591d5 100644
--- a/src/corelib/serialization/qcborvalue.cpp
+++ b/src/corelib/serialization/qcborvalue.cpp
@@ -1102,20 +1102,20 @@ static auto nextUtf32Character(const char16_t *&ptr, const char16_t *end) noexce
Q_ASSERT(ptr != end);
struct R {
char32_t c;
- qsizetype len = 1; // in UTF-8 code units (bytes)
- } r = { *ptr++ };
-
- if (r.c < 0x0800) {
- if (r.c >= 0x0080)
- ++r.len;
- } else if (!QChar::isHighSurrogate(r.c) || ptr == end) {
- r.len += 2;
+ qsizetype len; // in UTF-8 code units (bytes)
+ };
+
+ const char16_t c = *ptr++;
+
+ if (c < 0x0800) {
+ if (c < 0x0080)
+ return R{c, 1};
+ return R{c, 2};
+ } else if (!QChar::isHighSurrogate(c) || ptr == end) {
+ return R{c, 3};
} else {
- r.len += 3;
- r.c = QChar::surrogateToUcs4(r.c, *ptr++);
+ return R{QChar::surrogateToUcs4(c, *ptr++), 4};
}
-
- return r;
}
static qsizetype stringLengthInUtf8(const char16_t *ptr, const char16_t *end) noexcept
diff --git a/src/corelib/serialization/qjsonparseerror.h b/src/corelib/serialization/qjsonparseerror.h
index 803b04c53b6..d8fc94448e6 100644
--- a/src/corelib/serialization/qjsonparseerror.h
+++ b/src/corelib/serialization/qjsonparseerror.h
@@ -7,6 +7,7 @@
#include <QtCore/qtconfigmacros.h>
#include <QtCore/qtcoreexports.h>
+#include <QtCore/qtypes.h>
QT_BEGIN_NAMESPACE
@@ -34,7 +35,8 @@ struct Q_CORE_EXPORT QJsonParseError
QString errorString() const;
- int offset = -1;
+ std::conditional_t<QT_VERSION_MAJOR < 7, int, qint64>
+ offset = -1;
ParseError error = NoError;
};
diff --git a/src/corelib/serialization/qjsonparser.cpp b/src/corelib/serialization/qjsonparser.cpp
index df266a76c79..779287adb1d 100644
--- a/src/corelib/serialization/qjsonparser.cpp
+++ b/src/corelib/serialization/qjsonparser.cpp
@@ -321,7 +321,9 @@ QCborValue Parser::parse(QJsonParseError *error)
error:
container.reset();
if (error) {
- error->offset = json - head;
+ using OffType = decltype(error->offset);
+ error->offset = OffType(json - head);
+ Q_ASSERT(error->offset == json - head);
error->error = lastError;
}
return QCborValue();
diff --git a/src/corelib/text/qbytearray.h b/src/corelib/text/qbytearray.h
index 49d9e24d036..9fb832545f8 100644
--- a/src/corelib/text/qbytearray.h
+++ b/src/corelib/text/qbytearray.h
@@ -321,7 +321,7 @@ public:
{
if constexpr (std::is_same_v<InputIterator, iterator> || std::is_same_v<InputIterator, const_iterator>)
return assign(QByteArrayView(first, last));
- d.assign(first, last);
+ d->assign(first, last);
if (d.data())
d.data()[d.size] = '\0';
return *this;
@@ -512,10 +512,8 @@ public:
}
constexpr qsizetype size() const noexcept
{
-#if __has_cpp_attribute(assume)
constexpr size_t MaxSize = maxSize();
- [[assume(size_t(d.size) <= MaxSize)]];
-#endif
+ Q_PRESUME(size_t(d.size) <= MaxSize);
return d.size;
}
#if QT_DEPRECATED_SINCE(6, 4)
diff --git a/src/corelib/text/qchar.cpp b/src/corelib/text/qchar.cpp
index 684c9fbe23d..6be19473b85 100644
--- a/src/corelib/text/qchar.cpp
+++ b/src/corelib/text/qchar.cpp
@@ -1678,20 +1678,13 @@ char32_t QChar::toTitleCase(char32_t ucs4) noexcept
return convertCase_helper(ucs4, QUnicodeTables::TitleCase);
}
-static inline char32_t foldCase(const char16_t *ch, const char16_t *start)
+static inline char32_t foldCase(const char16_t *cur, const char16_t *start)
{
- char32_t ucs4 = *ch;
- if (QChar::isLowSurrogate(ucs4) && ch > start && QChar::isHighSurrogate(*(ch - 1)))
- ucs4 = QChar::surrogateToUcs4(*(ch - 1), ucs4);
- return convertCase_helper(ucs4, QUnicodeTables::CaseFold);
-}
-
-static inline char32_t foldCase(char32_t ch, char32_t &last) noexcept
-{
- char32_t ucs4 = ch;
- if (QChar::isLowSurrogate(ucs4) && QChar::isHighSurrogate(last))
- ucs4 = QChar::surrogateToUcs4(last, ucs4);
- last = ch;
+ char32_t ucs4;
+ if (QChar::isLowSurrogate(*cur) && cur > start && QChar::isHighSurrogate(cur[-1]))
+ ucs4 = QChar::surrogateToUcs4(cur[-1], *cur);
+ else
+ ucs4 = *cur;
return convertCase_helper(ucs4, QUnicodeTables::CaseFold);
}
@@ -1839,13 +1832,18 @@ static void decomposeHelper(QString *str, bool canonical, QChar::UnicodeVersion
const unsigned short *utf16 = reinterpret_cast<unsigned short *>(s.data());
const unsigned short *uc = utf16 + s.size();
while (uc != utf16 + from) {
- char32_t ucs4 = *(--uc);
- if (QChar(ucs4).isLowSurrogate() && uc != utf16) {
+ const char16_t c = *(--uc);
+ char32_t ucs4;
+ if (QChar::isLowSurrogate(c) && uc != utf16) {
ushort high = *(uc - 1);
if (QChar(high).isHighSurrogate()) {
--uc;
- ucs4 = QChar::surrogateToUcs4(high, ucs4);
+ ucs4 = QChar::surrogateToUcs4(high, c);
+ } else {
+ ucs4 = c; // keep lone surrogate
}
+ } else {
+ ucs4 = c;
}
if (QChar::unicodeVersion(ucs4) > version)
@@ -1943,13 +1941,18 @@ static void composeHelper(QString *str, QChar::UnicodeVersion version, qsizetype
qsizetype pos = from;
while (pos < s.size()) {
qsizetype i = pos;
- char32_t uc = s.at(pos).unicode();
- if (QChar(uc).isHighSurrogate() && pos < s.size()-1) {
+ char32_t uc;
+ const char16_t c = s.at(pos).unicode();
+ if (QChar::isHighSurrogate(c) && pos < s.size() - 1) {
ushort low = s.at(pos+1).unicode();
if (QChar(low).isLowSurrogate()) {
- uc = QChar::surrogateToUcs4(uc, low);
+ uc = QChar::surrogateToUcs4(c, low);
++pos;
+ } else {
+ uc = c; // keep lone surrogate
}
+ } else {
+ uc = c;
}
const QUnicodeTables::Properties *p = qGetProp(uc);
@@ -1993,35 +1996,40 @@ static void canonicalOrderHelper(QString *str, QChar::UnicodeVersion version, qs
QString &s = *str;
const qsizetype l = s.size()-1;
- char32_t u1, u2;
- char16_t c1, c2;
-
qsizetype pos = from;
while (pos < l) {
qsizetype p2 = pos+1;
- u1 = s.at(pos).unicode();
- if (QChar::isHighSurrogate(u1)) {
+ char32_t u1;
+ if (const char16_t hi = s.at(pos).unicode(); QChar::isHighSurrogate(hi)) {
const char16_t low = s.at(p2).unicode();
if (QChar::isLowSurrogate(low)) {
- u1 = QChar::surrogateToUcs4(u1, low);
+ u1 = QChar::surrogateToUcs4(hi, low);
if (p2 >= l)
break;
++p2;
+ } else {
+ u1 = hi;
}
+ } else {
+ u1 = hi;
}
- c1 = 0;
+ ushort c1 = 0;
advance:
- u2 = s.at(p2).unicode();
- if (QChar::isHighSurrogate(u2) && p2 < l) {
+ char32_t u2;
+ if (const char16_t hi = s.at(p2).unicode(); QChar::isHighSurrogate(hi) && p2 < l) {
const char16_t low = s.at(p2+1).unicode();
if (QChar::isLowSurrogate(low)) {
- u2 = QChar::surrogateToUcs4(u2, low);
+ u2 = QChar::surrogateToUcs4(hi, low);
++p2;
+ } else {
+ u2 = hi;
}
+ } else {
+ u2 = hi;
}
- c2 = 0;
+ ushort c2 = 0;
{
const QUnicodeTables::Properties *p = qGetProp(u2);
if (p->unicodeVersion <= version)
@@ -2089,7 +2097,7 @@ static bool normalizationQuickCheckHelper(QString *str, QString::NormalizationFo
uchar lastCombining = 0;
for (qsizetype i = from; i < length; ++i) {
qsizetype pos = i;
- char32_t uc = string[i];
+ const char16_t uc = string[i];
if (uc < 0x80) {
// ASCII characters are stable code points
lastCombining = 0;
@@ -2097,6 +2105,7 @@ static bool normalizationQuickCheckHelper(QString *str, QString::NormalizationFo
continue;
}
+ char32_t ucs4;
if (QChar::isHighSurrogate(uc)) {
ushort low = string[i + 1];
if (!QChar::isLowSurrogate(low)) {
@@ -2106,10 +2115,12 @@ static bool normalizationQuickCheckHelper(QString *str, QString::NormalizationFo
continue;
}
++i;
- uc = QChar::surrogateToUcs4(uc, low);
+ ucs4 = QChar::surrogateToUcs4(uc, low);
+ } else {
+ ucs4 = uc;
}
- const QUnicodeTables::Properties *p = qGetProp(uc);
+ const QUnicodeTables::Properties *p = qGetProp(ucs4);
if (p->combiningClass < lastCombining && p->combiningClass > 0)
return false;
diff --git a/src/corelib/text/qchar.h b/src/corelib/text/qchar.h
index 008282232fb..4a3aad0ca0c 100644
--- a/src/corelib/text/qchar.h
+++ b/src/corelib/text/qchar.h
@@ -499,26 +499,26 @@ public:
Unicode_16_0,
};
- inline Category category() const noexcept { return QChar::category(ucs); }
- inline Direction direction() const noexcept { return QChar::direction(ucs); }
- inline JoiningType joiningType() const noexcept { return QChar::joiningType(ucs); }
- inline unsigned char combiningClass() const noexcept { return QChar::combiningClass(ucs); }
+ Category category() const noexcept { return QChar::category(char32_t(ucs)); }
+ Direction direction() const noexcept { return QChar::direction(char32_t(ucs)); }
+ JoiningType joiningType() const noexcept { return QChar::joiningType(char32_t(ucs)); }
+ unsigned char combiningClass() const noexcept { return QChar::combiningClass(char32_t(ucs)); }
- inline QChar mirroredChar() const noexcept { return QChar(QChar::mirroredChar(ucs)); }
- inline bool hasMirrored() const noexcept { return QChar::hasMirrored(ucs); }
+ QChar mirroredChar() const noexcept { return QChar(QChar::mirroredChar(char32_t(ucs))); }
+ bool hasMirrored() const noexcept { return QChar::hasMirrored(char32_t(ucs)); }
QString decomposition() const;
- inline Decomposition decompositionTag() const noexcept { return QChar::decompositionTag(ucs); }
+ Decomposition decompositionTag() const noexcept { return QChar::decompositionTag(char32_t(ucs)); }
- inline int digitValue() const noexcept { return QChar::digitValue(ucs); }
- inline QChar toLower() const noexcept { return QChar(QChar::toLower(ucs)); }
- inline QChar toUpper() const noexcept { return QChar(QChar::toUpper(ucs)); }
- inline QChar toTitleCase() const noexcept { return QChar(QChar::toTitleCase(ucs)); }
- inline QChar toCaseFolded() const noexcept { return QChar(QChar::toCaseFolded(ucs)); }
+ int digitValue() const noexcept { return QChar::digitValue(char32_t(ucs)); }
+ QChar toLower() const noexcept { return QChar(QChar::toLower(char32_t(ucs))); }
+ QChar toUpper() const noexcept { return QChar(QChar::toUpper(char32_t(ucs))); }
+ QChar toTitleCase() const noexcept { return QChar(QChar::toTitleCase(char32_t(ucs))); }
+ QChar toCaseFolded() const noexcept { return QChar(QChar::toCaseFolded(char32_t(ucs))); }
- inline Script script() const noexcept { return QChar::script(ucs); }
+ Script script() const noexcept { return QChar::script(char32_t(ucs)); }
- inline UnicodeVersion unicodeVersion() const noexcept { return QChar::unicodeVersion(ucs); }
+ UnicodeVersion unicodeVersion() const noexcept { return QChar::unicodeVersion(char32_t(ucs)); }
constexpr inline char toLatin1() const noexcept { return ucs > 0xff ? '\0' : char(ucs); }
constexpr inline char16_t unicode() const noexcept { return ucs; }
@@ -528,23 +528,23 @@ public:
constexpr inline bool isNull() const noexcept { return ucs == 0; }
- inline bool isPrint() const noexcept { return QChar::isPrint(ucs); }
- constexpr inline bool isSpace() const noexcept { return QChar::isSpace(ucs); }
- inline bool isMark() const noexcept { return QChar::isMark(ucs); }
- inline bool isPunct() const noexcept { return QChar::isPunct(ucs); }
- inline bool isSymbol() const noexcept { return QChar::isSymbol(ucs); }
- constexpr inline bool isLetter() const noexcept { return QChar::isLetter(ucs); }
- constexpr inline bool isNumber() const noexcept { return QChar::isNumber(ucs); }
- constexpr inline bool isLetterOrNumber() const noexcept { return QChar::isLetterOrNumber(ucs); }
- constexpr inline bool isDigit() const noexcept { return QChar::isDigit(ucs); }
- constexpr inline bool isLower() const noexcept { return QChar::isLower(ucs); }
- constexpr inline bool isUpper() const noexcept { return QChar::isUpper(ucs); }
- constexpr inline bool isTitleCase() const noexcept { return QChar::isTitleCase(ucs); }
-
- constexpr inline bool isNonCharacter() const noexcept { return QChar::isNonCharacter(ucs); }
- constexpr inline bool isHighSurrogate() const noexcept { return QChar::isHighSurrogate(ucs); }
- constexpr inline bool isLowSurrogate() const noexcept { return QChar::isLowSurrogate(ucs); }
- constexpr inline bool isSurrogate() const noexcept { return QChar::isSurrogate(ucs); }
+ bool isPrint() const noexcept { return QChar::isPrint(char32_t(ucs)); }
+ constexpr bool isSpace() const noexcept { return QChar::isSpace(char32_t(ucs)); }
+ bool isMark() const noexcept { return QChar::isMark(char32_t(ucs)); }
+ bool isPunct() const noexcept { return QChar::isPunct(char32_t(ucs)); }
+ bool isSymbol() const noexcept { return QChar::isSymbol(char32_t(ucs)); }
+ constexpr bool isLetter() const noexcept { return QChar::isLetter(char32_t(ucs)); }
+ constexpr bool isNumber() const noexcept { return QChar::isNumber(char32_t(ucs)); }
+ constexpr bool isLetterOrNumber() const noexcept { return QChar::isLetterOrNumber(char32_t(ucs)); }
+ constexpr bool isDigit() const noexcept { return QChar::isDigit(char32_t(ucs)); }
+ constexpr bool isLower() const noexcept { return QChar::isLower(char32_t(ucs)); }
+ constexpr bool isUpper() const noexcept { return QChar::isUpper(char32_t(ucs)); }
+ constexpr bool isTitleCase() const noexcept { return QChar::isTitleCase(char32_t(ucs)); }
+
+ constexpr bool isNonCharacter() const noexcept { return QChar::isNonCharacter(char32_t(ucs)); }
+ constexpr bool isHighSurrogate() const noexcept { return QChar::isHighSurrogate(char32_t(ucs)); }
+ constexpr bool isLowSurrogate() const noexcept { return QChar::isLowSurrogate(char32_t(ucs)); }
+ constexpr bool isSurrogate() const noexcept { return QChar::isSurrogate(char32_t(ucs)); }
constexpr inline uchar cell() const noexcept { return uchar(ucs & 0xff); }
constexpr inline uchar row() const noexcept { return uchar((ucs>>8)&0xff); }
diff --git a/src/corelib/text/qcollator.cpp b/src/corelib/text/qcollator.cpp
index 9ead847843b..6609d17adf4 100644
--- a/src/corelib/text/qcollator.cpp
+++ b/src/corelib/text/qcollator.cpp
@@ -1,6 +1,7 @@
// Copyright (C) 2021 The Qt Company Ltd.
// Copyright (C) 2013 Aleix Pol Gonzalez <[email protected]>
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:critical reason:data-parser
#include "qcollator_p.h"
#include "qstringlist.h"
diff --git a/src/corelib/text/qcollator.h b/src/corelib/text/qcollator.h
index 870811fc48e..2b1e3963b0d 100644
--- a/src/corelib/text/qcollator.h
+++ b/src/corelib/text/qcollator.h
@@ -1,6 +1,7 @@
// Copyright (C) 2020 The Qt Company Ltd.
// Copyright (C) 2013 Aleix Pol Gonzalez <[email protected]>
// 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:trivial-impl-only
#ifndef QCOLLATOR_H
#define QCOLLATOR_H
diff --git a/src/corelib/text/qcollator_icu.cpp b/src/corelib/text/qcollator_icu.cpp
index 84f9c515374..e13e96285ef 100644
--- a/src/corelib/text/qcollator_icu.cpp
+++ b/src/corelib/text/qcollator_icu.cpp
@@ -1,6 +1,7 @@
// Copyright (C) 2020 The Qt Company Ltd.
// Copyright (C) 2013 Aleix Pol Gonzalez <[email protected]>
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:critical reason:data-parser
#include "qcollator_p.h"
#include "qlocale_p.h"
diff --git a/src/corelib/text/qcollator_macx.cpp b/src/corelib/text/qcollator_macx.cpp
index 23c23bd53a2..c0561877dd1 100644
--- a/src/corelib/text/qcollator_macx.cpp
+++ b/src/corelib/text/qcollator_macx.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2020 Aleix Pol Gonzalez <[email protected]>
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:critical reason:data-parser
#include "qcollator_p.h"
#include "qlocale_p.h"
diff --git a/src/corelib/text/qcollator_p.h b/src/corelib/text/qcollator_p.h
index b96cdbaa32a..400cafc0c8a 100644
--- a/src/corelib/text/qcollator_p.h
+++ b/src/corelib/text/qcollator_p.h
@@ -1,6 +1,7 @@
// Copyright (C) 2016 The Qt Company Ltd.
// Copyright (C) 2013 Aleix Pol Gonzalez <[email protected]>
// 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:trivial-impl-only
#ifndef QCOLLATOR_P_H
#define QCOLLATOR_P_H
diff --git a/src/corelib/text/qcollator_posix.cpp b/src/corelib/text/qcollator_posix.cpp
index 5ed80c1b8ea..2712133521c 100644
--- a/src/corelib/text/qcollator_posix.cpp
+++ b/src/corelib/text/qcollator_posix.cpp
@@ -1,6 +1,7 @@
// Copyright (C) 2021 The Qt Company Ltd.
// Copyright (C) 2013 Aleix Pol Gonzalez <[email protected]>
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:critical reason:data-parser
#include "qcollator_p.h"
#include "qstringlist.h"
diff --git a/src/corelib/text/qcollator_win.cpp b/src/corelib/text/qcollator_win.cpp
index b588f5ff46a..54228b79b31 100644
--- a/src/corelib/text/qcollator_win.cpp
+++ b/src/corelib/text/qcollator_win.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2020 Aleix Pol Gonzalez <[email protected]>
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:critical reason:data-parser
#include "qcollator_p.h"
#include "qlocale_p.h"
diff --git a/src/corelib/text/qlocale.qdoc b/src/corelib/text/qlocale.qdoc
index 3980e9d9a6d..bc88b27477d 100644
--- a/src/corelib/text/qlocale.qdoc
+++ b/src/corelib/text/qlocale.qdoc
@@ -1,5 +1,6 @@
// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+// Qt-Security score:insignificant reason:docs
/*!
\class QLocale
diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp
index eea66810b0b..46c01bf232a 100644
--- a/src/corelib/text/qstring.cpp
+++ b/src/corelib/text/qstring.cpp
@@ -1197,15 +1197,13 @@ Q_NEVER_INLINE static int ucstricmp(qsizetype alen, const char16_t *a, qsizetype
if (a == b)
return qt_lencmp(alen, blen);
- char32_t alast = 0;
- char32_t blast = 0;
qsizetype l = qMin(alen, blen);
qsizetype i;
for (i = 0; i < l; ++i) {
// qDebug() << Qt::hex << alast << blast;
// qDebug() << Qt::hex << "*a=" << *a << "alast=" << alast << "folded=" << foldCase (*a, alast);
// qDebug() << Qt::hex << "*b=" << *b << "blast=" << blast << "folded=" << foldCase (*b, blast);
- int diff = foldCase(a[i], alast) - foldCase(b[i], blast);
+ int diff = foldCase(a + i, a) - foldCase(b + i, b);
if ((diff))
return diff;
}
diff --git a/src/corelib/text/qstring.h b/src/corelib/text/qstring.h
index 868a5d5ef03..506d669d356 100644
--- a/src/corelib/text/qstring.h
+++ b/src/corelib/text/qstring.h
@@ -273,10 +273,8 @@ public:
}
constexpr qsizetype size() const noexcept
{
-#if __has_cpp_attribute(assume)
constexpr size_t MaxSize = maxSize();
- [[assume(size_t(d.size) <= MaxSize)]];
-#endif
+ Q_PRESUME(size_t(d.size) <= MaxSize);
return d.size;
}
#if QT_DEPRECATED_SINCE(6, 4)
@@ -642,7 +640,7 @@ public:
d.data()[d.size] = u'\0';
return *this;
} else {
- d.assign(first, last, [](QChar ch) -> char16_t { return ch.unicode(); });
+ d->assign(first, last, [](QChar ch) -> char16_t { return ch.unicode(); });
if (d.constAllocatedCapacity())
d.data()[d.size] = u'\0';
return *this;
diff --git a/src/corelib/text/qtliterals.qdoc b/src/corelib/text/qtliterals.qdoc
index c4671415ee4..8be03a02236 100644
--- a/src/corelib/text/qtliterals.qdoc
+++ b/src/corelib/text/qtliterals.qdoc
@@ -1,5 +1,6 @@
// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+// Qt-Security score:insignificant reason:docs
/*!
\namespace QtLiterals
@@ -43,4 +44,8 @@
// in the Qt namespace
using namespace Qt;
\endcode
+
+ The latter is discouraged, because it doesn't allow you to pick which literal
+ operators you want in case Qt adds conflicting operators in different
+ namespaces within Qt::Literals.
*/
diff --git a/src/corelib/thread/qsemaphore.cpp b/src/corelib/thread/qsemaphore.cpp
index 0de30d3b9f9..a308c4419e2 100644
--- a/src/corelib/thread/qsemaphore.cpp
+++ b/src/corelib/thread/qsemaphore.cpp
@@ -12,6 +12,9 @@
#include "qwaitcondition_p.h"
#include <chrono>
+#if !QT_CONFIG(thread)
+#include <limits>
+#endif
QT_BEGIN_NAMESPACE
@@ -684,7 +687,7 @@ bool QSemaphore::tryAcquire(int n, QDeadlineTimer timer)
// the calling thread (which is the only thread in the no-thread
// configuraton)
-QSemaphore::QSemaphore(int n)
+QSemaphore::QSemaphore(int)
{
}
@@ -704,6 +707,21 @@ void QSemaphore::release(int)
}
+int QSemaphore::available() const
+{
+ return std::numeric_limits<int>::max();
+}
+
+bool QSemaphore::tryAcquire(int)
+{
+ return true;
+}
+
+bool QSemaphore::tryAcquire(int, QDeadlineTimer)
+{
+ return true;
+}
+
#endif
QT_END_NAMESPACE
diff --git a/src/corelib/time/qtimezoneprivate.cpp b/src/corelib/time/qtimezoneprivate.cpp
index 5b61940cbbe..d8434f4fe1b 100644
--- a/src/corelib/time/qtimezoneprivate.cpp
+++ b/src/corelib/time/qtimezoneprivate.cpp
@@ -1081,12 +1081,6 @@ QList<QByteArray> QTimeZonePrivate::windowsIdToIanaIds(const QByteArray &windows
return list;
}
-// Define template for derived classes to reimplement so QSharedDataPointer clone() works correctly
-template<> QTimeZonePrivate *QSharedDataPointer<QTimeZonePrivate>::clone()
-{
- return d->clone();
-}
-
static bool isEntryInIanaList(QByteArrayView id, QByteArrayView ianaIds)
{
qsizetype cut;
diff --git a/src/corelib/time/qtimezoneprivate_p.h b/src/corelib/time/qtimezoneprivate_p.h
index 611c8e4b5e7..b1217402ce7 100644
--- a/src/corelib/time/qtimezoneprivate_p.h
+++ b/src/corelib/time/qtimezoneprivate_p.h
@@ -162,7 +162,7 @@ public:
QByteArray ianaId;
qsizetype nameLength = 0;
QTimeZone::TimeType timeType = QTimeZone::GenericTime;
- operator bool() { return nameLength > 0; }
+ operator bool() const { return nameLength > 0; }
};
static NamePrefixMatch findLongNamePrefix(QStringView text, const QLocale &locale,
std::optional<qint64> atEpochMillis = std::nullopt);
@@ -209,8 +209,6 @@ protected:
};
Q_DECLARE_TYPEINFO(QTimeZonePrivate::Data, Q_RELOCATABLE_TYPE);
-template<> QTimeZonePrivate *QSharedDataPointer<QTimeZonePrivate>::clone();
-
class Q_AUTOTEST_EXPORT QUtcTimeZonePrivate final : public QTimeZonePrivate
{
bool operator=(const QUtcTimeZonePrivate &) const = delete;
diff --git a/src/corelib/tools/qarraydataops.h b/src/corelib/tools/qarraydataops.h
index c20abd12c23..c6259354de9 100644
--- a/src/corelib/tools/qarraydataops.h
+++ b/src/corelib/tools/qarraydataops.h
@@ -9,12 +9,12 @@
#include <QtCore/qcontainertools_impl.h>
#include <QtCore/qnamespace.h>
-#include <memory>
+#include <QtCore/q20functional.h>
+#include <QtCore/q20memory.h>
#include <new>
#include <string.h>
#include <utility>
#include <iterator>
-#include <tuple>
#include <type_traits>
QT_BEGIN_NAMESPACE
@@ -844,7 +844,6 @@ protected:
public:
// using Base::truncate;
// using Base::destroyAll;
- // using Base::assign;
template<typename It>
void appendIteratorRange(It b, It e, QtPrivate::IfIsForwardIterator<It> = true)
@@ -910,6 +909,119 @@ public:
std::uninitialized_default_construct(b, e);
this->size = newSize;
}
+
+ using Base::assign;
+
+ template <typename InputIterator, typename Projection = q20::identity>
+ void assign(InputIterator first, InputIterator last, Projection proj = {})
+ {
+ // This function only provides the basic exception guarantee.
+ constexpr bool IsFwdIt = std::is_convertible_v<
+ typename std::iterator_traits<InputIterator>::iterator_category,
+ std::forward_iterator_tag>;
+ constexpr bool IsIdentity = std::is_same_v<Projection, q20::identity>;
+
+ const qsizetype n = IsFwdIt ? std::distance(first, last) : 0;
+ bool undoPrependOptimization = true;
+ bool needCapacity = n > this->constAllocatedCapacity();
+ if (needCapacity || this->needsDetach()) {
+ bool wasLastRef = !this->deref();
+ qsizetype newCapacity = this->detachCapacity(n);
+ if (wasLastRef && needCapacity) {
+ // free memory we can't reuse
+ this->destroyAll();
+ Data::deallocate(this->d);
+ }
+ if (!needCapacity && wasLastRef) {
+ // we were the last reference and can reuse the storage
+ this->d->ref_.storeRelaxed(1);
+ } else {
+ // we must allocate new memory
+ std::tie(this->d, this->ptr) = Data::allocate(newCapacity);
+ this->size = 0;
+ undoPrependOptimization = false;
+ }
+ }
+
+ if constexpr (!std::is_nothrow_constructible_v<T, decltype(std::invoke(proj, *first))>) {
+ // If construction can throw, and we have freeSpaceAtBegin(),
+ // it's easiest to just clear the container and start fresh.
+ // The alternative would be to keep track of two active, disjoint ranges.
+ if (undoPrependOptimization) {
+ this->truncate(0);
+ this->setBegin(Data::dataStart(this->d, alignof(typename Data::AlignmentDummy)));
+ undoPrependOptimization = false;
+ }
+ }
+
+ const auto dend = this->end();
+ T *dst = this->begin();
+ T *capacityBegin = dst;
+ qsizetype offset = 0;
+ if (undoPrependOptimization) {
+ capacityBegin = Data::dataStart(this->d, alignof(typename Data::AlignmentDummy));
+ offset = dst - capacityBegin;
+ }
+ if constexpr (!QTypeInfo<T>::isComplex) {
+ this->setBegin(capacityBegin); // undo prepend optimization
+ dst = capacityBegin;
+
+ // there's nothing to destroy or overwrite
+ } else if (offset) { // avoids dead stores
+ T *prependBufferEnd = dst;
+ this->setBegin(capacityBegin); // undo prepend optimization
+ dst = capacityBegin;
+
+ // By construction, the following loop is nothrow!
+ // (otherwise, we can't reach here)
+ // Assumes InputIterator operations don't throw.
+ // (but we can't statically assert that, as these operations
+ // have preconditons, so typically aren't noexcept)
+ while (true) {
+ if (dst == prependBufferEnd) { // ran out of prepend buffer space
+ this->size += offset;
+ // we now have a contiguous buffer, continue with the main loop:
+ break;
+ }
+ if (first == last) { // ran out of elements to assign
+ std::destroy(prependBufferEnd, dend);
+ this->size = dst - this->begin();
+ return;
+ }
+ // construct element in prepend buffer
+ q20::construct_at(dst, std::invoke(proj, *first));
+ ++dst;
+ ++first;
+ }
+ }
+
+ while (true) {
+ if (first == last) { // ran out of elements to assign
+ std::destroy(dst, dend);
+ break;
+ }
+ if (dst == dend) { // ran out of existing elements to overwrite
+ if constexpr (IsFwdIt && IsIdentity) {
+ dst = std::uninitialized_copy(first, last, dst);
+ break;
+ } else if constexpr (IsFwdIt && !IsIdentity
+ && std::is_nothrow_constructible_v<T, decltype(std::invoke(proj, *first))>) {
+ for (; first != last; ++dst, ++first) // uninitialized_copy with projection
+ q20::construct_at(dst, std::invoke(proj, *first));
+ break;
+ } else {
+ do {
+ this->emplace(this->size, std::invoke(proj, *first));
+ } while (++first != last);
+ return; // size() is already correct (and dst invalidated)!
+ }
+ }
+ *dst = std::invoke(proj, *first); // overwrite existing element
+ ++dst;
+ ++first;
+ }
+ this->size = dst - this->begin();
+ }
};
} // namespace QtPrivate
diff --git a/src/corelib/tools/qarraydatapointer.h b/src/corelib/tools/qarraydatapointer.h
index 7fa6f2e7dd9..52984e40f31 100644
--- a/src/corelib/tools/qarraydatapointer.h
+++ b/src/corelib/tools/qarraydatapointer.h
@@ -7,9 +7,6 @@
#include <QtCore/qarraydataops.h>
#include <QtCore/qcontainertools_impl.h>
-#include <QtCore/q20functional.h>
-#include <QtCore/q20memory.h>
-
QT_BEGIN_NAMESPACE
template <class T>
@@ -320,98 +317,6 @@ public:
this->ptr = res;
}
- template <typename InputIterator, typename Projection = q20::identity>
- void assign(InputIterator first, InputIterator last, Projection proj = {})
- {
- // This function only provides the basic exception guarantee.
- constexpr bool IsFwdIt = std::is_convertible_v<
- typename std::iterator_traits<InputIterator>::iterator_category,
- std::forward_iterator_tag>;
- constexpr bool IsIdentity = std::is_same_v<Projection, q20::identity>;
-
- if constexpr (IsFwdIt) {
- const qsizetype n = std::distance(first, last);
- if (needsDetach() || n > constAllocatedCapacity()) {
- QArrayDataPointer allocated(detachCapacity(n));
- swap(allocated);
- }
- } else if (needsDetach()) {
- QArrayDataPointer allocated(allocatedCapacity());
- swap(allocated);
- // We don't want to copy data that we know we'll overwrite
- }
-
- auto offset = freeSpaceAtBegin();
- const auto capacityBegin = begin() - offset;
- const auto prependBufferEnd = begin();
-
- if constexpr (!std::is_nothrow_constructible_v<T, decltype(std::invoke(proj, *first))>) {
- // If construction can throw, and we have freeSpaceAtBegin(),
- // it's easiest to just clear the container and start fresh.
- // The alternative would be to keep track of two active, disjoint ranges.
- if (offset) {
- (*this)->truncate(0);
- setBegin(capacityBegin);
- offset = 0;
- }
- }
-
- auto dst = capacityBegin;
- const auto dend = end();
- if (offset) { // avoids dead stores
- setBegin(capacityBegin); // undo prepend optimization
-
- // By construction, the following loop is nothrow!
- // (otherwise, we can't reach here)
- // Assumes InputIterator operations don't throw.
- // (but we can't statically assert that, as these operations
- // have preconditons, so typically aren't noexcept)
- while (true) {
- if (dst == prependBufferEnd) { // ran out of prepend buffer space
- size += offset;
- // we now have a contiguous buffer, continue with the main loop:
- break;
- }
- if (first == last) { // ran out of elements to assign
- std::destroy(prependBufferEnd, dend);
- size = dst - begin();
- return;
- }
- // construct element in prepend buffer
- q20::construct_at(dst, std::invoke(proj, *first));
- ++dst;
- ++first;
- }
- }
-
- while (true) {
- if (first == last) { // ran out of elements to assign
- std::destroy(dst, dend);
- break;
- }
- if (dst == dend) { // ran out of existing elements to overwrite
- if constexpr (IsFwdIt && IsIdentity) {
- dst = std::uninitialized_copy(first, last, dst);
- break;
- } else if constexpr (IsFwdIt && !IsIdentity
- && std::is_nothrow_constructible_v<T, decltype(std::invoke(proj, *first))>) {
- for (; first != last; ++dst, ++first) // uninitialized_copy with projection
- q20::construct_at(dst, std::invoke(proj, *first));
- break;
- } else {
- do {
- (*this)->emplace(size, std::invoke(proj, *first));
- } while (++first != last);
- return; // size() is already correct (and dst invalidated)!
- }
- }
- *dst = std::invoke(proj, *first); // overwrite existing element
- ++dst;
- ++first;
- }
- size = dst - begin();
- }
-
QArrayDataPointer sliced(qsizetype pos, qsizetype n) const &
{
QArrayDataPointer result(n);
diff --git a/src/corelib/tools/qcryptographichash.cpp b/src/corelib/tools/qcryptographichash.cpp
index fea5bdfa906..092ff46b084 100644
--- a/src/corelib/tools/qcryptographichash.cpp
+++ b/src/corelib/tools/qcryptographichash.cpp
@@ -235,6 +235,8 @@ public:
// when not called from the static hash() function, this function needs to be
// called with finalizeMutex held (finalize() will do that):
void finalizeUnchecked() noexcept;
+ QSpan<uchar> finalizeUnchecked(QSpan<uchar> buffer) noexcept;
+
// END functions that need to be called with finalizeMutex held
QByteArrayView resultView() const noexcept { return result.toByteArrayView(); }
static bool supportsAlgorithm(QCryptographicHash::Algorithm method);
@@ -268,7 +270,7 @@ public:
explicit EVP(QCryptographicHash::Algorithm method);
void reset() noexcept;
- void finalizeUnchecked(HashResult &result) noexcept;
+ void finalizeUnchecked(QSpan<uchar> buffer) noexcept;
};
#endif
@@ -281,7 +283,7 @@ public:
void reset(QCryptographicHash::Algorithm method) noexcept;
void addData(QCryptographicHash::Algorithm method, QByteArrayView data) noexcept;
- void finalizeUnchecked(QCryptographicHash::Algorithm method, HashResult &result) noexcept;
+ void finalizeUnchecked(QCryptographicHash::Algorithm method, QSpan<uchar> buffer) noexcept;
Sha1State sha1Context;
#ifdef USING_OPENSSL30
@@ -297,7 +299,7 @@ public:
SHA3Context sha3Context;
enum class Sha3Variant { Sha3, Keccak };
- static void sha3Finish(SHA3Context &ctx, HashResult &result, Sha3Variant sha3Variant);
+ static void sha3Finish(SHA3Context &ctx, QSpan<uchar> result, Sha3Variant sha3Variant);
blake2b_state blake2bContext;
blake2s_state blake2sContext;
} state;
@@ -308,7 +310,7 @@ public:
const QCryptographicHash::Algorithm method;
};
-void QCryptographicHashPrivate::State::sha3Finish(SHA3Context &ctx, HashResult &result,
+void QCryptographicHashPrivate::State::sha3Finish(SHA3Context &ctx, QSpan<uchar> result,
Sha3Variant sha3Variant)
{
/*
@@ -981,9 +983,23 @@ void QCryptographicHashPrivate::finalizeUnchecked() noexcept
state.finalizeUnchecked(method, result);
}
+/*!
+ \internal
+
+ Must be called with finalizeMutex held, except when called from the static
+ hash() function, where no sharing can take place.
+*/
+QSpan<uchar> QCryptographicHashPrivate::finalizeUnchecked(QSpan<uchar> buffer) noexcept
+{
+ buffer = buffer.first(hashLengthInternal(method));
+ state.finalizeUnchecked(method, buffer);
+ Q_ASSERT(result.size() == 0); // internal buffer wasn't used
+ return buffer;
+}
+
#ifdef USING_OPENSSL30
void QCryptographicHashPrivate::State::finalizeUnchecked(QCryptographicHash::Algorithm method,
- HashResult &result) noexcept
+ QSpan<uchar> result) noexcept
{
switch (method) {
case QCryptographicHash::Keccak_224:
@@ -1030,7 +1046,7 @@ void QCryptographicHashPrivate::State::finalizeUnchecked(QCryptographicHash::Alg
}
}
-void QCryptographicHashPrivate::EVP::finalizeUnchecked(HashResult &result) noexcept
+void QCryptographicHashPrivate::EVP::finalizeUnchecked(QSpan<uchar> result) noexcept
{
if (!initializationFailed) {
EVP_MD_CTX_ptr copy = EVP_MD_CTX_ptr(EVP_MD_CTX_new());
@@ -1043,7 +1059,7 @@ void QCryptographicHashPrivate::EVP::finalizeUnchecked(HashResult &result) noexc
#else // USING_OPENSSL30
void QCryptographicHashPrivate::State::finalizeUnchecked(QCryptographicHash::Algorithm method,
- HashResult &result) noexcept
+ QSpan<uchar> result) noexcept
{
switch (method) {
case QCryptographicHash::Sha1: {
@@ -1166,12 +1182,8 @@ QByteArrayView QCryptographicHash::hashInto(QSpan<std::byte> buffer,
QCryptographicHashPrivate hash(method);
for (QByteArrayView part : data)
hash.addData(part);
- hash.finalizeUnchecked(); // no mutex needed: no-one but us has access to 'hash'
- auto result = hash.resultView();
- Q_ASSERT(buffer.size() >= result.size());
- // ### optimize: have the method directly write into `buffer`
- memcpy(buffer.data(), result.data(), result.size());
- return buffer.first(result.size());
+ auto span = QSpan{reinterpret_cast<uchar *>(buffer.data()), buffer.size()};
+ return hash.finalizeUnchecked(span); // no mutex needed: no-one but us has access to 'hash'
}
/*!
diff --git a/src/corelib/tools/qhashfunctions.h b/src/corelib/tools/qhashfunctions.h
index d1e76b250bb..de749ee112e 100644
--- a/src/corelib/tools/qhashfunctions.h
+++ b/src/corelib/tools/qhashfunctions.h
@@ -413,14 +413,14 @@ qHashMultiCommutative(size_t seed, const T &... args)
template <typename InputIterator>
inline size_t qHashRange(InputIterator first, InputIterator last, size_t seed = 0)
- noexcept(noexcept(qHash(*first))) // assume iterator operations don't throw
+ noexcept(noexcept(qHash(*first, 0))) // assume iterator operations don't throw
{
return std::accumulate(first, last, seed, QtPrivate::QHashCombine(seed));
}
template <typename InputIterator>
inline size_t qHashRangeCommutative(InputIterator first, InputIterator last, size_t seed = 0)
- noexcept(noexcept(qHash(*first))) // assume iterator operations don't throw
+ noexcept(noexcept(qHash(*first, 0))) // assume iterator operations don't throw
{
return std::accumulate(first, last, seed, QtPrivate::QHashCombineCommutative(seed));
}
diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h
index 7a93ec688ef..a11f7913dc7 100644
--- a/src/corelib/tools/qlist.h
+++ b/src/corelib/tools/qlist.h
@@ -446,10 +446,8 @@ public:
static constexpr qsizetype maxSize() { return Data::maxSize(); }
constexpr qsizetype size() const noexcept
{
-#if __has_cpp_attribute(assume)
constexpr size_t MaxSize = maxSize();
- [[assume(size_t(d.size) <= MaxSize)]];
-#endif
+ Q_PRESUME(size_t(d.size) <= MaxSize);
return d.size;
}
constexpr qsizetype count() const noexcept { return size(); }
@@ -578,10 +576,15 @@ public:
template <typename InputIterator, if_input_iterator<InputIterator> = true>
QList &assign(InputIterator first, InputIterator last)
- { d.assign(first, last); return *this; }
+ { d->assign(first, last); return *this; }
QList &assign(std::initializer_list<T> l)
- { return assign(l.begin(), l.end()); }
+ {
+ if (l.size())
+ return assign(l.begin(), l.end());
+ clear();
+ return *this;
+ }
template <typename ...Args>
iterator emplace(const_iterator before, Args&&... args)
diff --git a/src/corelib/tools/qshareddata.h b/src/corelib/tools/qshareddata.h
index 7d0cec8c899..595efd7e3bf 100644
--- a/src/corelib/tools/qshareddata.h
+++ b/src/corelib/tools/qshareddata.h
@@ -4,16 +4,35 @@
#ifndef QSHAREDDATA_H
#define QSHAREDDATA_H
-#include <QtCore/qglobal.h>
#include <QtCore/qatomic.h>
#include <QtCore/qcompare.h>
#include <QtCore/qhashfunctions.h>
-
QT_BEGIN_NAMESPACE
-
template <class T> class QSharedDataPointer;
+template <class T> class QExplicitlySharedDataPointer;
+
+namespace QtPrivate {
+template <template <typename> class P, typename T> struct QSharedDataPointerTraits;
+template <typename T> struct QSharedDataPointerTraits<QSharedDataPointer, T>
+{
+ static constexpr bool ImplicitlyDetaches = true;
+ using Type = T;
+ using pointer = T *;
+ // for const-qualified functions:
+ using constT = const T;
+};
+
+template <typename T> struct QSharedDataPointerTraits<QExplicitlySharedDataPointer, T>
+{
+ static constexpr bool ImplicitlyDetaches = false;
+ using Type = T;
+ using pointer = T *;
+ // for const-qualified functions:
+ using constT = T;
+};
+}
class QSharedData
{
@@ -30,41 +49,38 @@ public:
struct QAdoptSharedDataTag { explicit constexpr QAdoptSharedDataTag() = default; };
-template <typename T>
-class QSharedDataPointer
+// CRTP common base class for both QSharedDataPointer and QExplicitlySharedDataPointer
+template <template <typename> class P, typename T> class QSharedDataPointerBase
{
+#ifndef Q_QDOC
+ using Self = P<T>;
+ using Traits = QtPrivate::QSharedDataPointerTraits<P, T>;
+ using constT = typename Traits::constT;
+
+protected:
+ constexpr QSharedDataPointerBase(T *ptr = nullptr) noexcept : d(ptr) {}
+
public:
- typedef T Type;
- typedef T *pointer;
+ // When adding anything public to this class, make sure to add the doc version to
+ // both QSharedDataPointer and QExplicitlySharedDataPointer.
+
+ using Type = T;
+ using pointer = T *;
void detach() { if (d && d->ref.loadRelaxed() != 1) detach_helper(); }
- T &operator*() { detach(); return *(d.get()); }
- const T &operator*() const { return *(d.get()); }
- T *operator->() { detach(); return d.get(); }
- const T *operator->() const noexcept { return d.get(); }
- operator T *() { detach(); return d.get(); }
+ T &operator*() { implicitlyDetach(); return *(d.get()); }
+ constT &operator*() const { return *(d.get()); }
+ T *operator->() { implicitlyDetach(); return d.get(); }
+ constT *operator->() const noexcept { return d.get(); }
+ operator T *() { implicitlyDetach(); return d.get(); }
operator const T *() const noexcept { return d.get(); }
- T *data() { detach(); return d.get(); }
- T *get() { detach(); return d.get(); }
+ T *data() { implicitlyDetach(); return d.get(); }
+ T *get() { implicitlyDetach(); return d.get(); }
const T *data() const noexcept { return d.get(); }
const T *get() const noexcept { return d.get(); }
const T *constData() const noexcept { return d.get(); }
T *take() noexcept { return std::exchange(d, nullptr).get(); }
- Q_NODISCARD_CTOR
- QSharedDataPointer() noexcept : d(nullptr) { }
- ~QSharedDataPointer() { if (d && !d->ref.deref()) delete d.get(); }
-
- Q_NODISCARD_CTOR
- explicit QSharedDataPointer(T *data) noexcept : d(data)
- { if (d) d->ref.ref(); }
- Q_NODISCARD_CTOR
- QSharedDataPointer(T *data, QAdoptSharedDataTag) noexcept : d(data)
- {}
- Q_NODISCARD_CTOR
- QSharedDataPointer(const QSharedDataPointer &o) noexcept : d(o.d)
- { if (d) d->ref.ref(); }
-
void reset(T *ptr = nullptr) noexcept
{
if (ptr != d.get()) {
@@ -72,10 +88,97 @@ public:
ptr->ref.ref();
T *old = std::exchange(d, Qt::totally_ordered_wrapper(ptr)).get();
if (old && !old->ref.deref())
- delete old;
+ destroy(old);
}
}
+ operator bool () const noexcept { return d != nullptr; }
+ bool operator!() const noexcept { return d == nullptr; }
+
+ void swap(Self &other) noexcept
+ { qt_ptr_swap(d, other.d); }
+
+private:
+ // The concrete class MUST override these, otherwise we will be calling
+ // ourselves.
+ T *clone() { return static_cast<Self *>(this)->clone(); }
+ template <typename... Args> static T *create(Args &&... args)
+ { return Self::create(std::forward(args)...); }
+ static void destroy(T *ptr) { Self::destroy(ptr); }
+
+ void implicitlyDetach()
+ {
+ if constexpr (Traits::ImplicitlyDetaches)
+ static_cast<Self *>(this)->detach();
+ }
+
+ friend bool comparesEqual(const QSharedDataPointerBase &lhs, const QSharedDataPointerBase &rhs) noexcept
+ { return lhs.d == rhs.d; }
+ friend Qt::strong_ordering
+ compareThreeWay(const QSharedDataPointerBase &lhs, const QSharedDataPointerBase &rhs) noexcept
+ { return Qt::compareThreeWay(lhs.d, rhs.d); }
+
+ friend bool comparesEqual(const QSharedDataPointerBase &lhs, const T *rhs) noexcept
+ { return lhs.d == rhs; }
+ friend Qt::strong_ordering
+ compareThreeWay(const QSharedDataPointerBase &lhs, const T *rhs) noexcept
+ { return Qt::compareThreeWay(lhs.d, rhs); }
+
+ friend bool comparesEqual(const QSharedDataPointerBase &lhs, std::nullptr_t) noexcept
+ { return lhs.d == nullptr; }
+ friend Qt::strong_ordering
+ compareThreeWay(const QSharedDataPointerBase &lhs, std::nullptr_t) noexcept
+ { return Qt::compareThreeWay(lhs.d, nullptr); }
+
+ friend size_t qHash(const QSharedDataPointerBase &ptr, size_t seed = 0) noexcept
+ { return qHash(ptr.data(), seed); }
+
+protected:
+ void detach_helper();
+
+ Qt::totally_ordered_wrapper<T *> d;
+#endif // !Q_QDOC
+};
+
+template <typename T>
+class QSharedDataPointer : public QSharedDataPointerBase<QSharedDataPointer, T>
+{
+ using Base = QSharedDataPointerBase<QSharedDataPointer, T>;
+ friend Base;
+public:
+ typedef T Type;
+ typedef T *pointer;
+
+ void detach() { Base::detach(); }
+#ifdef Q_QDOC
+ T &operator*();
+ const T &operator*() const;
+ T *operator->();
+ const T *operator->() const noexcept;
+ operator T *();
+ operator const T *() const noexcept;
+ T *data();
+ T *get();
+ const T *data() const noexcept;
+ const T *get() const noexcept;
+ const T *constData() const noexcept;
+ T *take() noexcept;
+#endif
+
+ Q_NODISCARD_CTOR
+ QSharedDataPointer() noexcept : Base(nullptr) { }
+ ~QSharedDataPointer() { if (d && !d->ref.deref()) destroy(d.get()); }
+
+ Q_NODISCARD_CTOR
+ explicit QSharedDataPointer(T *data) noexcept : Base(data)
+ { if (d) d->ref.ref(); }
+ Q_NODISCARD_CTOR
+ QSharedDataPointer(T *data, QAdoptSharedDataTag) noexcept : Base(data)
+ {}
+ Q_NODISCARD_CTOR
+ QSharedDataPointer(const QSharedDataPointer &o) noexcept : Base(o.d.get())
+ { if (d) d->ref.ref(); }
+
QSharedDataPointer &operator=(const QSharedDataPointer &o) noexcept
{
reset(o.d.get());
@@ -87,76 +190,80 @@ public:
return *this;
}
Q_NODISCARD_CTOR
- QSharedDataPointer(QSharedDataPointer &&o) noexcept : d(std::exchange(o.d, nullptr)) {}
+ QSharedDataPointer(QSharedDataPointer &&o) noexcept
+ : Base(std::exchange(o.d, nullptr).get())
+ {}
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QSharedDataPointer)
- operator bool () const noexcept { return d != nullptr; }
- bool operator!() const noexcept { return d == nullptr; }
+#ifdef Q_QDOC
+ void reset(T *ptr = nullptr) noexcept;
- void swap(QSharedDataPointer &other) noexcept
- { qt_ptr_swap(d, other.d); }
+ operator bool () const noexcept;
+ bool operator!() const noexcept;
+
+ void swap(QSharedDataPointer &other) noexcept;
+#else
+ using Base::reset;
+ using Base::swap;
+#endif
protected:
T *clone();
+ template <typename... Args> static T *create(Args &&... args)
+ { return new T(std::forward(args)...); }
+ static void destroy(T *ptr) { delete ptr; }
private:
- friend bool comparesEqual(const QSharedDataPointer &lhs, const QSharedDataPointer &rhs) noexcept
- { return lhs.d == rhs.d; }
- friend Qt::strong_ordering
- compareThreeWay(const QSharedDataPointer &lhs, const QSharedDataPointer &rhs) noexcept
- { return Qt::compareThreeWay(lhs.d, rhs.d); }
Q_DECLARE_STRONGLY_ORDERED(QSharedDataPointer)
-
- friend bool comparesEqual(const QSharedDataPointer &lhs, const T *rhs) noexcept
- { return lhs.d == rhs; }
- friend Qt::strong_ordering
- compareThreeWay(const QSharedDataPointer &lhs, const T *rhs) noexcept
- { return Qt::compareThreeWay(lhs.d, rhs); }
Q_DECLARE_STRONGLY_ORDERED(QSharedDataPointer, T*)
-
- friend bool comparesEqual(const QSharedDataPointer &lhs, std::nullptr_t) noexcept
- { return lhs.d == nullptr; }
- friend Qt::strong_ordering
- compareThreeWay(const QSharedDataPointer &lhs, std::nullptr_t) noexcept
- { return Qt::compareThreeWay(lhs.d, nullptr); }
Q_DECLARE_STRONGLY_ORDERED(QSharedDataPointer, std::nullptr_t)
- void detach_helper();
-
- Qt::totally_ordered_wrapper<T *> d;
+ using Base::d;
};
template <typename T>
-class QExplicitlySharedDataPointer
+class QExplicitlySharedDataPointer : public QSharedDataPointerBase<QExplicitlySharedDataPointer, T>
{
+ using Base = QSharedDataPointerBase<QExplicitlySharedDataPointer, T>;
+ friend Base;
public:
typedef T Type;
typedef T *pointer;
- T &operator*() const { return *(d.get()); }
- T *operator->() noexcept { return d.get(); }
- T *operator->() const noexcept { return d.get(); }
+ // override to make explicit. Can use explicit(!ImplicitlyShared) once we
+ // can depend on C++20.
explicit operator T *() { return d.get(); }
explicit operator const T *() const noexcept { return d.get(); }
+
+ // override to make const. There is no const(cond), but we could use
+ // requires(!ImplicitlyShared)
T *data() const noexcept { return d.get(); }
T *get() const noexcept { return d.get(); }
- const T *constData() const noexcept { return d.get(); }
- T *take() noexcept { return std::exchange(d, nullptr).get(); }
- void detach() { if (d && d->ref.loadRelaxed() != 1) detach_helper(); }
+#ifdef Q_QDOC
+ T &operator*() const;
+ T *operator->() noexcept;
+ T *operator->() const noexcept;
+ T *data() const noexcept;
+ T *get() const noexcept;
+ const T *constData() const noexcept;
+ T *take() noexcept;
+#endif
+
+ void detach() { Base::detach(); }
Q_NODISCARD_CTOR
- QExplicitlySharedDataPointer() noexcept : d(nullptr) { }
+ QExplicitlySharedDataPointer() noexcept : Base(nullptr) { }
~QExplicitlySharedDataPointer() { if (d && !d->ref.deref()) delete d.get(); }
Q_NODISCARD_CTOR
- explicit QExplicitlySharedDataPointer(T *data) noexcept : d(data)
+ explicit QExplicitlySharedDataPointer(T *data) noexcept : Base(data)
{ if (d) d->ref.ref(); }
Q_NODISCARD_CTOR
- QExplicitlySharedDataPointer(T *data, QAdoptSharedDataTag) noexcept : d(data)
+ QExplicitlySharedDataPointer(T *data, QAdoptSharedDataTag) noexcept : Base(data)
{}
Q_NODISCARD_CTOR
- QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer &o) noexcept : d(o.d)
+ QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer &o) noexcept : Base(o.d.get())
{ if (d) d->ref.ref(); }
template<typename X>
@@ -165,20 +272,9 @@ public:
#ifdef QT_ENABLE_QEXPLICITLYSHAREDDATAPOINTER_STATICCAST
#error This macro has been removed in Qt 6.9.
#endif
- : d(o.data())
+ : Base(o.data())
{ if (d) d->ref.ref(); }
- void reset(T *ptr = nullptr) noexcept
- {
- if (ptr != d) {
- if (ptr)
- ptr->ref.ref();
- T *old = std::exchange(d, Qt::totally_ordered_wrapper(ptr)).get();
- if (old && !old->ref.deref())
- delete old;
- }
- }
-
QExplicitlySharedDataPointer &operator=(const QExplicitlySharedDataPointer &o) noexcept
{
reset(o.d.get());
@@ -190,72 +286,52 @@ public:
return *this;
}
Q_NODISCARD_CTOR
- QExplicitlySharedDataPointer(QExplicitlySharedDataPointer &&o) noexcept : d(std::exchange(o.d, nullptr)) {}
+ QExplicitlySharedDataPointer(QExplicitlySharedDataPointer &&o) noexcept
+ : Base(std::exchange(o.d, nullptr).get())
+ {}
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QExplicitlySharedDataPointer)
- operator bool () const noexcept { return d != nullptr; }
- bool operator!() const noexcept { return d == nullptr; }
+#ifdef Q_QDOC
+ void reset(T *ptr = nullptr) noexcept;
- void swap(QExplicitlySharedDataPointer &other) noexcept
- { qt_ptr_swap(d, other.d); }
+ operator bool () const noexcept;
+ bool operator!() const noexcept;
+
+ void swap(QExplicitlySharedDataPointer &other) noexcept;
+#else
+ using Base::swap;
+ using Base::reset;
+#endif
protected:
T *clone();
+ template <typename... Args> static T *create(Args &&... args)
+ { return new T(std::forward(args)...); }
+ static void destroy(T *ptr) { delete ptr; }
private:
- friend bool comparesEqual(const QExplicitlySharedDataPointer &lhs,
- const QExplicitlySharedDataPointer &rhs) noexcept
- { return lhs.d == rhs.d; }
- friend Qt::strong_ordering
- compareThreeWay(const QExplicitlySharedDataPointer &lhs,
- const QExplicitlySharedDataPointer &rhs) noexcept
- { return Qt::compareThreeWay(lhs.d, rhs.d); }
Q_DECLARE_STRONGLY_ORDERED(QExplicitlySharedDataPointer)
-
- friend bool comparesEqual(const QExplicitlySharedDataPointer &lhs, const T *rhs) noexcept
- { return lhs.d == rhs; }
- friend Qt::strong_ordering
- compareThreeWay(const QExplicitlySharedDataPointer &lhs, const T *rhs) noexcept
- { return Qt::compareThreeWay(lhs.d, rhs); }
Q_DECLARE_STRONGLY_ORDERED(QExplicitlySharedDataPointer, const T*)
-
- friend bool comparesEqual(const QExplicitlySharedDataPointer &lhs, std::nullptr_t) noexcept
- { return lhs.d == nullptr; }
- friend Qt::strong_ordering
- compareThreeWay(const QExplicitlySharedDataPointer &lhs, std::nullptr_t) noexcept
- { return Qt::compareThreeWay(lhs.d, nullptr); }
Q_DECLARE_STRONGLY_ORDERED(QExplicitlySharedDataPointer, std::nullptr_t)
- void detach_helper();
-
- Qt::totally_ordered_wrapper<T *> d;
+ using Base::d;
};
// Declared here and as Q_OUTOFLINE_TEMPLATE to work-around MSVC bug causing missing symbols at link time.
template <typename T>
Q_INLINE_TEMPLATE T *QSharedDataPointer<T>::clone()
{
- return new T(*d);
-}
-
-template <typename T>
-Q_OUTOFLINE_TEMPLATE void QSharedDataPointer<T>::detach_helper()
-{
- T *x = clone();
- x->ref.ref();
- if (!d.get()->ref.deref())
- delete d.get();
- d.reset(x);
+ return new T(*this->d);
}
template <typename T>
Q_INLINE_TEMPLATE T *QExplicitlySharedDataPointer<T>::clone()
{
- return new T(*d.get());
+ return new T(*this->d.get());
}
-template <typename T>
-Q_OUTOFLINE_TEMPLATE void QExplicitlySharedDataPointer<T>::detach_helper()
+template <template <typename> class P, typename T> Q_OUTOFLINE_TEMPLATE void
+QSharedDataPointerBase<P, T>::detach_helper()
{
T *x = clone();
x->ref.ref();
@@ -272,17 +348,6 @@ template <typename T>
void swap(QExplicitlySharedDataPointer<T> &p1, QExplicitlySharedDataPointer<T> &p2) noexcept
{ p1.swap(p2); }
-template <typename T>
-size_t qHash(const QSharedDataPointer<T> &ptr, size_t seed = 0) noexcept
-{
- return qHash(ptr.data(), seed);
-}
-template <typename T>
-size_t qHash(const QExplicitlySharedDataPointer<T> &ptr, size_t seed = 0) noexcept
-{
- return qHash(ptr.data(), seed);
-}
-
template<typename T> Q_DECLARE_TYPEINFO_BODY(QSharedDataPointer<T>, Q_RELOCATABLE_TYPE);
template<typename T> Q_DECLARE_TYPEINFO_BODY(QExplicitlySharedDataPointer<T>, Q_RELOCATABLE_TYPE);
diff --git a/src/gui/doc/images/plaintext-layout.png b/src/gui/doc/images/plaintext-layout.png
deleted file mode 100644
index 9172d7a044d..00000000000
--- a/src/gui/doc/images/plaintext-layout.png
+++ /dev/null
Binary files differ
diff --git a/src/gui/doc/images/plaintext-layout.webp b/src/gui/doc/images/plaintext-layout.webp
new file mode 100644
index 00000000000..b8266ec5a8c
--- /dev/null
+++ b/src/gui/doc/images/plaintext-layout.webp
Binary files differ
diff --git a/src/gui/doc/src/qtgui.qdoc b/src/gui/doc/src/qtgui.qdoc
index dca2f10bf26..f5d60699deb 100644
--- a/src/gui/doc/src/qtgui.qdoc
+++ b/src/gui/doc/src/qtgui.qdoc
@@ -17,8 +17,7 @@
/*!
\module QtGuiPrivate
\title Qt GUI Private C++ Classes
- \qtcmakepackage Gui
- \qtcmaketargetitem GuiPrivate
+ \qtcmakepackage GuiPrivate
\qtvariable gui-private
\brief Provides access to private GUI functionality.
@@ -27,7 +26,7 @@
private Qt GUI APIs:
\badcode
- find_package(Qt6 REQUIRED COMPONENTS Gui)
+ find_package(Qt6 REQUIRED COMPONENTS GuiPrivate)
target_link_libraries(mytarget PRIVATE Qt6::GuiPrivate)
\endcode
*/
diff --git a/src/gui/doc/src/richtext.qdoc b/src/gui/doc/src/richtext.qdoc
index 429233ec8f1..2fa49a31e03 100644
--- a/src/gui/doc/src/richtext.qdoc
+++ b/src/gui/doc/src/richtext.qdoc
@@ -650,7 +650,7 @@
the QTextLayout class, to help developers perform word-wrapping and
layout tasks without the need to create a document first.
- \image plaintext-layout.png {Screenshot of a text that flows around a
+ \image plaintext-layout.webp {Screenshot of a text that flows around a
circle.}
Formatting and drawing a paragraph of plain text is straightforward.
diff --git a/src/gui/image/qplatformpixmap.cpp b/src/gui/image/qplatformpixmap.cpp
index a2977360951..d1eab7f6ed3 100644
--- a/src/gui/image/qplatformpixmap.cpp
+++ b/src/gui/image/qplatformpixmap.cpp
@@ -36,7 +36,6 @@ QPlatformPixmap::QPlatformPixmap(PixelType pixelType, int objectId)
h(0),
d(0),
is_null(true),
- ref(0),
detach_no(0),
type(pixelType),
id(objectId),
diff --git a/src/gui/image/qplatformpixmap.h b/src/gui/image/qplatformpixmap.h
index be86bf8850f..5621afa4da5 100644
--- a/src/gui/image/qplatformpixmap.h
+++ b/src/gui/image/qplatformpixmap.h
@@ -22,7 +22,7 @@ QT_BEGIN_NAMESPACE
class QImageReader;
-class Q_GUI_EXPORT QPlatformPixmap
+class Q_GUI_EXPORT QPlatformPixmap : public QSharedData
{
public:
enum PixelType {
@@ -113,10 +113,7 @@ private:
friend class QPixmap;
friend class QX11PlatformPixmap;
friend class QImagePixmapCleanupHooks; // Needs to set is_cached
- friend class QOpenGLTextureCache; //Needs to check the reference count
- friend class QExplicitlySharedDataPointer<QPlatformPixmap>;
- QAtomicInt ref;
int detach_no;
PixelType type;
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index 098d0331327..518843ffcbd 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -3407,6 +3407,15 @@ void QGuiApplicationPrivate::processExposeEvent(QWindowSystemInterfacePrivate::E
return;
QWindowPrivate *p = qt_window_private(window);
+ if (e->isExposed) {
+ // If the window has been automatically positioned or resized by the
+ // window manager, we now assume those have taken effect, even for
+ // asynchronous window managers. From this point on we want the window
+ // to keep its geometry, even when recreated.
+ p->positionAutomatic = false;
+ p->resizeAutomatic = false;
+ }
+
if (!p->receivedExpose) {
if (p->resizeEventPending) {
// as a convenience for plugins, send a resize event before the first expose event if they haven't done so
diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp
index c7b6e4ebff3..bb71f8fb6fc 100644
--- a/src/gui/kernel/qkeysequence.cpp
+++ b/src/gui/kernel/qkeysequence.cpp
@@ -1298,7 +1298,10 @@ QString QKeySequencePrivate::keyName(Qt::Key key, QKeySequence::SequenceFormat f
bool nativeText = (format == QKeySequence::NativeText);
QString p;
- if (key && key < Qt::Key_Escape && key != Qt::Key_Space) {
+ if (nativeText && (key > 0x00 && key <= 0x1f)) {
+ // Map C0 control codes to the corresponding Control Pictures
+ p = QChar::fromUcs2(0x2400 + key);
+ } else if (key && key < Qt::Key_Escape && key != Qt::Key_Space) {
if (!QChar::requiresSurrogates(key)) {
p = QChar::fromUcs2(key).toUpper();
} else {
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index c23be8eb3ad..bad5932c457 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -582,12 +582,6 @@ void QWindowPrivate::create(bool recursive)
platformWindow->initialize();
- // Now that the window is created and initialized the platform has had
- // a chance to position and size it automatically. From this point on
- // we want the window to keep its geometry, even when recreated.
- positionAutomatic = false;
- resizeAutomatic = false;
-
QObjectList childObjects = q->children();
for (int i = 0; i < childObjects.size(); i ++) {
QObject *object = childObjects.at(i);
diff --git a/src/gui/painting/qdrawhelper_avx2.cpp b/src/gui/painting/qdrawhelper_avx2.cpp
index 72853be6e97..d7496845197 100644
--- a/src/gui/painting/qdrawhelper_avx2.cpp
+++ b/src/gui/painting/qdrawhelper_avx2.cpp
@@ -1525,7 +1525,7 @@ void QT_FASTCALL storeRGBA16FFromARGB32PM_avx2(uchar *dest, const uint *src, int
const __m128 vsa = _mm_permute_ps(vsf, _MM_SHUFFLE(3, 3, 3, 3));
__m128 vsr = _mm_rcp_ps(vsa);
vsr = _mm_sub_ps(_mm_add_ps(vsr, vsr), _mm_mul_ps(vsr, _mm_mul_ps(vsr, vsa)));
- vsr = _mm_insert_ps(vsr, _mm_set_ss(1.0f), 0x30);
+ vsr = _mm_insert_ps(vsr, vf, 0x30);
vsf = _mm_mul_ps(vsf, vsr);
}
_mm_storel_epi64((__m128i *)(d + i), _mm_cvtps_ph(vsf, 0));
diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp
index 5763696266a..38c4a9ea87f 100644
--- a/src/gui/painting/qpainterpath.cpp
+++ b/src/gui/painting/qpainterpath.cpp
@@ -2937,6 +2937,8 @@ qreal QPainterPath::percentAtLength(qreal len) const
if (len > totalLength)
return 1;
+ Q_ASSERT(totalLength != 0);
+
if (d->cacheEnabled) {
const int ei = qMax(d->elementAtT(len / totalLength), 1); // Skip initial MoveTo
qreal res = 0;
@@ -3117,6 +3119,7 @@ QPointF QPainterPath::pointAtPercent(qreal t) const
qreal curLen = 0;
qreal bezierLen = 0;
QBezier b = d_ptr->bezierAtT(*this, t, &curLen, &bezierLen);
+ Q_ASSERT(bezierLen != 0);
qreal realT = (totalLength * t - curLen) / bezierLen;
return b.pointAt(qBound(qreal(0), realT, qreal(1)));
@@ -3141,10 +3144,14 @@ qreal QPainterPath::angleAtPercent(qreal t) const
return 0;
}
+ if (isEmpty())
+ return 0;
+
qreal totalLength = length();
qreal curLen = 0;
qreal bezierLen = 0;
QBezier bez = d_ptr->bezierAtT(*this, t, &curLen, &bezierLen);
+ Q_ASSERT(bezierLen != 0);
qreal realT = (totalLength * t - curLen) / bezierLen;
qreal m1 = slopeAt(realT, bez.x1, bez.x2, bez.x3, bez.x4);
@@ -3170,10 +3177,14 @@ qreal QPainterPath::slopeAtPercent(qreal t) const
return 0;
}
+ if (isEmpty())
+ return 0;
+
qreal totalLength = length();
qreal curLen = 0;
qreal bezierLen = 0;
QBezier bez = d_ptr->bezierAtT(*this, t, &curLen, &bezierLen);
+ Q_ASSERT(bezierLen != 0);
qreal realT = (totalLength * t - curLen) / bezierLen;
qreal m1 = slopeAt(realT, bez.x1, bez.x2, bez.x3, bez.x4);
diff --git a/src/gui/painting/qstroker.cpp b/src/gui/painting/qstroker.cpp
index 79799ca2ece..0d435c95048 100644
--- a/src/gui/painting/qstroker.cpp
+++ b/src/gui/painting/qstroker.cpp
@@ -1154,7 +1154,8 @@ void QDashStroker::processCurrentSubpath()
elen -= std::floor(elen * invSumLength) * sumLength;
// Update dash offset.
while (!done) {
- qreal dpos = pos + dashes[idash] - doffset - estart;
+ // parentheses to avoid float rounding issues: qreal(4) + 0.1 - 0.1 - 4 < 0
+ qreal dpos = (pos + dashes[idash]) - (doffset + estart);
Q_ASSERT(dpos >= 0);
@@ -1189,7 +1190,8 @@ void QDashStroker::processCurrentSubpath()
bool has_offset = doffset > 0;
bool evenDash = (idash & 1) == 0;
- qreal dpos = pos + dashes[idash] - doffset - estart;
+ // parentheses to avoid float rounding issues: qreal(4) + 0.1 - 0.1 - 4 < 0
+ qreal dpos = (pos + dashes[idash]) - (doffset + estart);
Q_ASSERT(dpos >= 0);
diff --git a/src/gui/platform/darwin/qappleiconengine.mm b/src/gui/platform/darwin/qappleiconengine.mm
index 20d50b0d8a8..3228b97fdb0 100644
--- a/src/gui/platform/darwin/qappleiconengine.mm
+++ b/src/gui/platform/darwin/qappleiconengine.mm
@@ -30,27 +30,28 @@ auto *loadImage(const QString &iconName)
{"call-start"_L1, @"phone.arrow.up.right"},
{"call-stop"_L1, @"phone.down"},
{"contact-new"_L1, @"person.crop.circle.badge.plus"},
- {"document-new"_L1, @"doc.badge.plus"},
- {"document-open"_L1, @"folder"},
- {"document-open-recent"_L1, @"doc.badge.clock"},
- {"document-page-setup"_L1, @"doc.badge.gearshape"},
+ {"document-new"_L1, @"plus"},
+ {"document-open"_L1, @"arrow.up.forward"},
+ {"document-open-recent"_L1, @"clock"},
+ {"document-page-setup"_L1, @"text.page"},
{"document-print"_L1, @"printer"},
- //{"document-print-preview"_L1, @""},
- {"document-properties"_L1, @"doc.badge.ellipsis"},
- //{"document-revert"_L1, @""},
+ {"document-print-preview"_L1, @"richtext.page"},
+ {"document-properties"_L1, @"info.circle.text.page"},
+ {"document-revert"_L1, @"arrow.counterclockwise"},
{"document-save"_L1, @"square.and.arrow.down"},
- //{"document-save-as"_L1, @""},
+ {"document-save-as"_L1, @"square.and.arrow.down.on.square"},
{"document-send"_L1, @"paperplane"},
+ {"document-export"_L1, @"square.and.arrow.up"},
{"edit-clear"_L1, @"xmark.circle"},
{"edit-copy"_L1, @"doc.on.doc"},
{"edit-cut"_L1, @"scissors"},
- {"edit-delete"_L1, @"delete.left"},
- {"edit-find"_L1, @"magnifyingglass"},
+ {"edit-delete"_L1, @"trash"},
+ {"edit-find"_L1, @"text.page.badge.magnifyingglass"},
//{"edit-find-replace"_L1, @"arrow.up.left.and.down.right.magnifyingglass"},
- {"edit-paste"_L1, @"clipboard"},
- {"edit-redo"_L1, @"arrowshape.turn.up.right"},
- //{"edit-select-all"_L1, @""},
- {"edit-undo"_L1, @"arrowshape.turn.up.left"},
+ {"edit-paste"_L1, @"document.on.clipboard"},
+ {"edit-redo"_L1, @"arrow.uturn.forward"},
+ {"edit-select-all"_L1, @"character.textbox"},
+ {"edit-undo"_L1, @"arrow.uturn.backward"},
{"folder-new"_L1, @"folder.badge.plus"},
{"format-indent-less"_L1, @"decrease.indent"},
{"format-indent-more"_L1, @"increase.indent"},
@@ -65,35 +66,36 @@ auto *loadImage(const QString &iconName)
{"format-text-underline"_L1, @"underline"},
{"format-text-strikethrough"_L1, @"strikethrough"},
//{"go-bottom"_L1, @""},
- {"go-down"_L1, @"arrowshape.down"},
- {"go-first"_L1, @"increase.indent"},
+ {"go-down"_L1, @"chevron.down"},
+ //{"go-first"_L1, @""},
{"go-home"_L1, @"house"},
//{"go-jump"_L1, @""},
//{"go-last"_L1, @""},
- {"go-next"_L1, @"arrowshape.right"},
- {"go-previous"_L1, @"arrowshape.left"},
+ {"go-next"_L1, @"chevron.right"},
+ {"go-previous"_L1, @"chevron.left"},
//{"go-top"_L1, @""},
- {"go-up"_L1, @"arrowshape.up"},
+ {"go-up"_L1, @"chevron.up"},
{"help-about"_L1, @"info.circle"},
//{"help-contents"_L1, @""},
{"help-faq"_L1, @"questionmark.app"},
{"insert-image"_L1, @"photo.badge.plus"},
{"insert-link"_L1, @"link.badge.plus"},
- //{"insert-object"_L1, @""},
- {"insert-text"_L1, @"textformat"},
+ {"insert-object"_L1, @"widget.small.badge.plus"},
+ {"insert-text"_L1, @"text.badge.plus"},
{"list-add"_L1, @"plus.circle"},
{"list-remove"_L1, @"minus.circle"},
{"mail-forward"_L1, @"arrowshape.turn.up.right"},
{"mail-mark-important"_L1, @"star"},
{"mail-mark-junk"_L1, @"xmark.bin"},
- {"mail-mark-notjunk"_L1, @"trash.slash"},
+ {"mail-mark-notjunk"_L1, @"arrow.up.bin"},
{"mail-mark-read"_L1, @"envelope.open"},
- {"mail-mark-unread"_L1, @"envelope.fill"},
+ {"mail-mark-unread"_L1, @"envelope.badge"},
{"mail-message-new"_L1, @"square.and.pencil"},
{"mail-reply-all"_L1, @"arrowshape.turn.up.left.2"},
{"mail-reply-sender"_L1, @"arrowshape.turn.up.left"},
- {"mail-send"_L1, @"paperplane"},
- {"mail-send-receive"_L1, @"envelope.arrow.triangle.branch"},
+ {"mail-send"_L1, @"arrow.up.circle.fill"},
+ {"mail-send-receive"_L1, @"arrow.trianglehead.2.clockwise.rotate.90"},
+ {"mail-replied"_L1, @"envelope.and.arrow.trianglehead.branch"},
{"media-eject"_L1, @"eject"},
{"media-playback-pause"_L1, @"pause"},
{"media-playback-start"_L1, @"play"},
@@ -108,61 +110,61 @@ auto *loadImage(const QString &iconName)
{"object-rotate-left"_L1, @"rotate.left"},
{"object-rotate-right"_L1, @"rotate.right"},
{"process-stop"_L1, @"stop.circle"},
- {"system-lock-screen"_L1, @"lock.display"},
- {"system-log-out"_L1, @"door.left.hand.open"},
+ {"system-lock-screen"_L1, @"lock"},
+ {"system-log-out"_L1, @"person.crop.circle"},
//{"system-run"_L1, @""},
{"system-search"_L1, @"magnifyingglass"},
- //{"system-reboot"_L1, @""},
+ {"system-reboot"_L1, @"restart"},
{"system-shutdown"_L1, @"power"},
- //{"tools-check-spelling"_L1, @""},
+ {"tools-check-spelling"_L1, @"textformat.characters.dottedunderline"},
{"view-fullscreen"_L1, @"arrow.up.left.and.arrow.down.right"},
{"view-refresh"_L1, @"arrow.clockwise"},
{"view-restore"_L1, @"arrow.down.right.and.arrow.up.left"},
- //{"view-sort-ascending"_L1, @""},
- //{"view-sort-descending"_L1, @""},
+ {"view-sort-ascending"_L1, @"arrow.up"},
+ {"view-sort-descending"_L1, @"arrow.down"},
{"window-close"_L1, @"xmark.circle"},
{"window-new"_L1, @"macwindow.badge.plus"},
{"zoom-fit-best"_L1, @"square.arrowtriangle.4.outward"},
{"zoom-in"_L1, @"plus.magnifyingglass"},
- //{"zoom-original"_L1, @""},
+ {"zoom-original"_L1, @"1.magnifyingglass"},
{"zoom-out"_L1, @"minus.magnifyingglass"},
{"process-working"_L1, @"circle.dotted"},
- //{"accessories-calculator"_L1, @""},
- //{"accessories-character-map"_L1, @""},
+ {"accessories-calculator"_L1, @"plus.forwardslash.minus"},
+ {"accessories-character-map"_L1, @"keyboard.macwindow"},
{"accessories-dictionary"_L1, @"character.book.closed"},
{"accessories-text-editor"_L1, @"textformat"},
{"help-browser"_L1, @"folder.badge.questionmark"},
{"multimedia-volume-control"_L1, @"speaker.wave.3"},
{"preferences-desktop-accessibility"_L1, @"accessibility"},
- //{"preferences-desktop-font"_L1, @""},
- {"preferences-desktop-keyboard"_L1, @"keyboard.badge.ellipsis"},
- //{"preferences-desktop-locale"_L1, @""},
- //{"preferences-desktop-multimedia"_L1, @""},
- //{"preferences-desktop-screensaver"_L1, @""},
- //{"preferences-desktop-theme"_L1, @""},
- //{"preferences-desktop-wallpaper"_L1, @""},
+ {"preferences-desktop-font"_L1, @"textformat.characters"},
+ {"preferences-desktop-keyboard"_L1, @"keyboard"},
+ {"preferences-desktop-locale"_L1, @"mappin.and.ellipse"},
+ {"preferences-desktop-multimedia"_L1, @"music.note.tv"},
+ {"preferences-desktop-screensaver"_L1, @"display"},
+ {"preferences-desktop-theme"_L1, @"paintpalette"},
+ {"preferences-desktop-wallpaper"_L1, @"photo.tv"},
{"system-file-manager"_L1, @"folder.badge.gearshape"},
- //{"system-software-install"_L1, @""},
- //{"system-software-update"_L1, @""}, d
- //{"utilities-system-monitor"_L1, @""},
+ {"system-software-install"_L1, @"laptopcomputer.and.arrow.down"},
+ {"system-software-update"_L1, @"laptopcomputer.badge.checkmark"},
+ {"utilities-system-monitor"_L1, @"chart.bar.xaxis"},
{"utilities-terminal"_L1, @"apple.terminal"},
- //{"applications-accessories"_L1, @""},
- //{"applications-development"_L1, @""},
- //{"applications-engineering"_L1, @""},
- {"applications-games"_L1, @"gamecontroller"},
- //{"applications-graphics"_L1, @""},
+ {"applications-accessories"_L1, @"scanner"},
+ {"applications-development"_L1, @"hammer"},
+ {"applications-engineering"_L1, @"wrench.and.screwdriver"},
+ {"applications-games"_L1, @"gamecontroller.circle"},
+ {"applications-graphics"_L1, @"theatermask.and.paintbrush"},
{"applications-internet"_L1, @"network"},
{"applications-multimedia"_L1, @"tv.and.mediabox"},
- //{"applications-office"_L1, @""},
- //{"applications-other"_L1, @""},
+ {"applications-office"_L1, @"square.and.pencil.circle"},
+ {"applications-other"_L1, @"app.grid"},
{"applications-science"_L1, @"atom"},
- //{"applications-system"_L1, @""},
- //{"applications-utilities"_L1, @""},
+ {"applications-system"_L1, @"gear"},
+ {"applications-utilities"_L1, @"wrench.and.screwdriver"},
{"preferences-desktop"_L1, @"menubar.dock.rectangle"},
- //{"preferences-desktop-peripherals"_L1, @""},
- //{"preferences-desktop-personal"_L1, @""},
- //{"preferences-other"_L1, @""},
- //{"preferences-system"_L1, @""},
+ {"preferences-desktop-peripherals"_L1, @"iphone.and.ipod"},
+ {"preferences-desktop-personal"_L1, @"person.badge.key"},
+ {"preferences-other"_L1, @"gear"},
+ {"preferences-system"_L1, @"gear"},
{"preferences-system-network"_L1, @"network"},
{"system-help"_L1, @"questionmark.diamond"},
{"audio-card"_L1, @"waveform.circle"},
@@ -175,40 +177,40 @@ auto *loadImage(const QString &iconName)
{"drive-harddisk"_L1, @"internaldrive"},
{"drive-optical"_L1, @"opticaldiscdrive"},
{"drive-removable-media"_L1, @"externaldrive"},
- {"input-gaming"_L1, @"gamecontroller"}, // "games" also using this one
+ {"input-gaming"_L1, @"gamecontroller"},
{"input-keyboard"_L1, @"keyboard"},
{"input-mouse"_L1, @"computermouse"},
{"input-tablet"_L1, @"ipad"},
{"media-flash"_L1, @"mediastick"},
//{"media-floppy"_L1, @""},
- //{"media-optical"_L1, @""},
+ {"media-optical"_L1, @"opticaldisc"},
{"media-tape"_L1, @"recordingtape"},
- //{"modem"_L1, @""},
- {"multimedia-player"_L1, @"play.rectangle"},
+ {"modem"_L1, @"phone.connection"},
+ {"multimedia-player"_L1, @"ipod"},
{"network-wired"_L1, @"app.connected.to.app.below.fill"},
{"network-wireless"_L1, @"wifi"},
{"network-workgroup"_L1, @"network"},
- //{"pda"_L1, @""},
+ {"pda"_L1, @"flipphone"},
{"phone"_L1, @"iphone"},
{"printer"_L1, @"printer"},
{"scanner"_L1, @"scanner"},
{"video-display"_L1, @"play.display"},
- //{"emblem-default"_L1, @""},
+ {"emblem-default"_L1, @"circle"},
{"emblem-documents"_L1, @"doc.circle"},
{"emblem-downloads"_L1, @"arrow.down.circle"},
- {"emblem-favorite"_L1, @"star"},
- {"emblem-important"_L1, @"exclamationmark.bubble.circle"},
- {"emblem-mail"_L1, @"envelope"},
- {"emblem-photos"_L1, @"photo.stack"},
- //{"emblem-readonly"_L1, @""},
- {"emblem-shared"_L1, @"folder.badge.person.crop"},
+ {"emblem-favorite"_L1, @"star.circle"},
+ {"emblem-important"_L1, @"exclamationmark.circle"},
+ {"emblem-mail"_L1, @"envelope.circle"},
+ {"emblem-photos"_L1, @"photo.circle"},
+ {"emblem-readonly"_L1, @"eye.circle"},
+ {"emblem-shared"_L1, @"person.2.circle"},
{"emblem-symbolic-link"_L1, @"link.circle"},
{"emblem-synchronized"_L1, @"arrow.triangle.2.circlepath.circle"},
- {"emblem-system"_L1, @"gear"},
- //{"emblem-unreadable"_L1, @""},
+ {"emblem-system"_L1, @"gear.circle"},
+ {"emblem-unreadable"_L1, @"eye.slash.circle"},
{"text-x-generic"_L1, @"doc"}, // until iOS 18/macOS 15; @"document" after that
{"folder"_L1, @"folder"},
- //{"folder-remote"_L1, @""},
+ {"folder-remote"_L1, @"icloud"},
{"network-server"_L1, @"server.rack"},
//{"start-here"_L1, @""},
{"user-bookmarks"_L1, @"bookmark.circle"},
@@ -229,28 +231,28 @@ auto *loadImage(const QString &iconName)
{"dialog-question"_L1, @"questionmark.circle"},
{"dialog-warning"_L1, @"exclamationmark.octagon"},
{"folder-drag-accept"_L1, @"plus.rectangle.on.folder"},
- //{"folder-open"_L1, @""},
+ {"folder-open"_L1, @"arrow.forward.folder"},
{"folder-visiting"_L1, @"folder.circle"},
- {"image-loading"_L1, @"photo.circle"},
- {"image-missing"_L1, @"photo"},
+ {"image-loading"_L1, @"photo.badge.arrow.down"},
+ {"image-missing"_L1, @"photo.badge.exclamationmark"},
{"mail-attachment"_L1, @"paperclip"},
{"mail-unread"_L1, @"envelope.badge"},
{"mail-read"_L1, @"envelope.open"},
- {"mail-replied"_L1, @"arrowshape.turn.up.left"},
+ //{"mail-replied"_L1, @""},
//{"mail-signed"_L1, @""},
- //{"mail-signed-verified"_L1, @""},
- {"media-playlist-repeat"_L1, @"repet"},
+ {"mail-signed-verified"_L1, @"envelope.badge.shield.half.filled"},
+ {"media-playlist-repeat"_L1, @"repeat"},
{"media-playlist-shuffle"_L1, @"shuffle"},
- //{"network-error"_L1, @""},
- //{"network-idle"_L1, @""},
- {"network-offline"_L1, @"network.slash"},
- //{"network-receive"_L1, @""},
- //{"network-transmit"_L1, @""},
- //{"network-transmit-receive"_L1, @""},
+ {"network-error"_L1, @"xmark.icloud"},
+ {"network-idle"_L1, @"icloud"},
+ {"network-offline"_L1, @"icloud.slash"},
+ {"network-receive"_L1, @"icloud.and.arrow.down"},
+ {"network-transmit"_L1, @"icloud.and.arrow.up"},
+ {"network-transmit-receive"_L1, @"arrow.trianglehead.2.clockwise.rotate.90.icloud"},
//{"printer-error"_L1, @""},
- {"printer-printing"_L1, @"printer.dotmatrix.filled.and.paper"}, // not sure
- {"security-high"_L1, @"lock.shield"},
- //{"security-medium"_L1, @""},
+ {"printer-printing"_L1, @"printer.dotmatrix"},
+ {"security-high"_L1, @"lock.badge.checkmark"},
+ {"security-medium"_L1, @"lock"},
{"security-low"_L1, @"lock.trianglebadge.exclamationmark"},
{"software-update-available"_L1, @"arrowshape.up.circle"},
{"software-update-urgent"_L1, @"exclamationmark.transmission"},
@@ -258,9 +260,9 @@ auto *loadImage(const QString &iconName)
{"sync-synchronizing"_L1, @"arrow.triangle.2.circlepath"},
{"task-due"_L1, @"clock.badge.exclamationmark"},
{"task-past-due"_L1, @"clock.badge.xmark"},
- {"user-available"_L1, @"person.crop.circle.badge.checkmark"},
- {"user-away"_L1, @"person.crop.circle.badge.clock"},
- //{"user-idle"_L1, @""},
+ {"user-available"_L1, @"person.crop.circle.badge"},
+ {"user-away"_L1, @"person.crop.circle.badge.moon"},
+ {"user-idle"_L1, @"person.crop.circle.badge.clock"},
{"user-offline"_L1, @"person.crop.circle.badge.xmark"},
//{"user-trash-full"_L1, @""},
{"weather-clear"_L1, @"sun.max"},
@@ -269,9 +271,9 @@ auto *loadImage(const QString &iconName)
{"weather-few-clouds-night"_L1, @"cloud.moon"},
{"weather-fog"_L1, @"cloud.fog"},
{"weather-overcast"_L1, @"cloud"},
- //{"weather-severe-alert"_L1, @""},
- {"weather-showers"_L1, @"cloud.rain"},
- //{"weather-showers-scattered"_L1, @""},
+ {"weather-severe-alert"_L1, @"cloud.bolt.rain"},
+ {"weather-showers"_L1, @"cloud.heavyrain"},
+ {"weather-showers-scattered"_L1, @"cloud.drizzle"},
{"weather-snow"_L1, @"cloud.snow"},
{"weather-storm"_L1, @"tropicalstorm"},
};
diff --git a/src/gui/platform/darwin/qapplekeymapper.mm b/src/gui/platform/darwin/qapplekeymapper.mm
index 214865864ff..49f7a8ff0cb 100644
--- a/src/gui/platform/darwin/qapplekeymapper.mm
+++ b/src/gui/platform/darwin/qapplekeymapper.mm
@@ -94,60 +94,10 @@ static CarbonModifiers toCarbonModifiers(Qt::KeyboardModifiers qtModifiers)
return carbonModifiers;
}
-// Keyboard keys (non-modifiers)
-static QHash<char16_t, Qt::Key> standardKeys = {
- { kHomeCharCode, Qt::Key_Home },
- { kEnterCharCode, Qt::Key_Enter },
- { kEndCharCode, Qt::Key_End },
- { kBackspaceCharCode, Qt::Key_Backspace },
- { kTabCharCode, Qt::Key_Tab },
- { kPageUpCharCode, Qt::Key_PageUp },
- { kPageDownCharCode, Qt::Key_PageDown },
- { kReturnCharCode, Qt::Key_Return },
- { kEscapeCharCode, Qt::Key_Escape },
- { kLeftArrowCharCode, Qt::Key_Left },
- { kRightArrowCharCode, Qt::Key_Right },
- { kUpArrowCharCode, Qt::Key_Up },
- { kDownArrowCharCode, Qt::Key_Down },
- { kHelpCharCode, Qt::Key_Help },
- { kDeleteCharCode, Qt::Key_Delete },
- // ASCII maps, for debugging
- { ':', Qt::Key_Colon },
- { ';', Qt::Key_Semicolon },
- { '<', Qt::Key_Less },
- { '=', Qt::Key_Equal },
- { '>', Qt::Key_Greater },
- { '?', Qt::Key_Question },
- { '@', Qt::Key_At },
- { ' ', Qt::Key_Space },
- { '!', Qt::Key_Exclam },
- { '"', Qt::Key_QuoteDbl },
- { '#', Qt::Key_NumberSign },
- { '$', Qt::Key_Dollar },
- { '%', Qt::Key_Percent },
- { '&', Qt::Key_Ampersand },
- { '\'', Qt::Key_Apostrophe },
- { '(', Qt::Key_ParenLeft },
- { ')', Qt::Key_ParenRight },
- { '*', Qt::Key_Asterisk },
- { '+', Qt::Key_Plus },
- { ',', Qt::Key_Comma },
- { '-', Qt::Key_Minus },
- { '.', Qt::Key_Period },
- { '/', Qt::Key_Slash },
- { '[', Qt::Key_BracketLeft },
- { ']', Qt::Key_BracketRight },
- { '\\', Qt::Key_Backslash },
- { '_', Qt::Key_Underscore },
- { '`', Qt::Key_QuoteLeft },
- { '{', Qt::Key_BraceLeft },
- { '}', Qt::Key_BraceRight },
- { '|', Qt::Key_Bar },
- { '~', Qt::Key_AsciiTilde },
- { '^', Qt::Key_AsciiCircum }
-};
-
-static QHash<char16_t, Qt::Key> virtualKeys = {
+// NSEvent.keyCode codes for keys that are independent of keyboard layout.
+// Some of these are technically possible to add custom key maps for, but
+// doing so would be unexpected.
+static QHash<char16_t, Qt::Key> layoutIndependentKeyCodes = {
{ kVK_F1, Qt::Key_F1 },
{ kVK_F2, Qt::Key_F2 },
{ kVK_F3, Qt::Key_F3 },
@@ -164,16 +114,57 @@ static QHash<char16_t, Qt::Key> virtualKeys = {
{ kVK_F14, Qt::Key_F14 },
{ kVK_F15, Qt::Key_F15 },
{ kVK_F16, Qt::Key_F16 },
+ { kVK_F17, Qt::Key_F17 },
+ { kVK_F18, Qt::Key_F18 },
+ { kVK_F19, Qt::Key_F19 },
+ { kVK_F20, Qt::Key_F20 },
+
{ kVK_Return, Qt::Key_Return },
{ kVK_Tab, Qt::Key_Tab },
+ { kVK_Space, Qt::Key_Space },
{ kVK_Escape, Qt::Key_Escape },
- { kVK_Help, Qt::Key_Help },
+ { kVK_Delete, Qt::Key_Backspace },
+ { kVK_ForwardDelete, Qt::Key_Delete },
+
+ { kVK_Home, Qt::Key_Home },
+ { kVK_End, Qt::Key_End },
+ { kVK_PageUp, Qt::Key_PageUp },
+ { kVK_PageDown, Qt::Key_PageDown },
+
{ kVK_UpArrow, Qt::Key_Up },
{ kVK_DownArrow, Qt::Key_Down },
{ kVK_LeftArrow, Qt::Key_Left },
{ kVK_RightArrow, Qt::Key_Right },
- { kVK_PageUp, Qt::Key_PageUp },
- { kVK_PageDown, Qt::Key_PageDown }
+
+ { kVK_CapsLock, Qt::Key_CapsLock },
+ { kVK_Shift, Qt::Key_Shift },
+ { kVK_RightShift, Qt::Key_Shift },
+
+#if 0
+ // FIXME: Map these here instead of relying on
+ // custom logic in [QNSView flagsChanged:]
+
+ { kVK_Command, Qt::Key_unknown },
+ { kVK_RightCommand, Qt::Key_unknown },
+ { kVK_Option, Qt::Key_unknown },
+ { kVK_RightOption, Qt::Key_unknown },
+ { kVK_Control, Qt::Key_unknown },
+ { kVK_RightControl, Qt::Key_unknown },
+ { kVK_Function, Qt::Key_unknown },
+#endif
+
+ { kVK_VolumeUp, Qt::Key_VolumeUp },
+ { kVK_VolumeDown, Qt::Key_VolumeDown },
+ { kVK_Mute, Qt::Key_VolumeMute },
+
+#if 0
+ // FIXME: Figure out which Qt::Key this maps to
+ { kVK_ContextualMenu, Qt::Key_unknown },
+#endif
+ { kVK_Help, Qt::Key_Help },
+
+ { kVK_ANSI_KeypadClear, Qt::Key_Clear },
+ { kVK_ANSI_KeypadEnter, Qt::Key_Enter },
};
static QHash<char16_t, Qt::Key> functionKeys = {
@@ -211,41 +202,19 @@ static int toKeyCode(const QChar &key, int virtualKey, int modifiers)
qCDebug(lcQpaKeyMapperKeys, "Mapping key: %d (0x%04x) / vk %d (0x%04x)",
key.unicode(), key.unicode(), virtualKey, virtualKey);
- if (key == char16_t(kClearCharCode) && virtualKey == 0x47)
- return Qt::Key_Clear;
-
- if (key.isDigit()) {
- qCDebug(lcQpaKeyMapperKeys, "Got digit key: %d", key.digitValue());
- return key.digitValue() + Qt::Key_0;
- }
-
- if (key.isLetter()) {
- qCDebug(lcQpaKeyMapperKeys, "Got letter key: %d", (key.toUpper().unicode() - 'A'));
- return (key.toUpper().unicode() - 'A') + Qt::Key_A;
- }
- if (key.isSymbol()) {
- qCDebug(lcQpaKeyMapperKeys, "Got symbol key: %d", (key.unicode()));
- return key.unicode();
- }
-
- if (auto qtKey = standardKeys.value(key.unicode())) {
+ // Check first if we have a virtual key that should be treated as layout
+ // independent. If so, we want to return early without inspecting the key.
+ if (auto qtKey = layoutIndependentKeyCodes.value(virtualKey)) {
+ qCDebug(lcQpaKeyMapperKeys) << "Got" << qtKey << "based on layout independent virtual key";
// To work like Qt for X11 we issue Backtab when Shift + Tab are pressed
if (qtKey == Qt::Key_Tab && (modifiers & Qt::ShiftModifier)) {
- qCDebug(lcQpaKeyMapperKeys, "Got key: Qt::Key_Backtab");
+ qCDebug(lcQpaKeyMapperKeys, "Transformed into Qt::Key_Backtab");
return Qt::Key_Backtab;
}
-
- qCDebug(lcQpaKeyMapperKeys) << "Got" << qtKey;
- return qtKey;
- }
-
- // Last ditch try to match the scan code
- if (auto qtKey = virtualKeys.value(virtualKey)) {
- qCDebug(lcQpaKeyMapperKeys) << "Got scancode" << qtKey;
return qtKey;
}
- // Check if they belong to key codes in private unicode range
+ // Then check if the key is one of the functions keys in the private Unicode range
if (key >= char16_t(NSUpArrowFunctionKey) && key <= char16_t(NSModeSwitchFunctionKey)) {
if (auto qtKey = functionKeys.value(key.unicode())) {
qCDebug(lcQpaKeyMapperKeys) << "Got" << qtKey;
@@ -257,6 +226,20 @@ static int toKeyCode(const QChar &key, int virtualKey, int modifiers)
}
}
+ if (key.isDigit()) {
+ qCDebug(lcQpaKeyMapperKeys, "Got digit key: %d", key.digitValue());
+ return key.digitValue() + Qt::Key_0;
+ }
+
+ if (key.isLetter()) {
+ qCDebug(lcQpaKeyMapperKeys, "Got letter key: %d", (key.toUpper().unicode() - 'A'));
+ return (key.toUpper().unicode() - 'A') + Qt::Key_A;
+ }
+ if (key.isSymbol()) {
+ qCDebug(lcQpaKeyMapperKeys, "Got symbol key: %d", (key.unicode()));
+ return key.unicode();
+ }
+
qCDebug(lcQpaKeyMapperKeys, "Unknown case.. %d[%d] %d", key.unicode(), key.toLatin1(), virtualKey);
return Qt::Key_unknown;
}
diff --git a/src/gui/text/qtextdocumentfragment.cpp b/src/gui/text/qtextdocumentfragment.cpp
index 1b6e76c2017..5797d1a68b4 100644
--- a/src/gui/text/qtextdocumentfragment.cpp
+++ b/src/gui/text/qtextdocumentfragment.cpp
@@ -16,6 +16,7 @@
#include <qbytearray.h>
#include <qdatastream.h>
#include <qdatetime.h>
+#include <QtCore/private/qstringiterator_p.h>
QT_BEGIN_NAMESPACE
@@ -582,8 +583,11 @@ bool QTextHtmlImporter::appendNodeText()
QString textToInsert;
textToInsert.reserve(text.size());
- for (QChar ch : text) {
- if (ch.isSpace()
+ QStringIterator it(text);
+ while (it.hasNext()) {
+ char32_t ch = it.next();
+
+ if (QChar::isSpace(ch)
&& ch != QChar::Nbsp
&& ch != QChar::ParagraphSeparator) {
@@ -646,12 +650,12 @@ bool QTextHtmlImporter::appendNodeText()
format.setAnchor(true);
format.setAnchorNames(namedAnchors);
- cursor.insertText(ch, format);
+ cursor.insertText(QString::fromUcs4(&ch, 1), format);
namedAnchors.clear();
format.clearProperty(QTextFormat::IsAnchor);
format.clearProperty(QTextFormat::AnchorName);
} else {
- textToInsert += ch;
+ textToInsert += QChar::fromUcs4(ch);
}
}
}
diff --git a/src/gui/text/qtextformat.cpp b/src/gui/text/qtextformat.cpp
index 53a984306c6..d722bceb289 100644
--- a/src/gui/text/qtextformat.cpp
+++ b/src/gui/text/qtextformat.cpp
@@ -657,8 +657,8 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QTextTableCellFormat &
\value FontStyleName
\value FontPointSize
\value FontPixelSize
- \value FontSizeAdjustment Specifies the change in size given to the fontsize already set using
- FontPointSize or FontPixelSize.
+ \value FontSizeAdjustment Specifies an integer adjustment added to the base font size set using
+ \c FontPointSize or \c FontPixelSize.
\value FontFixedPitch
\omitvalue FontSizeIncrement
\value FontWeight
diff --git a/src/gui/util/qundostack.cpp b/src/gui/util/qundostack.cpp
index 3d1d8a2b788..27b131cd733 100644
--- a/src/gui/util/qundostack.cpp
+++ b/src/gui/util/qundostack.cpp
@@ -425,16 +425,16 @@ void QUndoStackPrivate::setIndex(int idx, bool clean)
emit q->indexChanged(index);
}
- const ActionState newUndoState{q->canUndo(), q->undoText()};
- if (indexChanged || newUndoState != undoActionState) {
- undoActionState = newUndoState;
+ if (ActionState newUndoState{q->canUndo(), q->undoText()};
+ indexChanged || newUndoState != undoActionState) {
+ undoActionState = std::move(newUndoState);
emit q->canUndoChanged(undoActionState.enabled);
emit q->undoTextChanged(undoActionState.text);
}
- const ActionState newRedoState{q->canRedo(), q->redoText()};
- if (indexChanged || newRedoState != redoActionState) {
- redoActionState = newRedoState;
+ if (ActionState newRedoState{q->canRedo(), q->redoText()};
+ indexChanged || newRedoState != redoActionState) {
+ redoActionState = std::move(newRedoState);
emit q->canRedoChanged(redoActionState.enabled);
emit q->redoTextChanged(redoActionState.text);
}
diff --git a/src/gui/util/qundostack_p.h b/src/gui/util/qundostack_p.h
index fea201ce62d..6bdcf5fb20b 100644
--- a/src/gui/util/qundostack_p.h
+++ b/src/gui/util/qundostack_p.h
@@ -59,10 +59,17 @@ public:
bool enabled = false;
QString text;
- bool operator!=(const ActionState &other) const noexcept
- {
- return enabled != other.enabled || text != other.text;
- }
+ friend bool operator==(const ActionState &lhs, const ActionState &rhs) noexcept
+#ifdef __cpp_impl_three_way_comparison
+ = default;
+#else
+ { return lhs.enabled == rhs.enabled && lhs.text == rhs.text; }
+ friend bool operator!=(const ActionState &lhs, const ActionState &rhs) noexcept
+ { return !(lhs == rhs); }
+#endif
+ // some compiler's reject seed = 0) = delete, overload instead:
+ friend void qHash(const ActionState &key, size_t seed) = delete;
+ friend void qHash(const ActionState &key) = delete;
};
QList<QUndoCommand*> command_list;
diff --git a/src/network/kernel/qhostaddress.cpp b/src/network/kernel/qhostaddress.cpp
index ec67ee80a1e..82632110d32 100644
--- a/src/network/kernel/qhostaddress.cpp
+++ b/src/network/kernel/qhostaddress.cpp
@@ -140,13 +140,6 @@ bool QHostAddressPrivate::parse(const QString &ipString)
return false;
}
-void QHostAddressPrivate::clear()
-{
- a = 0;
- protocol = QHostAddress::UnknownNetworkLayerProtocol;
- memset(&a6, 0, sizeof(a6));
-}
-
AddressClassification QHostAddressPrivate::classify() const
{
if (a) {
diff --git a/src/network/kernel/qhostaddress_p.h b/src/network/kernel/qhostaddress_p.h
index 6cc28cd5a9b..608080e9ede 100644
--- a/src/network/kernel/qhostaddress_p.h
+++ b/src/network/kernel/qhostaddress_p.h
@@ -74,7 +74,13 @@ public:
void setAddress(const Q_IPV6ADDR &a_);
bool parse(const QString &ipString);
- void clear();
+ void clear()
+ {
+ a6 = {};
+ a = 0;
+ protocol = QHostAddress::UnknownNetworkLayerProtocol;
+ scopeId.clear();
+ }
QString scopeId;
diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp
index bcd9aecdea9..430197ccc6e 100644
--- a/src/network/socket/qnativesocketengine_unix.cpp
+++ b/src/network/socket/qnativesocketengine_unix.cpp
@@ -33,7 +33,7 @@
#include <sys/socket.h>
#include <netinet/sctp.h>
#endif
-#ifdef Q_OS_BSD4
+#ifdef AF_LINK
# include <net/if_dl.h>
#endif
@@ -142,10 +142,6 @@ static void convertToLevelAndOption(QNativeSocketEngine::SocketOption opt,
level = IPPROTO_IP;
#ifdef IP_PKTINFO
n = IP_PKTINFO;
-#elif defined(IP_RECVDSTADDR)
- // variant found in QNX and FreeBSD; it will get us only the
- // destination address, not the interface; we need IP_RECVIF for that.
- n = IP_RECVDSTADDR;
#endif
}
break;
@@ -326,6 +322,11 @@ int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) co
*/
bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt, int v)
{
+#ifdef QNATIVESOCKETENGINE_DEBUG
+# define perrorDebug(msg) perror("QNativeSocketEnginePrivate::setOption(): " msg)
+#else
+# define perrorDebug(msg) (void)0
+#endif
Q_Q(QNativeSocketEngine);
if (!q->isValid())
return false;
@@ -337,25 +338,16 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt
#if !defined(Q_OS_VXWORKS)
int flags = ::fcntl(socketDescriptor, F_GETFL, 0);
if (flags == -1) {
-#ifdef QNATIVESOCKETENGINE_DEBUG
- perror("QNativeSocketEnginePrivate::setOption(): fcntl(F_GETFL) failed");
-#endif
+ perrorDebug("fcntl(F_GETFL) failed");
return false;
}
if (::fcntl(socketDescriptor, F_SETFL, flags | O_NONBLOCK) == -1) {
-#ifdef QNATIVESOCKETENGINE_DEBUG
- perror("QNativeSocketEnginePrivate::setOption(): fcntl(F_SETFL) failed");
-#endif
+ perrorDebug("fcntl(F_SETFL) failed");
return false;
}
#else // Q_OS_VXWORKS
- int onoff = 1;
-
- if (qt_safe_ioctl(socketDescriptor, FIONBIO, &onoff) < 0) {
-
-#ifdef QNATIVESOCKETENGINE_DEBUG
- perror("QNativeSocketEnginePrivate::setOption(): ioctl(FIONBIO, 1) failed");
-#endif
+ if (qt_safe_ioctl(socketDescriptor, FIONBIO, &v) < 0) {
+ perrorDebug("ioctl(FIONBIO, 1) failed");
return false;
}
#endif // Q_OS_VXWORKS
@@ -364,6 +356,18 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt
case QNativeSocketEngine::BindExclusively:
return true;
+ case QNativeSocketEngine::ReceivePacketInformation:
+ if (socketProtocol == QAbstractSocket::IPv4Protocol) {
+#if !defined(IP_PKTINFO) && defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
+ // Seen on FreeBSD and QNX. We need both to get the information we want.
+ int r = 0;
+ r += ::setsockopt(socketDescriptor, IPPROTO_IP, IP_RECVDSTADDR, &v, sizeof(v));
+ r += ::setsockopt(socketDescriptor, IPPROTO_IP, IP_RECVIF, &v, sizeof(v));
+ return r == 0;
+#endif
+ }
+ break;
+
case QNativeSocketEngine::MaxStreamsSocketOption: {
#ifndef QT_NO_SCTP
sctp_initmsg sctpInitMsg;
@@ -417,6 +421,7 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt
if (n == -1)
return false;
return ::setsockopt(socketDescriptor, level, n, (char *) &v, sizeof(v)) == 0;
+#undef perrorDebug
}
bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16 port)
@@ -918,7 +923,7 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxS
{
// we use quintptr to force the alignment
quintptr cbuf[(CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int))
-#if !defined(IP_PKTINFO) && defined(IP_RECVIF) && defined(Q_OS_BSD4)
+#if !defined(IP_PKTINFO) && defined(IP_RECVIF) && defined(AF_LINK)
+ CMSG_SPACE(sizeof(sockaddr_dl))
#endif
#ifndef QT_NO_SCTP
@@ -1010,7 +1015,7 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxS
header->destinationAddress.setAddress(ntohl(addr->s_addr));
}
# endif
-# if defined(IP_RECVIF) && defined(Q_OS_BSD4)
+# if defined(IP_RECVIF) && defined(AF_LINK)
if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_RECVIF
&& cmsgptr->cmsg_len >= CMSG_LEN(sizeof(sockaddr_dl))) {
sockaddr_dl *sdl = reinterpret_cast<sockaddr_dl *>(CMSG_DATA(cmsgptr));
diff --git a/src/plugins/platforms/android/androidjniaccessibility.cpp b/src/plugins/platforms/android/androidjniaccessibility.cpp
index 028ae6d682a..6154f4121d2 100644
--- a/src/plugins/platforms/android/androidjniaccessibility.cpp
+++ b/src/plugins/platforms/android/androidjniaccessibility.cpp
@@ -726,9 +726,18 @@ namespace QtAndroidAccessibility
break;
}
+ float min = info.minValue.toFloat();
+ float max = info.maxValue.toFloat();
+ float current = info.currentValue.toFloat();
+ if (info.role == QAccessible::ProgressBar) {
+ rangeType = 2; // RANGE_TYPE_PERCENT
+ current = 100 * (current - min) / (max - min);
+ min = 0.0f;
+ max = 100.0f;
+ }
+
QJniObject rangeInfo("android/view/accessibility/AccessibilityNodeInfo$RangeInfo",
- "(IFFF)V", rangeType, info.minValue.toFloat(),
- info.maxValue.toFloat(), info.currentValue.toFloat());
+ "(IFFF)V", rangeType, min, max, current);
if (rangeInfo.isValid()) {
env->CallVoidMethod(node, m_setRangeInfoMethodID, rangeInfo.object());
diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp
index c8555cdc659..f64742ff133 100644
--- a/src/plugins/platforms/android/qandroidplatformscreen.cpp
+++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp
@@ -291,7 +291,7 @@ void QAndroidPlatformScreen::topVisibleWindowChanged()
if (w && w->handle()) {
QAndroidPlatformWindow *platformWindow = static_cast<QAndroidPlatformWindow *>(w->handle());
if (platformWindow) {
- platformWindow->updateSystemUiVisibility();
+ platformWindow->updateSystemUiVisibility(w->windowStates(), w->flags());
platformWindow->updateFocusedEditText();
}
}
diff --git a/src/plugins/platforms/android/qandroidplatformwindow.cpp b/src/plugins/platforms/android/qandroidplatformwindow.cpp
index 96c4bfa06f1..c4245998772 100644
--- a/src/plugins/platforms/android/qandroidplatformwindow.cpp
+++ b/src/plugins/platforms/android/qandroidplatformwindow.cpp
@@ -56,15 +56,12 @@ void QAndroidPlatformWindow::initialize()
isForeignWindow(), m_nativeParentQtWindow, listener);
m_nativeViewId = m_nativeQtWindow.callMethod<jint>("getId");
- m_windowFlags = Qt::Widget;
- m_windowState = Qt::WindowNoState;
// the surfaceType is overwritten in QAndroidPlatformOpenGLWindow ctor so let's save
// the fact that it's a raster window for now
m_isRaster = window->surfaceType() == QSurface::RasterSurface;
- setWindowState(window->windowStates());
// the following is in relation to the virtual geometry
- const bool forceMaximize = m_windowState & (Qt::WindowMaximized | Qt::WindowFullScreen);
+ const bool forceMaximize = window->windowStates() & (Qt::WindowMaximized | Qt::WindowFullScreen);
const QRect nativeScreenGeometry = platformScreen()->availableGeometry();
if (forceMaximize) {
setGeometry(nativeScreenGeometry);
@@ -123,7 +120,7 @@ void QAndroidPlatformWindow::raise()
QWindowSystemInterface::handleFocusWindowChanged(window(), Qt::ActiveWindowFocusReason);
return;
}
- updateSystemUiVisibility();
+ updateSystemUiVisibility(window()->windowStates(), window()->flags());
platformScreen()->raise(this);
}
@@ -167,13 +164,13 @@ void QAndroidPlatformWindow::setVisible(bool visible)
if (!visible && window() == qGuiApp->focusWindow()) {
platformScreen()->topVisibleWindowChanged();
} else {
- updateSystemUiVisibility();
- if ((m_windowState & Qt::WindowFullScreen)
- || (window()->flags() & Qt::ExpandedClientAreaHint)) {
+ const Qt::WindowStates states = window()->windowStates();
+ const Qt::WindowFlags flags = window()->flags();
+ updateSystemUiVisibility(states, flags);
+ if (states & Qt::WindowFullScreen || flags & Qt::ExpandedClientAreaHint)
setGeometry(platformScreen()->geometry());
- } else if (m_windowState & Qt::WindowMaximized) {
+ else if (states & Qt::WindowMaximized)
setGeometry(platformScreen()->availableGeometry());
- }
requestActivateWindow();
}
}
@@ -188,27 +185,18 @@ void QAndroidPlatformWindow::setVisible(bool visible)
void QAndroidPlatformWindow::setWindowState(Qt::WindowStates state)
{
- if (m_windowState == state)
- return;
-
QPlatformWindow::setWindowState(state);
- m_windowState = state;
if (window()->isVisible())
- updateSystemUiVisibility();
+ updateSystemUiVisibility(state, window()->flags());
}
void QAndroidPlatformWindow::setWindowFlags(Qt::WindowFlags flags)
{
- if (m_windowFlags == flags)
- return;
+ QPlatformWindow::setWindowFlags(flags);
- m_windowFlags = flags;
-}
-
-Qt::WindowFlags QAndroidPlatformWindow::windowFlags() const
-{
- return m_windowFlags;
+ if (window()->isVisible())
+ updateSystemUiVisibility(window()->windowStates(), flags);
}
void QAndroidPlatformWindow::setParent(const QPlatformWindow *window)
@@ -256,16 +244,15 @@ void QAndroidPlatformWindow::requestActivateWindow()
raise();
}
-void QAndroidPlatformWindow::updateSystemUiVisibility()
+void QAndroidPlatformWindow::updateSystemUiVisibility(Qt::WindowStates states, Qt::WindowFlags flags)
{
- const int flags = window()->flags();
const bool isNonRegularWindow = flags & (Qt::Popup | Qt::Dialog | Qt::Sheet) & ~Qt::Window;
if (!isNonRegularWindow) {
auto iface = qGuiApp->nativeInterface<QNativeInterface::QAndroidApplication>();
iface->runOnAndroidMainThread([=]() {
using namespace QtJniTypes;
auto activity = iface->context().object<Activity>();
- if (m_windowState & Qt::WindowFullScreen)
+ if (states & Qt::WindowFullScreen)
QtWindowInsetsController::callStaticMethod("showFullScreen", activity);
else if (flags & Qt::ExpandedClientAreaHint)
QtWindowInsetsController::callStaticMethod("showExpanded", activity);
diff --git a/src/plugins/platforms/android/qandroidplatformwindow.h b/src/plugins/platforms/android/qandroidplatformwindow.h
index 07f4e12b35c..826a8d30ade 100644
--- a/src/plugins/platforms/android/qandroidplatformwindow.h
+++ b/src/plugins/platforms/android/qandroidplatformwindow.h
@@ -43,7 +43,6 @@ public:
void setWindowState(Qt::WindowStates state) override;
void setWindowFlags(Qt::WindowFlags flags) override;
- Qt::WindowFlags windowFlags() const;
void setParent(const QPlatformWindow *window) override;
WId winId() const override;
@@ -58,7 +57,7 @@ public:
void propagateSizeHints() override;
void requestActivateWindow() override;
- void updateSystemUiVisibility();
+ void updateSystemUiVisibility(Qt::WindowStates states, Qt::WindowFlags flags);
void updateFocusedEditText();
inline bool isRaster() const { return m_isRaster; }
bool isExposed() const override;
@@ -82,8 +81,6 @@ protected:
bool isEmbeddingContainer() const;
virtual void clearSurface() {}
- Qt::WindowFlags m_windowFlags;
- Qt::WindowStates m_windowState;
bool m_isRaster;
int m_nativeViewId = -1;
diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
index d4c5d0f0425..e0ef6cec794 100644
--- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
+++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
@@ -161,7 +161,8 @@ typedef QSharedPointer<QFileDialogOptions> SharedPointerFileDialogOptions;
bool selectable = (m_options->acceptMode() == QFileDialogOptions::AcceptSave)
|| [self panel:m_panel shouldEnableURL:url];
- m_panel.nameFieldStringValue = selectable ? info.fileName().toNSString() : @"";
+ if (!openpanel_cast(m_panel))
+ m_panel.nameFieldStringValue = selectable ? info.fileName().toNSString() : @"";
[self updateProperties];
diff --git a/src/plugins/platforms/cocoa/qnsview_keys.mm b/src/plugins/platforms/cocoa/qnsview_keys.mm
index aab01a7b439..e9ef769ec4b 100644
--- a/src/plugins/platforms/cocoa/qnsview_keys.mm
+++ b/src/plugins/platforms/cocoa/qnsview_keys.mm
@@ -114,6 +114,9 @@ static bool sendAsShortcut(const KeyEvent &keyEvent, QWindow *window)
qCDebug(lcQpaKeys) << "Interpreting key event for focus object" << focusObject;
m_currentlyInterpretedKeyEvent = nsevent;
+ // Asking the input context to handle the event will involve both
+ // the current input method, as well as NSKeyBindingManager, which
+ // may result in action callbacks to doCommandBySelector.
if (![self.inputContext handleEvent:nsevent]) {
qCDebug(lcQpaKeys) << "Input context did not consume event";
m_sendKeyEvent = true;
diff --git a/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosimagepickercontroller.h b/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosimagepickercontroller.h
index 60b9bc8fc02..8fdcf88293e 100644
--- a/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosimagepickercontroller.h
+++ b/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosimagepickercontroller.h
@@ -2,6 +2,9 @@
// 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 QIOSIMAGEPICKERCONTROLLER_H
+#define QIOSIMAGEPICKERCONTROLLER_H
+
#import <UIKit/UIKit.h>
#include "../../qiosfiledialog.h"
@@ -9,3 +12,5 @@
@interface QIOSImagePickerController : UIImagePickerController <UIImagePickerControllerDelegate, UINavigationControllerDelegate>
- (instancetype)initWithQIOSFileDialog:(QIOSFileDialog *)fileDialog;
@end
+
+#endif // QIOSIMAGEPICKERCONTROLLER_H
diff --git a/src/plugins/platforms/ios/qiosdocumentpickercontroller.h b/src/plugins/platforms/ios/qiosdocumentpickercontroller.h
index 289c3ee3258..a227312c5b0 100644
--- a/src/plugins/platforms/ios/qiosdocumentpickercontroller.h
+++ b/src/plugins/platforms/ios/qiosdocumentpickercontroller.h
@@ -2,6 +2,9 @@
// 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 QIOSDOCUMENTPICKERCONTROLLER_H
+#define QIOSDOCUMENTPICKERCONTROLLER_H
+
#import <UIKit/UIKit.h>
#import <UniformTypeIdentifiers/UniformTypeIdentifiers.h>
@@ -12,3 +15,5 @@
UIAdaptivePresentationControllerDelegate>
- (instancetype)initWithQIOSFileDialog:(QIOSFileDialog *)fileDialog;
@end
+
+#endif // QIOSDOCUMENTPICKERCONTROLLER_H
diff --git a/src/plugins/platforms/ios/qiosdocumentpickercontroller.mm b/src/plugins/platforms/ios/qiosdocumentpickercontroller.mm
index 4e019b69cc4..6ca6554f673 100644
--- a/src/plugins/platforms/ios/qiosdocumentpickercontroller.mm
+++ b/src/plugins/platforms/ios/qiosdocumentpickercontroller.mm
@@ -7,8 +7,10 @@
#include "qiosdocumentpickercontroller.h"
+#include <QtCore/qpointer.h>
+
@implementation QIOSDocumentPickerController {
- QIOSFileDialog *m_fileDialog;
+ QPointer<QIOSFileDialog> m_fileDialog;
}
- (instancetype)initWithQIOSFileDialog:(QIOSFileDialog *)fileDialog
@@ -61,6 +63,9 @@
{
Q_UNUSED(controller);
+ if (!m_fileDialog)
+ return;
+
QList<QUrl> files;
for (NSURL* url in urls)
files.append(QUrl::fromNSURL(url));
@@ -71,12 +76,18 @@
- (void)documentPickerWasCancelled:(UIDocumentPickerViewController *)controller
{
+ if (!m_fileDialog)
+ return;
+
Q_UNUSED(controller);
emit m_fileDialog->reject();
}
- (void)presentationControllerDidDismiss:(UIPresentationController *)presentationController
{
+ if (!m_fileDialog)
+ return;
+
Q_UNUSED(presentationController);
// "Called on the delegate when the user has taken action to dismiss the
diff --git a/src/plugins/platforms/ios/qiostextresponder.h b/src/plugins/platforms/ios/qiostextresponder.h
index addfae3d748..7d73ed9821a 100644
--- a/src/plugins/platforms/ios/qiostextresponder.h
+++ b/src/plugins/platforms/ios/qiostextresponder.h
@@ -2,6 +2,9 @@
// 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 QIOSTEXTRESPONDER_H
+#define QIOSTEXTRESPONDER_H
+
#import <UIKit/UIKit.h>
#include <QtCore/qstring.h>
@@ -50,3 +53,5 @@ QT_END_NAMESPACE
@property(nonatomic, assign) id<UITextInputDelegate> inputDelegate;
@end
+
+#endif // QIOSTEXTRESPONDER_H
diff --git a/src/plugins/platforms/ios/quiview.h b/src/plugins/platforms/ios/quiview.h
index 84726216021..12ae3646ad9 100644
--- a/src/plugins/platforms/ios/quiview.h
+++ b/src/plugins/platforms/ios/quiview.h
@@ -2,6 +2,9 @@
// 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 QUIVIEW_H
+#define QUIVIEW_H
+
#import <UIKit/UIKit.h>
#include <qhash.h>
@@ -39,3 +42,5 @@ QT_END_NAMESPACE
@interface QUIMetalView : QUIView
@end
#endif
+
+#endif // QUIVIEW_H
diff --git a/src/plugins/platforms/wasm/qwasmaccessibility.cpp b/src/plugins/platforms/wasm/qwasmaccessibility.cpp
index 35e804531bc..5fa79482217 100644
--- a/src/plugins/platforms/wasm/qwasmaccessibility.cpp
+++ b/src/plugins/platforms/wasm/qwasmaccessibility.cpp
@@ -323,8 +323,9 @@ void QWasmAccessibility::setProperty(emscripten::val element, const std::string
}
-void QWasmAccessibility::addEventListener(emscripten::val element, const char *eventType)
+void QWasmAccessibility::addEventListener(QAccessibleInterface *iface, emscripten::val element, const char *eventType)
{
+ element.set("data-qta11yinterface", reinterpret_cast<size_t>(iface));
element.call<void>("addEventListener", emscripten::val(eventType),
QWasmSuspendResumeControl::get()->jsEventHandlerAt(m_eventHandlerIndex),
true);
@@ -352,7 +353,7 @@ emscripten::val QWasmAccessibility::createHtmlElement(QAccessibleInterface *ifac
case QAccessible::Button: {
element = document.call<emscripten::val>("createElement", std::string("button"));
- addEventListener(element, "click");
+ addEventListener(iface, element, "click");
} break;
case QAccessible::CheckBox: {
@@ -360,7 +361,7 @@ emscripten::val QWasmAccessibility::createHtmlElement(QAccessibleInterface *ifac
setAttribute(element, "type", "checkbox");
setAttribute(element, "checked", iface->state().checked);
setProperty(element, "indeterminate", iface->state().checkStateMixed);
- addEventListener(element, "change");
+ addEventListener(iface, element, "change");
} break;
case QAccessible::Switch: {
@@ -371,7 +372,7 @@ emscripten::val QWasmAccessibility::createHtmlElement(QAccessibleInterface *ifac
setAttribute(element, "aria-checked", "true");
else
setAttribute(element, "aria-checked", "false");
- addEventListener(element, "change");
+ addEventListener(iface, element, "change");
} break;
case QAccessible::RadioButton: {
@@ -379,7 +380,7 @@ emscripten::val QWasmAccessibility::createHtmlElement(QAccessibleInterface *ifac
setAttribute(element, "type", "radio");
setAttribute(element, "checked", iface->state().checked);
setProperty(element, "name", "buttonGroup");
- addEventListener(element, "change");
+ addEventListener(iface, element, "change");
} break;
case QAccessible::SpinBox:
@@ -413,7 +414,7 @@ emscripten::val QWasmAccessibility::createHtmlElement(QAccessibleInterface *ifac
element = document.call<emscripten::val>("createElement", std::string("button"));
setAttribute(element, "role", "tab");
setAttribute(element, "title", text.toStdString());
- addEventListener(element, "click");
+ addEventListener(iface, element, "click");
} break;
case QAccessible::ScrollBar: {
@@ -422,7 +423,7 @@ emscripten::val QWasmAccessibility::createHtmlElement(QAccessibleInterface *ifac
element = document.call<emscripten::val>("createElement", std::string("div"));
setAttribute(element, "role", "scrollbar");
setAttribute(element, "aria-valuenow", valueString);
- addEventListener(element, "change");
+ addEventListener(iface, element, "change");
} break;
case QAccessible::StaticText: {
@@ -436,7 +437,7 @@ emscripten::val QWasmAccessibility::createHtmlElement(QAccessibleInterface *ifac
element = document.call<emscripten::val>("createElement", std::string("div"));
setAttribute(element, "role", "toolbar");
setAttribute(element, "title", text.toStdString());
- addEventListener(element, "click");
+ addEventListener(iface, element, "click");
}break;
case QAccessible::MenuItem:
case QAccessible::ButtonMenu: {
@@ -444,7 +445,7 @@ emscripten::val QWasmAccessibility::createHtmlElement(QAccessibleInterface *ifac
element = document.call<emscripten::val>("createElement", std::string("button"));
setAttribute(element, "role", "menuitem");
setAttribute(element, "title", text.toStdString());
- addEventListener(element, "click");
+ addEventListener(iface, element, "click");
}break;
case QAccessible::MenuBar:
case QAccessible::PopupMenu: {
@@ -471,7 +472,7 @@ emscripten::val QWasmAccessibility::createHtmlElement(QAccessibleInterface *ifac
element = document.call<emscripten::val>("createElement", std::string("div"));
}
- addEventListener(element, "focus");
+ addEventListener(iface, element, "focus");
return element;
}();
@@ -542,6 +543,7 @@ void QWasmAccessibility::linkToParent(QAccessibleInterface *iface)
{
emscripten::val element = getHtmlElement(iface);
emscripten::val container = getElementContainer(iface);
+
if (container.isUndefined() || element.isUndefined())
return;
@@ -554,21 +556,21 @@ void QWasmAccessibility::linkToParent(QAccessibleInterface *iface)
emscripten::val next = emscripten::val::undefined();
const int thisIndex = iface->parent()->indexOfChild(iface);
- Q_ASSERT(thisIndex >= 0 && thisIndex < iface->parent()->childCount());
- for (int i = thisIndex + 1; i < iface->parent()->childCount(); ++i) {
- const auto elementI = getHtmlElement(iface->parent()->child(i));
- if (!elementI.isUndefined() &&
- elementI["parentElement"] == container) {
- next = elementI;
- break;
+ if (thisIndex >= 0) {
+ Q_ASSERT(thisIndex < iface->parent()->childCount());
+ for (int i = thisIndex + 1; i < iface->parent()->childCount(); ++i) {
+ const auto elementI = getHtmlElement(iface->parent()->child(i));
+ if (!elementI.isUndefined() &&
+ elementI["parentElement"] == container) {
+ next = elementI;
+ break;
+ }
}
+ if (next.isUndefined())
+ container.call<void>("appendChild", element);
+ else
+ container.call<void>("insertBefore", element, next);
}
- if (next.isUndefined()) {
- container.call<void>("appendChild", element);
- } else {
- container.call<void>("insertBefore", element, next);
- }
-
const auto activeElementAfter = emscripten::val::take_ownership(
getActiveElement_js(emscripten::val::undefined().as_handle()));
if (activeElementBefore != activeElementAfter) {
@@ -712,22 +714,26 @@ void QWasmAccessibility::handleLineEditUpdate(QAccessibleEvent *event)
void QWasmAccessibility::handleEventFromHtmlElement(const emscripten::val event)
{
- QAccessibleInterface *iface = m_elements.key(event["target"]);
+ if (event["target"].isNull() || event["target"].isUndefined())
+ return;
- if (iface == nullptr) {
+ if (event["target"]["data-qta11yinterface"].isNull() || event["target"]["data-qta11yinterface"].isUndefined())
return;
- } else {
- QString eventType = QString::fromStdString(event["type"].as<std::string>());
- const auto& actionNames = QAccessibleBridgeUtils::effectiveActionNames(iface);
-
- if (eventType == "focus") {
- if (actionNames.contains(QAccessibleActionInterface::setFocusAction()))
- iface->actionInterface()->doAction(QAccessibleActionInterface::setFocusAction());
- } else if (actionNames.contains(QAccessibleActionInterface::pressAction())) {
- iface->actionInterface()->doAction(QAccessibleActionInterface::pressAction());
- } else if (actionNames.contains(QAccessibleActionInterface::toggleAction())) {
- iface->actionInterface()->doAction(QAccessibleActionInterface::toggleAction());
- }
+
+ auto iface = reinterpret_cast<QAccessibleInterface *>(event["target"]["data-qta11yinterface"].as<size_t>());
+ if (m_elements.find(iface) == m_elements.end())
+ return;
+
+ const QString eventType = QString::fromStdString(event["type"].as<std::string>());
+ const auto& actionNames = QAccessibleBridgeUtils::effectiveActionNames(iface);
+
+ if (eventType == "focus") {
+ if (actionNames.contains(QAccessibleActionInterface::setFocusAction()))
+ iface->actionInterface()->doAction(QAccessibleActionInterface::setFocusAction());
+ } else if (actionNames.contains(QAccessibleActionInterface::pressAction())) {
+ iface->actionInterface()->doAction(QAccessibleActionInterface::pressAction());
+ } else if (actionNames.contains(QAccessibleActionInterface::toggleAction())) {
+ iface->actionInterface()->doAction(QAccessibleActionInterface::toggleAction());
}
}
diff --git a/src/plugins/platforms/wasm/qwasmaccessibility.h b/src/plugins/platforms/wasm/qwasmaccessibility.h
index 2b4716d64e7..26f3e0e9afe 100644
--- a/src/plugins/platforms/wasm/qwasmaccessibility.h
+++ b/src/plugins/platforms/wasm/qwasmaccessibility.h
@@ -116,7 +116,7 @@ private:
void setProperty(emscripten::val element, const std::string &attr, const char *val);
void setProperty(emscripten::val element, const std::string &attr, bool val);
- void addEventListener(emscripten::val element, const char *eventType);
+ void addEventListener(QAccessibleInterface *, emscripten::val element, const char *eventType);
private:
static QWasmAccessibility *s_instance;
diff --git a/src/plugins/platforms/wasm/qwasminputcontext.cpp b/src/plugins/platforms/wasm/qwasminputcontext.cpp
index 614d5bd25a3..18a457198f1 100644
--- a/src/plugins/platforms/wasm/qwasminputcontext.cpp
+++ b/src/plugins/platforms/wasm/qwasminputcontext.cpp
@@ -225,8 +225,8 @@ void QWasmInputContext::updateGeometry()
qCDebug(qLcQpaWasmInputContext) << Q_FUNC_INFO << "propagating inputItemRectangle:" << inputItemRectangle;
m_inputElement["style"].set("left", std::to_string(inputItemRectangle.x()) + "px");
m_inputElement["style"].set("top", std::to_string(inputItemRectangle.y()) + "px");
- m_inputElement["style"].set("width", std::to_string(inputItemRectangle.width()) + "px");
- m_inputElement["style"].set("height", std::to_string(inputItemRectangle.height()) + "px");
+ m_inputElement["style"].set("width", "1px");
+ m_inputElement["style"].set("height", "1px");
}
}
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 82a86d6ff3a..01716fba60c 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -4019,9 +4019,11 @@ void QWindowsWindow::requestUpdate()
// request or we are waiting for the event loop to process
// the Posted event on the GUI thread.
if (m_vsyncUpdatePending.testAndSetAcquire(UpdateState::Requested, UpdateState::Posted)) {
- QMetaObject::invokeMethod(w, [w] {
+ QWindowsWindow *oldSelf = this;
+ QMetaObject::invokeMethod(w, [w, oldSelf] {
+ // 'oldSelf' is only used for comparison, don't access it directly!
auto *self = static_cast<QWindowsWindow *>(w->handle());
- if (self) {
+ if (self && self == oldSelf) {
// The platform window is still alive
self->m_vsyncUpdatePending.storeRelease(UpdateState::Ready);
self->deliverUpdateRequest();
diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm
index 5ba6f3e1649..0b05a31ca5c 100644
--- a/src/plugins/styles/mac/qmacstyle_mac.mm
+++ b/src/plugins/styles/mac/qmacstyle_mac.mm
@@ -5849,6 +5849,9 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
const auto aquaSize = d->effectiveAquaSizeConstrain(opt, widget);
const auto cw = QMacStylePrivate::CocoaControl(QMacStylePrivate::Stepper, aquaSize);
NSStepperCell *cell = static_cast<NSStepperCell *>(d->cocoaCell(cw));
+ const auto controlSize = cell.controlSize;
+ if (qt_apple_runningWithLiquidGlass())
+ cell.controlSize = NSControlSizeMini;
cell.enabled = (sb->state & State_Enabled);
const CGRect newRect = [cell drawingRectForBounds:updown.toCGRect()];
@@ -5869,6 +5872,8 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
[cell stopTracking:pressPoint at:pressPoint inView:d->backingStoreNSView mouseIsUp:NO];
d->restoreNSGraphicsContext(cg);
+ if (qt_apple_runningWithLiquidGlass())
+ cell.controlSize = controlSize;
}
}
break;
diff --git a/src/plugins/styles/modernwindows/qwindows11style.cpp b/src/plugins/styles/modernwindows/qwindows11style.cpp
index 28b12bd81f9..3b1b7a7eacb 100644
--- a/src/plugins/styles/modernwindows/qwindows11style.cpp
+++ b/src/plugins/styles/modernwindows/qwindows11style.cpp
@@ -923,15 +923,13 @@ void QWindows11Style::drawPrimitive(PrimitiveElement element, const QStyleOption
case PE_IndicatorRadioButton: {
const bool isRtl = option->direction == Qt::RightToLeft;
const bool isOn = option->state & State_On;
- qreal innerRadius = 7.0f;
+ qreal innerRadius = radioButtonInnerRadius(state);
if (d->transitionsEnabled() && option->styleObject) {
if (option->styleObject->property("_q_end_radius").isNull())
option->styleObject->setProperty("_q_end_radius", innerRadius);
QNumberStyleAnimation *animation = qobject_cast<QNumberStyleAnimation *>(d->animation(option->styleObject));
innerRadius = animation ? animation->currentValue() : option->styleObject->property("_q_end_radius").toFloat();
option->styleObject->setProperty("_q_inner_radius", innerRadius);
- } else {
- innerRadius = radioButtonInnerRadius(state);
}
QRectF rect = isRtl ? option->rect.adjusted(0, 0, -2, 0) : option->rect.adjusted(2, 0, 0, 0);
@@ -1331,11 +1329,12 @@ void QWindows11Style::drawControl(ControlElement element, const QStyleOption *op
}
}
break;
- case QStyle::CE_ProgressBarGroove:{
- if (const QStyleOptionProgressBar* progbaropt = qstyleoption_cast<const QStyleOptionProgressBar*>(option)) {
- QRect rect = subElementRect(SE_ProgressBarContents, progbaropt, widget);
+#if QT_CONFIG(progressbar)
+ case CE_ProgressBarGroove:
+ if (const auto baropt = qstyleoption_cast<const QStyleOptionProgressBar*>(option)) {
+ QRect rect = option->rect;
QPointF center = rect.center();
- if (progbaropt->state & QStyle::State_Horizontal) {
+ if (baropt->state & QStyle::State_Horizontal) {
rect.setHeight(1);
rect.moveTop(center.y());
} else {
@@ -1347,11 +1346,10 @@ void QWindows11Style::drawControl(ControlElement element, const QStyleOption *op
painter->drawRect(rect);
}
break;
- }
- case QStyle::CE_ProgressBarContents:
+ case CE_ProgressBarContents:
if (const auto baropt = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) {
QPainterStateGuard psg(painter);
- QRectF rect = subElementRect(SE_ProgressBarContents, baropt, widget);
+ QRectF rect = option->rect;
painter->translate(rect.topLeft());
rect.translate(-rect.topLeft());
@@ -1411,16 +1409,17 @@ void QWindows11Style::drawControl(ControlElement element, const QStyleOption *op
drawRoundedRect(painter, rect, Qt::NoPen, baropt->palette.accent());
}
break;
- case QStyle::CE_ProgressBarLabel:
- if (const QStyleOptionProgressBar* progbaropt = qstyleoption_cast<const QStyleOptionProgressBar*>(option)) {
- const bool vertical = !(progbaropt->state & QStyle::State_Horizontal);
+ case CE_ProgressBarLabel:
+ if (const auto baropt = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) {
+ const bool vertical = !(baropt->state & QStyle::State_Horizontal);
if (!vertical) {
- QRect rect = subElementRect(SE_ProgressBarLabel, progbaropt, widget);
- painter->setPen(progbaropt->palette.text().color());
- painter->drawText(rect, progbaropt->text, progbaropt->textAlignment);
+ proxy()->drawItemText(painter, baropt->rect, Qt::AlignCenter | Qt::TextSingleLine,
+ baropt->palette, baropt->state & State_Enabled, baropt->text,
+ QPalette::Text);
}
}
break;
+#endif // QT_CONFIG(progressbar)
case CE_PushButtonLabel:
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) {
QRect textRect = btn->rect;
@@ -1914,15 +1913,18 @@ QRect QWindows11Style::subElementRect(QStyle::SubElement element, const QStyleOp
ret = QWindowsVistaStyle::subElementRect(element, option, widget);
}
break;
- case QStyle::SE_ProgressBarLabel:
- if (const QStyleOptionProgressBar *pb = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) {
- if (pb->textAlignment.testFlags(Qt::AlignVCenter)) {
- ret = option->rect.adjusted(0, 6, 0, 0);
- } else {
- ret = QWindowsVistaStyle::subElementRect(element, option, widget);
- }
+#if QT_CONFIG(progressbar)
+ case SE_ProgressBarGroove:
+ case SE_ProgressBarContents:
+ case SE_ProgressBarLabel:
+ if (const auto *pb = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) {
+ QStyleOptionProgressBar optCopy(*pb);
+ // we only support label right from content
+ optCopy.textAlignment = Qt::AlignRight;
+ return QWindowsVistaStyle::subElementRect(element, &optCopy, widget);
}
break;
+#endif // QT_CONFIG(progressbar)
case QStyle::SE_HeaderLabel:
case QStyle::SE_HeaderArrow:
ret = QCommonStyle::subElementRect(element, option, widget);
@@ -2448,9 +2450,6 @@ void QWindows11Style::polish(QPalette& result)
SET_IF_UNRESOLVED(QPalette::Inactive, QPalette::Text, result.text().color());
SET_IF_UNRESOLVED(QPalette::Inactive, QPalette::WindowText, result.windowText().color());
- if (highContrastTheme)
- result.setColor(QPalette::Active, QPalette::HighlightedText, result.windowText().color());
-
auto *d = const_cast<QWindows11StylePrivate *>(d_func());
d->m_titleBarMinIcon = QIcon();
d->m_titleBarMaxIcon = QIcon();
diff --git a/src/plugins/tls/schannel/qtls_schannel.cpp b/src/plugins/tls/schannel/qtls_schannel.cpp
index 12c2625f39d..667f2d8a6c3 100644
--- a/src/plugins/tls/schannel/qtls_schannel.cpp
+++ b/src/plugins/tls/schannel/qtls_schannel.cpp
@@ -1238,9 +1238,10 @@ bool TlsCryptographSchannel::createContext()
};
#endif
+ const QString encodedTargetName = QUrl::fromUserInput(targetName()).host(QUrl::EncodeUnicode);
auto status = InitializeSecurityContext(&credentialHandle, // phCredential
nullptr, // phContext
- const_reinterpret_cast<SEC_WCHAR *>(targetName().utf16()), // pszTargetName
+ const_reinterpret_cast<SEC_WCHAR *>(encodedTargetName.utf16()), // pszTargetName
contextReq, // fContextReq
0, // Reserved1
0, // TargetDataRep (unused)
diff --git a/src/testinternal/QtRunCMakeTestWrappers.cmake b/src/testinternal/QtRunCMakeTestWrappers.cmake
index fdf93692e1f..cead9e52c82 100644
--- a/src/testinternal/QtRunCMakeTestWrappers.cmake
+++ b/src/testinternal/QtRunCMakeTestWrappers.cmake
@@ -30,10 +30,24 @@ function(qt_internal_add_RunCMake_test test)
string(JOIN "\n" pre_run_code ${_qt_internal_skip_build_test_pre_run})
+ set(android_code "")
+ if(ANDROID)
+ qt_internal_get_android_cmake_policy_version_minimum_value(version)
+ string(APPEND android_code "
+# Avoid cmake policy deprecation warnings with older android NDKs appearing in stderr, which
+# causes test failures if the test doesn't set
+# set(RunCMake_TEST_OUTPUT_MERGE 1)
+# to avoid stderr being polluted.
+if(NOT QT_NO_SET_RUN_CMAKE_TESTS_CMAKE_POLICY_VERSION_MINIMUM)
+ set(ENV{CMAKE_POLICY_VERSION_MINIMUM} ${version})
+endif()")
+ endif()
+
_qt_internal_configure_file(CONFIGURE
OUTPUT "${wrapper_file}"
CONTENT "
${pre_run_code}
+${android_code}
include(\"${script_path_to_include}\")
")
diff --git a/src/testlib/qtest.h b/src/testlib/qtest.h
index c749cbd492f..431f91d5474 100644
--- a/src/testlib/qtest.h
+++ b/src/testlib/qtest.h
@@ -181,29 +181,17 @@ inline bool qCompare(quint32 const &t1, quint64 const &t2, const char *actual,
}
namespace Internal {
-template <typename T>
-class HasInitMain // SFINAE test for the presence of initMain()
-{
-private:
- using YesType = char[1];
- using NoType = char[2];
-
- template <typename C> static YesType& test( decltype(&C::initMain) ) ;
- template <typename C> static NoType& test(...);
-
-public:
- enum { value = sizeof(test<T>(nullptr)) == sizeof(YesType) };
-};
+template <typename T, typename = void>
+struct HasInitMain : std::false_type{};
-template<typename T>
-typename std::enable_if<HasInitMain<T>::value, void>::type callInitMain()
-{
- T::initMain();
-}
+template <typename T>
+struct HasInitMain<T, std::void_t<decltype(&T::initMain)>> : std::true_type {};
template<typename T>
-typename std::enable_if<!HasInitMain<T>::value, void>::type callInitMain()
+void callInitMain()
{
+ if constexpr (HasInitMain<T>::value)
+ T::initMain();
}
} // namespace Internal
diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp
index 6c7e71294ed..784e69d2486 100644
--- a/src/testlib/qtestcase.cpp
+++ b/src/testlib/qtestcase.cpp
@@ -393,6 +393,7 @@ static QString mainSourcePath;
static bool inTestFunction = false;
#if defined(Q_OS_MACOS)
+static std::optional<QTestPrivate::AppNapDisabler> appNapDisabler;
static IOPMAssertionID macPowerSavingDisabled = 0;
#endif
@@ -1881,13 +1882,12 @@ void QTest::qInit(QObject *testObject, int argc, char **argv)
QTestPrivate::disableWindowRestore();
// Disable App Nap which may cause tests to stall
- QTestPrivate::AppNapDisabler appNapDisabler;
+ if (!appNapDisabler)
+ appNapDisabler.emplace();
- if (qApp && (qstrcmp(qApp->metaObject()->className(), "QApplication") == 0)) {
- IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep,
- kIOPMAssertionLevelOn, CFSTR("QtTest running tests"),
- &macPowerSavingDisabled);
- }
+ IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep,
+ kIOPMAssertionLevelOn, CFSTR("QtTest running tests"),
+ &macPowerSavingDisabled);
#endif
QTestPrivate::parseBlackList();
@@ -2041,6 +2041,7 @@ void QTest::qCleanup()
#if defined(Q_OS_MACOS)
IOPMAssertionRelease(macPowerSavingDisabled);
+ appNapDisabler = std::nullopt;
#endif
}
diff --git a/src/testlib/qtestcase.h b/src/testlib/qtestcase.h
index ebb32238d67..ad3874bd4c9 100644
--- a/src/testlib/qtestcase.h
+++ b/src/testlib/qtestcase.h
@@ -430,7 +430,7 @@ namespace QTest
Q_TESTLIB_EXPORT int qExec(QObject *testObject, const QStringList &arguments);
#if QT_CONFIG(batch_test_support) || defined(Q_QDOC)
- using TestEntryFunction = int (*)(int, char **);
+ using TestEntryFunction = std::function<int(int, char **)>;
Q_TESTLIB_EXPORT void qRegisterTestCase(const QString &name, TestEntryFunction entryFunction);
#endif // QT_CONFIG(batch_test_support)
diff --git a/src/testlib/qtestregistry_p.h b/src/testlib/qtestregistry_p.h
index 85e236cd046..fcfa6c60701 100644
--- a/src/testlib/qtestregistry_p.h
+++ b/src/testlib/qtestregistry_p.h
@@ -26,7 +26,7 @@ QT_BEGIN_NAMESPACE
namespace QTest {
class TestRegistry {
public:
- using TestEntryFunction = int(*)(int argv, char** argc);
+ using TestEntryFunction = std::function<int(int, char **)>;
static TestRegistry* instance();
diff --git a/src/tools/androidtestrunner/main.cpp b/src/tools/androidtestrunner/main.cpp
index 0e04d10e692..b517d85c5fb 100644
--- a/src/tools/androidtestrunner/main.cpp
+++ b/src/tools/androidtestrunner/main.cpp
@@ -328,6 +328,53 @@ static bool processAndroidManifest()
return true;
}
+static QStringList queryDangerousPermissions()
+{
+ QByteArray output;
+ const QStringList args({ "shell"_L1, "dumpsys"_L1, "package"_L1, "permissions"_L1 });
+ if (!execAdbCommand(args, &output, false)) {
+ qWarning("Failed to query permissions via dumpsys");
+ return {};
+ }
+
+ /*
+ * Permissions section from this command look like:
+ *
+ * Permission [android.permission.INTERNET] (c8cafdc):
+ * sourcePackage=android
+ * uid=1000 gids=[3003] type=0 prot=normal|instant
+ * perm=PermissionInfo{5f5bfbb android.permission.INTERNET}
+ * flags=0x0
+ */
+ const static QRegularExpression regex("^\\s*Permission\\s+\\[([^\\]]+)\\]\\s+\\(([^)]+)\\):"_L1);
+ QStringList dangerousPermissions;
+ QString currentPerm;
+
+ const QStringList lines = QString::fromUtf8(output).split(u'\n');
+ for (const QString &line : lines) {
+ QRegularExpressionMatch match = regex.match(line);
+ if (match.hasMatch()) {
+ currentPerm = match.captured(1);
+ continue;
+ }
+
+ if (currentPerm.isEmpty())
+ continue;
+
+ int protIndex = line.indexOf("prot="_L1);
+ if (protIndex == -1)
+ continue;
+
+ QString protectionTypes = line.mid(protIndex + 5).trimmed();
+ if (protectionTypes.contains("dangerous"_L1, Qt::CaseInsensitive)) {
+ dangerousPermissions.append(currentPerm);
+ currentPerm.clear();
+ }
+ }
+
+ return dangerousPermissions;
+}
+
static void setOutputFile(QString file, QString format)
{
if (format.isEmpty())
@@ -938,7 +985,11 @@ int main(int argc, char *argv[])
return EXIT_ERROR;
}
+ const QStringList dangerousPermisisons = queryDangerousPermissions();
for (const auto &permission : g_options.permissions) {
+ if (!dangerousPermisisons.contains(permission))
+ continue;
+
if (!execAdbCommand({ "shell"_L1, "pm"_L1, "grant"_L1, g_options.package, permission },
nullptr)) {
qWarning("Unable to grant '%s' to '%s'. Probably the Android version mismatch.",
diff --git a/src/tools/macdeployqt/macdeployqt/main.cpp b/src/tools/macdeployqt/macdeployqt/main.cpp
index f5e6ab8f31a..ecbccdef2b3 100644
--- a/src/tools/macdeployqt/macdeployqt/main.cpp
+++ b/src/tools/macdeployqt/macdeployqt/main.cpp
@@ -77,7 +77,7 @@ int main(int argc, char **argv)
QStringList qmlDirs;
QStringList qmlImportPaths;
extern bool runCodesign;
- extern QString codesignIdentiy;
+ QString codesignIdentity = QStringLiteral("-");
extern bool hardenedRuntime;
bool noCodesignExplicit = false;
extern bool appstoreCompliant;
@@ -166,7 +166,7 @@ int main(int argc, char **argv)
return 1;
} else {
runCodesign = true;
- codesignIdentiy = argument.mid(index+1);
+ codesignIdentity = argument.mid(index + 1);
}
} else if (argument.startsWith(QByteArray("-sign-for-notarization"))) {
LogDebug() << "Argument found:" << argument;
@@ -182,7 +182,7 @@ int main(int argc, char **argv)
runCodesign = true;
hardenedRuntime = true;
secureTimestamp = true;
- codesignIdentiy = argument.mid(index+1);
+ codesignIdentity = argument.mid(index + 1);
}
} else if (argument.startsWith(QByteArray("-hardened-runtime"))) {
LogDebug() << "Argument found:" << argument;
@@ -273,7 +273,7 @@ int main(int argc, char **argv)
stripAppBinary(appBundlePath);
if (runCodesign)
- codesign(codesignIdentiy, appBundlePath);
+ codesign(codesignIdentity, appBundlePath);
if (dmg) {
LogNormal();
diff --git a/src/tools/macdeployqt/shared/shared.cpp b/src/tools/macdeployqt/shared/shared.cpp
index 4e81229ebf5..bd7f4fba854 100644
--- a/src/tools/macdeployqt/shared/shared.cpp
+++ b/src/tools/macdeployqt/shared/shared.cpp
@@ -30,7 +30,6 @@ bool runStripEnabled = true;
bool alwaysOwerwriteEnabled = false;
bool runCodesign = true;
QStringList librarySearchPath;
-QString codesignIdentiy = "-";
QString extraEntitlements;
bool hardenedRuntime = false;
bool secureTimestamp = false;
diff --git a/src/widgets/doc/src/external-resources.qdoc b/src/widgets/doc/src/external-resources.qdoc
index 17459b6a5bc..96117546a29 100644
--- a/src/widgets/doc/src/external-resources.qdoc
+++ b/src/widgets/doc/src/external-resources.qdoc
@@ -8,7 +8,7 @@
*/
/*!
- \externalpage http://www.nvg.ntnu.no/sinclair/computers/zxspectrum/zxspectrum.htm
+ \externalpage https://rk.nvg.ntnu.no/sinclair/computers/zxspectrum/zxspectrum.htm
\title Sinclair Spectrum
*/
/*!
diff --git a/src/widgets/doc/src/modelview.qdoc b/src/widgets/doc/src/modelview.qdoc
index b2448a2c705..121cc30ed09 100644
--- a/src/widgets/doc/src/modelview.qdoc
+++ b/src/widgets/doc/src/modelview.qdoc
@@ -573,281 +573,10 @@
out of range when using ModelTest.
- \section1 4. Good Sources of Additional Information
-
- \section2 4.1 Books
-
- Model/View programming is covered quite extensively in the documentation of
- Qt but also in several good books.
-
- \list 1
- \li \b{C++ GUI Programming with Qt 4} / Jasmin Blanchette, Mark Summerfield,
- \e{Prentice Hall, 2nd edition}, ISBN 0-13-235416-0. Also available in
- German: \b{C++ GUI Programmierung mit Qt 4: Die offizielle Einführung},
- \e{Addison-Wesley}, ISBN 3-827327-29-6
- \li \b{The Book of Qt4, The Art of Building Qt Applications} / Daniel Molkentin,
- \e{Open Source Press}, ISBN 1-59327-147-6.
- Translated from \b{Qt 4, Einführung in die Applikationsentwicklung},
- \e{Open Source Press}, ISBN 3-937514-12-0.
- \li \b{Foundations of Qt Development} / Johan Thelin, \e{Apress}, ISBN 1-59059-831-8.
- \li \b{Advanced Qt Programming} / Mark Summerfield, \e{Prentice Hall}, ISBN 0-321-63590-6.
- This book covers Model/View programming on more than 150 pages.
- \endlist
-
- The following list provides an overview of example programs contained in the first three
- books listed above. Some of them make very good templates for developing similar
- applications.
-
- \table
- \header
- \li Example name
- \li View class used
- \li Model used
- \li Aspects covered
- \li
- \row
- \li Team Leaders
- \li QListview
- \li QStringListModel
- \li
- \li Book 1, Chapter 10, Figure 10.6
- \row
- \li Color Names
- \li QListView
- \li QSortFilterProxyModel
- applied to QStringListModel
- \li
- \li Book 1, Chapter 10, Figure 10.8
- \row
- \li Currencies
- \li QTableView
- \li custom model based on
- QAbstractTableModel
- \li Read only
- \li Book 1, Chapter 10, Figure 10.10
- \row
- \li Cities
- \li QTableView
- \li Custom model based on
- QAbstractTableModel
- \li Read / write
- \li Book 1, Chapter 10, Figure 10.12
- \row
- \li Boolean Parser
- \li QTreeView
- \li Custom model based on
- QAbstractItemModel
- \li Read only
- \li Book 1, Chapter 10, Figure 10.14
- \row
- \li Track Editor
- \li {2, 1} QTableWidget
- \li Custom delegate providing a custom editor
- \li Book 1, Chapter 10, Figure 10.15
-
- \row
- \li Address Book
- \li QListView
- QTableView
- QTreeView
- \li Custom model based on
- QAbstractTableModel
- \li Read / write
- \li Book2, Chapter 8.4
- \row
- \li Address Book with sorting
- \li
- \li QSortfilterProxyModel
- \li Introducing sort and filter capabilities
- \li Book2, Chapter 8.5
- \row
- \li Address Book
- with checkboxes
- \li
- \li
- \li Introducing checkboxes in model/view
- \li Book2, Chapter 8.6
- \row
- \li Address Book with transposed grid
- \li
- \li Custom proxy Model based on QAbstractProxyModel
- \li Introducing a custom model
- \li Book2, Chapter 8.7
- \row
- \li Address Book with drag and drop
- \li
- \li
- \li Introducing drag and drop support
- \li Book2, Chapter 8.8
- \row
- \li Address Book with custom editor
- \li
- \li
- \li Introducing custom delegates
- \li Book2, Chapter 8.9
- \row
- \li Views
- \li QListView
- QTableView
- QTreeView
- \li QStandardItemModel
- \li Read only
- \li Book 3, Chapter 5, figure 5-3
- \row
- \li Bardelegate
- \li QTableView
- \li
- \li Custom delegate for presentation based on QAbstractItemDelegate
- \li Book 3, Chapter 5, figure 5-5
- \row
- \li Editdelegate
- \li QTableView
- \li
- \li Custom delegate for editing based on QAbstractItemDelegate
- \li Book 3, Chapter 5, figure 5-6
- \row
- \li Singleitemview
- \li Custom view based on QAbstractItemView
- \li
- \li Custom view
- \li Book 3,
- Chapter 5,
- figure 5-7
- \row
- \li listmodel
- \li QTableView
- \li Custom Model based on QAbstractTableModel
- \li Read only
- \li Book 3, Chapter 5, Figure 5-8
- \row
- \li treemodel
- \li QTreeView
- \li Custom Model based on QAbstractItemModel
- \li Read only
- \li Book 3, Chapter 5, Figure 5-10
- \row
- \li edit integers
- \li QListView
- \li Custom Model based on QAbstractListModel
- \li Read / write
- \li Book 3, Chapter 5, Listing 5-37, Figure 5-11
- \row
- \li sorting
- \li QTableView
- \li QSortFilterProxyModel applied to QStringListModel
- \li Demonstrates sorting
- \li Book 3, Chapter 5, Figure 5-12
- \endtable
-
-
- \section2 4.2 Qt Documentation
-
- Qt 5.0 comes with 19 examples for model/view.
- The examples can be found on the \l{Item Views Examples} page.
-
- \table
- \header
- \li Example name
- \li View class used
- \li Model used
- \li Aspects covered
- \row
- \li Address Book
- \li QTableView
- \li QAbstractTableModel
- QSortFilterProxyModel
- \li Usage of QSortFilterProxyModel to generate different
- subsets from one data pool
- \row
- \li Basic Sort/Filter Model
- \li QTreeView
- \li QStandardItemModel
- QSortFilterProxyModel
- \li
- \row
- \li Chart
- \li Custom view
- \li QStandardItemModel
- \li Designing custom views that cooperate with selection models
- \row
- \li Color Editor Factory
- \li {2, 1} QTableWidget
- \li Enhancing the standard delegate with a new custom editor to choose colours
- \row
- \li Combo Widget Mapper
- \li QDataWidgetMapper to map QLineEdit, QTextEdit and QComboBox
- \li QStandardItemModel
- \li Shows how a QComboBox can serve as a view class
- \row
- \li Custom Sort/Filter Model
- \li QTreeView
- \li QStandardItemModel
- QSortFilterProxyModel
- \li Subclass QSortFilterProxyModel for advanced sorting and filtering
- \row
- \li Dir View
- \li QTreeView
- \li QFileSystemModel
- \li Very small example to demonstrate how to assign a model to a view
- \row
- \li Editable Tree Model
- \li QTreeView
- \li Custom tree model
- \li Comprehensive example for working with trees, demonstrates
- editing cells and tree structure with an underlying custom
- model
- \row
- \li Fetch More
- \li QListView
- \li Custom list model
- \li Dynamically changing model
- \row
- \li Frozen Column
- \li QTableView
- \li QStandardItemModel
- \li
- \row
- \li Interview
- \li Multiple
- \li Custom item model
- \li Multiple views
- \row
- \li Pixelator
- \li QTableView
- \li Custom table model
- \li Implementation of a custom delegate
- \row
- \li Puzzle
- \li QListView
- \li Custom list model
- \li Model/view with drag and drop
- \row
- \li Simple DOM Model
- \li QTreeView
- \li Custom tree model
- \li Read only example for a custom tree model
- \row
- \li Simple Tree Model
- \li QTreeView
- \li Custom tree model
- \li Read only example for a custom tree model
- \row
- \li Simple Widget Mapper
- \li QDataWidgetMapper to map QLineEdit, QTextEdit and QSpinBox
- \li QStandardItemModel
- \li Basic QDataWidgetMapper usage
- \row
- \li Spreadsheet
- \li {2, 1} QTableView
- \li Custom delegates
- \row
- \li Star Delegate
- \li {2, 1} QTableWidget
- \li Comprehensive custom delegate example.
- \endtable
+ \section1 Examples
- A \l{Model/View Programming}{reference document} for model/view technology
- is also available.
+ Qt comes with multiple examples for model/view. You can find them on the
+ \l{Item Views Examples} page.
*/
/*!
diff --git a/src/widgets/doc/src/qtwidgets-examples.qdoc b/src/widgets/doc/src/qtwidgets-examples.qdoc
index 45677c471ba..364c985b310 100644
--- a/src/widgets/doc/src/qtwidgets-examples.qdoc
+++ b/src/widgets/doc/src/qtwidgets-examples.qdoc
@@ -164,3 +164,15 @@
regular expressions for the Widget-based applications.
*/
+/*!
+ \group examples-user-input
+ \ingroup all-examples
+ \title User Input Examples
+ \brief Using user input in Qt Widgets applications.
+
+ \image imagegestures-example.png {Application handling touch gestures}
+
+ Qt provides the functionality for handling user input and drag-and-drop in
+ widget-based applications.
+
+*/
diff --git a/src/widgets/doc/src/qtwidgets-toc.qdoc b/src/widgets/doc/src/qtwidgets-toc.qdoc
index bc447b8bd58..beddf853a22 100644
--- a/src/widgets/doc/src/qtwidgets-toc.qdoc
+++ b/src/widgets/doc/src/qtwidgets-toc.qdoc
@@ -53,6 +53,7 @@
\li \l{Rich Text Examples}
\li \l{Graphics View Examples}
\li \l{Widget Tools Examples}
+ \li \l{User Input Examples}
\endlist
\endlist
diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp
index 51aea4079a1..6288aae096a 100644
--- a/src/widgets/itemviews/qabstractitemview.cpp
+++ b/src/widgets/itemviews/qabstractitemview.cpp
@@ -3108,7 +3108,8 @@ void QAbstractItemView::keyboardSearch(const QString &search)
QModelIndex startMatch;
QModelIndexList previous;
do {
- match = d->model->match(current, Qt::DisplayRole, d->keyboardInput);
+ match = d->model->match(current, Qt::DisplayRole, d->keyboardInput, 1,
+ d->keyboardSearchFlags);
if (match == previous)
break;
firstMatch = match.value(0);
@@ -3251,6 +3252,30 @@ void QAbstractItemView::setUpdateThreshold(int threshold)
}
/*!
+ \property QAbstractItemView::keyboardSearchFlags
+ \since 6.11
+ This property determines how the default implementation of
+ keyboardSearch() matches the given string against the model's data.
+
+ The default value is \c{Qt::MatchStartsWith|Qt::MatchWrap}.
+
+ \sa keyboardSearch()
+ \sa QAbstractItemModel::match()
+*/
+
+Qt::MatchFlags QAbstractItemView::keyboardSearchFlags() const
+{
+ Q_D(const QAbstractItemView);
+ return d->keyboardSearchFlags;
+}
+
+void QAbstractItemView::setKeyboardSearchFlags(Qt::MatchFlags searchFlags)
+{
+ Q_D(QAbstractItemView);
+ d->keyboardSearchFlags = searchFlags;
+}
+
+/*!
Opens a persistent editor on the item at the given \a index.
If no editor exists, the delegate will create a new editor.
diff --git a/src/widgets/itemviews/qabstractitemview.h b/src/widgets/itemviews/qabstractitemview.h
index 63adac8d6f2..ce509dc9e98 100644
--- a/src/widgets/itemviews/qabstractitemview.h
+++ b/src/widgets/itemviews/qabstractitemview.h
@@ -48,6 +48,8 @@ class Q_WIDGETS_EXPORT QAbstractItemView : public QAbstractScrollArea
Q_PROPERTY(ScrollMode horizontalScrollMode READ horizontalScrollMode
WRITE setHorizontalScrollMode RESET resetHorizontalScrollMode)
Q_PROPERTY(int updateThreshold READ updateThreshold WRITE setUpdateThreshold)
+ Q_PROPERTY(Qt::MatchFlags keyboardSearchFlags READ keyboardSearchFlags
+ WRITE setKeyboardSearchFlags)
public:
enum SelectionMode {
@@ -182,6 +184,9 @@ public:
int updateThreshold() const;
void setUpdateThreshold(int threshold);
+ Qt::MatchFlags keyboardSearchFlags() const;
+ void setKeyboardSearchFlags(Qt::MatchFlags searchFlags);
+
void openPersistentEditor(const QModelIndex &index);
void closePersistentEditor(const QModelIndex &index);
bool isPersistentEditorOpen(const QModelIndex &index) const;
@@ -204,7 +209,7 @@ public:
virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const override;
- using QAbstractScrollArea::update;
+ using QWidget::update;
public Q_SLOTS:
virtual void reset();
diff --git a/src/widgets/itemviews/qabstractitemview_p.h b/src/widgets/itemviews/qabstractitemview_p.h
index b24b2d21c33..60799fb8a50 100644
--- a/src/widgets/itemviews/qabstractitemview_p.h
+++ b/src/widgets/itemviews/qabstractitemview_p.h
@@ -383,6 +383,7 @@ public:
QString keyboardInput;
QElapsedTimer keyboardInputTime;
+ Qt::MatchFlags keyboardSearchFlags = Qt::MatchStartsWith | Qt::MatchWrap;
bool autoScroll;
QBasicTimer autoScrollTimer;
diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp
index da1fbbd60df..84ff04c9f34 100644
--- a/src/widgets/itemviews/qtreeview.cpp
+++ b/src/widgets/itemviews/qtreeview.cpp
@@ -1030,7 +1030,8 @@ void QTreeView::keyboardSearch(const QString &search)
searchFrom = searchFrom.sibling(searchFrom.row(), start.column());
if (searchFrom.parent() == start.parent())
searchFrom = start;
- QModelIndexList match = d->model->match(searchFrom, Qt::DisplayRole, searchString);
+ QModelIndexList match = d->model->match(searchFrom, Qt::DisplayRole, searchString, 1,
+ keyboardSearchFlags());
if (match.size()) {
int hitIndex = d->viewIndex(match.at(0));
if (hitIndex >= 0 && hitIndex < startIndex)
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index 53ce4dd8211..fa95a1d2538 100644
--- a/src/widgets/kernel/qapplication.cpp
+++ b/src/widgets/kernel/qapplication.cpp
@@ -1508,11 +1508,15 @@ void QApplicationPrivate::setFocusWidget(QWidget *focus, Qt::FocusReason reason)
return;
}
- if (focus && (reason == Qt::BacktabFocusReason || reason == Qt::TabFocusReason)
- && qt_in_tab_key_event)
- focus->window()->setAttribute(Qt::WA_KeyboardFocusChange);
- else if (focus && reason == Qt::ShortcutFocusReason) {
- focus->window()->setAttribute(Qt::WA_KeyboardFocusChange);
+ if (focus) {
+ if ((reason == Qt::BacktabFocusReason || reason == Qt::TabFocusReason)
+ && qt_in_tab_key_event)
+ focus->window()->setAttribute(Qt::WA_KeyboardFocusChange);
+ else if (reason == Qt::ShortcutFocusReason) {
+ focus->window()->setAttribute(Qt::WA_KeyboardFocusChange);
+ } else {
+ focus->window()->setAttribute(Qt::WA_KeyboardFocusChange, false);
+ }
}
QWidget *prev = focus_widget;
focus_widget = focus;
diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp
index 82d16cb1252..b2cfb27e814 100644
--- a/src/widgets/styles/qstylesheetstyle.cpp
+++ b/src/widgets/styles/qstylesheetstyle.cpp
@@ -3419,29 +3419,28 @@ void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionC
}
QRect gr = subControlRect(cc, opt, SC_SliderGroove, w);
- if (slider->subControls & SC_SliderGroove) {
+ if (slider->subControls & SC_SliderGroove)
grooveSubRule.drawRule(p, gr);
- }
if (slider->subControls & SC_SliderHandle) {
QRect hr = subControlRect(cc, opt, SC_SliderHandle, w);
- QRenderRule subRule1 = renderRule(w, opt, PseudoElement_SliderSubPage);
- if (subRule1.hasDrawable()) {
- QRect r(gr.topLeft(),
- slider->orientation == Qt::Horizontal
- ? QPoint(hr.x()+hr.width()/2, gr.y()+gr.height() - 1)
- : QPoint(gr.x()+gr.width() - 1, hr.y()+hr.height()/2));
- subRule1.drawRule(p, r);
- }
-
- QRenderRule subRule2 = renderRule(w, opt, PseudoElement_SliderAddPage);
- if (subRule2.hasDrawable()) {
- QRect r(slider->orientation == Qt::Horizontal
- ? QPoint(hr.x()+hr.width()/2+1, gr.y())
- : QPoint(gr.x(), hr.y()+hr.height()/2+1),
- gr.bottomRight());
- subRule2.drawRule(p, r);
+ if (slider->subControls & SC_SliderGroove) {
+ const bool isHor = slider->orientation == Qt::Horizontal;
+ QRenderRule subRule1 = renderRule(w, opt, PseudoElement_SliderSubPage);
+ if (subRule1.hasDrawable()) {
+ QRect r(gr.topLeft(),
+ isHor ? QPoint(hr.x() + hr.width() / 2, gr.y() + gr.height() - 1)
+ : QPoint(gr.x() + gr.width() - 1, hr.y() + hr.height() / 2));
+ subRule1.drawRule(p, r);
+ }
+ QRenderRule subRule2 = renderRule(w, opt, PseudoElement_SliderAddPage);
+ if (subRule2.hasDrawable()) {
+ QRect r(isHor ? QPoint(hr.x() + hr.width() / 2 + 1, gr.y())
+ : QPoint(gr.x(), hr.y() + hr.height() / 2 + 1),
+ gr.bottomRight());
+ subRule2.drawRule(p, r);
+ }
}
handleSubRule.drawRule(p, handleSubRule.boxRect(hr, Margin));
diff --git a/src/widgets/widgets/qmdisubwindow.cpp b/src/widgets/widgets/qmdisubwindow.cpp
index 1ca6b8a47a1..7aff0da3327 100644
--- a/src/widgets/widgets/qmdisubwindow.cpp
+++ b/src/widgets/widgets/qmdisubwindow.cpp
@@ -2220,7 +2220,7 @@ QMdiSubWindow::QMdiSubWindow(QWidget *parent, Qt::WindowFlags flags)
d->titleBarPalette = d->desktopPalette();
d->font = QApplication::font("QMdiSubWindowTitleBar");
// We don't want the menu icon by default on mac.
-#ifndef Q_OS_MAC
+#ifndef Q_OS_DARWIN
if (windowIcon().isNull())
d->menuIcon = style()->standardIcon(QStyle::SP_TitleBarMenuButton, nullptr, this);
else
@@ -2847,8 +2847,11 @@ bool QMdiSubWindow::event(QEvent *event)
break;
case QEvent::WindowIconChange:
d->menuIcon = windowIcon();
+ // We don't want the default menu icon on mac.
+#ifndef Q_OS_DARWIN
if (d->menuIcon.isNull())
d->menuIcon = style()->standardIcon(QStyle::SP_TitleBarMenuButton, nullptr, this);
+#endif
if (d->controlContainer)
d->controlContainer->updateWindowIcon(d->menuIcon);
if (!maximizedSystemMenuIconWidget())
diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp
index 7d4228709be..92ff14dd44f 100644
--- a/src/widgets/widgets/qmenu.cpp
+++ b/src/widgets/widgets/qmenu.cpp
@@ -771,7 +771,8 @@ void QMenuPrivate::setCurrentAction(QAction *action, int popup, SelectionReason
#endif
hideMenu(hideActiveMenu);
} else if (!currentAction || !currentAction->menu()) {
- sloppyState.startTimerIfNotRunning();
+ if (reason != SelectionReason::SelectedFromAPI)
+ sloppyState.startTimerIfNotRunning();
}
}
}
@@ -2172,7 +2173,7 @@ void QMenu::hideTearOffMenu()
void QMenu::setActiveAction(QAction *act)
{
Q_D(QMenu);
- d->setCurrentAction(act, 0);
+ d->setCurrentAction(act, 0, QMenuPrivate::SelectionReason::SelectedFromAPI);
if (d->scroll && act)
d->scrollMenu(act, QMenuPrivate::QMenuScroller::ScrollCenter);
}
@@ -2971,7 +2972,7 @@ void QMenu::mouseReleaseEvent(QMouseEvent *e)
#endif
d->activateAction(action, QAction::Trigger);
}
- } else if (!action || action->isEnabled()) {
+ } else if (!action || (action->isEnabled() && !action->isSeparator())) {
d->hideUpToMenuBar();
}
}
diff --git a/src/widgets/widgets/qmenu_p.h b/src/widgets/widgets/qmenu_p.h
index dd1f058a288..d9dcd7d0362 100644
--- a/src/widgets/widgets/qmenu_p.h
+++ b/src/widgets/widgets/qmenu_p.h
@@ -362,7 +362,8 @@ public:
} delayState;
enum SelectionReason {
SelectedFromKeyboard,
- SelectedFromElsewhere
+ SelectedFromAPI,
+ SelectedFromElsewhere,
};
enum class SelectionDirection {
Up,
diff --git a/tests/auto/cmake/test_qt_add_ui_common/functions.cmake b/tests/auto/cmake/test_qt_add_ui_common/functions.cmake
index b06ba25e21f..d3878da3fbc 100644
--- a/tests/auto/cmake/test_qt_add_ui_common/functions.cmake
+++ b/tests/auto/cmake/test_qt_add_ui_common/functions.cmake
@@ -8,7 +8,30 @@ function(generate_hash_folder target_name infile out_folder)
set(${out_folder} "${short_hash}" PARENT_SCOPE)
endfunction()
+function(check_generator_works out_var generator_name)
+ message(STATUS "Checking if generator '${generator_name}' works")
+ string(CONCAT source_dir
+ "${CMAKE_CURRENT_SOURCE_DIR}/../"
+ "test_qt_add_ui_common/vs_generator_test")
+ set(build_dir
+ "${CMAKE_CURRENT_BINARY_DIR}/vs_generator_test-build")
+ run_cmake_configure(SOURCE_DIR "${source_dir}"
+ BUILD_DIR "${build_dir}"
+ GENERATOR "${generator_name}"
+ CLEAN_FIRST
+ RESULT_VARIABLE cmake_result)
+
+ if("${cmake_result}" EQUAL 0)
+ set(generator_works "TRUE")
+ else()
+ set(generator_works "FALSE")
+ endif()
+ message(STATUS "Checking if generator '${generator_name}' works - ${generator_works}")
+ set(${out_var} "${generator_works}" PARENT_SCOPE)
+endfunction()
+
function(get_latest_vs_generator output)
+ message(STATUS "Checking which latest Visual Studio generator can be used.")
execute_process(COMMAND ${CMAKE_COMMAND} -G
ERROR_VARIABLE CMAKE_GENERATORS_ERROR
OUTPUT_STRIP_TRAILING_WHITESPACE)
@@ -23,7 +46,14 @@ function(get_latest_vs_generator output)
set(last_generator "")
foreach(generator IN LISTS vs_generators)
string(REGEX MATCH "Visual Studio ([0-9]+) [0-9]+" unused "${generator}")
+
if("${CMAKE_MATCH_1}" VERSION_GREATER "${last_version}")
+ # Skip Visual Studio 18 2026 because it's not installed in CI yet
+ check_generator_works(generator_works "${CMAKE_MATCH_0}")
+ if(NOT generator_works)
+ continue()
+ endif()
+
set(last_version "${CMAKE_MATCH_1}")
set(last_generator "${CMAKE_MATCH_0}")
endif()
diff --git a/tests/auto/cmake/test_qt_add_ui_common/vs_generator_test/CMakeLists.txt b/tests/auto/cmake/test_qt_add_ui_common/vs_generator_test/CMakeLists.txt
new file mode 100644
index 00000000000..dbde5e369e5
--- /dev/null
+++ b/tests/auto/cmake/test_qt_add_ui_common/vs_generator_test/CMakeLists.txt
@@ -0,0 +1,6 @@
+# Copyright (C) 2025 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+cmake_minimum_required(VERSION 3.16)
+
+project(VsGeneratorTest LANGUAGES CXX)
diff --git a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp
index 3804f53cae9..0b65673c393 100644
--- a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp
+++ b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp
@@ -92,6 +92,7 @@ private slots:
void qIsNull();
void for_each();
void qassert();
+ void qpresume();
void qtry();
void checkptr();
void qstaticassert();
@@ -266,6 +267,18 @@ void tst_QGlobal::qassert()
QVERIFY(passed);
}
+/*non-static*/ Q_NEVER_INLINE char presumedValue(const char *str)
+{
+ Q_PRESUME(str);
+ // an optimizing compiler should delete the str? check
+ return str ? str[0] : '\0';
+}
+
+void tst_QGlobal::qpresume()
+{
+ QCOMPARE(presumedValue("Hello World"), 'H');
+}
+
void tst_QGlobal::qtry()
{
int i = 0;
diff --git a/tests/auto/corelib/io/qdirlisting/tst_qdirlisting.cpp b/tests/auto/corelib/io/qdirlisting/tst_qdirlisting.cpp
index 3a8ea31740c..29b78415924 100644
--- a/tests/auto/corelib/io/qdirlisting/tst_qdirlisting.cpp
+++ b/tests/auto/corelib/io/qdirlisting/tst_qdirlisting.cpp
@@ -92,8 +92,8 @@ private slots:
void uncPaths();
#endif
#ifndef Q_OS_WIN
- void hiddenFiles();
- void hiddenDirs();
+ void hidden_data();
+ void hidden();
#endif
void withStdAlgorithms();
@@ -871,47 +871,46 @@ void tst_QDirListing::uncPaths()
// anything starting by a '.' is a hidden file.
// For that reason these two tests aren't run on Windows.
-void tst_QDirListing::hiddenFiles()
+void tst_QDirListing::hidden_data()
{
- QStringList expected = {
- "hiddenDirs_hiddenFiles/normalFile"_L1,
+ QTest::addColumn<QDirListing::IteratorFlags>("flags");
+ QTest::addColumn<QStringList>("expected");
+
+ using F = QDirListing::IteratorFlag;
+
+ QTest::newRow("Recursive-ExcludeDirs")
+ << (F::ExcludeDirs | F::IncludeHidden | F::Recursive)
+ << QStringList{
+ "hiddenDirs_hiddenFiles/.hiddenDirectory/.hiddenFile"_L1,
+ "hiddenDirs_hiddenFiles/.hiddenDirectory/normalFile"_L1,
"hiddenDirs_hiddenFiles/.hiddenFile"_L1,
- "hiddenDirs_hiddenFiles/normalDirectory/normalFile"_L1,
"hiddenDirs_hiddenFiles/normalDirectory/.hiddenFile"_L1,
- "hiddenDirs_hiddenFiles/.hiddenDirectory/normalFile"_L1,
- "hiddenDirs_hiddenFiles/.hiddenDirectory/.hiddenFile"_L1,
- };
- expected.sort();
-
- constexpr auto flags = ItFlag::ExcludeDirs | ItFlag::IncludeHidden | ItFlag::Recursive;
- QStringList list;
- list.reserve(expected.size());
- for (const auto &dirEntry : QDirListing(u"hiddenDirs_hiddenFiles"_s, flags)) {
- QVERIFY(dirEntry.isFile());
- list.emplace_back(dirEntry.filePath());
- }
- list.sort();
+ "hiddenDirs_hiddenFiles/normalDirectory/normalFile"_L1,
+ "hiddenDirs_hiddenFiles/normalFile"_L1,
+ };
- QCOMPARE_EQ(list, expected);
+ QTest::newRow("Recursive-ExcludeFiles")
+ << (F::ExcludeFiles | F::IncludeHidden | F::Recursive)
+ << QStringList{
+ "hiddenDirs_hiddenFiles/.hiddenDirectory"_L1,
+ "hiddenDirs_hiddenFiles/.hiddenDirectory/.hidden-subdir"_L1,
+ "hiddenDirs_hiddenFiles/.hiddenDirectory/subdir"_L1,
+ "hiddenDirs_hiddenFiles/normalDirectory"_L1,
+ "hiddenDirs_hiddenFiles/normalDirectory/.hidden-subdir"_L1,
+ "hiddenDirs_hiddenFiles/normalDirectory/subdir"_L1,
+ };
}
-void tst_QDirListing::hiddenDirs()
+void tst_QDirListing::hidden()
{
- QStringList expected = {
- "hiddenDirs_hiddenFiles/normalDirectory"_L1,
- "hiddenDirs_hiddenFiles/normalDirectory/subdir"_L1,
- "hiddenDirs_hiddenFiles/normalDirectory/.hidden-subdir"_L1,
- "hiddenDirs_hiddenFiles/.hiddenDirectory"_L1,
- "hiddenDirs_hiddenFiles/.hiddenDirectory/subdir"_L1,
- "hiddenDirs_hiddenFiles/.hiddenDirectory/.hidden-subdir"_L1,
- };
- expected.sort();
+ QFETCH(QDirListing::IteratorFlags, flags);
+ QFETCH(QStringList, expected);
- constexpr auto flags = ItFlag::ExcludeFiles | ItFlag::IncludeHidden | ItFlag::Recursive;
QStringList list;
list.reserve(expected.size());
+ bool isDir = flags.testFlags(ItFlag::ExcludeFiles);
for (const auto &dirEntry : QDirListing(u"hiddenDirs_hiddenFiles"_s, flags)) {
- QVERIFY(dirEntry.isDir());
+ QVERIFY(isDir ? dirEntry.isDir() : dirEntry.isFile());
list.emplace_back(dirEntry.filePath());
}
list.sort();
diff --git a/tests/auto/corelib/io/qprocessenvironment/tst_qprocessenvironment.cpp b/tests/auto/corelib/io/qprocessenvironment/tst_qprocessenvironment.cpp
index 560d4196b28..6a898e7af0d 100644
--- a/tests/auto/corelib/io/qprocessenvironment/tst_qprocessenvironment.cpp
+++ b/tests/auto/corelib/io/qprocessenvironment/tst_qprocessenvironment.cpp
@@ -291,7 +291,7 @@ void tst_QProcessEnvironment::putenv()
static bool testRan = false;
if (testRan)
- QFAIL("You cannot run this test more than once, since we modify the environment");
+ QSKIP("You cannot run this test more than once, since we modify the environment");
testRan = true;
QByteArray valBefore = qgetenv(envname);
diff --git a/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp b/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp
index 472e03adcac..00672ef0b6a 100644
--- a/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp
+++ b/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp
@@ -678,8 +678,20 @@ void tst_QResourceEngine::registerNestedRccFile()
"/registeredNestedRccFile"));
QVERIFY2(QResource::registerResource(":/nestedrcc/runtime_resource.rcc",
"/registeredNestedRccFile"),
- "Second QResource::registerResource call failed.");
+ "Second QResource::registerResource call does not failed.");
QVERIFY(QFile::exists(":/registeredNestedRccFile/runtime_resource/search_file.txt"));
+
+ // clean up
+ QVERIFY(QResource::unregisterResource(":/nestedrcc/runtime_resource.rcc",
+ "/registeredNestedRccFile"));
+
+ QVERIFY(QFile::exists(":/registeredNestedRccFile/runtime_resource/search_file.txt"));
+
+ QVERIFY(QResource::unregisterResource(":/nestedrcc/runtime_resource.rcc",
+ "/registeredNestedRccFile"));
+
+ // verify clean up
+ QVERIFY(!QFile::exists(":/registeredNestedRccFile/runtime_resource/search_file.txt"));
}
QTEST_MAIN(tst_QResourceEngine)
diff --git a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp
index 3dd36bdae35..5453237cadb 100644
--- a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp
+++ b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp
@@ -182,7 +182,16 @@ private slots:
void childKeys();
void testIniParsing_data();
void testIniParsing();
+
void testEscapes();
+ void testEscapedKeys_data();
+ void testEscapedKeys();
+ void testUnescapedKeys_data();
+ void testUnescapedKeys();
+ void testEscapedStringList_data();
+ void testEscapedStringList();
+ void testUnescapedStringList_data();
+ void testUnescapedStringList();
void testNormalizedKey_data();
void testNormalizedKey();
void testVariantTypes_data() { populateWithFormats(); }
@@ -2831,35 +2840,6 @@ void tst_QSettings::testEscapes()
{
QSettings settings(QSettings::UserScope, "software.org", "KillerAPP");
-#define testEscapedKey(plainKey, escKey) \
- QCOMPARE(iniEscapedKey(plainKey), QByteArray(escKey)); \
- QCOMPARE(iniUnescapedKey(escKey), QString(plainKey));
-
-#define testUnescapedKey(escKey, plainKey, reescKey) \
- QCOMPARE(iniUnescapedKey(escKey), QString(plainKey)); \
- QCOMPARE(iniEscapedKey(plainKey), QByteArray(reescKey)); \
- QCOMPARE(iniUnescapedKey(reescKey), QString(plainKey));
-
-#define testEscapedStringList(plainStrList, escStrList) \
- { \
- QStringList plainList(plainStrList); \
- QByteArray escList(escStrList); \
- QCOMPARE(iniEscapedStringList(plainList), escList); \
- QCOMPARE(iniUnescapedStringList(escList), plainList); \
- } \
-
-
-#define testUnescapedStringList(escStrList, plainStrList, reescStrList) \
- { \
- QStringList plainList(plainStrList); \
- QByteArray escList(escStrList); \
- QByteArray reescList(reescStrList); \
- QCOMPARE(iniUnescapedStringList(escList), plainList); \
- QCOMPARE(iniEscapedStringList(plainList), reescList); \
- QCOMPARE(iniUnescapedStringList(reescList), plainList); \
- } \
-
-
#define testVariant(val, escStr, func) \
{ \
QVariant v(val); \
@@ -2875,57 +2855,6 @@ void tst_QSettings::testEscapes()
QCOMPARE(v.toString(), QString(vStr)); \
}
- testEscapedKey("", "");
- testEscapedKey(" ", "%20");
- testEscapedKey(" 0123 abcd ", "%200123%20abcd%20");
- testEscapedKey("~!@#$%^&*()_+.-/\\=", "%7E%21%40%23%24%25%5E%26%2A%28%29_%2B.-\\%5C%3D");
- testEscapedKey(QString() + QChar(0xabcd) + QChar(0x1234) + QChar(0x0081), "%UABCD%U1234%81");
- testEscapedKey(QString() + QChar(0xFE) + QChar(0xFF) + QChar(0x100) + QChar(0x101), "%FE%FF%U0100%U0101");
-
- testUnescapedKey("", "", "");
- testUnescapedKey("%20", " ", "%20");
- testUnescapedKey("/alpha/beta", "/alpha/beta", "\\alpha\\beta");
- testUnescapedKey("\\alpha\\beta", "/alpha/beta", "\\alpha\\beta");
- testUnescapedKey("%5Calpha%5Cbeta", "\\alpha\\beta", "%5Calpha%5Cbeta");
- testUnescapedKey("%", "%", "%25");
- testUnescapedKey("%f%!%%%%1x%x1%U%Uz%U123%U1234%1234%", QString("%f%!%%%%1x%x1%U%Uz%U123") + QChar(0x1234) + "\x12" + "34%",
- "%25f%25%21%25%25%25%251x%25x1%25U%25Uz%25U123%U1234%1234%25");
-
- testEscapedStringList("", "");
- testEscapedStringList(" ", "\" \"");
- testEscapedStringList(";", "\";\"");
- testEscapedStringList(",", "\",\"");
- testEscapedStringList("=", "\"=\"");
- testEscapedStringList("abc-def", "abc-def");
- testEscapedStringList(QChar(0) + QString("0"), "\\0\\x30");
- testEscapedStringList("~!@#$%^&*()_+.-/\\=", "\"~!@#$%^&*()_+.-/\\\\=\"");
- testEscapedStringList("~!@#$%^&*()_+.-/\\", "~!@#$%^&*()_+.-/\\\\");
- testEscapedStringList(QString("\x7F") + "12aFz", QByteArray("\x7f") + "12aFz");
- testEscapedStringList(QString(" \t\n\\n") + QChar(0x123) + QChar(0x4567), "\" \\t\\n\\\\n\xC4\xA3\xE4\x95\xA7\"");
- testEscapedStringList(QString("\a\b\f\n\r\t\v'\"?\001\002\x03\x04"), "\\a\\b\\f\\n\\r\\t\\v'\\\"?\\x1\\x2\\x3\\x4");
- testEscapedStringList(QStringList() << "," << ";" << "a" << "ab, \tc, d ", "\",\", \";\", a, \"ab, \\tc, d \"");
-
- /*
- Test .ini syntax that cannot be generated by QSettings (but can be entered by users).
- */
- testUnescapedStringList("", "", "");
- testUnescapedStringList("\"\"", "", "");
- testUnescapedStringList("\"abcdef\"", "abcdef", "abcdef");
- testUnescapedStringList("\"\\?\\'\\\"\"", "?'\"", "?'\\\"");
- testUnescapedStringList("\\0\\00\\000\\0000000\\1\\111\\11111\\x\\x0\\xABCDEFGH\\x0123456\\",
- QString() + QChar(0) + QChar(0) + QChar(0) + QChar(0) + QChar(1)
- + QChar(0111) + QChar(011111) + QChar(0) + QChar(0xCDEF) + "GH"
- + QChar(0x3456),
- "\\0\\0\\0\\0\\x1I\xE1\x89\x89\\0\xEC\xB7\xAFGH\xE3\x91\x96");
- testUnescapedStringList(QByteArray("\\c\\d\\e\\f\\g\\$\\*\\\0", 16), "\f", "\\f");
- testUnescapedStringList("\"a\", \t\"bc \", \" d\" , \"ef \" ,,g, hi i,,, ,",
- QStringList() << "a" << "bc " << " d" << "ef " << "" << "g" << "hi i"
- << "" << "" << "" << "",
- "a, \"bc \", \" d\", \"ef \", , g, hi i, , , , ");
- testUnescapedStringList("a , b , c d , efg ",
- QStringList() << "a" << "b" << "c d" << "efg",
- "a, b, c d, efg");
-
// streaming qvariant into a string
testVariant(QString("Hello World!"), QString("Hello World!"), toString);
testVariant(QString("Hello, World!"), QString("Hello, World!"), toString);
@@ -2949,6 +2878,190 @@ void tst_QSettings::testEscapes()
testBadEscape("@Rect(1 2 3)", "@Rect(1 2 3)");
testBadEscape("@@Rect(1 2 3)", "@Rect(1 2 3)");
}
+
+void tst_QSettings::testEscapedKeys_data()
+{
+ QTest::addColumn<QString>("plainKey");
+ QTest::addColumn<QByteArray>("escKey");
+
+ QTest::newRow("empty-string") << u""_s << ""_ba;
+ QTest::newRow("space") << u" "_s << "%20"_ba;
+ QTest::newRow(" 0123 abcd ") << " 0123 abcd " << "%200123%20abcd%20"_ba;
+
+ QTest::newRow("special-characters")
+ << "~!@#$%^&*()_+.-/\\="
+ << "%7E%21%40%23%24%25%5E%26%2A%28%29_%2B.-\\%5C%3D"_ba;
+
+ const std::array arr1 = {QChar(0xabcd), QChar(0x1234), QChar(0x0081)};
+ QTest::newRow("qchar-array1") << QString(arr1) << "%UABCD%U1234%81"_ba;
+
+ const std::array arr2 = {QChar(0xFE), QChar(0xFF), QChar(0x100), QChar(0x101)};
+ QTest::newRow("qchar-array2") << QString(arr2) << "%FE%FF%U0100%U0101"_ba;
+}
+
+void tst_QSettings::testEscapedKeys()
+{
+ QFETCH(QString, plainKey);
+ QFETCH(QByteArray, escKey);
+
+ QSettings settings(QSettings::UserScope, "example.org", "KillerAPP");
+
+ QCOMPARE(iniEscapedKey(plainKey), escKey);
+ QCOMPARE(iniUnescapedKey(escKey), plainKey);
+}
+
+void tst_QSettings::testUnescapedKeys_data()
+{
+ QTest::addColumn<QByteArray>("escKey");
+ QTest::addColumn<QString>("plainKey");
+ QTest::addColumn<QByteArray>("reescKey");
+
+ QTest::newRow("empty-string") << ""_ba << u""_s << ""_ba;
+ QTest::newRow("space") << "%20"_ba << u" "_s << "%20"_ba;
+ QTest::newRow("%") << "%"_ba << u"%"_s << "%25"_ba;
+
+ QTest::newRow("/alpha/beta") << "/alpha/beta"_ba << "/alpha/beta" << "\\alpha\\beta"_ba;
+ QTest::newRow("\\alpha\\beta") << "\\alpha\\beta"_ba << "/alpha/beta" << "\\alpha\\beta"_ba;
+ QTest::newRow("%5Calpha%5Cbeta") << "%5Calpha%5Cbeta"_ba << "\\alpha\\beta" << "%5Calpha%5Cbeta"_ba;
+
+ QTest::newRow("many-percent")
+ << "%f%!%%%%1x%x1%U%Uz%U123%U1234%1234%"_ba
+ << QString("%f%!%%%%1x%x1%U%Uz%U123"_L1 + QChar(0x1234) + "\x12" + "34%")
+ << "%25f%25%21%25%25%25%251x%25x1%25U%25Uz%25U123%U1234%1234%25"_ba;
+}
+
+void tst_QSettings::testUnescapedKeys()
+{
+ QFETCH(QByteArray, escKey);
+ QFETCH(QString, plainKey);
+ QFETCH(QByteArray, reescKey);
+
+ QSettings settings(QSettings::UserScope, "example.org", "KillerAPP");
+
+ QCOMPARE(iniUnescapedKey(escKey), plainKey);
+ QCOMPARE(iniEscapedKey(plainKey), reescKey);
+ QCOMPARE(iniUnescapedKey(reescKey), plainKey);
+}
+
+void tst_QSettings::testEscapedStringList_data()
+{
+ QTest::addColumn<QStringList>("plainStrList");
+ QTest::addColumn<QByteArray>("escapedList");
+
+ QTest::newRow("empty-string") << QStringList{u""_s} << ""_ba;
+ QTest::newRow("space") << QStringList{u" "_s} << "\" \""_ba;
+ QTest::newRow(";") << QStringList{u";"_s} << "\";\""_ba;
+ QTest::newRow(",") << QStringList{u","_s} << "\",\""_ba;
+ QTest::newRow("=") << QStringList{u"="_s} << "\"=\""_ba;
+ QTest::newRow("abc-def") << QStringList{u"abc-def"_s} << "abc-def"_ba;
+
+ QTest::newRow("starts-with-NUL")
+ << QStringList{QChar(0) + u"0"_s}
+ << "\\0\\x30"_ba;
+
+ QTest::newRow("special-characters1")
+ << QStringList{u"~!@#$%^&*()_+.-/\\="_s}
+ << "\"~!@#$%^&*()_+.-/\\\\=\""_ba;
+
+ QTest::newRow("special-characters2")
+ << QStringList{u"~!@#$%^&*()_+.-/\\"_s}
+ << "~!@#$%^&*()_+.-/\\\\"_ba;
+
+ QTest::newRow("DEL-character")
+ << QStringList{u"\x7F"_s + u"12aFz"_s}
+ << "\x7f"_ba + "12aFz"_ba;
+
+ QTest::newRow("tab-newline")
+ << QStringList{u" \t\n\\n"_s + QChar(0x123) + QChar(0x4567)}
+ << "\" \\t\\n\\\\n\xC4\xA3\xE4\x95\xA7\""_ba;
+
+ QTest::newRow("backslash-espcaped-input")
+ << QStringList{u"\a\b\f\n\r\t\v'\"?\001\002\x03\x04"_s}
+ << "\\a\\b\\f\\n\\r\\t\\v'\\\"?\\x1\\x2\\x3\\x4"_ba;
+
+ QTest::newRow("stringlist-with-tab")
+ << QStringList{u","_s, u";"_s, u"a"_s, u"ab, \tc, d "_s}
+ << "\",\", \";\", a, \"ab, \\tc, d \""_ba;
+}
+
+void tst_QSettings::testEscapedStringList()
+{
+ QFETCH(QStringList, plainStrList);
+ QFETCH(QByteArray, escapedList);
+
+ QSettings settings(QSettings::UserScope, "example.org", "KillerAPP");
+
+ QCOMPARE(iniEscapedStringList(plainStrList), escapedList);
+ QCOMPARE(iniUnescapedStringList(escapedList), plainStrList);
+}
+
+void tst_QSettings::testUnescapedStringList_data()
+{
+ QTest::addColumn<QByteArray>("escStrList");
+ QTest::addColumn<QStringList>("plainStrList");
+ QTest::addColumn<QByteArray>("reescStrList");
+
+ /*
+ Test .ini syntax that cannot be generated by QSettings (but can be entered by users).
+ */
+ QTest::newRow("empty")
+ << ""_ba
+ << QStringList{u""_s}
+ << ""_ba;
+
+ QTest::newRow("empty-double-quotes")
+ << "\"\""_ba
+ << QStringList{u""_s}
+ << ""_ba;
+
+ QTest::newRow("plain-quoted-string")
+ << "\"abcdef\""_ba
+ << QStringList{u"abcdef"_s}
+ << "abcdef"_ba;
+
+ QTest::newRow("backslash-non-letter-characters")
+ << "\"\\?\\'\\\"\""_ba
+ << QStringList{u"?'\""_s}
+ << "?'\\\""_ba;
+
+ const std::array arr = {QChar(0), QChar(0), QChar(0), QChar(0), QChar(1),
+ QChar(0111), QChar(011111), QChar(0), QChar(0xCDEF),
+ QChar(u'G'), QChar(u'H'), QChar(0x3456)};
+ QTest::newRow("array-of-qchar")
+ << "\\0\\00\\000\\0000000\\1\\111\\11111\\x\\x0\\xABCDEFGH\\x0123456\\"_ba
+ << QStringList{QString{arr}}
+ << "\\0\\0\\0\\0\\x1I\xE1\x89\x89\\0\xEC\xB7\xAFGH\xE3\x91\x96"_ba;
+
+ QTest::newRow("backslash-escapes")
+ << QByteArray("\\c\\d\\e\\f\\g\\$\\*\\\0", 16)
+ << QStringList{u"\f"_s}
+ << "\\f"_ba;
+
+ QTest::newRow("double-quotes-tab-character")
+ << "\"a\", \t\"bc \", \" d\" , \"ef \" ,,g, hi i,,, ,"_ba
+ << QStringList{u"a"_s, u"bc "_s, u" d"_s, u"ef "_s, u""_s, u"g"_s,
+ u"hi i"_s, u""_s, u""_s, u""_s, u""_s}
+ << "a, \"bc \", \" d\", \"ef \", , g, hi i, , , , "_ba;
+
+ QTest::newRow("abcdefg-extra-whitespaces")
+ << "a , b , c d , efg "_ba
+ << QStringList{u"a"_s, u"b"_s, u"c d"_s, u"efg"_s}
+ << "a, b, c d, efg"_ba;
+}
+
+void tst_QSettings::testUnescapedStringList()
+{
+ QFETCH(QByteArray, escStrList);
+ QFETCH(QStringList, plainStrList);
+ QFETCH(QByteArray, reescStrList);
+
+ QSettings settings(QSettings::UserScope, "example.org", "KillerAPP");
+
+ QCOMPARE(iniUnescapedStringList(escStrList), plainStrList);
+ QCOMPARE(iniEscapedStringList(plainStrList), reescStrList);
+ QCOMPARE(iniUnescapedStringList(reescStrList), plainStrList);
+}
+
#endif
void tst_QSettings::testCaseSensitivity()
diff --git a/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp b/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp
index 7c0e5e10b71..bb7555f0329 100644
--- a/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp
+++ b/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp
@@ -22,6 +22,7 @@ private slots:
void variantProperty();
void notifySignal();
void enumerator();
+ void enumProperty();
void classInfo();
void relatedMetaObject();
void staticMetacall();
@@ -1019,6 +1020,26 @@ void tst_QMetaObjectBuilder::enumerator()
QVERIFY(checkForSideEffects(builder, QMetaObjectBuilder::Enumerators));
}
+void tst_QMetaObjectBuilder::enumProperty()
+{
+ // When adding property with an enumeration type, QMetaProperty::isEnumType()
+ // should return true.
+ QMetaObjectBuilder builder;
+ builder.setSuperClass(QObject::metaObject());
+
+ auto enumMetaType = QMetaType::fromType<Qt::Orientation>();
+ QVERIFY(enumMetaType.isValid());
+
+ builder.addProperty("orientation", "Qt::Orientation", enumMetaType);
+
+ auto *mo = builder.toMetaObject();
+ QVERIFY(mo != nullptr);
+ const int index = mo->indexOfProperty("orientation");
+ QVERIFY(index != -1);
+ QVERIFY(mo->property(index).isEnumType());
+ free(mo);
+}
+
void tst_QMetaObjectBuilder::classInfo()
{
QMetaObjectBuilder builder;
@@ -1711,7 +1732,7 @@ void tst_QMetaObjectBuilder::usage_templateConnect()
testObject.data(), &TestObject::voidSlotInt));
// Something that isn't a signal
- QTest::ignoreMessage(QtWarningMsg, "QObject::connect: signal not found in TestObject");
+ QTest::ignoreMessage(QtWarningMsg, "QObject::connect(TestObject, TestObject): signal not found");
con = QObject::connect(testObject.data(), &TestObject::setIntProp,
testObject.data(), &TestObject::intPropChanged);
QVERIFY(!con);
diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
index 220d3af568b..afb0bf0169a 100644
--- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
+++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
@@ -4864,18 +4864,18 @@ void tst_QObject::pointerConnect()
QVERIFY(!QObject::disconnect(con));
//connect a slot to a signal (== error)
- QTest::ignoreMessage(QtWarningMsg, "QObject::connect: signal not found in ReceiverObject");
+ QTest::ignoreMessage(QtWarningMsg, "QObject::connect(ReceiverObject, SenderObject): signal not found");
con = connect(&r1, &ReceiverObject::slot4 , &s, &SenderObject::signal4);
QVERIFY(!con);
QVERIFY(!QObject::disconnect(con));
//connect an arbitrary PMF to a slot
- QTest::ignoreMessage(QtWarningMsg, "QObject::connect: signal not found in ReceiverObject");
+ QTest::ignoreMessage(QtWarningMsg, "QObject::connect(ReceiverObject, ReceiverObject): signal not found");
con = connect(&r1, &ReceiverObject::reset, &r1, &ReceiverObject::slot1);
QVERIFY(!con);
QVERIFY(!QObject::disconnect(con));
- QTest::ignoreMessage(QtWarningMsg, "QObject::connect: signal not found in ReceiverObject");
+ QTest::ignoreMessage(QtWarningMsg, "QObject::connect(ReceiverObject, ReceiverObject): signal not found");
con = connect(&r1, &ReceiverObject::reset, &r1, [](){});
QVERIFY(!con);
QVERIFY(!QObject::disconnect(con));
diff --git a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp
index adff512e6a3..81316b061d0 100644
--- a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp
+++ b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp
@@ -45,11 +45,11 @@ using namespace std::chrono_literals;
class tst_QTimer : public QObject
{
Q_OBJECT
-public:
- static void initMain();
private slots:
+ void initTestCase();
void cleanupTestCase();
+
void zeroTimer();
void singleShotTimeout();
void timeout();
@@ -1678,11 +1678,11 @@ struct StaticSingleShotUser
};
// NOTE: to prevent any static initialization order fiasco, we implement
-// initMain() to instantiate staticSingleShotUser before qApp
+// initTestCase() to instantiate staticSingleShotUser before qApp
static StaticSingleShotUser *s_staticSingleShotUser = nullptr;
-void tst_QTimer::initMain()
+void tst_QTimer::initTestCase()
{
s_staticSingleShotUser = new StaticSingleShotUser;
}
diff --git a/tests/auto/corelib/serialization/json/tst_qtjson.cpp b/tests/auto/corelib/serialization/json/tst_qtjson.cpp
index 2e0d8dd7be2..dbaf6873af2 100644
--- a/tests/auto/corelib/serialization/json/tst_qtjson.cpp
+++ b/tests/auto/corelib/serialization/json/tst_qtjson.cpp
@@ -3595,7 +3595,7 @@ void tst_QtJson::bom()
QCOMPARE(error.error, QJsonParseError::NoError);
}
-void tst_QtJson::nesting()
+static void nesting_test()
{
// check that we abort parsing too deeply nested json documents.
// this is to make sure we don't crash because the parser exhausts the
@@ -3654,6 +3654,26 @@ void tst_QtJson::nesting()
}
+void tst_QtJson::nesting()
+{
+#if defined(Q_OS_QNX) || defined(Q_OS_VXWORKS) || defined(Q_OS_WASM)
+ // This test misbehaving probably indicates a stack overflow due to the
+ // recursive parser in qjsonparser.cpp. The recursion prevention limit may
+ // be too high for this platform. Someone should investigate.
+ QSKIP("Test freezes or crashes - probably a stack overflow");
+#endif
+
+ QThread *thr = QThread::create(nesting_test);
+#if defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer) || \
+ defined(__SANITIZE_THREAD__) || __has_feature(thread_sanitizer)
+ // force a larger stack size - 8 MB seems sufficient
+ thr->setStackSize(8192 * 1024);
+#endif
+ thr->start();
+ thr->wait();
+ delete thr;
+}
+
void tst_QtJson::longStrings()
{
// test around 15 and 16 bit boundaries, as these are limits
diff --git a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
index 76fcee11b7b..806b6b43161 100644
--- a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
+++ b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
@@ -3998,7 +3998,7 @@ void tst_QFuture::signalConnect()
#if defined(Q_CC_MSVC_ONLY) && (Q_CC_MSVC < 1940 || !defined(_DEBUG))
#define EXPECT_FUTURE_CONNECT_FAIL() QEXPECT_FAIL("", "QTBUG-101761, test fails on Windows/MSVC", Continue)
#else
- QTest::ignoreMessage(QtWarningMsg, "QObject::connect: signal not found in SenderObject");
+ QTest::ignoreMessage(QtWarningMsg, "QObject::connect(SenderObject, SenderObject): signal not found");
#define EXPECT_FUTURE_CONNECT_FAIL()
#endif
diff --git a/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp
index b9e239af31d..fde06d2edd9 100644
--- a/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp
+++ b/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp
@@ -2411,7 +2411,7 @@ void tst_QDateTime::springForward_data()
QTest::newRow("PT from day after")
<< pacific << QDate(2015, 3, 8) << QTime(2, 30) << -1 << -420;
}
- if (const QTimeZone eastern("America/Ottawa"); eastern.isValid()) {
+ if (const QTimeZone eastern("America/Toronto"); eastern.isValid()) {
QTest::newRow("ET from day before")
<< eastern << QDate(2015, 3, 8) << QTime(2, 30) << 1 << -300;
QTest::newRow("ET from day after")
@@ -3500,11 +3500,11 @@ void tst_QDateTime::fromStringStringFormat_localTimeZone_data()
QTest::newRow("local-timezone-ttt-with-zone:Etc/GMT+3")
<< "GMT"_ba << u"2008-10-13 Etc/GMT+3 11.50"_s << u"yyyy-MM-dd ttt hh.mm"_s << 1900
<< QDateTime(); // Zone name not valid when offset expected
- QTimeZone gmtWithOffset("GMT-2");
+ QTimeZone gmtWithOffset("GMT-0");
if (gmtWithOffset.isValid()) {
lacksRows = false;
- QTest::newRow("local-timezone-with-offset:GMT-2")
- << "GMT"_ba << u"2008-10-13 GMT-2 11.50"_s << u"yyyy-MM-dd t hh.mm"_s << 1900
+ QTest::newRow("local-timezone-with-offset:GMT-0")
+ << "GMT"_ba << u"2008-10-13 GMT-0 11.50"_s << u"yyyy-MM-dd t hh.mm"_s << 1900
<< QDateTime(QDate(2008, 10, 13), QTime(11, 50), gmtWithOffset);
}
QTimeZone gmt("GMT");
diff --git a/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp b/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp
index 3b66ad76a2f..6a72b5ddf38 100644
--- a/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp
+++ b/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp
@@ -1887,12 +1887,14 @@ void tst_QTimeZone::roundtripDisplayNames_data()
"UTC"_ba,
// Those named overtly in tst_QDateTime - special cases first:
"UTC-02:00"_ba, "UTC+02:00"_ba, "UTC+12:00"_ba,
- "Etc/GMT+3"_ba, "GMT-2"_ba, "GMT"_ba,
+ "Etc/GMT+3"_ba, "GMT-0"_ba, "GMT"_ba,
// ... then ordinary names in alphabetic order:
- "America/New_York"_ba, "America/Sao_Paulo"_ba, "America/Vancouver"_ba,
- "Asia/Kathmandu"_ba, "Asia/Singapore"_ba,
+ "America/Anchorage"_ba, "America/Metlakatla"_ba, "America/New_York"_ba,
+ "America/Sao_Paulo"_ba, "America/Toronto"_ba, "America/Vancouver"_ba,
+ "Asia/Kathmandu"_ba, "Asia/Manila"_ba, "Asia/Singapore"_ba,
"Australia/Brisbane"_ba, "Australia/Eucla"_ba, "Australia/Sydney"_ba,
- "Europe/Berlin"_ba, "Europe/Helsinki"_ba, "Europe/Rome"_ba, "Europe/Oslo"_ba,
+ "Europe/Berlin"_ba, "Europe/Helsinki"_ba, "Europe/Lisbon"_ba, "Europe/Oslo"_ba,
+ "Europe/Rome"_ba,
"Pacific/Apia"_ba, "Pacific/Auckland"_ba, "Pacific/Kiritimati"_ba,
"Vulcan/ShiKahr"_ba // Invalid: also worth testing.
};
diff --git a/tests/auto/corelib/tools/qhash/tst_qhash.cpp b/tests/auto/corelib/tools/qhash/tst_qhash.cpp
index b03750389bd..8ec9cb516d3 100644
--- a/tests/auto/corelib/tools/qhash/tst_qhash.cpp
+++ b/tests/auto/corelib/tools/qhash/tst_qhash.cpp
@@ -3153,6 +3153,8 @@ qHash(const StdHashKeyType<HasQHash> &s, size_t seed)
template <typename T>
void stdHashImpl()
{
+ T::StdHashUsed = false;
+
QHash<T, int> hash;
for (int i = 0; i < 1000; ++i)
hash.insert(T{i}, i);
diff --git a/tests/auto/corelib/tools/qlist/tst_qlist.cpp b/tests/auto/corelib/tools/qlist/tst_qlist.cpp
index e84c35691da..a19cebe3faf 100644
--- a/tests/auto/corelib/tools/qlist/tst_qlist.cpp
+++ b/tests/auto/corelib/tools/qlist/tst_qlist.cpp
@@ -121,6 +121,84 @@ Q_DECLARE_TYPEINFO(Movable, Q_RELOCATABLE_TYPE);
QT_END_NAMESPACE
Q_DECLARE_METATYPE(Movable);
+struct NoexceptMovable
+{
+ NoexceptMovable(char input = 'j') noexcept
+ : i(input)
+ {
+ counter.fetchAndAddRelaxed(1);
+ }
+ NoexceptMovable(const NoexceptMovable &other) noexcept
+ : i(other.i)
+ {
+ check(other.state, Constructed);
+ counter.fetchAndAddRelaxed(1);
+ }
+ NoexceptMovable(NoexceptMovable &&other) noexcept
+ : i(other.i)
+ {
+ check(other.state, Constructed);
+ counter.fetchAndAddRelaxed(1);
+ other.that = nullptr;
+ }
+
+ ~NoexceptMovable() // implicitly noexcept
+ {
+ check(state, Constructed);
+ i = 0;
+ counter.fetchAndAddRelaxed(-1);
+ state = Destructed; // this is likely a dead store
+ }
+
+ bool operator ==(const NoexceptMovable &other) const noexcept
+ {
+ check(state, Constructed);
+ check(other.state, Constructed);
+ return i == other.i;
+ }
+
+ NoexceptMovable &operator=(const NoexceptMovable &other) noexcept
+ {
+ check(state, Constructed);
+ check(other.state, Constructed);
+ i = other.i;
+ that = this;
+ return *this;
+ }
+ NoexceptMovable &operator=(NoexceptMovable &&other) noexcept
+ {
+ check(state, Constructed);
+ check(other.state, Constructed);
+ i = other.i;
+ that = other.that;
+ other.that = nullptr;
+ return *this;
+ }
+ bool wasConstructedAt(const NoexceptMovable *other) const noexcept
+ {
+ return that == other;
+ }
+ char i;
+ static inline QAtomicInt counter;
+private:
+ NoexceptMovable *that = this; // used to check if an instance was moved
+
+ enum State { Constructed = 106, Destructed = 110 };
+ State state = Constructed;
+
+ static void check(const State state1, const State state2) noexcept
+ {
+ QCOMPARE(state1, state2);
+ }
+
+ friend inline size_t qHash(const NoexceptMovable &key, size_t seed) noexcept
+ { return qHash(key.i, seed); }
+};
+
+QT_BEGIN_NAMESPACE
+Q_DECLARE_TYPEINFO(NoexceptMovable, Q_RELOCATABLE_TYPE);
+QT_END_NAMESPACE
+
struct Custom {
Custom(char input = 'j')
: i(input)
@@ -225,37 +303,47 @@ private slots:
void constructors_reserveAndInitialize() const;
void copyConstructorInt() const { copyConstructor<int>(); }
void copyConstructorMovable() const { copyConstructor<Movable>(); }
+ void copyConstructorNoexceptMovable() const { copyConstructor<NoexceptMovable>(); }
void copyConstructorCustom() const { copyConstructor<Custom>(); }
void assignmentInt() const { testAssignment<int>(); }
void assignmentMovable() const { testAssignment<Movable>(); }
+ void assignmentNoexceptMovable() const { testAssignment<NoexceptMovable>(); }
void assignmentCustom() const { testAssignment<Custom>(); }
void assignFromInitializerListInt() const { assignFromInitializerList<int>(); }
void assignFromInitializerListMovable() const { assignFromInitializerList<Movable>(); }
+ void assignFromInitializerListNoexceptMovable() const { assignFromInitializerList<NoexceptMovable>(); }
void assignFromInitializerListCustom() const { assignFromInitializerList<Custom>(); }
void addInt() const { add<int>(); }
void addMovable() const { add<Movable>(); }
+ void addNoexceptMovable() const { add<NoexceptMovable>(); }
void addCustom() const { add<Custom>(); }
void appendInt() const { append<int>(); }
void appendMovable() const { append<Movable>(); }
+ void appendNoexceptMovable() const { append<NoexceptMovable>(); }
void appendCustom() const { append<Custom>(); }
void appendRvalue() const;
void appendList() const;
void assignEmpty() const;
void assignInt() const { assign<int>(); }
void assignMovable() const { assign<Movable>(); }
+ void assignNoexceptMovable() const { assign<NoexceptMovable>(); }
void assignCustom() const { assign<Custom>(); }
void assignUsesPrependBuffer_int_data() { assignUsesPrependBuffer_data(); }
void assignUsesPrependBuffer_int() const { assignUsesPrependBuffer<int>(); }
void assignUsesPrependBuffer_Movable_data() { assignUsesPrependBuffer_data(); }
void assignUsesPrependBuffer_Movable() const { assignUsesPrependBuffer<Movable>(); }
+ void assignUsesPrependBuffer_NoexceptMovable_data() { assignUsesPrependBuffer_data(); }
+ void assignUsesPrependBuffer_NoexceptMovable() const { assignUsesPrependBuffer<NoexceptMovable>(); }
void assignUsesPrependBuffer_Custom_data() { assignUsesPrependBuffer_data(); }
void assignUsesPrependBuffer_Custom() const { assignUsesPrependBuffer<Custom>(); }
void at() const;
void capacityInt() const { capacity<int>(); }
void capacityMovable() const { capacity<Movable>(); }
+ void capacityNoexceptMovable() const { capacity<NoexceptMovable>(); }
void capacityCustom() const { capacity<Custom>(); }
void clearInt() const { clear<int>(); }
void clearMovable() const { clear<Movable>(); }
+ void clearNoexceptMovable() const { clear<NoexceptMovable>(); }
void clearCustom() const { clear<Custom>(); }
void constData() const;
void constFirst() const;
@@ -263,43 +351,54 @@ private slots:
void contains() const;
void countInt() const { count<int>(); }
void countMovable() const { count<Movable>(); }
+ void countNoexceptMovable() const { count<NoexceptMovable>(); }
void countCustom() const { count<Custom>(); }
void cpp17ctad() const;
void data() const;
void reinterpreted() const;
void emptyInt() const { empty<int>(); }
void emptyMovable() const { empty<Movable>(); }
+ void emptyNoexceptMovable() const { empty<NoexceptMovable>(); }
void emptyCustom() const { empty<Custom>(); }
void endsWith() const;
void eraseEmptyInt() const { eraseEmpty<int>(); }
void eraseEmptyMovable() const { eraseEmpty<Movable>(); }
+ void eraseEmptyNoexceptMovable() const { eraseEmpty<NoexceptMovable>(); }
void eraseEmptyCustom() const { eraseEmpty<Custom>(); }
void eraseEmptyReservedInt() const { eraseEmptyReserved<int>(); }
void eraseEmptyReservedMovable() const { eraseEmptyReserved<Movable>(); }
+ void eraseEmptyReservedNoexceptMovable() const { eraseEmptyReserved<NoexceptMovable>(); }
void eraseEmptyReservedCustom() const { eraseEmptyReserved<Custom>(); }
void eraseInt() const { erase<int>(false); }
void eraseIntShared() const { erase<int>(true); }
void eraseMovable() const { erase<Movable>(false); }
+ void eraseNoexceptMovable() const { erase<NoexceptMovable>(false); }
void eraseMovableShared() const { erase<Movable>(true); }
+ void eraseNoexceptMovableShared() const { erase<NoexceptMovable>(true); }
void eraseCustom() const { erase<Custom>(false); }
void eraseCustomShared() const { erase<Custom>(true); }
void eraseReservedInt() const { eraseReserved<int>(); }
void eraseReservedMovable() const { eraseReserved<Movable>(); }
+ void eraseReservedNoexceptMovable() const { eraseReserved<NoexceptMovable>(); }
void eraseReservedCustom() const { eraseReserved<Custom>(); }
void fillInt() const { fill<int>(); }
void fillMovable() const { fill<Movable>(); }
+ void fillNoexceptMovable() const { fill<NoexceptMovable>(); }
void fillCustom() const { fill<Custom>(); }
void fillDetachInt() const { fillDetach<int>(); }
void fillDetachMovable() const { fillDetach<Movable>(); }
+ void fillDetachNoexceptMovable() const { fillDetach<NoexceptMovable>(); }
void fillDetachCustom() const { fillDetach<Custom>(); }
void first() const;
void freeSpaceAtBeginEventuallyShrinks() const;
void fromListInt() const { fromList<int>(); }
void fromListMovable() const { fromList<Movable>(); }
+ void fromListNoexceptMovable() const { fromList<NoexceptMovable>(); }
void fromListCustom() const { fromList<Custom>(); }
void indexOf() const;
void insertInt() const { insert<int>(); }
void insertMovable() const { insert<Movable>(); }
+ void insertNoexceptMovable() const { insert<NoexceptMovable>(); }
void insertCustom() const { insert<Custom>(); }
void insertZeroCount_data();
void insertZeroCount() const;
@@ -310,17 +409,21 @@ private slots:
void sliced() const;
void moveInt() const { move<int>(); }
void moveMovable() const { move<Movable>(); }
+ void moveNoexceptMovable() const { move<NoexceptMovable>(); }
void moveCustom() const { move<Custom>(); }
void prependInt() const { prepend<int>(); }
void prependMovable() const { prepend<Movable>(); }
+ void prependNoexceptMovable() const { prepend<NoexceptMovable>(); }
void prependCustom() const { prepend<Custom>(); }
void prependRvalue() const;
void qhashInt() const { qhash<int>(); }
void qhashMovable() const { qhash<Movable>(); }
+ void qhashNoexceptMovable() const { qhash<NoexceptMovable>(); }
void qhashCustom() const { qhash<Custom>(); }
void removeAllWithAlias() const;
void removeInt() const { remove<int>(); }
void removeMovable() const { remove<Movable>(); }
+ void removeNoexceptMovable() const { remove<NoexceptMovable>(); }
void removeCustom() const { remove<Custom>(); }
void removeFirstLast() const;
void resizePOD_data() const;
@@ -339,10 +442,12 @@ private slots:
void reverseIterators() const;
void sizeInt() const { size<int>(); }
void sizeMovable() const { size<Movable>(); }
+ void sizeNoexceptMovable() const { size<NoexceptMovable>(); }
void sizeCustom() const { size<Custom>(); }
void startsWith() const;
void swapInt() const { swap<int>(); }
void swapMovable() const { swap<Movable>(); }
+ void swapNoexceptMovable() const { swap<NoexceptMovable>(); }
void swapCustom() const { swap<Custom>(); }
void toAddress() const;
void toList() const;
@@ -356,10 +461,12 @@ private slots:
void reserveZero();
void initializeListInt() { initializeList<int>(); }
void initializeListMovable() { initializeList<Movable>(); }
+ void initializeListNoexceptMovable() { initializeList<NoexceptMovable>(); }
void initializeListCustom() { initializeList<Custom>(); }
void const_shared_null();
void detachInt() const { detach<int>(); }
void detachMovable() const { detach<Movable>(); }
+ void detachNoexceptMovable() const { detach<NoexceptMovable>(); }
void detachCustom() const { detach<Custom>(); }
void detachThreadSafetyInt() const;
void detachThreadSafetyMovable() const;
@@ -369,9 +476,11 @@ private slots:
void emplaceInt() { emplaceImpl<int>(); }
void emplaceCustom() { emplaceImpl<Custom>(); }
void emplaceMovable() { emplaceImpl<Movable>(); }
+ void emplaceNoexceptMovable() { emplaceImpl<NoexceptMovable>(); }
void emplaceConsistentWithStdVectorInt() { emplaceConsistentWithStdVectorImpl<int>(); }
void emplaceConsistentWithStdVectorCustom() { emplaceConsistentWithStdVectorImpl<Custom>(); }
void emplaceConsistentWithStdVectorMovable() { emplaceConsistentWithStdVectorImpl<Movable>(); }
+ void emplaceConsistentWithStdVectorNoexceptMovable() { emplaceConsistentWithStdVectorImpl<NoexceptMovable>(); }
void emplaceConsistentWithStdVectorQString() { emplaceConsistentWithStdVectorImpl<QString>(); }
void emplaceReturnsIterator();
void emplaceFront() const;
@@ -383,35 +492,45 @@ private slots:
void replaceInt() const { replace<int>(); }
void replaceCustom() const { replace<Custom>(); }
void replaceMovable() const { replace<Movable>(); }
+ void replaceNoexceptMovable() const { replace<NoexceptMovable>(); }
void fromReadOnlyData() const;
void reallocateCustomAlignedType_qtbug90359() const;
void reinsertToBeginInt_qtbug91360() const { reinsertToBegin<int>(); }
void reinsertToBeginMovable_qtbug91360() const { reinsertToBegin<Movable>(); }
+ void reinsertToBeginNoexceptMovable_qtbug91360() const { reinsertToBegin<NoexceptMovable>(); }
void reinsertToBeginCustom_qtbug91360() const { reinsertToBegin<Custom>(); }
void reinsertToEndInt_qtbug91360() const { reinsertToEnd<int>(); }
void reinsertToEndMovable_qtbug91360() const { reinsertToEnd<Movable>(); }
+ void reinsertToEndNoexceptMovable_qtbug91360() const { reinsertToEnd<NoexceptMovable>(); }
void reinsertToEndCustom_qtbug91360() const { reinsertToEnd<Custom>(); }
void reinsertRangeToEndInt_qtbug91360() const { reinsertRangeToEnd<int>(); }
void reinsertRangeToEndMovable_qtbug91360() const { reinsertRangeToEnd<Movable>(); }
+ void reinsertRangeToEndNoexceptMovable_qtbug91360() const { reinsertRangeToEnd<NoexceptMovable>(); }
void reinsertRangeToEndCustom_qtbug91360() const { reinsertRangeToEnd<Custom>(); }
// QList reference stability tests:
void stability_reserveInt() const { stability_reserve<int>(); }
void stability_reserveMovable() const { stability_reserve<Movable>(); }
+ void stability_reserveNoexceptMovable() const { stability_reserve<NoexceptMovable>(); }
void stability_reserveCustom() const { stability_reserve<Custom>(); }
void stability_eraseInt() const { stability_erase<int>(); }
void stability_eraseMovable() const { stability_erase<Movable>(); }
+ void stability_eraseNoexceptMovable() const { stability_erase<NoexceptMovable>(); }
void stability_eraseCustom() const { stability_erase<Custom>(); }
void stability_appendInt() const { stability_append<int>(); }
void stability_appendMovable() const { stability_append<Movable>(); }
+ void stability_appendNoexceptMovable() const { stability_append<NoexceptMovable>(); }
void stability_appendCustom() const { stability_append<Custom>(); }
void stability_insertElementInt() const { stability_insertElement<int>(); }
void stability_insertElementMovable() const { stability_insertElement<Movable>(); }
+ void stability_insertElementNoexceptMovable() const { stability_insertElement<NoexceptMovable>(); }
void stability_insertElementCustom() const { stability_insertElement<Custom>(); }
void stability_emplaceInt() const { stability_emplace<int>(); }
void stability_emplaceMovable() const { stability_emplace<Movable>(); }
+ void stability_emplaceNoexceptMovable() const { stability_emplace<NoexceptMovable>(); }
void stability_emplaceCustom() const { stability_emplace<Custom>(); }
void stability_resizeInt() const { stability_resize<int>(); }
void stability_resizeMovable() const { stability_resize<Movable>(); }
+ void stability_resizeNoexceptMovable() const { stability_resize<NoexceptMovable>(); }
void stability_resizeCustom() const { stability_resize<Custom>(); }
private:
@@ -515,16 +634,9 @@ template<typename T> struct SimpleValue
}
static const uint MaxIndex = 6;
- static const T Values[MaxIndex];
+ static inline const T Values[MaxIndex] = { 110, 105, 101, 114, 111, 98 };
};
-template<>
-const int SimpleValue<int>::Values[] = { 110, 105, 101, 114, 111, 98 };
-template<>
-const Movable SimpleValue<Movable>::Values[] = { 110, 105, 101, 114, 111, 98 };
-template<>
-const Custom SimpleValue<Custom>::Values[] = { 110, 105, 101, 114, 111, 98 };
-
// Make some macros for the tests to use in order to be slightly more readable...
#define T_FOO SimpleValue<T>::at(0)
#define T_BAR SimpleValue<T>::at(1)
@@ -656,12 +768,36 @@ void tst_QList::assignFromInitializerList() const
T val2(SimpleValue<T>::at(2));
T val3(SimpleValue<T>::at(3));
- QList<T> v1 = {val1, val2, val3};
+ QList<T> v1 = {};
+ QCOMPARE(v1.size(), 0);
+
+ v1 = {val1, val2, val3};
QCOMPARE(v1, QList<T>() << val1 << val2 << val3);
QCOMPARE(v1, (QList<T> {val1, val2, val3}));
v1 = {};
QCOMPARE(v1.size(), 0);
+
+ // repeat, but make v1 shared before we assign
+ QList v2 = {val3, val1, val2};
+ v1 = v2;
+ v1 = {val1, val2, val3};
+ QCOMPARE(v1, QList<T>() << val1 << val2 << val3);
+ QCOMPARE(v1, (QList<T> {val1, val2, val3}));
+ v1 = v2;
+ v1 = {};
+ QCOMPARE(v1.size(), 0);
+
+ // repeat again, but now detached copies
+ v1 = v2;
+ v1.detach();
+ v1 = {val1, val2, val3};
+ QCOMPARE(v1, QList<T>() << val1 << val2 << val3);
+ QCOMPARE(v1, (QList<T> {val1, val2, val3}));
+ v1 = v2;
+ v1.detach();
+ v1 = {};
+ QCOMPARE(v1.size(), 0);
}
template<typename T>
@@ -834,6 +970,65 @@ void tst_QList::assign() const
QVERIFY(!myvecCopy.isSharedWith(myvec));
QCOMPARE(myvecCopy, QList<T>() << T_FOO << T_FOO);
}
+
+ // test assigning an empty range to an empty list
+ {
+ QList<T> myvec, empty;
+
+ const T *ptr = nullptr;
+ myvec.assign(ptr, ptr);
+ QVERIFY(myvec.isEmpty());
+
+ ptr = SimpleValue<T>::Values + 3;
+ myvec.assign(ptr, ptr);
+ QVERIFY(myvec.isEmpty());
+ }
+
+ // test assigning empty to non-empty
+ {
+ QList<T> nonempty = SimpleValue<T>::vector(2);
+ QList<T> myvec;
+
+ const T *ptr = nullptr;
+ myvec = nonempty;
+ myvec.assign(ptr, ptr);
+ QVERIFY(myvec.isEmpty());
+
+ ptr = SimpleValue<T>::Values + 3;
+ myvec = nonempty;
+ myvec.assign(ptr, ptr);
+ QVERIFY(myvec.isEmpty());
+
+ // repeat, after having detached
+ ptr = nullptr;
+ myvec = nonempty;
+ myvec.detach();
+ myvec.assign(ptr, ptr);
+ QVERIFY(myvec.isEmpty());
+
+ ptr = SimpleValue<T>::Values + 3;
+ myvec = nonempty;
+ myvec.detach();
+ myvec.assign(ptr, ptr);
+ QVERIFY(myvec.isEmpty());
+ }
+
+ // assign a smaller range
+ {
+ QList<T> myvec = SimpleValue<T>::vector(3);
+ QCOMPARE(myvec.size(), 3);
+
+ myvec.assign(SimpleValue<T>::Values + 3, SimpleValue<T>::Values + 5);
+ QCOMPARE(myvec.size(), 2);
+ QCOMPARE(myvec.at(0), T_CAT);
+ QCOMPARE(myvec.at(1), T_DOG);
+
+ // with detaching:
+ QList copy = myvec;
+ myvec.assign(SimpleValue<T>::Values, SimpleValue<T>::Values + 1);
+ QCOMPARE(myvec.size(), 1);
+ QCOMPARE(myvec.at(0), T_FOO);
+ }
}
inline namespace Scenarios {
@@ -2108,10 +2303,15 @@ void tst_QList::qhash() const
TST_QLIST_CHECK_LEAKS(T)
QList<T> l1, l2;
- QCOMPARE(qHash(l1), qHash(l2));
+ QCOMPARE(qHash(l1, 0), qHash(l2, 0));
l1 << SimpleValue<T>::at(0);
l2 << SimpleValue<T>::at(0);
- QCOMPARE(qHash(l1), qHash(l2));
+ QCOMPARE(qHash(l1, 0), qHash(l2, 0));
+
+ QCOMPARE(qHash(l1, 1), qHash(l2, 1));
+ l1.clear();
+ l2.clear();
+ QCOMPARE(qHash(l1, 1), qHash(l2, 1));
}
template <typename T>
diff --git a/tests/auto/corelib/tools/qscopeguard/tst_qscopeguard.cpp b/tests/auto/corelib/tools/qscopeguard/tst_qscopeguard.cpp
index 1dadbb9efea..b3f96588304 100644
--- a/tests/auto/corelib/tools/qscopeguard/tst_qscopeguard.cpp
+++ b/tests/auto/corelib/tools/qscopeguard/tst_qscopeguard.cpp
@@ -26,6 +26,8 @@ private Q_SLOTS:
void optionalGuard();
void leavingScope();
void exceptions();
+
+ void init();
};
void func()
@@ -169,7 +171,6 @@ void tst_QScopeGuard::leavingScope()
void tst_QScopeGuard::exceptions()
{
- s_globalState = 0;
bool caught = false;
QT_TRY
{
@@ -187,5 +188,10 @@ void tst_QScopeGuard::exceptions()
}
+void tst_QScopeGuard::init()
+{
+ s_globalState = 0;
+}
+
QTEST_MAIN(tst_QScopeGuard)
#include "tst_qscopeguard.moc"
diff --git a/tests/auto/gui/kernel/qsurfaceformat/tst_qsurfaceformat.cpp b/tests/auto/gui/kernel/qsurfaceformat/tst_qsurfaceformat.cpp
index 3f655bd905d..28085e1405f 100644
--- a/tests/auto/gui/kernel/qsurfaceformat/tst_qsurfaceformat.cpp
+++ b/tests/auto/gui/kernel/qsurfaceformat/tst_qsurfaceformat.cpp
@@ -54,10 +54,10 @@ void tst_QSurfaceFormat::versionCheck()
format.setMinorVersion(formatMinor);
format.setMajorVersion(formatMajor);
- QCOMPARE(format.version() >= qMakePair(compareMajor, compareMinor), expected);
+ QCOMPARE(format.version() >= std::pair(compareMajor, compareMinor), expected);
format.setVersion(formatMajor, formatMinor);
- QCOMPARE(format.version() >= qMakePair(compareMajor, compareMinor), expected);
+ QCOMPARE(format.version() >= std::pair(compareMajor, compareMinor), expected);
}
#include <tst_qsurfaceformat.moc>
diff --git a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp
index 64add80907a..7dac778d5ff 100644
--- a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp
+++ b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp
@@ -292,6 +292,8 @@ private slots:
void alphaBlitToNonAlphaFormats_data();
void alphaBlitToNonAlphaFormats();
+ void floatRounding();
+
private:
void fillData();
void setPenColor(QPainter& p);
@@ -3843,26 +3845,23 @@ void tst_QPainter::linearGradientSymmetry_data()
QTest::addColumn<QGradientStops>("stops");
if (sizeof(qreal) != sizeof(float)) {
- QGradientStops stops;
- stops << qMakePair(qreal(0.0), QColor(Qt::blue));
- stops << qMakePair(qreal(0.2), QColor(220, 220, 220, 0));
- stops << qMakePair(qreal(0.6), QColor(Qt::red));
- stops << qMakePair(qreal(0.9), QColor(220, 220, 220, 255));
- stops << qMakePair(qreal(1.0), QColor(Qt::black));
+ QGradientStops stops = {{qreal(0.0), QColor(Qt::blue)},
+ {qreal(0.2), QColor(220, 220, 220, 0)},
+ {qreal(0.6), QColor(Qt::red)},
+ {qreal(0.9), QColor(220, 220, 220, 255)},
+ {qreal(1.0), QColor(Qt::black)}};
QTest::newRow("multiple stops") << stops;
}
{
- QGradientStops stops;
- stops << qMakePair(qreal(0.0), QColor(Qt::blue));
- stops << qMakePair(qreal(1.0), QColor(Qt::black));
+ QGradientStops stops = {{qreal(0.0), QColor(Qt::blue)},
+ {qreal(1.0), QColor(Qt::black)}};
QTest::newRow("two stops") << stops;
}
if (sizeof(qreal) != sizeof(float)) {
- QGradientStops stops;
- stops << qMakePair(qreal(0.3), QColor(Qt::blue));
- stops << qMakePair(qreal(0.6), QColor(Qt::black));
+ QGradientStops stops = {{qreal(0.3), QColor(Qt::blue)},
+ {qreal(0.6), QColor(Qt::black)}};
QTest::newRow("two stops 2") << stops;
}
}
@@ -3913,12 +3912,10 @@ void tst_QPainter::gradientPixelFormat()
QImage a(8, 64, QImage::Format_ARGB32_Premultiplied);
QImage b(8, 64, format);
-
- QGradientStops stops;
- stops << qMakePair(qreal(0.0), QColor(Qt::blue));
- stops << qMakePair(qreal(0.3), QColor(Qt::red));
- stops << qMakePair(qreal(0.6), QColor(Qt::green));
- stops << qMakePair(qreal(1.0), QColor(Qt::black));
+ QGradientStops stops = {{qreal(0.0), QColor(Qt::blue)},
+ {qreal(0.3), QColor(Qt::red)},
+ {qreal(0.6), QColor(Qt::green)},
+ {qreal(1.0), QColor(Qt::black)}};
a.fill(0);
b.fill(0);
@@ -5751,6 +5748,30 @@ void tst_QPainter::alphaBlitToNonAlphaFormats()
}
}
+void tst_QPainter::floatRounding()
+{
+ // oss-fuzz issue 429123947
+ // The following triggered an assert in QDashStroker::processCurrentSubpath(): "dpos >= 0"
+ // when it expected the calculation's result to be zero but it was actually smaller:
+ // qreal(4) + qreal(0.1) - qreal(0.1) - qreal(4)
+ // actual result: -4.440892098500626e-16
+ QImage img(5, 5, QImage::Format_RGB888);
+ QPainter p(&img);
+
+ QList<qreal> pattern {0.1, 0.3, 0.1, 0.1, 0.3, 0.1};
+ QPainterPathStroker stroker;
+ stroker.setDashPattern(pattern);
+
+ QPainterPath pp;
+ pp.moveTo(4.0, 0.0);
+ pp.lineTo(0.1, 0.0);
+ pp.lineTo(0.0, 0.0);
+ pp.lineTo(0.0, 5.0);
+
+ QPolygonF poly = stroker.createStroke(pp).toFillPolygon();
+ p.drawPolygon(poly);
+}
+
QTEST_MAIN(tst_QPainter)
#include "tst_qpainter.moc"
diff --git a/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp b/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp
index bd9e00fc376..7b4193e3749 100644
--- a/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp
+++ b/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp
@@ -86,6 +86,9 @@ private slots:
void intersectionPointOnEdge();
void boundsAtStartPoint();
+
+ void percentAtEmptyPath_data();
+ void percentAtEmptyPath();
};
void tst_QPainterPath::cleanupTestCase()
@@ -1637,6 +1640,29 @@ void tst_QPainterPath::boundsAtStartPoint()
QCOMPARE(constructedPath.controlPointRect(), defaultPath.controlPointRect());
}
+void tst_QPainterPath::percentAtEmptyPath_data()
+{
+ const QPointF qpf(2., 2.);
+ QTest::addColumn<QPainterPath>("path");
+
+ QTest::newRow("defaultConstructed") << QPainterPath();
+ QTest::newRow("withStartPoint") << QPainterPath(qpf);
+ QPainterPath pp(qpf);
+ pp.lineTo(qpf);
+ QTest::newRow("equalPoints") << pp;
+}
+
+void tst_QPainterPath::percentAtEmptyPath()
+{
+ QFETCH(QPainterPath, path);
+
+ path.angleAtPercent(0.5);
+ path.pointAtPercent(0.5);
+ path.slopeAtPercent(0.5);
+
+ path.percentAtLength(0);
+}
+
QTEST_APPLESS_MAIN(tst_QPainterPath)
#include "tst_qpainterpath.moc"
diff --git a/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp b/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp
index ab0e8693644..511007e0ae4 100644
--- a/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp
+++ b/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp
@@ -3525,7 +3525,7 @@ void tst_QRhi::renderToTextureMultipleUniformBuffersAndDynamicOffset()
// "see" an all zero matrix and zero opacity, thus leading to different
// rendering output. This way we can verify if using dynamic offsets, and
// more than one at the same time, is functional.
- QVarLengthArray<QPair<int, quint32>, 2> dynamicOffset = {
+ QVarLengthArray<std::pair<int, quint32>, 2> dynamicOffset = {
{ 0, quint32(ubufElemSize * 2) },
{ 1, quint32(ubuf2ElemSize * 3) },
};
diff --git a/tests/auto/gui/rhi/qshader/tst_qshader.cpp b/tests/auto/gui/rhi/qshader/tst_qshader.cpp
index 9e179c95c35..371da0d800c 100644
--- a/tests/auto/gui/rhi/qshader/tst_qshader.cpp
+++ b/tests/auto/gui/rhi/qshader/tst_qshader.cpp
@@ -279,7 +279,7 @@ void tst_QShader::mslResourceMapping()
QCOMPARE(resMap.size(), 2);
QCOMPARE(resMap.value(0).first, 0); // mapped to native buffer index 0
- QCOMPARE(resMap.value(1), qMakePair(0, 0)); // mapped to native texture index 0 and sampler index 0
+ QCOMPARE(resMap.value(1), std::pair(0, 0)); // mapped to native texture index 0 and sampler index 0
}
void tst_QShader::serializeShaderDesc()
@@ -667,7 +667,8 @@ void tst_QShader::loadV7()
QCOMPARE(tese.description().inputBuiltinVariables()[3].type, QShaderDescription::TessCoordBuiltin);
QCOMPARE(tese.nativeResourceBindingMap(QShaderKey(QShader::MslShader, QShaderVersion(12))).size(), 1);
- QCOMPARE(tese.nativeResourceBindingMap(QShaderKey(QShader::MslShader, QShaderVersion(12))).value(0), qMakePair(0, -1));
+ QCOMPARE(tese.nativeResourceBindingMap(QShaderKey(QShader::MslShader, QShaderVersion(12))).value(0),
+ std::pair(0, -1));
QShader frag = getShader(QLatin1String(":/data/metal_enabled_tessellation_v7.frag.qsb"));
QVERIFY(frag.isValid());
diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
index fa1d70a942b..fdc2dde7921 100644
--- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
+++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
@@ -781,7 +781,7 @@ private:
void parseContentLength()
{
- int index = receivedData.indexOf("content-length:");
+ int index = receivedData.toLower().indexOf("content-length:");
if (index == -1)
return;
@@ -3620,7 +3620,7 @@ void tst_QNetworkReply::connectToIPv6Address()
QByteArray content = reply->readAll();
//qDebug() << server.receivedData;
QByteArray hostinfo = "\r\nhost: " + hostfield + ':' + QByteArray::number(server.serverPort()) + "\r\n";
- QVERIFY(server.receivedData.contains(hostinfo));
+ QVERIFY(server.receivedData.toLower().contains(hostinfo));
QCOMPARE(content, dataToSend);
QCOMPARE(reply->url(), request.url());
QCOMPARE(reply->error(), error);
@@ -8793,7 +8793,11 @@ void tst_QNetworkReply::httpUserAgent()
QVERIFY(reply->isFinished());
QCOMPARE(reply->error(), QNetworkReply::NoError);
- QVERIFY(server.receivedData.contains("\r\nuser-agent: abcDEFghi\r\n"));
+ const char userAgentSearch[] = "\r\nuser-agent: ";
+ qsizetype userAgentIndex = server.receivedData.toLower().indexOf(userAgentSearch);
+ QCOMPARE_NE(userAgentIndex, -1);
+ userAgentIndex += sizeof(userAgentSearch) - 1;
+ QVERIFY(server.receivedData.slice(userAgentIndex).startsWith("abcDEFghi\r\n"));
}
void tst_QNetworkReply::synchronousAuthenticationCache()
@@ -8813,7 +8817,7 @@ void tst_QNetworkReply::synchronousAuthenticationCache()
"content-type: text/plain\r\n"
"\r\n"
"auth";
- QRegularExpression rx("authorization: Basic ([^\r\n]*)\r\n");
+ QRegularExpression rx("[Aa]uthorization: Basic ([^\r\n]*)\r\n");
QRegularExpressionMatch match = rx.match(receivedData);
if (match.hasMatch()) {
if (QByteArray::fromBase64(match.captured(1).toLatin1()) == "login:password") {
@@ -9526,7 +9530,7 @@ void tst_QNetworkReply::ioHttpCookiesDuringRedirect()
manager.setRedirectPolicy(oldRedirectPolicy);
QVERIFY(waitForFinish(reply) == Success);
- QVERIFY(target.receivedData.contains("\r\ncookie: hello=world\r\n"));
+ QVERIFY(target.receivedData.toLower().contains("\r\ncookie: hello=world\r\n"));
QVERIFY(validateRedirectedResponseHeaders(reply));
}
@@ -10439,7 +10443,7 @@ void tst_QNetworkReply::contentEncoding()
{
// Check that we included the content encoding method in our Accept-Encoding header
const QByteArray &receivedData = server.receivedData;
- int start = receivedData.indexOf("accept-encoding");
+ int start = receivedData.toLower().indexOf("accept-encoding");
QVERIFY(start != -1);
int end = receivedData.indexOf("\r\n", start);
QVERIFY(end != -1);
diff --git a/tests/auto/network/access/qnetworkreply_local/minihttpserver.h b/tests/auto/network/access/qnetworkreply_local/minihttpserver.h
index daad88cdbcc..ae1069d7a7d 100644
--- a/tests/auto/network/access/qnetworkreply_local/minihttpserver.h
+++ b/tests/auto/network/access/qnetworkreply_local/minihttpserver.h
@@ -152,7 +152,7 @@ private:
void parseContentLength(State &st, QByteArrayView header)
{
- qsizetype index = header.indexOf("\r\ncontent-length:");
+ qsizetype index = header.toByteArray().toLower().indexOf("\r\ncontent-length:");
if (index == -1)
return;
st.foundContentLength = true;
diff --git a/tests/auto/network/access/qnetworkreply_local/tst_qnetworkreply_local.cpp b/tests/auto/network/access/qnetworkreply_local/tst_qnetworkreply_local.cpp
index 8bed904c230..977a047c58e 100644
--- a/tests/auto/network/access/qnetworkreply_local/tst_qnetworkreply_local.cpp
+++ b/tests/auto/network/access/qnetworkreply_local/tst_qnetworkreply_local.cpp
@@ -270,7 +270,7 @@ void tst_QNetworkReply_local::fullServerName()
QVERIFY(receivedData.startsWith(expectedGet));
const QByteArray expectedHost = "host: " % url.host().toUtf8() % "\r\n";
- QVERIFY(receivedData.contains(expectedHost));
+ QVERIFY(receivedData.toLower().contains(expectedHost));
}
#endif
diff --git a/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp b/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp
index 0d2b7bfde64..7417f0648e4 100644
--- a/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp
+++ b/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp
@@ -30,6 +30,7 @@ public:
tst_QHostAddress();
private slots:
+ void constructor();
void constructor_QString_data();
void constructor_QString();
void setAddress_QString_data();
@@ -62,6 +63,43 @@ tst_QHostAddress::tst_QHostAddress()
qRegisterMetaType<QHostAddress>("QHostAddress");
}
+static void verifyClear(const QHostAddress &addr)
+{
+ QVERIFY(addr.isNull());
+ QVERIFY(!addr.isLoopback());
+ QVERIFY(!addr.isGlobal());
+ QVERIFY(!addr.isLinkLocal());
+ QVERIFY(!addr.isSiteLocal());
+ QVERIFY(!addr.isUniqueLocalUnicast());
+ QVERIFY(!addr.isMulticast());
+ QVERIFY(!addr.isBroadcast());
+ QVERIFY(!addr.isPrivateUse());
+ QCOMPARE(addr, QHostAddress());
+ QCOMPARE(addr, QHostAddress::Null);
+ QCOMPARE(addr.protocol(), QHostAddress::UnknownNetworkLayerProtocol);
+
+ bool ok = true;
+ QCOMPARE(addr.toIPv4Address(&ok), 0);
+ QVERIFY(!ok);
+
+ QCOMPARE(QByteArrayView::fromArray(addr.toIPv6Address().c),
+ QByteArrayView::fromArray(QIPv6Address{}.c));
+ QCOMPARE(addr.scopeId(), QString());
+
+ QCOMPARE(addr.toString(), QString());
+
+ size_t seed = QHashSeed::globalSeed();
+ QCOMPARE(qHash(addr, seed), qHash(QHostAddress(), seed));
+ seed = 0;
+ QCOMPARE(qHash(addr, seed), qHash(QHostAddress(), seed));
+}
+
+void tst_QHostAddress::constructor()
+{
+ QHostAddress addr;
+ verifyClear(addr);
+}
+
void tst_QHostAddress::constructor_QString_data()
{
setAddress_QString_data();
@@ -94,6 +132,9 @@ void tst_QHostAddress::constructor_QString()
QVERIFY( hostAddr.isNull() );
QVERIFY( hostAddr.protocol() == QHostAddress::UnknownNetworkLayerProtocol );
}
+
+ hostAddr.clear();
+ verifyClear(hostAddr);
}
void tst_QHostAddress::setAddress_QString_data()
@@ -201,6 +242,9 @@ void tst_QHostAddress::setAddress_QString()
QVERIFY( hostAddr.isNull() );
QVERIFY( hostAddr.protocol() == QHostAddress::UnknownNetworkLayerProtocol );
}
+
+ hostAddr.clear();
+ verifyClear(hostAddr);
}
void tst_QHostAddress::specialAddresses_data()
@@ -239,6 +283,7 @@ void tst_QHostAddress::specialAddresses()
QFETCH(QHostAddress::SpecialAddress, address);
QFETCH(bool, result);
QCOMPARE(QHostAddress(text) == address, result);
+ size_t seed = QHashSeed::globalSeed();
//check special address equal to itself (QTBUG-22898), note two overloads of operator==
QVERIFY(QHostAddress(address) == QHostAddress(address));
@@ -252,11 +297,19 @@ void tst_QHostAddress::specialAddresses()
QHostAddress ha;
ha.setAddress(address);
QVERIFY(ha == address);
+ QCOMPARE(qHash(ha, seed), qHash(QHostAddress(address), seed));
+ QCOMPARE(qHash(ha, 0), qHash(QHostAddress(address), 0));
}
QHostAddress setter;
setter.setAddress(text);
- QCOMPARE(setter == address, result);
+ if (result) {
+ QCOMPARE(setter, address);
+ QCOMPARE(qHash(setter, seed), qHash(QHostAddress(address), seed));
+ QCOMPARE(qHash(setter, 0), qHash(QHostAddress(address), 0));
+ } else {
+ QCOMPARE_NE(setter, address);
+ }
}
@@ -288,8 +341,11 @@ void tst_QHostAddress::compare()
QCOMPARE(first == second, result);
QCOMPARE(second == first, result);
- if (result == true)
- QCOMPARE(qHash(first), qHash(second));
+ if (result == true) {
+ size_t seed = QHashSeed::globalSeed();
+ QCOMPARE(qHash(first, seed), qHash(second, seed));
+ QCOMPARE(qHash(first, 0), qHash(second, 0));
+ }
}
void tst_QHostAddress::isEqual_data()
@@ -370,6 +426,11 @@ void tst_QHostAddress::scopeId()
address2 = address;
QCOMPARE(address2.scopeId(), QString("eth0"));
QCOMPARE(address2.toString().toLower(), QString("fe80::2e0:4cff:fefb:662a%eth0"));
+
+ address.clear();
+ verifyClear(address);
+ address2.clear();
+ verifyClear(address2);
}
void tst_QHostAddress::hashKey()
diff --git a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp
index 4814206cd75..40292f0c44d 100644
--- a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp
+++ b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp
@@ -132,6 +132,7 @@ private:
bool m_skipUnsupportedIPv6Tests;
bool m_workaroundLinuxKernelBug;
+ int loopbackInterface = 0; // unknown by default
QList<QHostAddress> allAddresses;
QHostAddress multicastGroup4, multicastGroup6;
QList<QHostAddress> linklocalMulticastGroups;
@@ -140,6 +141,16 @@ private:
QUdpSocket *m_asyncReceiver;
};
+// Unlike for IPv6 with IPV6_PKTINFO, IPv4 has no standardized way of obtaining
+// the packet's destination addresses. This means the destinationAddress() be
+// empty, so whitelist the OSes for which we know we have an implementation.
+// That's currently all of them, which means there probably is code in this
+// test that assumes this works without checking this variable.
+//
+// Note: this applies to single-stack operations; dual stack implementations
+// appear to be buggy or not present at all in some OSes.
+static constexpr bool HasWorkingIPv4DestinationAddress = true;
+
#ifdef SHOULD_CHECK_SYSCALL_SUPPORT
bool tst_QUdpSocket::ipv6SetsockoptionMissing(int level, int optname)
{
@@ -246,7 +257,23 @@ void tst_QUdpSocket::initTestCase()
if (!QtNetworkSettings::verifyTestNetworkSettings())
QSKIP("No network test server available");
#endif
- allAddresses = QNetworkInterface::allAddresses();
+
+ allAddresses.clear();
+ for (const QNetworkInterface &iface : QNetworkInterface::allInterfaces()) {
+ if (!iface.flags().testAnyFlags(QNetworkInterface::IsUp))
+ continue;
+ if (iface.flags().testAnyFlags(QNetworkInterface::IsLoopBack))
+ loopbackInterface = iface.index();
+
+ // add this interface's addresses
+ const QList<QNetworkAddressEntry> addresses = iface.addressEntries();
+ for (const QNetworkAddressEntry &entry : addresses) {
+ allAddresses += entry.ip();
+ if (!loopbackInterface && entry.ip().isLoopback())
+ loopbackInterface = iface.index();
+ }
+ }
+
m_skipUnsupportedIPv6Tests = shouldSkipIpv6TestsForBrokenSetsockopt();
// Create a pair of random multicast groups so we avoid clashing with any
@@ -568,12 +595,12 @@ void tst_QUdpSocket::broadcasting()
QVERIFY2(allAddresses.contains(dgram.senderAddress()),
dgram.senderAddress().toString().toLatin1());
QCOMPARE(dgram.senderPort(), int(broadcastSocket.localPort()));
- if (!dgram.destinationAddress().isNull()) {
+ if (HasWorkingIPv4DestinationAddress) {
QVERIFY2(dgram.destinationAddress() == QHostAddress::Broadcast
|| broadcastAddresses.contains(dgram.destinationAddress()),
dgram.destinationAddress().toString().toLatin1());
- QCOMPARE(dgram.destinationPort(), int(serverSocket.localPort()));
}
+ QCOMPARE(dgram.destinationPort(), int(serverSocket.localPort()));
int ttl = dgram.hopLimit();
if (ttl != -1)
@@ -738,15 +765,7 @@ void tst_QUdpSocket::loop()
QCOMPARE(paulDatagram.senderPort(), int(peter.localPort()));
QCOMPARE(peterDatagram.senderPort(), int(paul.localPort()));
- // Unlike for IPv6 with IPV6_PKTINFO, IPv4 has no standardized way of
- // obtaining the packet's destination addresses. The destinationAddress and
- // destinationPort calls could fail, so whitelist the OSes for which we
- // know we have an implementation.
-#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4) || defined(Q_OS_WIN)
- QVERIFY(peterDatagram.destinationPort() != -1);
- QVERIFY(paulDatagram.destinationPort() != -1);
-#endif
- if (peterDatagram.destinationPort() == -1) {
+ if (!HasWorkingIPv4DestinationAddress) {
QCOMPARE(peterDatagram.destinationAddress().protocol(), QAbstractSocket::UnknownNetworkLayerProtocol);
QCOMPARE(paulDatagram.destinationAddress().protocol(), QAbstractSocket::UnknownNetworkLayerProtocol);
} else {
@@ -754,6 +773,11 @@ void tst_QUdpSocket::loop()
QCOMPARE(paulDatagram.destinationAddress(), makeNonAny(paul.localAddress()));
QVERIFY(peterDatagram.destinationAddress().isEqual(makeNonAny(peter.localAddress())));
QVERIFY(paulDatagram.destinationAddress().isEqual(makeNonAny(paul.localAddress())));
+
+ if (loopbackInterface) {
+ QCOMPARE(peterDatagram.interfaceIndex(), loopbackInterface);
+ QCOMPARE(paulDatagram.interfaceIndex(), loopbackInterface);
+ }
}
}
@@ -820,6 +844,11 @@ void tst_QUdpSocket::ipv6Loop()
QCOMPARE(paulDatagram.destinationAddress(), makeNonAny(paul.localAddress()));
QCOMPARE(peterDatagram.destinationPort(), peterPort);
QCOMPARE(paulDatagram.destinationPort(), paulPort);
+
+ if (loopbackInterface) {
+ QCOMPARE(peterDatagram.interfaceIndex(), loopbackInterface);
+ QCOMPARE(paulDatagram.interfaceIndex(), loopbackInterface);
+ }
}
void tst_QUdpSocket::dualStack()
@@ -850,6 +879,8 @@ void tst_QUdpSocket::dualStack()
QCOMPARE(dgram.destinationPort(), int(dualSock.localPort()));
QVERIFY(dgram.destinationAddress().isEqual(makeNonAny(dualSock.localAddress(), QHostAddress::LocalHost)));
} else {
+ // Observed on QNX: the IPV6_PKTINFO ancillary data appears to be
+ // missing if the sender is IPv4.
qInfo("Getting IPv4 destination address failed.");
}
@@ -889,12 +920,11 @@ void tst_QUdpSocket::dualStack()
QCOMPARE(dgram.data(), dualData);
QCOMPARE(dgram.senderPort(), int(dualSock.localPort()));
QCOMPARE(dgram.senderAddress(), makeNonAny(dualSock.localAddress(), QHostAddress::LocalHost));
-#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4) || defined(Q_OS_WIN)
- QVERIFY(dgram.destinationPort() != -1);
-#endif
- if (dgram.destinationPort() != -1) {
- QCOMPARE(dgram.destinationPort(), int(v4Sock.localPort()));
+ QCOMPARE(dgram.destinationPort(), int(v4Sock.localPort()));
+ if (HasWorkingIPv4DestinationAddress) {
QCOMPARE(dgram.destinationAddress(), makeNonAny(v4Sock.localAddress(), QHostAddress::LocalHost));
+ if (loopbackInterface)
+ QCOMPARE(dgram.interfaceIndex(), loopbackInterface);
}
}
@@ -1748,10 +1778,10 @@ void tst_QUdpSocket::multicast()
QVERIFY2(allAddresses.contains(dgram.senderAddress()),
dgram.senderAddress().toString().toLatin1());
QCOMPARE(dgram.senderPort(), int(sender.localPort()));
- if (!dgram.destinationAddress().isNull()) {
+ if (HasWorkingIPv4DestinationAddress) {
QCOMPARE(dgram.destinationAddress(), groupAddress);
- QCOMPARE(dgram.destinationPort(), int(receiver.localPort()));
}
+ QCOMPARE(dgram.destinationPort(), int(receiver.localPort()));
int ttl = dgram.hopLimit();
if (ttl != -1)
@@ -1962,19 +1992,12 @@ void tst_QUdpSocket::linkLocalIPv4()
QCOMPARE(dgram.data().size(), testData.size());
QCOMPARE(dgram.data(), testData);
- // Unlike for IPv6 with IPV6_PKTINFO, IPv4 has no standardized way of
- // obtaining the packet's destination addresses. The destinationAddress
- // and destinationPort calls could fail, so whitelist the OSes we know
- // we have an implementation.
-#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4) || defined(Q_OS_WIN)
- QVERIFY(dgram.destinationPort() != -1);
-#endif
- if (dgram.destinationPort() == -1) {
+ if (!HasWorkingIPv4DestinationAddress) {
QCOMPARE(dgram.destinationAddress().protocol(), QAbstractSocket::UnknownNetworkLayerProtocol);
} else {
QCOMPARE(dgram.destinationAddress(), s->localAddress());
- QCOMPARE(dgram.destinationPort(), int(neutral.localPort()));
}
+ QCOMPARE(dgram.destinationPort(), int(neutral.localPort()));
QVERIFY(neutral.writeDatagram(dgram.makeReply(testData)));
QVERIFY2(s->waitForReadyRead(10000), QtNetworkSettings::msgSocketError(*s).constData());
diff --git a/tests/auto/testlib/initmain/tst_initmain.cpp b/tests/auto/testlib/initmain/tst_initmain.cpp
index 75a0d9ceb4d..cdaac0c14f4 100644
--- a/tests/auto/testlib/initmain/tst_initmain.cpp
+++ b/tests/auto/testlib/initmain/tst_initmain.cpp
@@ -19,6 +19,9 @@ private:
static bool m_initMainCalled;
};
+static_assert(QTest::Internals::HasInitMain<tst_InitMain>::value);
+static_assert(!QTest::Internals::HasInitMain<QObject>::value);
+
bool tst_InitMain::m_initMainCalled = false;
void tst_InitMain::testcase()
diff --git a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
index 17acdea014e..2f0cbf78b25 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
@@ -25,6 +25,7 @@
#include <QtWidgets/qtablewidget.h>
#include <QtGui/qevent.h>
+#include <QtGui/qstylehints.h>
#include <QtGui/private/qhighdpiscaling_p.h>
#include <QtCore/qmimedata.h>
@@ -3333,7 +3334,7 @@ void tst_QGraphicsProxyWidget::clickFocus()
EventSpy proxySpy(proxy);
EventSpy widgetSpy(proxy->widget());
- view.setFrameStyle(0);
+ view.setFrameStyle(QFrame::NoFrame);
view.resize(300, 300);
view.show();
QVERIFY(QTest::qWaitForWindowFocused(&view));
@@ -3469,10 +3470,12 @@ void tst_QGraphicsProxyWidget::QTBUG_6986_sendMouseEventToAlienWidget()
auto *hoverButton = new HoverButton(background);
hoverButton->setText("Second button"_L1);
hoverButton->setGeometry(10, 10, 200, 50);
+ hoverButton->setAttribute(Qt::WA_Hover, true);
scene.addWidget(background);
auto *hideButton = new QPushButton("I'm a button with a very very long text"_L1);
hideButton->setGeometry(10, 10, 400, 50);
+ hideButton->setAttribute(Qt::WA_Hover, true);
QGraphicsProxyWidget *topButton = scene.addWidget(hideButton);
connect(hideButton, &QPushButton::clicked, &scene, [&]() { topButton->hide(); });
topButton->setFocus();
@@ -3659,6 +3662,11 @@ public:
return QWidget::event(event);
}
+ void paintEvent(QPaintEvent *) override
+ {
+ QPainter p(this);
+ p.fillRect(rect(), Qt::green);
+ }
};
#if QT_CONFIG(wheelevent)
@@ -3676,6 +3684,11 @@ public:
*/
void tst_QGraphicsProxyWidget::wheelEventPropagation()
{
+ qApp->styleHints()->setWheelScrollLines(3);
+ const auto guard = qScopeGuard([&]() {
+ qApp->styleHints()->setWheelScrollLines(-1);
+ });
+
QGraphicsScene scene(0, 0, 600, 600);
auto *label = new QLabel("Direct"_L1);
@@ -3697,6 +3710,11 @@ void tst_QGraphicsProxyWidget::wheelEventPropagation()
int wheelEventCount = 0;
protected:
+ void paintEvent(QPaintEvent *) override
+ {
+ QPainter p(this);
+ p.fillRect(rect(), Qt::green);
+ }
void wheelEvent(QWheelEvent *) override
{
++wheelEventCount;
@@ -3710,10 +3728,13 @@ void tst_QGraphicsProxyWidget::wheelEventPropagation()
QGraphicsView view(&scene);
view.setFixedHeight(200);
+ view.setFixedWidth(700);
+ view.setFrameStyle(QFrame::NoFrame);
view.show();
QVERIFY(QTest::qWaitForWindowActive(&view));
QVERIFY(view.verticalScrollBar()->isVisible());
+ QVERIFY(!view.horizontalScrollBar()->isVisible());
view.verticalScrollBar()->setValue(0);
QSignalSpy scrollSpy(view.verticalScrollBar(), &QScrollBar::valueChanged);
@@ -3729,6 +3750,8 @@ void tst_QGraphicsProxyWidget::wheelEventPropagation()
phase);
QCoreApplication::processEvents();
};
+ auto vs = view.verticalScrollBar();
+ vs->setSingleStep(9); // each wheel event: wheelScrollLines() * 9 = 27px
qsizetype scrollCount = 0;
// test non-kinetic events; they are not grabbed, and should scroll the view unless
@@ -3816,6 +3839,7 @@ void tst_QGraphicsProxyWidget::forwardTouchEvent()
QGraphicsView view(&scene);
view.show();
+ view.setFrameStyle(QFrame::NoFrame);
QVERIFY(QTest::qWaitForWindowActive(&view));
EventSpy eventSpy(widget);
@@ -3832,16 +3856,14 @@ void tst_QGraphicsProxyWidget::forwardTouchEvent()
QTest::touchEvent(&view, device.get()).move(0, QPoint(16, 16), &view);
QTest::touchEvent(&view, device.get()).release(0, QPoint(15, 15), &view);
- QApplication::processEvents();
-
- QCOMPARE(eventSpy.counts[QEvent::TouchBegin], 1);
- QCOMPARE(eventSpy.counts[QEvent::TouchUpdate], 2);
- QCOMPARE(eventSpy.counts[QEvent::TouchEnd], 1);
+ QTRY_COMPARE(eventSpy.counts[QEvent::TouchBegin], 1);
+ QTRY_COMPARE(eventSpy.counts[QEvent::TouchUpdate], 2);
+ QTRY_COMPARE(eventSpy.counts[QEvent::TouchEnd], 1);
}
void tst_QGraphicsProxyWidget::touchEventPropagation()
{
- QGraphicsScene scene(0, 0, 300, 200);
+ QGraphicsScene scene;
auto *simpleWidget = new QWidget;
simpleWidget->setObjectName("simpleWidget");
simpleWidget->setAttribute(Qt::WA_AcceptTouchEvents, true);
@@ -3873,15 +3895,26 @@ void tst_QGraphicsProxyWidget::touchEventPropagation()
vbox->addWidget(touchWidget2);
QGraphicsProxyWidget *formProxy = scene.addWidget(formWidget);
formProxy->setAcceptTouchEvents(true);
- formProxy->setGeometry(QRectF(50, 50, 200, 160));
+ const auto minSize = formWidget->minimumSize();
+ formProxy->setGeometry(QRectF(50, 50, minSize.width(), minSize.height()));
+
+ // topLeft must be 0/0
+ const auto sceneRect = scene.sceneRect();
+ scene.setSceneRect(QRectF(0, 0, sceneRect.width(), sceneRect.height()));
QGraphicsView view(&scene);
+ // by setting NoFrame, view and view.viewport() have the same
+ // coordinate system
+ view.setFrameStyle(QFrame::NoFrame);
+ // make sure to not have scrollbars
view.setFixedSize(scene.width(), scene.height());
view.verticalScrollBar()->setValue(0);
view.horizontalScrollBar()->setValue(0);
view.viewport()->setObjectName("GraphicsView's Viewport");
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
+ QVERIFY(!view.horizontalScrollBar()->isVisible());
+ QVERIFY(!view.verticalScrollBar()->isVisible());
class TouchEventSpy : public QObject
{
@@ -3913,8 +3946,12 @@ void tst_QGraphicsProxyWidget::touchEventPropagation()
case QEvent::TouchEnd: {
auto *touchEvent = static_cast<QTouchEvent *>(event);
// instead of detaching each QEventPoint, just store the relative positions
- for (const auto &touchPoint : touchEvent->points())
- records[touchPoint.id()] << TouchRecord{receiver, event->type(), touchPoint.position()};
+ for (const auto& touchPoint : touchEvent->points()) {
+ records[touchPoint.id()]
+ << TouchRecord{ receiver, event->type(), touchPoint.position() };
+ qCDebug(lcTests) << touchPoint.id() << "recv:" << receiver << "type"
+ << event->type() << "pos" << touchPoint.position();
+ }
qCDebug(lcTests) << "Recording" << event << receiver;
break;
}
@@ -3944,9 +3981,9 @@ void tst_QGraphicsProxyWidget::touchEventPropagation()
};
// verify that the embedded widget gets the correctly translated event
- QTest::touchEvent(&view, touchDevice.get()).press(0, simpleCenter.toPoint());
+ QTest::touchEvent(&view, touchDevice.get()).press(0, view.mapFromScene(simpleCenter));
// window, viewport, scene, simpleProxy, simpleWidget
- QCOMPARE(eventSpy.count(), 5);
+ QTRY_COMPARE(eventSpy.count(), 5);
QCOMPARE(eventSpy.at(0).receiver, view.windowHandle());
QCOMPARE(eventSpy.at(1).receiver, view.viewport());
QCOMPARE(eventSpy.at(2).receiver, &scene);
@@ -3969,7 +4006,7 @@ void tst_QGraphicsProxyWidget::touchEventPropagation()
QCOMPARE(formWidget->childAt(touchWidget2->pos() + tw2Center), touchWidget2);
// touch events are sent to the view, in view coordinates
- const QPoint formProxyPox = view.mapFromScene(formProxy->pos().toPoint());
+ const QPoint formProxyPox = view.mapFromScene(formProxy->pos());
const QPoint pb1TouchPos = pushButton1->pos() + pb1Center + formProxyPox;
const QPoint pb2TouchPos = pushButton2->pos() + pb2Center + formProxyPox;
const QPoint tw1TouchPos = touchWidget1->pos() + tw1Center + formProxyPox;
diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
index df19ea1568e..48310996c46 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
@@ -2058,28 +2058,21 @@ void tst_QGraphicsView::mapFromSceneRect()
QWidget topLevel;
QGraphicsView view(&scene,&topLevel);
view.rotate(90);
- view.setFixedSize(200, 200);
- view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
- view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ const auto fw = view.frameWidth() * 2;
+ view.setFixedSize(200 + fw, 200 + fw);
topLevel.show();
- QVERIFY(QTest::qWaitForWindowActive(&view));
+ QVERIFY(QTest::qWaitForWindowActive(&topLevel));
+ QVERIFY(!view.horizontalScrollBar()->isVisible());
+ QVERIFY(!view.verticalScrollBar()->isVisible());
- QPolygon polygon;
- polygon << QPoint(98, 98);
- polygon << QPoint(98, 108);
- polygon << QPoint(88, 108);
- polygon << QPoint(88, 98);
-
-
- QPolygon viewPolygon = view.mapFromScene(0, 0, 10, 10);
- for (int i = 0; i < 4; ++i) {
- QVERIFY(qAbs(viewPolygon[i].x() - polygon[i].x()) < 3);
- QVERIFY(qAbs(viewPolygon[i].y() - polygon[i].y()) < 3);
- }
+ const QRectF input(0, 0, 10, 10);
+ // fixed size is 200x200 so center is 100x100
+ const QPolygon polygon{ QPoint(100, 100), QPoint(100, 110), QPoint(90, 110), QPoint(90, 100) };
+ const QPolygon viewPolygon = view.mapFromScene(input);
+ QCOMPARE(viewPolygon, polygon);
QPoint pt = view.mapFromScene(QPointF());
- QPolygon p;
- p << pt << pt << pt << pt;
+ QPolygon p{ pt, pt, pt, pt };
QCOMPARE(view.mapFromScene(QRectF()), p);
}
@@ -2088,28 +2081,18 @@ void tst_QGraphicsView::mapFromScenePoly()
QGraphicsScene scene;
QGraphicsView view(&scene);
view.rotate(90);
- view.setFixedSize(200, 200);
- view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
- view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ const auto fw = view.frameWidth() * 2;
+ view.setFixedSize(200 + fw, 200 + fw);
view.show();
-
- QPolygonF polygon;
- polygon << QPoint(0, 0);
- polygon << QPoint(10, 0);
- polygon << QPoint(10, 10);
- polygon << QPoint(0, 10);
-
- QPolygon polygon2;
- polygon2 << QPoint(98, 98);
- polygon2 << QPoint(98, 108);
- polygon2 << QPoint(88, 108);
- polygon2 << QPoint(88, 98);
-
- QPolygon viewPolygon = view.mapFromScene(polygon);
- for (int i = 0; i < 4; ++i) {
- QVERIFY(qAbs(viewPolygon[i].x() - polygon2[i].x()) < 3);
- QVERIFY(qAbs(viewPolygon[i].y() - polygon2[i].y()) < 3);
- }
+ QVERIFY(QTest::qWaitForWindowActive(&view));
+ QVERIFY(!view.horizontalScrollBar()->isVisible());
+ QVERIFY(!view.verticalScrollBar()->isVisible());
+
+ const QPolygonF input{ QPoint(0, 0), QPoint(10, 0), QPoint(10, 10), QPoint(0, 10) };
+ // fixed size is 200x200 so center is 100x100
+ const QPolygon polygon{ QPoint(100, 100), QPoint(100, 110), QPoint(90, 110), QPoint(90, 100) };
+ const QPolygon viewPolygon = view.mapFromScene(input);
+ QCOMPARE(viewPolygon, polygon);
}
void tst_QGraphicsView::mapFromScenePath()
@@ -2117,34 +2100,22 @@ void tst_QGraphicsView::mapFromScenePath()
QGraphicsScene scene;
QGraphicsView view(&scene);
view.rotate(90);
- view.setFixedSize(200, 200);
- view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
- view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ const auto fw = view.frameWidth() * 2;
+ view.setFixedSize(200 + fw, 200 + fw);
view.show();
-
- QPolygonF polygon;
- polygon << QPoint(0, 0);
- polygon << QPoint(10, 0);
- polygon << QPoint(10, 10);
- polygon << QPoint(0, 10);
+ QVERIFY(QTest::qWaitForWindowActive(&view));
+ QVERIFY(!view.horizontalScrollBar()->isVisible());
+ QVERIFY(!view.verticalScrollBar()->isVisible());
+
+ const QPolygonF input{ QPoint(0, 0), QPoint(10, 0), QPoint(10, 10), QPoint(0, 10) };
+ QPainterPath inputPath;
+ inputPath.addPolygon(input);
+ // fixed size is 200x200 so center is 100x100
+ const QPolygon polygon{ QPoint(100, 100), QPoint(100, 110), QPoint(90, 110), QPoint(90, 100) };
QPainterPath path;
path.addPolygon(polygon);
-
- QPolygon polygon2;
- polygon2 << QPoint(98, 98);
- polygon2 << QPoint(98, 108);
- polygon2 << QPoint(88, 108);
- polygon2 << QPoint(88, 98);
- QPainterPath path2;
- path2.addPolygon(polygon2);
-
- QPolygonF pathPoly = view.mapFromScene(path).toFillPolygon();
- QPolygonF path2Poly = path2.toFillPolygon();
-
- for (int i = 0; i < pathPoly.size(); ++i) {
- QVERIFY(qAbs(pathPoly[i].x() - path2Poly[i].x()) < 3);
- QVERIFY(qAbs(pathPoly[i].y() - path2Poly[i].y()) < 3);
- }
+ QPainterPath viewPath = view.mapFromScene(inputPath);
+ QCOMPARE(viewPath, path);
}
void tst_QGraphicsView::sendEvent()
diff --git a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp
index 8ee122ece18..6859f22c044 100644
--- a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp
+++ b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp
@@ -842,6 +842,20 @@ void tst_QComboBox::virtualAutocompletion()
QApplication::sendEvent(testWidget, &kp2);
QApplication::sendEvent(testWidget, &kr2);
QTRY_COMPARE(testWidget->currentIndex(), 3);
+
+ QKeyEvent kp3(QEvent::KeyPress, Qt::Key_R, {}, "r");
+ QKeyEvent kr3(QEvent::KeyRelease, Qt::Key_R, {}, "r");
+ QTest::qWait(QApplication::keyboardInputInterval());
+ QApplication::sendEvent(testWidget, &kp3);
+ QApplication::sendEvent(testWidget, &kr3);
+ QTRY_COMPARE(testWidget->currentIndex(), 3);
+
+ QTest::qWait(QApplication::keyboardInputInterval());
+ testWidget->view()->setKeyboardSearchFlags(Qt::MatchContains | Qt::MatchWrap);
+ QApplication::sendEvent(testWidget, &kp3);
+ QApplication::sendEvent(testWidget, &kr3);
+ QTRY_COMPARE(testWidget->currentIndex(), 1);
+
#if defined(Q_PROCESSOR_ARM) || defined(Q_PROCESSOR_MIPS)
QApplication::setKeyboardInputInterval(oldInterval);
#endif
diff --git a/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp b/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp
index 4de87cdb7a4..704770edfcc 100644
--- a/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp
+++ b/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp
@@ -19,8 +19,9 @@
#include <QTranslator>
#include <qscreen.h>
-#include <qobject.h>
+#include <QtCore/qobject.h>
#include <QtCore/qscopeguard.h>
+#include <QtCore/qtimer.h>
#include <QtWidgets/private/qapplication_p.h>
@@ -129,6 +130,8 @@ private slots:
void pressDragRelease_data();
void pressDragRelease();
+ void setActiveAction_disablesSloppyTimer();
+
protected slots:
void onSimpleActivated( QAction*);
void onComplexActionTriggered();
@@ -1525,6 +1528,50 @@ void tst_QMenuBar::pressDragRelease()
QTRY_COMPARE(triggeredSpy.size(), 1);
}
+void tst_QMenuBar::setActiveAction_disablesSloppyTimer()
+{
+ QMenuBar menuBar;
+ QMenu *menu = new QMenu(&menuBar);
+ menuBar.addMenu(menu);
+
+ QAction *item1 = menu->addAction("Item 1");
+ QAction *item2 = menu->addAction("Item 2");
+
+ // Create submenu for first item
+ QMenu *submenu = new QMenu(&menuBar);
+ submenu->addAction("Subitem 1");
+ submenu->addAction("Subitem 2");
+ submenu->addAction("Subitem 3");
+ item1->setMenu(submenu);
+
+ using namespace std::chrono_literals;
+
+ QTimer::singleShot(0, [&]() {
+ menu->show();
+ });
+
+ QTimer::singleShot(100ms, [&]() {
+ menu->setActiveAction(item1);
+ QCOMPARE_EQ(menu->activeAction(), item1);
+ });
+
+ QTimer::singleShot(200ms, [&] {
+ menu->setActiveAction(item2);
+ QCOMPARE_EQ(menu->activeAction(), item2);
+ });
+
+ bool done = false;
+ // QTBUG-138956: sloppy timer should not fire when calling setActiveAction
+ QTimer::singleShot(2s, [&] {
+ QCOMPARE_EQ(menu->activeAction(), item2);
+ done = true;
+ });
+
+ QVERIFY(QTest::qWaitFor([&]{
+ return done;
+ }));
+}
+
// QTBUG-56526
void tst_QMenuBar::platformMenu()
{
diff --git a/tests/benchmarks/corelib/time/qtimezone/tst_bench_qtimezone.cpp b/tests/benchmarks/corelib/time/qtimezone/tst_bench_qtimezone.cpp
index 3b58b6927ae..fbcce88fe81 100644
--- a/tests/benchmarks/corelib/time/qtimezone/tst_bench_qtimezone.cpp
+++ b/tests/benchmarks/corelib/time/qtimezone/tst_bench_qtimezone.cpp
@@ -41,15 +41,17 @@ static QList<QByteArray> enoughZones()
QByteArray("UTC"),
// Those named overtly in tst_QDateTime - special cases first:
QByteArray("UTC-02:00"), QByteArray("UTC+02:00"), QByteArray("UTC+12:00"),
- QByteArray("Etc/GMT+3"), QByteArray("GMT-2"), QByteArray("GMT"),
+ QByteArray("Etc/GMT+3"), QByteArray("GMT-0"), QByteArray("GMT"),
// ... then ordinary names in alphabetic order:
+ QByteArray("America/Anchorage"), QByteArray("America/Metlakatla"),
QByteArray("America/New_York"), QByteArray("America/Sao_Paulo"),
- QByteArray("America/Vancouver"),
- QByteArray("Asia/Kathmandu"), QByteArray("Asia/Singapore"),
+ QByteArray("America/Toronto"), QByteArray("America/Vancouver"),
+ QByteArray("Asia/Kathmandu"), QByteArray("Asia/Manila"), QByteArray("Asia/Singapore"),
QByteArray("Australia/Brisbane"), QByteArray("Australia/Eucla"),
QByteArray("Australia/Sydney"),
QByteArray("Europe/Berlin"), QByteArray("Europe/Helsinki"),
- QByteArray("Europe/Rome"), QByteArray("Europe/Oslo"),
+ QByteArray("Europe/Lisbon"), QByteArray("Europe/Oslo"),
+ QByteArray("Europe/Rome"),
QByteArray("Pacific/Apia"), QByteArray("Pacific/Auckland"),
QByteArray("Pacific/Kiritimati")
};