summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/CMakeLists.txt6
-rw-r--r--src/corelib/Qt6AndroidDynamicFeatureHelpers.cmake152
-rw-r--r--src/corelib/Qt6AndroidGradleHelpers.cmake631
-rw-r--r--src/corelib/Qt6AndroidMacros.cmake216
-rw-r--r--src/corelib/Qt6AndroidPermissionHelpers.cmake126
-rw-r--r--src/corelib/Qt6CoreConfigExtras.cmake.in4
-rw-r--r--src/corelib/Qt6CoreMacros.cmake3
-rw-r--r--src/corelib/animation/qabstractanimation.cpp1
-rw-r--r--src/corelib/animation/qabstractanimation.h1
-rw-r--r--src/corelib/animation/qabstractanimation_p.h1
-rw-r--r--src/corelib/animation/qanimationgroup.cpp1
-rw-r--r--src/corelib/animation/qanimationgroup.h1
-rw-r--r--src/corelib/animation/qanimationgroup_p.h1
-rw-r--r--src/corelib/animation/qparallelanimationgroup.cpp1
-rw-r--r--src/corelib/animation/qparallelanimationgroup.h1
-rw-r--r--src/corelib/animation/qparallelanimationgroup_p.h1
-rw-r--r--src/corelib/animation/qpauseanimation.cpp1
-rw-r--r--src/corelib/animation/qpauseanimation.h1
-rw-r--r--src/corelib/animation/qpropertyanimation.cpp8
-rw-r--r--src/corelib/animation/qpropertyanimation.h1
-rw-r--r--src/corelib/animation/qpropertyanimation_p.h1
-rw-r--r--src/corelib/animation/qsequentialanimationgroup.cpp1
-rw-r--r--src/corelib/animation/qsequentialanimationgroup.h1
-rw-r--r--src/corelib/animation/qsequentialanimationgroup_p.h1
-rw-r--r--src/corelib/animation/qvariantanimation.cpp1
-rw-r--r--src/corelib/animation/qvariantanimation.h1
-rw-r--r--src/corelib/animation/qvariantanimation_p.h1
-rw-r--r--src/corelib/configure.cmake1
-rw-r--r--src/corelib/doc/REUSE.toml8
-rw-r--r--src/corelib/doc/snippets/CMakeLists.txt3
-rw-r--r--src/corelib/doc/snippets/code/doc_src_containers.cpp554
-rw-r--r--src/corelib/doc/snippets/code/doc_src_groups.cpp33
-rw-r--r--src/corelib/doc/snippets/code/doc_src_objecttrees.cpp36
-rw-r--r--src/corelib/doc/snippets/code/doc_src_properties.cpp69
-rw-r--r--src/corelib/doc/snippets/code/doc_src_qalgorithms.cpp20
-rw-r--r--src/corelib/doc/snippets/code/doc_src_qcache.cpp40
-rw-r--r--src/corelib/doc/snippets/code/doc_src_qiterator.cpp557
-rw-r--r--src/corelib/doc/snippets/code/doc_src_qnamespace.cpp2
-rw-r--r--src/corelib/doc/snippets/code/doc_src_qplugin.cpp4
-rw-r--r--src/corelib/doc/snippets/code/doc_src_qset.cpp193
-rw-r--r--src/corelib/doc/snippets/code/doc_src_qvarlengtharray.cpp32
-rw-r--r--src/corelib/doc/snippets/code/doc_src_resources.cpp23
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_animation_qparallelanimationgroup.cpp17
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_animation_qpropertyanimation.cpp151
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_animation_qsequentialanimationgroup.cpp5
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_animation_qvariantanimation.cpp20
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_concurrent_qthreadpool.cpp15
-rw-r--r--src/corelib/doc/snippets/eventfilters/CMakeLists.txt10
-rw-r--r--src/corelib/doc/snippets/qmetaobject-invokable/CMakeLists.txt8
-rw-r--r--src/corelib/doc/snippets/qmetaobject-revision/CMakeLists.txt8
-rw-r--r--src/corelib/doc/snippets/qprocess/CMakeLists.txt8
-rw-r--r--src/corelib/doc/snippets/qsignalmapper/CMakeLists.txt18
-rw-r--r--src/corelib/doc/snippets/qsignalmapper/buttonwidget.cpp65
-rw-r--r--src/corelib/doc/snippets/qsignalmapper/buttonwidget.h4
-rw-r--r--src/corelib/doc/src/animation.qdoc20
-rw-r--r--src/corelib/doc/src/objectmodel/objecttrees.qdoc8
-rw-r--r--src/corelib/io/qfile.cpp1
-rw-r--r--src/corelib/io/qfile.h1
-rw-r--r--src/corelib/io/qfile_p.h1
-rw-r--r--src/corelib/io/qfilesystemengine_unix.cpp11
-rw-r--r--src/corelib/io/qiodevice.cpp7
-rw-r--r--src/corelib/io/qsavefile.cpp1
-rw-r--r--src/corelib/io/qsavefile.h1
-rw-r--r--src/corelib/io/qsavefile_p.h1
-rw-r--r--src/corelib/io/qtemporaryfile.cpp6
-rw-r--r--src/corelib/io/qurl.cpp32
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp5
-rw-r--r--src/corelib/kernel/qmetaobject.cpp14
-rw-r--r--src/corelib/kernel/qmetaobjectbuilder.cpp20
-rw-r--r--src/corelib/kernel/qmetaobjectbuilder_p.h2
-rw-r--r--src/corelib/kernel/qmetatype.cpp112
-rw-r--r--src/corelib/kernel/qmetatype_p.h26
-rw-r--r--src/corelib/kernel/qsignalmapper.cpp10
-rw-r--r--src/corelib/kernel/qtranslator.cpp18
-rw-r--r--src/corelib/kernel/qvariant.h11
-rw-r--r--src/corelib/platform/windows/qt_winrtbase_p.h1
-rw-r--r--src/corelib/thread/qatomicwait.cpp14
-rw-r--r--src/corelib/thread/qmutex.cpp19
-rw-r--r--src/corelib/tools/qarraydata.h10
-rw-r--r--src/corelib/tools/qarraydataops.h4
-rw-r--r--src/corelib/tools/qatomicscopedvaluerollback.h28
-rw-r--r--src/corelib/tools/qfreelist_p.h22
-rw-r--r--src/corelib/tools/qhashfunctions.h32
-rw-r--r--src/corelib/tools/qsharedpointer_impl.h10
84 files changed, 2500 insertions, 1017 deletions
diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt
index 4d83bbf794e..249b9b8c1ee 100644
--- a/src/corelib/CMakeLists.txt
+++ b/src/corelib/CMakeLists.txt
@@ -16,7 +16,11 @@ qt_internal_extend_sbom(WrapZLIB::WrapZLIB
if(ANDROID)
set(corelib_extra_cmake_files
- "${CMAKE_CURRENT_SOURCE_DIR}/${QT_CMAKE_EXPORT_NAMESPACE}AndroidMacros.cmake")
+ "${CMAKE_CURRENT_SOURCE_DIR}/${QT_CMAKE_EXPORT_NAMESPACE}AndroidMacros.cmake"
+ "${CMAKE_CURRENT_SOURCE_DIR}/${QT_CMAKE_EXPORT_NAMESPACE}AndroidDynamicFeatureHelpers.cmake"
+ "${CMAKE_CURRENT_SOURCE_DIR}/${QT_CMAKE_EXPORT_NAMESPACE}AndroidGradleHelpers.cmake"
+ "${CMAKE_CURRENT_SOURCE_DIR}/${QT_CMAKE_EXPORT_NAMESPACE}AndroidPermissionHelpers.cmake"
+ )
endif()
if(WASM)
set(corelib_extra_cmake_files
diff --git a/src/corelib/Qt6AndroidDynamicFeatureHelpers.cmake b/src/corelib/Qt6AndroidDynamicFeatureHelpers.cmake
new file mode 100644
index 00000000000..e8a81bde1d7
--- /dev/null
+++ b/src/corelib/Qt6AndroidDynamicFeatureHelpers.cmake
@@ -0,0 +1,152 @@
+# Copyright (C) 2025 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+# Collects the dynamic features for the target
+
+function(_qt_internal_android_add_dynamic_feature_deployment target)
+ get_target_property(dynamic_features ${target} _qt_android_dynamic_features)
+ if(NOT dynamic_features)
+ return()
+ endif()
+
+ foreach(dynamic_feature IN LISTS dynamic_features)
+ get_target_property(is_imported ${dynamic_feature} IMPORTED)
+ if(is_imported)
+ message(FATAL_ERROR "Imported target ${dynamic_feature} can not be a"
+ " 'DYNAMIC_FEATURE'.")
+ endif()
+
+ get_target_property(type ${dynamic_feature} TYPE)
+ if(NOT type STREQUAL "SHARED_LIBRARY")
+ message(FATAL_ERROR "Cannot make ${dynamic_feature} 'DYNAMIC_FEATURE'."
+ " The target must be the 'SHARED_LIBRARY'.")
+ endif()
+
+ get_target_property(android_type ${dynamic_feature} _qt_android_target_type)
+ if(NOT android_type STREQUAL "" AND NOT android_type MATCHES "-NOTFOUND$"
+ AND NOT android_type STREQUAL "DYNAMIC_FEATURE")
+ message(FATAL_ERROR "Cannot make ${dynamic_feature} 'DYNAMIC_FEATURE',"
+ " it's already '${android_type}'. The target must be the plain 'SHARED_LIBRARY'.")
+ endif()
+
+ # Mark the target as DYNAMIC_FEATURE, since we used it in this role once.
+ set_target_properties(${dynamic_feature} PROPERTIES _qt_android_target_type DYNAMIC_FEATURE)
+ _qt_internal_set_android_dynamic_feature_gradle_defaults(${dynamic_feature})
+
+ _qt_internal_android_get_dynamic_feature_deployment_dir(dynamic_feature_deployment_dir
+ ${target} ${dynamic_feature})
+ _qt_internal_android_generate_target_build_gradle(${dynamic_feature}
+ DEPLOYMENT_DIR "${dynamic_feature_deployment_dir}")
+ _qt_internal_android_generate_dynamic_feature_manifest(${target} ${dynamic_feature})
+ _qt_internal_android_copy_dynamic_feature(${target} ${dynamic_feature})
+ endforeach()
+endfunction()
+
+# Sets the default values of the gradle properties for the Android dynamic feature target.
+function(_qt_internal_set_android_dynamic_feature_gradle_defaults target)
+ _qt_internal_android_java_dir(android_java_dir)
+
+ # TODO: make androidx.core:core versionc configurable.
+ # Currently, it is hardcoded to 1.16.0.
+ set(implementation_dependencies "project(':app')" "'androidx.core:core:1.16.0'")
+
+ set_target_properties(${target} PROPERTIES
+ _qt_android_gradle_java_source_dirs "src;java"
+ _qt_android_gradle_aidl_source_dirs "src;aidl"
+ _qt_android_gradle_res_source_dirs "res"
+ _qt_android_gradle_resources_source_dirs "resources"
+ _qt_android_gradle_renderscript_source_dirs "src"
+ _qt_android_gradle_assets_source_dirs "assets"
+ _qt_android_gradle_jniLibs_source_dirs "libs"
+ _qt_android_manifest "AndroidManifest.xml"
+ _qt_android_gradle_implementation_dependencies "${implementation_dependencies}"
+ )
+endfunction()
+
+# Copies the dynamic feature library to the respective gradle build tree.
+function(_qt_internal_android_copy_dynamic_feature target dynamic_feature)
+ if(NOT TARGET ${dynamic_feature})
+ message(FATAL_ERROR "${dynamic_feature} is not a target.")
+ endif()
+
+ _qt_internal_android_get_dynamic_feature_deployment_dir(dynamic_feature_deployment_dir
+ ${target} ${dynamic_feature})
+
+ set(dynamic_feature_libs_dir "${dynamic_feature_deployment_dir}/libs/${CMAKE_ANDROID_ARCH_ABI}")
+ get_target_property(output_name ${dynamic_feature} OUTPUT_NAME)
+ if(NOT output_name)
+ get_target_property(suffix "${dynamic_feature}" SUFFIX)
+ set(output_name "lib${dynamic_feature}${suffix}")
+ endif()
+ set(output_file_path "${dynamic_feature_libs_dir}/${output_name}")
+ _qt_internal_copy_file_if_different_command(copy_command
+ "$<TARGET_FILE:${dynamic_feature}>"
+ "${output_file_path}"
+ )
+ add_custom_command(OUTPUT ${output_file_path}
+ COMMAND ${copy_command}
+ DEPENDS ${dynamic_feature}
+ COMMENT "Copying ${dynamic_feature} dynamic feature to ${target} deployment directory"
+ )
+ add_custom_target(${target}_deploy_dynamic_features DEPENDS "${output_file_path}")
+endfunction()
+
+# Generates the feature name strings and copy them to the respective deployment directory.
+function(_qt_internal_android_generate_dynamic_feature_names target)
+ get_target_property(dynamic_features ${target} _qt_android_dynamic_features)
+ if(NOT dynamic_features)
+ return()
+ endif()
+
+ # Collect the titles
+ string(JOIN "\n" content
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+ "<resources>"
+ )
+ foreach(feature IN LISTS dynamic_features)
+ string(APPEND content "\n <string name=\"${feature}_title\">${feature}</string>")
+ endforeach()
+ string(APPEND content "\n</resources>")
+
+ _qt_internal_android_get_target_deployment_dir(deployment_dir ${target})
+ # TODO: androiddeployqt wipes the android build directory. Generate feature_names.xml target
+ # build dir and copy after androiddeployqt run. We should skip feature_names.xml copying when
+ # androiddeployqt is not involved into the deployment process anymore.
+ #
+ # set(output_file "${deployment_dir}/res/values/feature_names.xml")
+ set(output_file "$<TARGET_PROPERTY:${target},BINARY_DIR>/res/values/feature_names.xml")
+ _qt_internal_configure_file(GENERATE OUTPUT "${output_file}" CONTENT "${content}")
+ set(output_file_in_deployment_dir "${deployment_dir}/res/values/feature_names.xml")
+ add_custom_command(OUTPUT "${output_file_in_deployment_dir}"
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different
+ "${output_file}"
+ "${output_file_in_deployment_dir}"
+ DEPENDS "${output_file}" ${target}_android_deploy_aux
+ VERBATIM
+ )
+ add_custom_target(${target}_copy_feature_names
+ DEPENDS
+ "${output_file_in_deployment_dir}"
+ )
+endfunction()
+
+# Returns the dynamic feature deployment directory in the target build tree.
+function(_qt_internal_android_get_dynamic_feature_deployment_dir out_var target dynamic_feature)
+ _qt_internal_android_get_target_android_build_dir(android_build_dir ${target})
+ set(${out_var} "${android_build_dir}/${dynamic_feature}" PARENT_SCOPE)
+endfunction()
+
+# Generates the AndroidManifest.xml file for the dynamic_feature.
+function(_qt_internal_android_generate_dynamic_feature_manifest target dynamic_feature)
+ set(android_manifest_filename AndroidManifest.xml)
+ _qt_internal_android_get_dynamic_feature_deployment_dir(dynamic_feature_deployment_dir ${target}
+ ${dynamic_feature})
+
+ _qt_internal_android_get_template_path(template_file ${target}
+ "dynamic_feature/${android_manifest_filename}")
+
+ set(APP_TARGET "${target}")
+ set(TITLE_VAR "@string/${dynamic_feature}_title")
+
+ set(output_file "${dynamic_feature_deployment_dir}/AndroidManifest.xml")
+ _qt_internal_configure_file(CONFIGURE OUTPUT "${output_file}" INPUT "${template_file}")
+endfunction()
diff --git a/src/corelib/Qt6AndroidGradleHelpers.cmake b/src/corelib/Qt6AndroidGradleHelpers.cmake
new file mode 100644
index 00000000000..09184c93b69
--- /dev/null
+++ b/src/corelib/Qt6AndroidGradleHelpers.cmake
@@ -0,0 +1,631 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+# Returns the path to the template file from either user defined template directory, or
+# Qt default template directory.
+function(_qt_internal_android_get_template_path out_var target template_name)
+ if(template_name STREQUAL "")
+ message(FATAL_ERROR "Template name is empty."
+ " This is the Qt issue, please report a bug at https://bugreports.qt.io.")
+ endif()
+
+ _qt_internal_android_template_dir(template_directory)
+ get_filename_component(template_directory "${template_directory}" ABSOLUTE)
+
+ # The paths are ordered according to their priority, from highest to lowest.
+ set(possible_paths
+ "${template_directory}/${template_name}.in"
+ )
+
+ get_target_property(android_target_type ${target} _qt_android_target_type)
+ if(android_target_type STREQUAL "APPLICATION")
+ _qt_internal_android_get_package_source_dir(user_template_directory ${target})
+ get_filename_component(user_template_directory "${user_template_directory}" ABSOLUTE)
+
+ # Add user template with the higher priority
+ list(PREPEND possible_paths "${user_template_directory}/${template_name}.in")
+ endif()
+
+ set(template_path "")
+ foreach(possible_path IN LISTS possible_paths)
+ if(EXISTS "${possible_path}")
+ set(template_path "${possible_path}")
+ break()
+ endif()
+ endforeach()
+
+ if(template_path STREQUAL "")
+ message(FATAL_ERROR "'${template_name}' is not found."
+ " This is the Qt issue, please report a bug at https://bugreports.qt.io.")
+ endif()
+
+ set(${out_var} "${template_path}" PARENT_SCOPE)
+endfunction()
+
+# Generates the settings.gradle file for the target. Writes the result to the target android build
+# directory.
+function(_qt_internal_android_generate_bundle_settings_gradle target)
+ set(settings_gradle_filename "settings.gradle")
+ _qt_internal_android_get_target_android_build_dir(android_build_dir ${target})
+ set(settings_gradle_file "${android_build_dir}/${settings_gradle_filename}")
+
+ # Skip generating the file if it's already provided by user.
+ get_target_property(deployment_files ${target} _qt_android_deployment_files)
+ if("${settings_gradle_file}" IN_LIST deployment_files)
+ return()
+ endif()
+
+ _qt_internal_android_get_template_path(template_file ${target} "${settings_gradle_filename}")
+
+ set(android_app_name "$<TARGET_PROPERTY:${target},QT_ANDROID_APP_NAME>")
+ string(JOIN "" ROOT_PROJECT_NAME
+ "$<IF:$<BOOL:${android_app_name}>,"
+ "${android_app_name},"
+ "${target}"
+ ">"
+ )
+
+ set(target_dynamic_features "$<TARGET_PROPERTY:${target},_qt_android_dynamic_features>")
+ set(include_prefix "include(\":")
+ set(include_suffix "\")")
+ set(include_glue "${include_suffix}\n${include_prefix}")
+ string(JOIN "" SUBPROJECTS
+ "$<$<BOOL:${target_dynamic_features}>:"
+ "${include_prefix}"
+ "$<JOIN:${target_dynamic_features},${include_glue}>"
+ "${include_suffix}"
+ ">"
+ )
+
+ _qt_internal_configure_file(GENERATE OUTPUT ${settings_gradle_file}
+ INPUT "${template_file}")
+ set_property(TARGET ${target} APPEND PROPERTY _qt_android_deployment_files
+ "${settings_gradle_file}")
+endfunction()
+
+# Generates the source sets for the target.
+function(_qt_internal_android_get_gradle_source_sets out_var target)
+ set(known_types java aidl res resources renderscript assets jniLibs)
+ set(source_set "")
+ set(indent " ")
+ foreach(type IN LISTS known_types)
+ set(source_dirs
+ "$<GENEX_EVAL:$<TARGET_PROPERTY:${target},_qt_android_gradle_${type}_source_dirs>>")
+ string(JOIN "" source_set
+ "${source_set}"
+ "$<$<BOOL:${source_dirs}>:"
+ "${indent}${type}.srcDirs = ['$<JOIN:${source_dirs},'$<COMMA> '>']\n"
+ ">"
+ )
+ endforeach()
+
+ set(manifest
+ "$<TARGET_PROPERTY:${target},_qt_android_manifest>")
+ string(JOIN "" source_set
+ "${source_set}"
+ "$<$<BOOL:${manifest}>:"
+ "${indent}manifest.srcFile '${manifest}'\n"
+ ">"
+ )
+ set(${out_var} "${source_set}" PARENT_SCOPE)
+endfunction()
+
+# Generates the gradle dependency list for the target.
+function(_qt_internal_android_get_gradle_dependencies out_var target)
+ # Use dependencies from file tree by default
+ set(known_dependencies
+ "implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])")
+ foreach(dep_type implementation api)
+ string(JOIN "\n " dep_prefix
+ "\n //noinspection GradleDependency"
+ "${dep_type} "
+ )
+ set(dep_postfix "")
+ set(dep_property "$<GENEX_EVAL:$<TARGET_PROPERTY:${target},_qt_android_gradle_${dep_type}_dependencies>>")
+ string(JOIN "" known_dependencies
+ "${known_dependencies}"
+ "$<$<BOOL:${dep_property}>:"
+ "${dep_prefix}$<JOIN:${dep_property},${dep_postfix}${dep_prefix}>${dep_postfix}"
+ ">"
+ )
+ endforeach()
+ set(${out_var} "${known_dependencies}" PARENT_SCOPE)
+endfunction()
+
+# Sets the default values of the gradle properties for the Android executable target.
+function(_qt_internal_set_android_application_gradle_defaults target)
+ _qt_internal_android_java_dir(android_java_dir)
+
+ set(target_dynamic_features "$<TARGET_PROPERTY:${target},_qt_android_dynamic_features>")
+ string(JOIN "" implementation_dependencies
+ "$<$<BOOL:${target_dynamic_features}>:'com.google.android.play:feature-delivery:2.1.0'>"
+ )
+ # TODO: make androidx.core:core version configurable.
+ # Currently, it is hardcoded to 1.16.0.
+ list(APPEND implementation_dependencies "'androidx.core:core:1.16.0'")
+
+ set_target_properties(${target} PROPERTIES
+ _qt_android_gradle_java_source_dirs "${android_java_dir}/src;src;java"
+ _qt_android_gradle_aidl_source_dirs "${android_java_dir}/src;src;aidl"
+ _qt_android_gradle_res_source_dirs "${android_java_dir}/res;res"
+ _qt_android_gradle_resources_source_dirs "resources"
+ _qt_android_gradle_renderscript_source_dirs "src"
+ _qt_android_gradle_assets_source_dirs "assets"
+ _qt_android_gradle_jniLibs_source_dirs "libs"
+ _qt_android_manifest "AndroidManifest.xml"
+ _qt_android_gradle_implementation_dependencies "${implementation_dependencies}"
+ )
+endfunction()
+
+# Generates the build.gradle file for the target. Writes the result to the target app deployment
+# directory.
+function(_qt_internal_android_generate_target_build_gradle target)
+ cmake_parse_arguments(PARSE_ARGV 1 arg "" "DEPLOYMENT_DIR" "")
+
+ if(NOT arg_DEPLOYMENT_DIR)
+ message(FATAL_ERROR "DEPLOYMENT_DIR is not specified.")
+ endif()
+
+ set(build_gradle_filename "build.gradle")
+ set(out_file "${arg_DEPLOYMENT_DIR}/${build_gradle_filename}")
+
+ # Skip generating the file if it's already provided by user.
+ get_target_property(deployment_files ${target} _qt_android_deployment_files)
+ if("${out_file}" IN_LIST deployment_files)
+ return()
+ endif()
+
+ # TODO: The current build.gradle.in templates hardcodes couple values that needs to be
+ # configurable in the future. For example the buildscript dependencies, or the use of
+ # androidx.core:core:1.13.1 and the dependency for all user applications.
+
+ _qt_internal_android_get_gradle_property(PACKAGE_NAME ${target}
+ QT_ANDROID_PACKAGE_NAME "org.qtproject.example.$<MAKE_C_IDENTIFIER:${target}>")
+
+ _qt_internal_android_get_target_sdk_build_tools_revision(ANDROID_BUILD_TOOLS_VERSION
+ ${target})
+
+ _qt_internal_detect_latest_android_platform(ANDROID_COMPILE_SDK_VERSION)
+ if(NOT ANDROID_COMPILE_SDK_VERSION)
+ message(FATAL_ERROR "Unable to detect the android platform in ${ANDROID_SDK_ROOT}. "
+ "Please check your Android SDK installation.")
+ endif()
+
+ _qt_internal_android_get_gradle_source_sets(SOURCE_SETS ${target})
+ _qt_internal_android_get_gradle_dependencies(GRADLE_DEPENDENCIES ${target})
+
+ _qt_internal_android_get_gradle_property(min_sdk_version ${target}
+ QT_ANDROID_MIN_SDK_VERSION "28")
+
+ _qt_internal_android_get_gradle_property(target_sdk_version ${target}
+ QT_ANDROID_TARGET_SDK_VERSION "34")
+
+ set(target_abis "$<TARGET_PROPERTY:${target},_qt_android_abis>")
+ set(target_abi_list "$<JOIN:${target_abis};${CMAKE_ANDROID_ARCH_ABI},'$<COMMA> '>")
+
+ string(JOIN "\n " DEFAULT_CONFIG_VALUES
+ "resConfig 'en'"
+ "minSdkVersion ${min_sdk_version}"
+ "targetSdkVersion ${target_sdk_version}"
+ "ndk.abiFilters = ['${target_abi_list}']"
+ )
+
+ set(target_dynamic_features "$<TARGET_PROPERTY:${target},_qt_android_dynamic_features>")
+ set(include_prefix "\":")
+ set(include_suffix "\"")
+ set(include_glue "${include_suffix}$<COMMA>${include_prefix}")
+ string(APPEND ANDROID_DEPLOYMENT_EXTRAS
+ "$<$<BOOL:${target_dynamic_features}>:dynamicFeatures = ["
+ "${include_prefix}"
+ "$<JOIN:${target_dynamic_features},${include_glue}>"
+ "${include_suffix}]"
+ ">"
+ )
+
+ get_target_property(android_target_type ${target} _qt_android_target_type)
+ if(android_target_type STREQUAL "APPLICATION")
+ set(GRADLE_PLUGIN_TYPE "com.android.application")
+ set(template_subdir "app")
+ elseif(android_target_type STREQUAL "DYNAMIC_FEATURE")
+ set(GRADLE_PLUGIN_TYPE "com.android.dynamic-feature")
+ set(template_subdir "dynamic_feature")
+ else()
+ message(FATAL_ERROR "Unsupported target type for android bundle deployment ${target}")
+ endif()
+
+ _qt_internal_android_get_template_path(template_file ${target}
+ "${template_subdir}/${build_gradle_filename}")
+ _qt_internal_configure_file(GENERATE
+ OUTPUT "${out_file}"
+ INPUT "${template_file}"
+ )
+ set_property(TARGET ${target} APPEND PROPERTY _qt_android_deployment_files "${out_file}")
+endfunction()
+
+# Prepares the artifacts for the gradle build of the target.
+function(_qt_internal_android_prepare_gradle_build target)
+ _qt_internal_android_get_target_android_build_dir(android_build_dir ${target})
+ _qt_internal_android_get_target_deployment_dir(deployment_dir ${target})
+
+ _qt_internal_android_copy_gradle_files(${target} "${android_build_dir}")
+ _qt_internal_android_copy_target_package_sources(${target})
+
+ _qt_internal_android_generate_bundle_gradle_properties(${target})
+ _qt_internal_android_generate_bundle_settings_gradle(${target})
+ _qt_internal_android_generate_bundle_local_properties(${target})
+ _qt_internal_android_generate_target_build_gradle(${target} DEPLOYMENT_DIR "${deployment_dir}")
+ _qt_internal_android_generate_target_gradle_properties(${target}
+ DEPLOYMENT_DIR "${deployment_dir}")
+ _qt_internal_android_generate_target_android_manifest(${target}
+ DEPLOYMENT_DIR "${deployment_dir}")
+
+
+ _qt_internal_android_add_gradle_build(${target} apk)
+ _qt_internal_android_add_gradle_build(${target} aab)
+
+ # Make global apk, aab, and aar targets depend on the respective targets.
+ _qt_internal_android_add_global_package_dependencies(${target})
+ _qt_internal_create_global_apk_all_target_if_needed()
+endfunction()
+
+# Adds the modern gradle build targets.
+# These targets use the settings.gradle based build directory structure.
+function(_qt_internal_android_add_gradle_build target type)
+ _qt_internal_android_get_deployment_type_option(android_deployment_type_option
+ "assembleRelease" "assembleDebug")
+
+ _qt_internal_android_gradlew_name(gradlew_file_name)
+ _qt_internal_android_get_target_android_build_dir(android_build_dir ${target})
+ set(gradlew "${android_build_dir}/${gradlew_file_name}")
+
+ set(extra_args "")
+ if(type STREQUAL "aab")
+ set(extra_args "bundle")
+ endif()
+
+ set(package_file_path "${android_build_dir}/${target}.${type}")
+
+ _qt_internal_android_package_path(package_build_dir ${target} ${type})
+ _qt_internal_android_get_deployment_type_option(deployment_type_suffix
+ "release" "debug")
+ set(package_build_file_path
+ "${package_build_dir}/${deployment_type_suffix}/app-${deployment_type_suffix}.${type}")
+
+ set(extra_deps "")
+ if(TARGET ${target}_copy_feature_names)
+ list(APPEND extra_deps ${target}_copy_feature_names)
+ endif()
+
+ if(TARGET ${target}_deploy_dynamic_features)
+ list(APPEND extra_deps ${target}_deploy_dynamic_features)
+ endif()
+
+ set(gradle_scripts "$<TARGET_PROPERTY:${target},_qt_android_deployment_files>")
+ add_custom_command(OUTPUT "${package_file_path}"
+ BYPRODUCTS "${package_build_file_path}"
+ COMMAND
+ "${gradlew}" ${android_deployment_type_option} ${extra_args}
+ COMMAND
+ ${CMAKE_COMMAND} -E copy_if_different
+ "${package_build_file_path}" "${package_file_path}"
+ DEPENDS
+ ${target}
+ ${gradle_scripts}
+ ${target}_copy_gradle_files
+ ${target}_android_deploy_aux
+ ${extra_deps}
+ WORKING_DIRECTORY
+ "${android_build_dir}"
+ VERBATIM
+ )
+
+ add_custom_target(${target}_make_${type} DEPENDS "${package_file_path}")
+endfunction()
+
+# Returns the path to the android executable package either apk or aab.
+function(_qt_internal_android_package_path out_var target type)
+ set(supported_package_types apk aab)
+ if(NOT type IN_LIST supported_package_types)
+ message(FATAL_ERROR "Invalid package type, supported types: ${supported_package_types}")
+ endif()
+
+ # aab packages are located in the bundle directory
+ if(type STREQUAL "aab")
+ set(type "bundle")
+ endif()
+
+ _qt_internal_android_get_target_deployment_dir(deployment_dir ${target})
+
+ set(${out_var} "${deployment_dir}/build/outputs/${type}" PARENT_SCOPE)
+endfunction()
+
+# Returns the path to the gradle build directory.
+function(_qt_internal_android_gradle_template_dir out_var)
+ if(PROJECT_NAME STREQUAL "QtBase" OR QT_SUPERBUILD)
+ set(${out_var} "${QtBase_SOURCE_DIR}/src/3rdparty/gradle" PARENT_SCOPE)
+ else()
+ set(${out_var} "${QT6_INSTALL_PREFIX}/${QT6_INSTALL_DATA}/src/3rdparty/gradle" PARENT_SCOPE)
+ endif()
+endfunction()
+
+# Returns the path to the android java dir.
+function(_qt_internal_android_java_dir out_var)
+ if(PROJECT_NAME STREQUAL "QtBase" OR QT_SUPERBUILD)
+ set(${out_var} "${QtBase_SOURCE_DIR}/src/android/java" PARENT_SCOPE)
+ else()
+ set(${out_var} "${QT6_INSTALL_PREFIX}/${QT6_INSTALL_DATA}/src/android/java" PARENT_SCOPE)
+ endif()
+endfunction()
+
+# Returns the platform-spefic name of the gradlew script.
+function(_qt_internal_android_gradlew_name out_var)
+ if(CMAKE_HOST_WIN32)
+ set(gradlew_file_name "gradlew.bat")
+ else()
+ set(gradlew_file_name "gradlew")
+ endif()
+
+ set(${out_var} "${gradlew_file_name}" PARENT_SCOPE)
+endfunction()
+
+# Return the path to the gradlew script.
+function(_qt_internal_android_gradlew_path out_var target)
+ _qt_internal_android_get_target_android_build_dir(android_build_dir ${target})
+ set(${out_var} "${android_build_dir}/${gradlew_file_name}" PARENT_SCOPE)
+endfunction()
+
+# Returns the generator expression for the gradle_property value. Defaults to the default_value
+# argument.
+function(_qt_internal_android_get_gradle_property out_var target target_property default_value)
+ set(target_property_genex "$<GENEX_EVAL:$<TARGET_PROPERTY:${target},${target_property}>>")
+ string(JOIN "" result
+ "$<IF:$<BOOL:${target_property_genex}>,"
+ "${target_property_genex},"
+ "${default_value}"
+ ">"
+ )
+ set(${out_var} "${result}" PARENT_SCOPE)
+endfunction()
+
+# Generates gradle.properties for the specific target. Usually contains the
+# target build type(executable, dynamic feature, library).
+function(_qt_internal_android_generate_target_gradle_properties target)
+ cmake_parse_arguments(PARSE_ARGV 1 arg "" "DEPLOYMENT_DIR" "")
+
+ if(NOT arg_DEPLOYMENT_DIR)
+ message(FATAL_ERROR "DEPLOYMENT_DIR is not specified.")
+ endif()
+
+ set(gradle_properties_file_name "gradle.properties")
+ set(out_file "${arg_DEPLOYMENT_DIR}/${gradle_properties_file_name}")
+ # Skip generating the file if it's already provided by user.
+ get_target_property(deployment_files ${target} _qt_android_deployment_files)
+ if("${out_file}" IN_LIST deployment_files)
+ return()
+ endif()
+
+ _qt_internal_android_get_template_path(template_file ${target}
+ "app/${gradle_properties_file_name}")
+ _qt_internal_configure_file(CONFIGURE
+ OUTPUT "${out_file}"
+ INPUT "${template_file}"
+ )
+ set_property(TARGET ${target} APPEND PROPERTY _qt_android_deployment_files "${out_file}")
+endfunction()
+
+# Constucts generator expression that returns either target property or the default value
+function(_qt_internal_android_get_manifest_property out_var target property default)
+ set(target_property "$<TARGET_PROPERTY:${target},${property}>")
+ string(JOIN "" out_genex
+ "$<IF:$<BOOL:${target_property}>,"
+ "${target_property},"
+ "${default}"
+ ">"
+ )
+
+ set(${out_var} "${out_genex}" PARENT_SCOPE)
+endfunction()
+
+# Generates the target AndroidManifest.xml
+function(_qt_internal_android_generate_target_android_manifest target)
+ cmake_parse_arguments(PARSE_ARGV 1 arg "" "DEPLOYMENT_DIR" "")
+
+ if(NOT arg_DEPLOYMENT_DIR)
+ message(FATAL_ERROR "DEPLOYMENT_DIR is not specified.")
+ endif()
+
+ set(android_manifest_filename "AndroidManifest.xml")
+ set(out_file "${arg_DEPLOYMENT_DIR}/${android_manifest_filename}")
+
+ # Skip generating the file if it's already provided by user.
+ get_target_property(deployment_files ${target} _qt_android_deployment_files)
+ if("${out_file}" IN_LIST deployment_files)
+ return()
+ endif()
+
+ _qt_internal_android_get_template_path(template_file ${target}
+ "app/${android_manifest_filename}")
+ set(temporary_file "${out_file}.tmp")
+
+ # The file cannot be generated at cmake configure time, because androiddeployqt
+ # will override it at build time. We use this trick with temporary file to override
+ # it after the aux run of androiddeployqt.
+ add_custom_command(OUTPUT "${out_file}"
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different
+ "${temporary_file}"
+ "${out_file}"
+ DEPENDS
+ "${template_file}"
+ "${temporary_file}"
+ ${target}_android_deploy_aux
+ )
+
+ _qt_internal_android_get_manifest_property(APP_PACKAGE_NAME ${target}
+ QT_ANDROID_PACKAGE_NAME "org.qtproject.example.$<MAKE_C_IDENTIFIER:${target}>")
+ _qt_internal_android_get_manifest_property(APP_NAME ${target}
+ QT_ANDROID_APP_NAME "${target}")
+ _qt_internal_android_get_manifest_property(APP_VERSION_CODE ${target}
+ QT_ANDROID_VERSION_CODE "1")
+ _qt_internal_android_get_manifest_property(APP_VERSION_NAME ${target}
+ QT_ANDROID_VERSION_NAME "1")
+ _qt_internal_android_get_manifest_property(APP_LIB_NAME ${target} OUTPUT_NAME "${target}")
+
+ # For application icon we substitute the whole attribute definition, but not only value
+ # otherwise it leads to the Manifest processing issue.
+ set(target_property "$<TARGET_PROPERTY:${target},QT_ANDROID_APP_ICON>")
+ string(JOIN "" APP_ICON
+ "$<$<BOOL:${target_property}>:"
+ "android:icon=\"${target_property}\""
+ ">"
+ )
+
+ file(READ "${template_file}" manifest_content)
+ string(REPLACE ">" "$<ANGLE-R>" manifest_content "${manifest_content}")
+ string(REPLACE ";" "$<SEMICOLON>" manifest_content "${manifest_content}")
+ string(REPLACE "," "$<COMMA>" manifest_content "${manifest_content}")
+
+ _qt_internal_android_convert_permissions(APP_PERMISSIONS ${target} XML)
+
+ set(feature_prefix "\n <uses-feature android:name=\"")
+ set(feature_suffix " \" android:required=\"false\" /$<ANGLE-R>")
+ set(feature_property "$<TARGET_PROPERTY:${target},QT_ANDROID_FEATURES>")
+ string(JOIN "" APP_FEATURES
+ "$<$<BOOL:${feature_property}>:"
+ "${feature_prefix}"
+ "$<JOIN:${feature_property},${feature_suffix},${feature_prefix}>"
+ "${feature_suffix}"
+ ">"
+ )
+
+ set(APP_ARGUMENTS "${QT_ANDROID_APPLICATION_ARGUMENTS}")
+
+ _qt_internal_configure_file(GENERATE OUTPUT "${temporary_file}"
+ CONTENT "${manifest_content}")
+
+ set_property(TARGET ${target} APPEND PROPERTY
+ _qt_android_deployment_files "${out_file}" "${temporary_file}")
+endfunction()
+
+# Generates the top-level gradle.properties in the android-build directory
+# The file contains the information about the versions of the android build
+# tools, the list of supported ABIs.
+function(_qt_internal_android_generate_bundle_gradle_properties target)
+ set(EXTRA_PROPERTIES "")
+
+ set(gradle_properties_file_name "gradle.properties")
+ _qt_internal_android_get_target_android_build_dir(android_build_dir ${target})
+ set(out_file "${android_build_dir}/${gradle_properties_file_name}")
+
+ # Skip generating the file if it's already provided by user.
+ get_target_property(deployment_files ${target} _qt_android_deployment_files)
+ if("${out_file}" IN_LIST deployment_files)
+ return()
+ endif()
+
+ _qt_internal_android_get_template_path(template_file ${target} "${gradle_properties_file_name}")
+ _qt_internal_configure_file(CONFIGURE
+ OUTPUT "${out_file}"
+ INPUT "${template_file}"
+ )
+ set_property(TARGET ${target} APPEND PROPERTY _qt_android_deployment_files "${out_file}")
+endfunction()
+
+# Generates the local.properties for gradle builds. Contains the path to the
+# Android SDK root.
+function(_qt_internal_android_generate_bundle_local_properties target)
+ _qt_internal_android_get_target_android_build_dir(android_build_dir ${target})
+ set(out_file "${android_build_dir}/local.properties")
+
+ # Skip generating the file if it's already provided by user.
+ get_target_property(deployment_files ${target} _qt_android_deployment_files)
+ if("${out_file}" IN_LIST deployment_files)
+ return()
+ endif()
+
+ file(TO_CMAKE_PATH "${ANDROID_SDK_ROOT}" ANDROID_SDK_ROOT_NATIVE)
+ _qt_internal_configure_file(CONFIGURE OUTPUT "${out_file}"
+ CONTENT "sdk.dir=${ANDROID_SDK_ROOT_NATIVE}\n")
+endfunction()
+
+# Copies the customized Android package sources to the Android build directory
+function(_qt_internal_android_copy_target_package_sources target)
+ _qt_internal_android_get_package_source_dir(package_source_dir ${target})
+
+ if(NOT package_source_dir)
+ return()
+ endif()
+ get_filename_component(package_source_dir "${package_source_dir}" ABSOLUTE)
+
+ # Collect deployment files from use-defined package source directory
+ file(GLOB_RECURSE package_files
+ LIST_DIRECTORIES false
+ RELATIVE "${package_source_dir}"
+ "${package_source_dir}/*"
+ )
+
+ # Do not copy files that we treat as CMake templates, having '.in' extention.
+ #
+ # TODO: If it ever will be an issue we may exclude only templates that are
+ # known by our build system.
+ list(FILTER package_files EXCLUDE REGEX ".+\\.in$")
+
+ _qt_internal_android_get_target_android_build_dir(android_build_dir ${target})
+ list(TRANSFORM package_files PREPEND "${android_build_dir}/" OUTPUT_VARIABLE out_package_files)
+ list(TRANSFORM package_files PREPEND "${package_source_dir}/" OUTPUT_VARIABLE in_package_files)
+
+ if(in_package_files)
+ # TODO: Add cmake < 3.26 support
+ if(CMAKE_VERSION VERSION_LESS 3.26)
+ message(FATAL_ERROR "The use of QT_ANDROID_PACKAGE_SOURCE_DIR property with
+ the QT_USE_ANDROID_MODERN_BUNDLE option enabled requires CMake version >= 3.26.")
+ endif()
+ set(copy_commands COMMAND "${CMAKE_COMMAND}" -E copy_directory_if_different
+ "${package_source_dir}" "${android_build_dir}")
+ else()
+ # We actually have nothing to deploy.
+ return()
+ endif()
+
+ add_custom_command(OUTPUT ${out_package_files}
+ ${copy_commands}
+ DEPENDS
+ ${in_package_files}
+ VERBATIM
+ )
+
+ set_target_properties(${target} PROPERTIES _qt_android_deployment_files "${out_package_files}")
+endfunction()
+
+# Copies gradle scripts to a build directory.
+function(_qt_internal_android_copy_gradle_files target output_directory)
+ _qt_internal_android_gradlew_name(gradlew_file_name)
+ _qt_internal_android_gradle_template_dir(gradle_template_dir)
+
+ set(gradlew_file_src "${gradle_template_dir}/${gradlew_file_name}")
+ set(gradlew_file_dst "${output_directory}/${gradlew_file_name}")
+
+ add_custom_command(OUTPUT "${gradlew_file_dst}"
+ COMMAND
+ ${CMAKE_COMMAND} -E copy_if_different "${gradlew_file_src}" "${gradlew_file_dst}"
+ DEPENDS "${gradlew_file_src}"
+ COMMENT "Copying gradlew script for ${target}"
+ VERBATIM
+ )
+
+ # TODO: make a more precise directory copying
+ set(gradle_dir_src "${gradle_template_dir}/gradle")
+ set(gradle_dir_dst "${output_directory}/gradle")
+ add_custom_command(OUTPUT "${gradle_dir_dst}"
+ COMMAND
+ ${CMAKE_COMMAND} -E copy_directory "${gradle_dir_src}" "${gradle_dir_dst}"
+ DEPENDS "${gradle_dir_src}"
+ COMMENT "Copying gradle support files for ${target}"
+ VERBATIM
+ )
+
+ add_custom_target(${target}_copy_gradle_files
+ DEPENDS
+ "${gradlew_file_dst}"
+ "${gradle_dir_dst}"
+ )
+endfunction()
diff --git a/src/corelib/Qt6AndroidMacros.cmake b/src/corelib/Qt6AndroidMacros.cmake
index aa0e5bfed24..ed97a42c83f 100644
--- a/src/corelib/Qt6AndroidMacros.cmake
+++ b/src/corelib/Qt6AndroidMacros.cmake
@@ -120,6 +120,29 @@ function(_qt_internal_generate_android_permissions_json out_result target)
set(${out_result} "${result}" PARENT_SCOPE)
endfunction()
+# Add the specific dynamic library as the dynamic feature for the Android application target.
+function(qt6_add_android_dynamic_features target)
+ cmake_parse_arguments(PARSE_ARGV 1 arg "" "" "FEATURE_TARGETS")
+ if(NOT QT_USE_ANDROID_MODERN_BUNDLE)
+ message(FATAL_ERROR "qt6_add_android_dynamic_features is only supported with"
+ " 'QT_USE_ANDROID_MODERN_BUNDLE' enabled.")
+ endif()
+ if(NOT TARGET ${target})
+ message(FATAL_ERROR "${target} is not a target. Cannot add the dynamic features.")
+ endif()
+ get_target_property(android_type ${target} _qt_android_target_type)
+ if(NOT android_type STREQUAL "APPLICATION")
+ message(FATAL_ERROR "${target} is not an android executable target."
+ " Cannot add the dynamic features.")
+ endif()
+ if(arg_FEATURE_TARGETS)
+ set_property(TARGET ${target}
+ APPEND PROPERTY _qt_android_dynamic_features ${arg_FEATURE_TARGETS})
+ else()
+ message(WARNING "No dynamic features provided.")
+ endif()
+endfunction()
+
# Generate the deployment settings json file for a cmake target.
function(qt6_android_generate_deployment_settings target)
# Information extracted from mkspecs/features/android/android_deployment_settings.prf
@@ -324,8 +347,9 @@ function(qt6_android_generate_deployment_settings target)
__qt_internal_collect_plugin_library_files_v2("${target}" "${plugin_targets}" plugin_targets)
string(APPEND file_contents " \"android-deploy-plugins\":\"${plugin_targets}\",\n")
- _qt_internal_generate_android_permissions_json(permissions_json_array "${target}")
- string(APPEND file_contents " \"permissions\": ${permissions_json_array},\n")
+
+ _qt_internal_android_convert_permissions(permissions_genex ${target} JSON)
+ string(APPEND file_contents " \"permissions\": ${permissions_genex},\n")
# App binary
string(APPEND file_contents
@@ -415,44 +439,6 @@ if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
endfunction()
endif()
-function(_qt_internal_add_android_permission target)
- if(NOT TARGET ${target})
- message(FATAL_ERROR "Empty or invalid target for adding Android permission: (${target})")
- endif()
-
- cmake_parse_arguments(arg "" "NAME" "ATTRIBUTES" ${ARGN})
-
- if(NOT arg_NAME)
- message(FATAL_ERROR "NAME for adding Android permission cannot be empty (${target})")
- endif()
-
- set(permission_entry "${arg_NAME}")
-
- if(arg_ATTRIBUTES)
- # Permission with additional attributes
- list(LENGTH arg_ATTRIBUTES attributes_len)
- math(EXPR attributes_modulus "${attributes_len} % 2")
- if(NOT (attributes_len GREATER 1 AND attributes_modulus EQUAL 0))
- message(FATAL_ERROR "Android permission: ${arg_NAME} attributes: ${arg_ATTRIBUTES} must"
- " be name-value pairs (for example: minSdkVersion 30)")
- endif()
- # Combine name-value pairs
- set(index 0)
- set(attributes "")
- while(index LESS attributes_len)
- list(GET arg_ATTRIBUTES ${index} name)
- math(EXPR index "${index} + 1")
- list(GET arg_ATTRIBUTES ${index} value)
- string(APPEND attributes "android:${name}=\'${value}\' ")
- math(EXPR index "${index} + 1")
- endwhile()
- set(permission_entry "${permission_entry}\;${attributes}")
- endif()
-
- # Append the permission to the target's property
- set_property(TARGET ${target} APPEND PROPERTY QT_ANDROID_PERMISSIONS "${permission_entry}")
-endfunction()
-
function(qt6_add_android_permission target)
_qt_internal_add_android_permission(${ARGV})
endfunction()
@@ -519,18 +505,6 @@ function(qt6_android_add_apk_target target)
">"
)
- # Make global apk and aab targets depend on the current apk target.
- if(TARGET aab)
- add_dependencies(aab ${target}_make_aab)
- endif()
- if(TARGET aar)
- add_dependencies(aar ${target}_make_aar)
- endif()
- if(TARGET apk)
- add_dependencies(apk ${target}_make_apk)
- _qt_internal_create_global_apk_all_target_if_needed()
- endif()
-
_qt_internal_android_get_deployment_tool(deployment_tool)
# No need to use genex for the BINARY_DIR since it's read-only.
@@ -719,6 +693,10 @@ function(qt6_android_add_apk_target target)
)
add_dependencies(${target}_make_aab ${target}_prepare_apk_dir)
+ # Make global apk, aab, and aar targets depend on the respective targets.
+ _qt_internal_android_add_global_package_dependencies(${target})
+ _qt_internal_create_global_apk_all_target_if_needed()
+
if(QT_IS_ANDROID_MULTI_ABI_EXTERNAL_PROJECT)
# When building per-ABI external projects we only need to copy ABI-specific libraries and
# resources to the "main" ABI android build folder.
@@ -1661,13 +1639,26 @@ endfunction()
# module and is executed implicitly when configuring user projects.
function(_qt_internal_android_executable_finalizer target)
set_property(TARGET ${target} PROPERTY _qt_android_executable_finalizer_called TRUE)
+ set_property(TARGET ${target} PROPERTY _qt_android_in_finalizer "EXECUTABLE")
_qt_internal_expose_android_package_source_dir_to_ide(${target})
_qt_internal_configure_android_multiabi_target("${target}")
qt6_android_generate_deployment_settings("${target}")
- qt6_android_add_apk_target("${target}")
+ if(QT_USE_ANDROID_MODERN_BUNDLE)
+ _qt_internal_android_generate_dynamic_feature_names("${target}")
+ _qt_internal_android_add_dynamic_feature_deployment("${target}")
+
+ _qt_internal_android_prepare_gradle_build("${target}")
+ _qt_internal_android_add_aux_deployment("${target}")
+
+ _qt_internal_collect_apk_dependencies_defer()
+ _qt_internal_collect_apk_imported_dependencies_defer("${target}")
+ else()
+ qt6_android_add_apk_target("${target}")
+ endif()
_qt_internal_android_create_runner_wrapper("${target}")
+ set_property(TARGET ${target} PROPERTY _qt_android_in_finalizer "")
endfunction()
# Helper to add the android executable finalizer.
@@ -1737,8 +1728,9 @@ function(_qt_internal_android_app_runner_arguments target out_runner_path out_ar
set(${out_runner_path} "${runner_dir}/qt-android-runner.py" PARENT_SCOPE)
_qt_internal_android_get_target_android_build_dir(android_build_dir ${target})
+ _qt_internal_android_get_platform_tools_path(platform_tools)
set(${out_arguments}
- "--adb" "${ANDROID_SDK_ROOT}/platform-tools/adb"
+ "--adb" "${platform_tools}/adb"
"--build-path" "${android_build_dir}"
"--apk" "${android_build_dir}/${target}.apk"
PARENT_SCOPE
@@ -1754,8 +1746,13 @@ function(_qt_internal_android_get_target_android_build_dir out_build_dir target)
endif()
endfunction()
+function(_qt_internal_android_get_target_deployment_dir out_deploy_dir target)
+ _qt_internal_android_get_target_android_build_dir(build_dir ${target})
+ set(${out_deploy_dir} "${build_dir}/app" PARENT_SCOPE)
+endfunction()
+
function(_qt_internal_expose_android_package_source_dir_to_ide target)
- get_target_property(android_package_source_dir ${target} QT_ANDROID_PACKAGE_SOURCE_DIR)
+ _qt_internal_android_get_package_source_dir(android_package_source_dir ${target})
if(android_package_source_dir)
get_target_property(target_source_dir ${target} SOURCE_DIR)
if(NOT IS_ABSOLUTE "${android_package_source_dir}")
@@ -1778,6 +1775,71 @@ function(_qt_internal_expose_android_package_source_dir_to_ide target)
endif()
endfunction()
+function(_qt_internal_android_add_aux_deployment target)
+ cmake_parse_arguments(arg "" "OUTPUT_TARGET_NAME;DEPLOYMENT_DIRECTORY" "EXTRA_ARGS" ${ARGN})
+ _qt_internal_validate_all_args_are_parsed(arg)
+
+ string(JOIN "" deployment_file
+ "$<GENEX_EVAL:"
+ "$<TARGET_PROPERTY:${target},QT_ANDROID_DEPLOYMENT_SETTINGS_FILE>"
+ ">"
+ )
+
+ _qt_internal_android_get_deployment_tool(deployment_tool)
+ if(arg_DEPLOYMENT_DIRECTORY)
+ set(deployment_dir "${arg_DEPLOYMENT_DIRECTORY}")
+ else()
+ _qt_internal_android_get_target_deployment_dir(deployment_dir ${target})
+ endif()
+
+ cmake_policy(PUSH)
+ if(POLICY CMP0116)
+ # Without explicitly setting this policy to NEW, we get a warning
+ # even though we ensure there's actually no problem here.
+ # See https://gitlab.kitware.com/cmake/cmake/-/issues/21959
+ cmake_policy(SET CMP0116 NEW)
+ set(relative_to_dir ${CMAKE_CURRENT_BINARY_DIR})
+ else()
+ set(relative_to_dir ${CMAKE_BINARY_DIR})
+ endif()
+
+ set(target_file_copy_relative_path
+ "libs/${CMAKE_ANDROID_ARCH_ABI}/$<TARGET_FILE_NAME:${target}>")
+ _qt_internal_copy_file_if_different_command(copy_command
+ "$<TARGET_FILE:${target}>"
+ "${deployment_dir}/${target_file_copy_relative_path}"
+ )
+
+ _qt_internal_android_get_use_terminal_for_deployment(uses_terminal)
+
+ # TODO: We use androiddeployqt to collect target depdenencies and produce the lib.xml file
+ # which autoloads the collected libraries. Should be done using GRE and transitive properties
+ # in the future.
+ set(libs_xml "${deployment_dir}/res/values/libs.xml")
+ add_custom_command(OUTPUT "${libs_xml}"
+ COMMAND ${copy_command}
+ COMMAND "${deployment_tool}"
+ --input "${deployment_file}"
+ --output "${deployment_dir}"
+ --builddir "${relative_to_dir}"
+ --aux-mode
+ ${arg_EXTRA_ARGS}
+ #TODO: Support signing
+ COMMENT "Deploying Android artifacts for ${target}"
+ DEPENDS "${target}" "${deployment_file}"
+ VERBATIM
+ ${uses_terminal}
+ )
+
+ if(NOT arg_OUTPUT_TARGET_NAME)
+ set(arg_OUTPUT_TARGET_NAME ${target}_android_deploy_aux)
+ endif()
+
+ add_custom_target(${arg_OUTPUT_TARGET_NAME} DEPENDS "${libs_xml}")
+
+ cmake_policy(POP)
+endfunction()
+
# Enables the terminal usage for the add_custom_command calls when verbose deployment is enabled.
function(_qt_internal_android_get_use_terminal_for_deployment out_var)
if(QT_ENABLE_VERBOSE_DEPLOYMENT)
@@ -1822,6 +1884,45 @@ function(_qt_internal_android_get_deployment_type_option out_var release_flag de
endif()
endfunction()
+# Returns the path to the android template directory, that are used by CMake
+# deployment procedures.
+function(_qt_internal_android_template_dir out_var)
+ if(PROJECT_NAME STREQUAL "QtBase" OR QT_SUPERBUILD)
+ set(${out_var} "${QtBase_SOURCE_DIR}/src/android/templates_cmake" PARENT_SCOPE)
+ else()
+ set(${out_var}
+ "${QT6_INSTALL_PREFIX}/${QT6_INSTALL_DATA}/src/android/templates_cmake" PARENT_SCOPE)
+ endif()
+endfunction()
+
+# Return the path to the target template directory if it's set for the target.
+# Then this path is stored in the target QT_ANDROID_PACKAGE_SOURCE_DIR property
+# and can only be effectively read in android finalizers.
+function(_qt_internal_android_get_package_source_dir out_var target)
+ get_target_property(in_finalizer ${target} _qt_android_in_finalizer)
+ if(NOT in_finalizer)
+ message(FATAL_ERROR "The '_qt_internal_android_get_package_source_dir' function is"
+ " called outside the Android finalizer."
+ " This is the Qt issue, please report a bug at https://bugreports.qt.io.")
+ endif()
+ get_target_property(package_src_dir ${target} QT_ANDROID_PACKAGE_SOURCE_DIR)
+ if(NOT package_src_dir)
+ set(package_src_dir "")
+ endif()
+ set(${out_var} "${package_src_dir}" PARENT_SCOPE)
+endfunction()
+
+# Add target_make_<apk|aab> as the depednecy for the respective global apk/aab
+# target.
+function(_qt_internal_android_add_global_package_dependencies target)
+ foreach(type apk aab aar)
+ # Make global apk and aab targets depend on the current apk target.
+ if(TARGET ${type} AND TARGET ${target}_make_${type})
+ add_dependencies(${type} ${target}_make_${type})
+ endif()
+ endforeach()
+endfunction()
+
function(_qt_internal_android_get_target_abis out_abis target)
get_target_property(target_abis ${target} QT_ANDROID_ABIS)
if(target_abis)
@@ -1840,5 +1941,10 @@ function(_qt_internal_android_get_target_abis out_abis target)
set(${out_abis} "${android_abis}" PARENT_SCOPE)
endfunction()
+# Returns the path to the Android platform-tools(adb is located there).
+function(_qt_internal_android_get_platform_tools_path out_var)
+ set(${out_var} "${ANDROID_SDK_ROOT}/platform-tools" PARENT_SCOPE)
+endfunction()
+
set(QT_INTERNAL_ANDROID_TARGET_BUILD_DIR_SUPPORT ON CACHE INTERNAL
"Indicates that Qt supports per-target Android build directories")
diff --git a/src/corelib/Qt6AndroidPermissionHelpers.cmake b/src/corelib/Qt6AndroidPermissionHelpers.cmake
new file mode 100644
index 00000000000..7f851e14667
--- /dev/null
+++ b/src/corelib/Qt6AndroidPermissionHelpers.cmake
@@ -0,0 +1,126 @@
+# Copyright (C) 2025 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+# Generates the generator expression that converts the 'target'
+# QT_ANDROID_PERMISSIONS property to the specific 'type'.
+#
+# It's expected that each element in QT_ANDROID_PERMISSIONS list has specific
+# format:
+# <name>\;<permission>\\\;<extra1>\;<value>\\\;<extra2>\;<value>
+#
+# Synopsis
+# _qt_internal_android_convert_permissions(out_var target <JSON|XML>)
+#
+# Arguments
+#
+# `out_var`
+# The name of the variable where the resulting generator expression is
+# stored.
+#
+# `target`
+# The name of the target.
+#
+# `JSON`
+# Generate JSON array known by androiddeployqt.
+#
+# `XML`
+# Generate XML content compatible with AndroidManifest.xml.
+function(_qt_internal_android_convert_permissions out_var target type)
+ set(permissions_property "$<TARGET_PROPERTY:${target},QT_ANDROID_PERMISSIONS>")
+ set(permissions_genex "$<$<BOOL:${permissions_property}>:")
+ if(type STREQUAL "JSON")
+ set(pref "{ \"")
+ set(post "\" }")
+ set(indent "\n ")
+ string(APPEND permissions_genex
+ "[${indent}$<JOIN:"
+ "$<JOIN:"
+ "${pref}$<JOIN:"
+ "${permissions_property},"
+ "${post}$<COMMA>${indent}${pref}"
+ ">${post},"
+ "\": \""
+ ">,"
+ "\"$<COMMA> \""
+ ">\n ]"
+ )
+ elseif(type STREQUAL "XML")
+ set(pref "<uses-permission\n android:")
+ set(post "' /$<ANGLE-R>\n")
+ string(APPEND permissions_genex
+ "$<JOIN:"
+ "$<JOIN:"
+ "${pref}$<JOIN:"
+ "${permissions_property},"
+ "${post}${pref}"
+ ">${post}\n,"
+ "='"
+ ">,"
+ "' android:"
+ ">"
+ )
+ else()
+ message(FATAL_ERROR "Invalid type ${type}. Supported types: JSON, XML")
+ endif()
+ string(APPEND permissions_genex ">")
+
+ set(${out_var} "${permissions_genex}" PARENT_SCOPE)
+endfunction()
+
+# Add the specific Android permission to the target. The permission is stored
+# in the QT_ANDROID_PERMISSIONS property(the property is not a public API)
+# and has the following format:
+# <name>\;<permission>\\\;<extra1>\;<value>\\\;<extra2>\;<value>
+#
+# Synopsis
+# _qt_internal_add_android_permission(target NAME <permission>
+# ATTRIBUTES <extra1> <value1>
+# [<extra2> <value2>]...
+# )
+#
+# Arguments
+#
+# `target`
+# The Android target.
+#
+# `NAME`
+# The permission name. E.g. 'android.permission.CAMERA'.
+#
+# `ATTRIBUTES`
+# Extra permission attribute key-value pairs.
+# See https://developer.android.com/guide/topics/manifest/uses-permission-element
+# for details.
+function(_qt_internal_add_android_permission target)
+ if(NOT TARGET ${target})
+ message(FATAL_ERROR "Empty or invalid target for adding Android permission: (${target})")
+ endif()
+
+ cmake_parse_arguments(arg "" "NAME" "ATTRIBUTES" ${ARGN})
+
+ if(NOT arg_NAME)
+ message(FATAL_ERROR "NAME for adding Android permission cannot be empty (${target})")
+ endif()
+
+ set(permission_entry "name\;${arg_NAME}")
+ if(arg_ATTRIBUTES)
+ # Permission with additional attributes
+ list(LENGTH arg_ATTRIBUTES attributes_len)
+ math(EXPR attributes_modulus "${attributes_len} % 2")
+ if(NOT (attributes_len GREATER 1 AND attributes_modulus EQUAL 0))
+ message(FATAL_ERROR "Android permission: ${arg_NAME} attributes: ${arg_ATTRIBUTES}"
+ " must be name-value pairs (for example: minSdkVersion 30)")
+ endif()
+ # Combine name-value pairs
+ set(index 0)
+ while(index LESS attributes_len)
+ list(GET arg_ATTRIBUTES ${index} name)
+ math(EXPR index "${index} + 1")
+ list(GET arg_ATTRIBUTES ${index} value)
+ string(APPEND permission_entry "\\\;${name}\;${value}")
+ math(EXPR index "${index} + 1")
+ endwhile()
+ endif()
+
+ # Append the permission to the target's property
+ set_property(TARGET ${target} APPEND PROPERTY QT_ANDROID_PERMISSIONS "${permission_entry}")
+endfunction()
diff --git a/src/corelib/Qt6CoreConfigExtras.cmake.in b/src/corelib/Qt6CoreConfigExtras.cmake.in
index 15405197a61..8a88d558fa8 100644
--- a/src/corelib/Qt6CoreConfigExtras.cmake.in
+++ b/src/corelib/Qt6CoreConfigExtras.cmake.in
@@ -30,6 +30,10 @@ _qt_internal_setup_deploy_support()
if(ANDROID_PLATFORM)
include("${CMAKE_CURRENT_LIST_DIR}/@[email protected]")
+ include("${CMAKE_CURRENT_LIST_DIR}/@[email protected]")
+ include("${CMAKE_CURRENT_LIST_DIR}/@[email protected]")
+ include("${CMAKE_CURRENT_LIST_DIR}/@[email protected]")
+
_qt_internal_create_global_android_targets()
_qt_internal_collect_default_android_abis()
if(__qt_Core_targets_file_included)
diff --git a/src/corelib/Qt6CoreMacros.cmake b/src/corelib/Qt6CoreMacros.cmake
index 7b522f99abb..5bc85ae7f7a 100644
--- a/src/corelib/Qt6CoreMacros.cmake
+++ b/src/corelib/Qt6CoreMacros.cmake
@@ -683,6 +683,9 @@ function(_qt_internal_create_executable target)
)
qt6_android_apply_arch_suffix("${target}")
+ if(QT_USE_ANDROID_MODERN_BUNDLE)
+ _qt_internal_set_android_application_gradle_defaults(${target})
+ endif()
else()
cmake_policy(PUSH)
__qt_internal_set_cmp0156()
diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp
index d74894e1e42..4388122b7b9 100644
--- a/src/corelib/animation/qabstractanimation.cpp
+++ b/src/corelib/animation/qabstractanimation.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:significant reason:default
/*!
\class QAbstractAnimation
diff --git a/src/corelib/animation/qabstractanimation.h b/src/corelib/animation/qabstractanimation.h
index 69a30556a3a..b4b43e64a1d 100644
--- a/src/corelib/animation/qabstractanimation.h
+++ b/src/corelib/animation/qabstractanimation.h
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:significant reason:default
#ifndef QABSTRACTANIMATION_H
#define QABSTRACTANIMATION_H
diff --git a/src/corelib/animation/qabstractanimation_p.h b/src/corelib/animation/qabstractanimation_p.h
index d6c245f36f0..51c635f1bed 100644
--- a/src/corelib/animation/qabstractanimation_p.h
+++ b/src/corelib/animation/qabstractanimation_p.h
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:significant reason:default
#ifndef QABSTRACTANIMATION_P_H
#define QABSTRACTANIMATION_P_H
diff --git a/src/corelib/animation/qanimationgroup.cpp b/src/corelib/animation/qanimationgroup.cpp
index d2572a7462b..ae96069e86f 100644
--- a/src/corelib/animation/qanimationgroup.cpp
+++ b/src/corelib/animation/qanimationgroup.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:significant reason:default
/*!
\class QAnimationGroup
diff --git a/src/corelib/animation/qanimationgroup.h b/src/corelib/animation/qanimationgroup.h
index 412e2d442ea..07d24ae1f73 100644
--- a/src/corelib/animation/qanimationgroup.h
+++ b/src/corelib/animation/qanimationgroup.h
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:significant reason:default
#ifndef QANIMATIONGROUP_H
#define QANIMATIONGROUP_H
diff --git a/src/corelib/animation/qanimationgroup_p.h b/src/corelib/animation/qanimationgroup_p.h
index 334f780968a..a09bc6ebcc6 100644
--- a/src/corelib/animation/qanimationgroup_p.h
+++ b/src/corelib/animation/qanimationgroup_p.h
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:significant reason:default
#ifndef QANIMATIONGROUP_P_H
#define QANIMATIONGROUP_P_H
diff --git a/src/corelib/animation/qparallelanimationgroup.cpp b/src/corelib/animation/qparallelanimationgroup.cpp
index 86e9417b595..0b43a73434f 100644
--- a/src/corelib/animation/qparallelanimationgroup.cpp
+++ b/src/corelib/animation/qparallelanimationgroup.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:significant reason:default
/*!
\class QParallelAnimationGroup
diff --git a/src/corelib/animation/qparallelanimationgroup.h b/src/corelib/animation/qparallelanimationgroup.h
index 77bc6eabac7..9442f4f7355 100644
--- a/src/corelib/animation/qparallelanimationgroup.h
+++ b/src/corelib/animation/qparallelanimationgroup.h
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:significant reason:default
#ifndef QPARALLELANIMATIONGROUP_H
#define QPARALLELANIMATIONGROUP_H
diff --git a/src/corelib/animation/qparallelanimationgroup_p.h b/src/corelib/animation/qparallelanimationgroup_p.h
index 62c53d36097..482b9555c7d 100644
--- a/src/corelib/animation/qparallelanimationgroup_p.h
+++ b/src/corelib/animation/qparallelanimationgroup_p.h
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:significant reason:default
#ifndef QPARALLELANIMATIONGROUP_P_H
#define QPARALLELANIMATIONGROUP_P_H
diff --git a/src/corelib/animation/qpauseanimation.cpp b/src/corelib/animation/qpauseanimation.cpp
index 344b21946e3..74e22e2f053 100644
--- a/src/corelib/animation/qpauseanimation.cpp
+++ b/src/corelib/animation/qpauseanimation.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:significant reason:default
/*!
\class QPauseAnimation
diff --git a/src/corelib/animation/qpauseanimation.h b/src/corelib/animation/qpauseanimation.h
index f661459f835..bf7863a171c 100644
--- a/src/corelib/animation/qpauseanimation.h
+++ b/src/corelib/animation/qpauseanimation.h
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:significant reason:default
#ifndef QPAUSEANIMATION_H
#define QPAUSEANIMATION_H
diff --git a/src/corelib/animation/qpropertyanimation.cpp b/src/corelib/animation/qpropertyanimation.cpp
index 04f048af753..73ce8ca02c1 100644
--- a/src/corelib/animation/qpropertyanimation.cpp
+++ b/src/corelib/animation/qpropertyanimation.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:significant reason:default
/*!
\class QPropertyAnimation
@@ -20,7 +21,12 @@
makes it possible to animate many of Qt's widgets. Let's look at
an example:
- \snippet code/src_corelib_animation_qpropertyanimation.cpp 0
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp includes
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp class_decl
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp ctor_impl
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp first_example
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp ctor_close
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp main
\note You can also control an animation's lifespan by choosing a
\l{QAbstractAnimation::DeletionPolicy}{delete policy} while starting the
diff --git a/src/corelib/animation/qpropertyanimation.h b/src/corelib/animation/qpropertyanimation.h
index 038c202b8f3..590a6ddaf15 100644
--- a/src/corelib/animation/qpropertyanimation.h
+++ b/src/corelib/animation/qpropertyanimation.h
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:significant reason:default
#ifndef QPROPERTYANIMATION_H
#define QPROPERTYANIMATION_H
diff --git a/src/corelib/animation/qpropertyanimation_p.h b/src/corelib/animation/qpropertyanimation_p.h
index ef5534cd9c3..c1918ae1bf8 100644
--- a/src/corelib/animation/qpropertyanimation_p.h
+++ b/src/corelib/animation/qpropertyanimation_p.h
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:significant reason:default
#ifndef QPROPERTYANIMATION_P_H
#define QPROPERTYANIMATION_P_H
diff --git a/src/corelib/animation/qsequentialanimationgroup.cpp b/src/corelib/animation/qsequentialanimationgroup.cpp
index 260481dbef5..d11249ca7ed 100644
--- a/src/corelib/animation/qsequentialanimationgroup.cpp
+++ b/src/corelib/animation/qsequentialanimationgroup.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:significant reason:default
/*!
\class QSequentialAnimationGroup
diff --git a/src/corelib/animation/qsequentialanimationgroup.h b/src/corelib/animation/qsequentialanimationgroup.h
index 6786078170d..b7f9c1b17a1 100644
--- a/src/corelib/animation/qsequentialanimationgroup.h
+++ b/src/corelib/animation/qsequentialanimationgroup.h
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:significant reason:default
#ifndef QSEQUENTIALANIMATIONGROUP_H
#define QSEQUENTIALANIMATIONGROUP_H
diff --git a/src/corelib/animation/qsequentialanimationgroup_p.h b/src/corelib/animation/qsequentialanimationgroup_p.h
index cbdf204d0a6..131902b5aa5 100644
--- a/src/corelib/animation/qsequentialanimationgroup_p.h
+++ b/src/corelib/animation/qsequentialanimationgroup_p.h
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:significant reason:default
#ifndef QSEQUENTIALANIMATIONGROUP_P_H
#define QSEQUENTIALANIMATIONGROUP_P_H
diff --git a/src/corelib/animation/qvariantanimation.cpp b/src/corelib/animation/qvariantanimation.cpp
index be5c09519e9..bd12d5dae95 100644
--- a/src/corelib/animation/qvariantanimation.cpp
+++ b/src/corelib/animation/qvariantanimation.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:significant reason:default
#include "qvariantanimation.h"
#include "qvariantanimation_p.h"
diff --git a/src/corelib/animation/qvariantanimation.h b/src/corelib/animation/qvariantanimation.h
index 4bdb9713578..172ee0d6090 100644
--- a/src/corelib/animation/qvariantanimation.h
+++ b/src/corelib/animation/qvariantanimation.h
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:significant reason:default
#ifndef QVARIANTANIMATION_H
#define QVARIANTANIMATION_H
diff --git a/src/corelib/animation/qvariantanimation_p.h b/src/corelib/animation/qvariantanimation_p.h
index 0ac238a882b..5fdd9666dba 100644
--- a/src/corelib/animation/qvariantanimation_p.h
+++ b/src/corelib/animation/qvariantanimation_p.h
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:significant reason:default
#ifndef QVARIANTANIMATION_P_H
#define QVARIANTANIMATION_P_H
diff --git a/src/corelib/configure.cmake b/src/corelib/configure.cmake
index 909041cf44b..096dce9e84e 100644
--- a/src/corelib/configure.cmake
+++ b/src/corelib/configure.cmake
@@ -591,6 +591,7 @@ qt_config_compile_test(cpp_winrt
runtimeobject
CODE
"// Including winrt/base.h causes an error in some configurations (Windows 10 SDK + c++20)
+# include <guiddef.h> // required by clang-cl: https://github.com/microsoft/cppwinrt/issues/1179
# include <winrt/base.h>
int main(void)
diff --git a/src/corelib/doc/REUSE.toml b/src/corelib/doc/REUSE.toml
index 254251a0b6b..969cc0d9938 100644
--- a/src/corelib/doc/REUSE.toml
+++ b/src/corelib/doc/REUSE.toml
@@ -3,23 +3,23 @@ version = 1
[[annotations]]
path = ["snippets/**"]
precedence = "closest"
-SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd."
+SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd."
SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR BSD-3-Clause"
[[annotations]]
path = ["**qdocinc", "**/images/**"]
precedence = "closest"
-SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd."
+SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd."
SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only"
[[annotations]]
path = ["src/corelib/doc/qtcore.qdocconf"]
precedence = "closest"
-SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd."
+SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd."
SPDX-License-Identifier = "BSD-3-Clause"
[[annotations]]
path = ["src/corelib/doc/include/QtCoreDoc"]
precedence = "closest"
-SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd."
+SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd."
SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only"
diff --git a/src/corelib/doc/snippets/CMakeLists.txt b/src/corelib/doc/snippets/CMakeLists.txt
index 937433f2e21..78cd4f6b001 100644
--- a/src/corelib/doc/snippets/CMakeLists.txt
+++ b/src/corelib/doc/snippets/CMakeLists.txt
@@ -39,6 +39,7 @@ qt_internal_extend_target(corelib_snippets CONDITION QT_FEATURE_widgets
hellotrmain.cpp
fileinfo/main.cpp
pointer/pointer.cpp
+ qsignalmapper/buttonwidget.cpp
qsortfilterproxymodel-details/main.cpp
qstring/main.cpp
qtcast/qtcast.cpp
@@ -53,6 +54,8 @@ qt_internal_extend_target(corelib_snippets CONDITION QT_FEATURE_gui
qdebug/qdebugsnippet.cpp
)
+set_target_properties(corelib_snippets PROPERTIES COMPILE_OPTIONS "-w")
+
if ("${CMAKE_CXX_COMPILE_FEATURES}" MATCHES "cxx_std_23")
set_property(TARGET corelib_snippets PROPERTY CXX_STANDARD 23)
endif()
diff --git a/src/corelib/doc/snippets/code/doc_src_containers.cpp b/src/corelib/doc/snippets/code/doc_src_containers.cpp
index b5684624929..167437c0151 100644
--- a/src/corelib/doc/snippets/code/doc_src_containers.cpp
+++ b/src/corelib/doc/snippets/code/doc_src_containers.cpp
@@ -3,6 +3,8 @@
#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses
+#include <QtCore>
+
//! [0]
class Employee
{
@@ -18,225 +20,225 @@ private:
};
//! [0]
-//! [range_for]
-QList<QString> list = {"A", "B", "C", "D"};
-for (const auto &item : list) {
- ...
-}
-//! [range_for]
-
-//! [range_for_as_const]
-QList<QString> list = {"A", "B", "C", "D"};
-for (const auto &item : std::as_const(list)) {
- ...
-}
-//! [range_for_as_const]
-
-//! [index]
-QList<QString> list = {"A", "B", "C", "D"};
-for (qsizetype i = 0; i < list.size(); ++i) {
- const auto &item = list.at(i);
- ...
-}
-//! [index]
-
-//! [1]
-QList<QString> list = {"A", "B", "C", "D"};
-
-QListIterator<QString> i(list);
-while (i.hasNext())
- QString s = i.next();
-//! [1]
-
-
-//! [2]
-QListIterator<QString> i(list);
-i.toBack();
-while (i.hasPrevious())
- QString s = i.previous();
-//! [2]
-
-
-//! [3]
-QMutableListIterator<int> i(list);
-while (i.hasNext()) {
- if (i.next() % 2 != 0)
- i.remove();
-}
-//! [3]
-
-
-//! [4]
-QMutableListIterator<int> i(list);
-i.toBack();
-while (i.hasPrevious()) {
- if (i.previous() % 2 != 0)
- i.remove();
-}
-//! [4]
-
-
-//! [5]
-QMutableListIterator<int> i(list);
-while (i.hasNext()) {
- if (i.next() > 128)
- i.setValue(128);
-}
-//! [5]
-
-
-//! [6]
-QMutableListIterator<int> i(list);
-while (i.hasNext())
- i.next() *= 2;
-//! [6]
-
-
-//! [7]
-QMap<QString, QString> map = {
- {"Paris", "France"},
- {"Guatemala City", "Guatemala"},
- {"Mexico City", "Mexico"},
- {"Moscow", "Russia"}
-};
-...
-
-QMutableMapIterator<QString, QString> i(map);
-while (i.hasNext()) {
- if (i.next().key().endsWith("City"))
- i.remove();
-}
-//! [7]
-
-
-//! [8]
-QMap<int, QWidget *> map;
-QHash<int, QWidget *> hash;
-
-QMapIterator<int, QWidget *> i(map);
-while (i.hasNext()) {
- i.next();
- hash.insert(i.key(), i.value());
-}
-//! [8]
-
-
-//! [9]
-QMutableMapIterator<int, QWidget *> i(map);
-while (i.findNext(widget))
- i.remove();
-//! [9]
+void examles()
+{
+ {
+ //! [range_for]
+ QList<QString> list = {"A", "B", "C", "D"};
+ for (const auto &item : list) {
+ //...
+ }
+ //! [range_for]
+ }
+ {
+ //! [range_for_as_const]
+ QList<QString> list = {"A", "B", "C", "D"};
+ for (const auto &item : std::as_const(list)) {
+ //...
+ }
+ //! [range_for_as_const]
+ }
-//! [10]
-QList<QString> list = {"A", "B", "C", "D"};
+ {
+ //! [index]
+ QList<QString> list = {"A", "B", "C", "D"};
+ for (qsizetype i = 0; i < list.size(); ++i) {
+ const auto &item = list.at(i);
+ //...
+ }
+ //! [index]
+ }
-for (auto i = list.begin(), end = list.end(); i != end; ++i)
- *i = (*i).toLower();
-//! [10]
+ {
+ //! [1]
+ QList<QString> list = {"A", "B", "C", "D"};
+ QListIterator<QString> i(list);
+ while (i.hasNext())
+ QString s = i.next();
+ //! [1]
+ }
-//! [11]
-QList<QString> list = {"A", "B", "C", "D"};
+ {
+ QList<QString> list = {"A", "B", "C", "D"};
-for (auto i = list.rbegin(), rend = list.rend(); i != rend; ++i)
- *i = i->toLower();
-//! [11]
+ //! [2]
+ QListIterator<QString> i(list);
+ i.toBack();
+ while (i.hasPrevious())
+ QString s = i.previous();
+ //! [2]
+ }
+ {
+ QList<int> list = {1, 2, 3, 4};
+ {
+ //! [3]
+ QMutableListIterator<int> i(list);
+ while (i.hasNext()) {
+ if (i.next() % 2 != 0)
+ i.remove();
+ }
+ //! [3]
+ }
+
+ {
+ //! [4]
+ QMutableListIterator<int> i(list);
+ i.toBack();
+ while (i.hasPrevious()) {
+ if (i.previous() % 2 != 0)
+ i.remove();
+ }
+ //! [4]
+ }
+
+ {
+ //! [5]
+ QMutableListIterator<int> i(list);
+ while (i.hasNext()) {
+ if (i.next() > 128)
+ i.setValue(128);
+ }
+ //! [5]
+ }
+
+ {
+ //! [6]
+ QMutableListIterator<int> i(list);
+ while (i.hasNext())
+ i.next() *= 2;
+ //! [6]
+ }
+ }
-//! [12]
-for (auto i = list.cbegin(), end = list.cend(); i != end; ++i)
- qDebug() << *i;
-//! [12]
+ {
+ //! [7]
+ QMap<QString, QString> map = {
+ {"Paris", "France"},
+ {"Guatemala City", "Guatemala"},
+ {"Mexico City", "Mexico"},
+ {"Moscow", "Russia"}
+ };
+ //...
+
+ QMutableMapIterator<QString, QString> i(map);
+ while (i.hasNext()) {
+ if (i.next().key().endsWith("City"))
+ i.remove();
+ }
+ //! [7]
+ }
+ {
+ //! [10]
+ QList<QString> list = {"A", "B", "C", "D"};
-//! [13]
-QMap<int, int> map;
-...
-for (auto i = map.cbegin(), end = map.cend(); i != end; ++i)
- qDebug() << i.key() << ':' << i.value();
-//! [13]
+ for (auto i = list.begin(), end = list.end(); i != end; ++i)
+ *i = (*i).toLower();
+ //! [10]
+ }
+ {
+ //! [11]
+ QList<QString> list = {"A", "B", "C", "D"};
-//! [14]
-// RIGHT
-const QList<int> sizes = splitter->sizes();
-for (auto i = sizes.begin(), end = sizes.end(); i != end; ++i)
- ...
+ for (auto i = list.rbegin(), rend = list.rend(); i != rend; ++i)
+ *i = i->toLower();
+ //! [11]
-// WRONG
-for (auto i = splitter->sizes().begin();
- i != splitter->sizes().end(); ++i)
- ...
-//! [14]
+ //! [12]
+ for (auto i = list.cbegin(), end = list.cend(); i != end; ++i)
+ qDebug() << *i;
+ //! [12]
-//! [15]
-QList<QString> values;
-...
-QString str;
-foreach (str, values)
- qDebug() << str;
-//! [15]
+ //! [13]
+ QMap<int, int> map;
+ //...
+ for (auto i = map.cbegin(), end = map.cend(); i != end; ++i)
+ qDebug() << i.key() << ':' << i.value();
+ //! [13]
+ }
-//! [16]
-QList<QString> values;
-...
-QListIterator<QString> i(values);
-while (i.hasNext()) {
- QString s = i.next();
- qDebug() << s;
-}
-//! [16]
+ {
+ //! [15]
+ QList<QString> values;
+ //...
+ QString str;
+ foreach (str, values)
+ qDebug() << str;
+ //! [15]
+ }
+ {
+ //! [16]
+ QList<QString> values;
+ //...
+ QListIterator<QString> i(values);
+ while (i.hasNext()) {
+ QString s = i.next();
+ qDebug() << s;
+ }
+ //! [16]
+ }
-//! [17]
-QList<QString> values;
-...
-foreach (const QString &str, values)
- qDebug() << str;
-//! [17]
+ {
+ //! [17]
+ QList<QString> values;
+ //...
+ foreach (const QString &str, values)
+ qDebug() << str;
+ //! [17]
+ }
+ {
+ //! [18]
+ QList<QString> values;
+ //...
+ foreach (const QString &str, values) {
+ if (str.isEmpty())
+ break;
+ qDebug() << str;
+ }
+ //! [18]
+ }
-//! [18]
-QList<QString> values;
-...
-foreach (const QString &str, values) {
- if (str.isEmpty())
- break;
- qDebug() << str;
-}
-//! [18]
+ {
+ //! [19]
+ QMap<QString, int> map;
+ //...
+ foreach (const QString &str, map.keys())
+ qDebug() << str << ':' << map.value(str);
+ //! [19]
+ }
+ {
+ //! [20]
+ QMultiMap<QString, int> map;
+ //...
+ foreach (const QString &str, map.uniqueKeys()) {
+ foreach (int i, map.values(str))
+ qDebug() << str << ':' << i;
+ }
+ //! [20]
+ }
-//! [19]
-QMap<QString, int> map;
-...
-foreach (const QString &str, map.keys())
- qDebug() << str << ':' << map.value(str);
-//! [19]
+ {
+ #if 0
+ //! [22]
+ CONFIG += no_keywords
+ //! [22]
-//! [20]
-QMultiMap<QString, int> map;
-...
-foreach (const QString &str, map.uniqueKeys()) {
- foreach (int i, map.values(str))
- qDebug() << str << ':' << i;
+ //! [cmake_no_keywords]
+ target_compile_definitions(my_app PRIVATE QT_NO_KEYWORDS)
+ //! [cmake_no_keywords]
+ #endif
+ }
}
-//! [20]
-
-
-//! [22]
-CONFIG += no_keywords
-//! [22]
-
-
-//! [cmake_no_keywords]
-target_compile_definitions(my_app PRIVATE QT_NO_KEYWORDS)
-//! [cmake_no_keywords]
-
//! [23]
QString onlyLetters(const QString &in)
@@ -250,61 +252,111 @@ QString onlyLetters(const QString &in)
}
//! [23]
-//! [24]
-QList<int> a, b;
-a.resize(100000); // make a big list filled with 0.
-
-QList<int>::iterator i = a.begin();
-// WRONG way of using the iterator i:
-b = a;
-/*
- Now we should be careful with iterator i since it will point to shared data
- If we do *i = 4 then we would change the shared instance (both vectors)
- The behavior differs from STL containers. Avoid doing such things in Qt.
-*/
-
-a[0] = 5;
-/*
- Container a is now detached from the shared data,
- and even though i was an iterator from the container a, it now works as an iterator in b.
- Here the situation is that (*i) == 0.
-*/
-
-b.clear(); // Now the iterator i is completely invalid.
-
-int j = *i; // Undefined behavior!
-/*
- The data from b (which i pointed to) is gone.
- This would be well-defined with STL containers (and (*i) == 5),
- but with QList this is likely to crash.
-*/
-//! [24]
-
-//! [25]
-QList<int> list = {1, 2, 3, 4, 4, 5};
-QSet<int> set(list.cbegin(), list.cend());
-/*
- Will generate a QSet containing 1, 2, 3, 4, 5.
-*/
-//! [25]
-
-//! [26]
-QList<int> list = {2, 3, 1};
-
-std::sort(list.begin(), list.end());
-/*
- Sort the list, now contains { 1, 2, 3 }
-*/
-
-std::reverse(list.begin(), list.end());
-/*
- Reverse the list, now contains { 3, 2, 1 }
-*/
-
-int even_elements =
- std::count_if(list.begin(), list.end(), [](int element) { return (element % 2 == 0); });
-/*
- Count how many elements that are even numbers, 1
-*/
-
-//! [26]
+void wrap()
+{
+ //! [24]
+ QList<int> a, b;
+ a.resize(100000); // make a big list filled with 0.
+
+ QList<int>::iterator i = a.begin();
+ // WRONG way of using the iterator i:
+ b = a;
+ /*
+ Now we should be careful with iterator i since it will point to shared data
+ If we do *i = 4 then we would change the shared instance (both vectors)
+ The behavior differs from STL containers. Avoid doing such things in Qt.
+ */
+
+ a[0] = 5;
+ /*
+ Container a is now detached from the shared data,
+ and even though i was an iterator from the container a, it now works as an iterator in b.
+ Here the situation is that (*i) == 0.
+ */
+
+ b.clear(); // Now the iterator i is completely invalid.
+
+ int j = *i; // Undefined behavior!
+ /*
+ The data from b (which i pointed to) is gone.
+ This would be well-defined with STL containers (and (*i) == 5),
+ but with QList this is likely to crash.
+ */
+ //! [24]
+
+ {
+ //! [25]
+ QList<int> list = {1, 2, 3, 4, 4, 5};
+ QSet<int> set(list.cbegin(), list.cend());
+ /*
+ Will generate a QSet containing 1, 2, 3, 4, 5.
+ */
+ //! [25]
+ }
+
+ //! [26]
+ QList<int> list = {2, 3, 1};
+
+ std::sort(list.begin(), list.end());
+ /*
+ Sort the list, now contains { 1, 2, 3 }
+ */
+
+ std::reverse(list.begin(), list.end());
+ /*
+ Reverse the list, now contains { 3, 2, 1 }
+ */
+
+ int even_elements =
+ std::count_if(list.begin(), list.end(), [](int element) { return (element % 2 == 0); });
+ /*
+ Count how many elements that are even numbers, 1
+ */
+ //! [26]
+}
+
+#if __has_include(<QWidget>)
+
+#include <QWidget>
+#include <QSplitter>
+
+void examples_with_widgets()
+{
+ {
+ //! [8]
+ QMap<int, QWidget *> map;
+ QHash<int, QWidget *> hash;
+
+ QMapIterator<int, QWidget *> i(map);
+ while (i.hasNext()) {
+ i.next();
+ hash.insert(i.key(), i.value());
+ }
+ //! [8]
+ }
+
+ {
+ QMap<int, QWidget *> map;
+ QWidget* widget;
+ //! [9]
+ QMutableMapIterator<int, QWidget *> i(map);
+ while (i.findNext(widget))
+ i.remove();
+ //! [9]
+ }
+
+ QSplitter* splitter;
+
+ //! [14]
+ // RIGHT
+ const QList<int> sizes = splitter->sizes();
+ for (auto i = sizes.begin(), end = sizes.end(); i != end; ++i)
+ {/*...*/}
+
+ // WRONG
+ for (auto i = splitter->sizes().begin();
+ i != splitter->sizes().end(); ++i)
+ {/*...*/}
+ //! [14]
+}
+#endif
diff --git a/src/corelib/doc/snippets/code/doc_src_groups.cpp b/src/corelib/doc/snippets/code/doc_src_groups.cpp
index a0901904db0..2d7c2f96056 100644
--- a/src/corelib/doc/snippets/code/doc_src_groups.cpp
+++ b/src/corelib/doc/snippets/code/doc_src_groups.cpp
@@ -1,6 +1,15 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+#include <QPen>
+#include <QPainter>
+
+class QPenPrivate {
+public:
+ int ref = 1;
+ Qt::PenStyle style;
+};
+
//! [0]
void QPen::setStyle(Qt::PenStyle style)
{
@@ -11,19 +20,21 @@ void QPen::setStyle(Qt::PenStyle style)
void QPen::detach()
{
if (d->ref != 1) {
- ... // perform a deep copy
+ //... // perform a deep copy
}
}
//! [0]
+void example()
+{
+ //! [1]
+ QPixmap p1, p2;
+ p1.load("image.bmp");
+ p2 = p1; // p1 and p2 share data
-//! [1]
-QPixmap p1, p2;
-p1.load("image.bmp");
-p2 = p1; // p1 and p2 share data
-
-QPainter paint;
-paint.begin(&p2); // cuts p2 loose from p1
-paint.drawText(0,50, "Hi");
-paint.end();
-//! [1]
+ QPainter paint;
+ paint.begin(&p2); // cuts p2 loose from p1
+ paint.drawText(0,50, "Hi");
+ paint.end();
+ //! [1]
+}
diff --git a/src/corelib/doc/snippets/code/doc_src_objecttrees.cpp b/src/corelib/doc/snippets/code/doc_src_objecttrees.cpp
index b7c71ccb6b0..8b55ad9b157 100644
--- a/src/corelib/doc/snippets/code/doc_src_objecttrees.cpp
+++ b/src/corelib/doc/snippets/code/doc_src_objecttrees.cpp
@@ -1,23 +1,31 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-//![0]
+#include <QPushButton>
+
+//![open]
int main()
{
- QWidget window;
- QPushButton quit("Quit", &window);
- ...
-}
-//![0]
+//![open]
+ {
+ //![example1]
+ QWidget window;
+ QPushButton quit("Quit", &window);
+ //...
+ //![example1]
+ }
-//![1]
-int main()
-{
- QPushButton quit("Quit");
- QWidget window;
+ {
+ //![example2]
+ QPushButton quit("Quit");
+ QWidget window;
+
+ quit.setParent(&window);
+ //...
+ //![example2]
+ }
- quit.setParent(&window);
- ...
+//![close]
}
-//![1]
+//![close]
diff --git a/src/corelib/doc/snippets/code/doc_src_properties.cpp b/src/corelib/doc/snippets/code/doc_src_properties.cpp
index 190a8437101..eafa7acda3b 100644
--- a/src/corelib/doc/snippets/code/doc_src_properties.cpp
+++ b/src/corelib/doc/snippets/code/doc_src_properties.cpp
@@ -1,6 +1,7 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+#ifdef QPROPERTY_MACRO
//! [0]
Q_PROPERTY(type name
(READ getFunction [WRITE setFunction] |
@@ -25,33 +26,40 @@ Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
Q_PROPERTY(QCursor cursor READ cursor WRITE setCursor RESET unsetCursor)
//! [1]
-
//! [2]
Q_PROPERTY(QDate date READ getDate WRITE setDate)
//! [2]
+#endif
+#if __has_include(<QPushButton>)
+#include <QPushButton>
+void button_example()
+{
+ //! [3]
+ QPushButton *button = new QPushButton;
+ QObject *object = button;
-//! [3]
-QPushButton *button = new QPushButton;
-QObject *object = button;
-
-button->setDown(true);
-object->setProperty("down", true);
-//! [3]
-
-
-//! [4]
-QObject *object = ...
-const QMetaObject *metaobject = object->metaObject();
-int count = metaobject->propertyCount();
-for (int i=0; i<count; ++i) {
- QMetaProperty metaproperty = metaobject->property(i);
- const char *name = metaproperty.name();
- QVariant value = object->property(name);
- ...
+ button->setDown(true);
+ object->setProperty("down", true);
+ //! [3]
}
-//! [4]
+#endif
+#include <QMetaProperty>
+void qobject_example()
+{
+ //! [4]
+ QObject *object = new QObject;
+ const QMetaObject *metaobject = object->metaObject();
+ int count = metaobject->propertyCount();
+ for (int i=0; i<count; ++i) {
+ QMetaProperty metaproperty = metaobject->property(i);
+ const char *name = metaproperty.name();
+ QVariant value = object->property(name);
+ //...
+ }
+ //! [4]
+}
//! [5]
class MyClass : public QObject
@@ -85,16 +93,17 @@ private:
};
//! [5]
+void example(){
+ //! [6]
+ MyClass *myinstance = new MyClass;
+ QObject *object = myinstance;
-//! [6]
-MyClass *myinstance = new MyClass;
-QObject *object = myinstance;
-
-myinstance->setPriority(MyClass::VeryHigh);
-object->setProperty("priority", "VeryHigh");
-//! [6]
-
+ myinstance->setPriority(MyClass::VeryHigh);
+ object->setProperty("priority", "VeryHigh");
+ //! [6]
+}
+#ifdef QPROPERTY_MACRO
//! [7]
Q_CLASSINFO("DefaultProperty", "content")
//! [7]
@@ -103,7 +112,7 @@ Q_CLASSINFO("DefaultProperty", "content")
Q_PROPERTY(QColor color MEMBER m_color NOTIFY colorChanged)
Q_PROPERTY(qreal spacing MEMBER m_spacing NOTIFY spacingChanged)
Q_PROPERTY(QString text MEMBER m_text NOTIFY textChanged)
- ...
+ //...
signals:
void colorChanged();
void spacingChanged();
@@ -114,4 +123,4 @@ private:
qreal m_spacing;
QString m_text;
//! [8]
-
+#endif
diff --git a/src/corelib/doc/snippets/code/doc_src_qalgorithms.cpp b/src/corelib/doc/snippets/code/doc_src_qalgorithms.cpp
index f2b94a74165..9155345508a 100644
--- a/src/corelib/doc/snippets/code/doc_src_qalgorithms.cpp
+++ b/src/corelib/doc/snippets/code/doc_src_qalgorithms.cpp
@@ -1,11 +1,17 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-//! [1]
-QList<Employee *> list;
-list.append(new Employee("Blackpool", "Stephen"));
-list.append(new Employee("Twist", "Oliver"));
+#include <QList>
+#include <QColor>
-qDeleteAll(list.begin(), list.end());
-list.clear();
-//! [1]
+void example()
+{
+ //! [1]
+ QList<QColor *> list;
+ list.append(new QColor(Qt::blue));
+ list.append(new QColor(Qt::yellow));
+
+ qDeleteAll(list.begin(), list.end());
+ list.clear();
+ //! [1]
+}
diff --git a/src/corelib/doc/snippets/code/doc_src_qcache.cpp b/src/corelib/doc/snippets/code/doc_src_qcache.cpp
index a15a8027600..3157981f3fa 100644
--- a/src/corelib/doc/snippets/code/doc_src_qcache.cpp
+++ b/src/corelib/doc/snippets/code/doc_src_qcache.cpp
@@ -1,20 +1,34 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-//! [0]
-QCache<int, Employee> cache;
-//! [0]
+#include <QCache>
+struct Employee {
+ void setId(int id);
+ int id() const { return 0; }
+ void setName(const QString &name);
+};
-//! [1]
-Employee *employee = new Employee;
-employee->setId(37);
-employee->setName("Richard Schmit");
-...
-cache.insert(employee->id(), employee);
-//! [1]
+struct MyDataStructure { };
+void example()
+{
+ //! [0]
+ QCache<int, Employee> cache;
+ //! [0]
-//! [2]
-QCache<int, MyDataStructure> cache(5000);
-//! [2]
+
+ //! [1]
+ Employee *employee = new Employee;
+ employee->setId(37);
+ employee->setName("Richard Schmit");
+ //...
+ cache.insert(employee->id(), employee);
+ //! [1]
+
+ {
+ //! [2]
+ QCache<int, MyDataStructure> cache(5000);
+ //! [2]
+ }
+}
diff --git a/src/corelib/doc/snippets/code/doc_src_qiterator.cpp b/src/corelib/doc/snippets/code/doc_src_qiterator.cpp
index 0d921b87e67..209e98af522 100644
--- a/src/corelib/doc/snippets/code/doc_src_qiterator.cpp
+++ b/src/corelib/doc/snippets/code/doc_src_qiterator.cpp
@@ -1,278 +1,349 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-
-//! [0]
-QList<float> list;
-...
-QListIterator<float> i(list);
-while (i.hasNext())
- float f = i.next();
-//! [0]
-
-
-//! [1]
-QListIterator<float> i(list);
-i.toBack();
-while (i.hasPrevious())
- float f = i.previous();
-//! [1]
-
-//! [6]
-QSet<QString> set;
-...
-QSetIterator<QString> i(set);
-while (i.hasNext())
- float f = i.next();
-//! [6]
-
-//! [8]
-QList<float> list;
-...
-QMutableListIterator<float> i(list);
-while (i.hasNext())
- float f = i.next();
-//! [8]
-
-
-//! [9]
-QMutableListIterator<float> i(list);
-i.toBack();
-while (i.hasPrevious())
- float f = i.previous();
-//! [9]
-
-
-//! [10]
-QMutableListIterator<int> i(list);
-while (i.hasNext()) {
- int val = i.next();
- if (val < 0) {
- i.setValue(-val);
- } else if (val == 0) {
- i.remove();
+#include <QList>
+#include <QSet>
+
+void example()
+{
+ {
+ //! [0]
+ QList<float> list;
+ //...
+ QListIterator<float> i(list);
+ while (i.hasNext())
+ float f = i.next();
+ //! [0]
}
-}
-//! [10]
-
-//! [17]
-QSet<float> set;
-...
-QMutableSetIterator<float> i(set);
-while (i.hasNext())
- float f = i.next();
-//! [17]
-//! [19]
-QMutableListIterator<int> i(list);
-while (i.hasNext()) {
- int val = i.next();
- if (val < -32768 || val > 32767)
- i.remove();
-}
-//! [19]
-
-//! [22]
-QMutableSetIterator<int> i(set);
-while (i.hasNext()) {
- int val = i.next();
- if (val < -32768 || val > 32767)
- i.remove();
-}
-//! [22]
-
-
-//! [23]
-QMutableListIterator<double> i(list);
-while (i.hasNext()) {
- double val = i.next();
- i.setValue(std::sqrt(val));
-}
-//! [23]
-
-//! [26]
-QMap<int, QWidget *> map;
-...
-QMapIterator<int, QWidget *> i(map);
-while (i.hasNext()) {
- i.next();
- qDebug() << i.key() << ": " << i.value();
-}
-//! [26]
-
-
-//! [27]
-QMapIterator<int, QWidget *> i(map);
-i.toBack();
-while (i.hasPrevious()) {
- i.previous();
- qDebug() << i.key() << ": " << i.value();
-}
-//! [27]
-
-
-//! [28]
-QMapIterator<int, QWidget *> i(map);
-while (i.findNext(widget)) {
- qDebug() << "Found widget " << widget << " under key "
- << i.key();
-}
-//! [28]
-
-//! [26multi]
-QMultiMap<int, QWidget *> multimap;
-...
-QMultiMapIterator<int, QWidget *> i(multimap);
-while (i.hasNext()) {
- i.next();
- qDebug() << i.key() << ": " << i.value();
-}
-//! [26multi]
+ QList<float> list;
+ {
+ //! [1]
+ QListIterator<float> i(list);
+ i.toBack();
+ while (i.hasPrevious())
+ float f = i.previous();
+ //! [1]
+ }
-//! [27multi]
-QMultiMapIterator<int, QWidget *> i(multimap);
-i.toBack();
-while (i.hasPrevious()) {
- i.previous();
- qDebug() << i.key() << ": " << i.value();
-}
-//! [27multi]
+ {
+ //! [6]
+ QSet<QString> set;
+ //...
+ QSetIterator<QString> i(set);
+ while (i.hasNext())
+ QString f = i.next();
+ //! [6]
+ }
+ {
+ //! [8]
+ QList<float> list;
+ //...
+ QMutableListIterator<float> i(list);
+ while (i.hasNext())
+ float f = i.next();
+ //! [8]
+ }
-//! [28multi]
-QMultiMapIterator<int, QWidget *> i(multimap);
-while (i.findNext(widget)) {
- qDebug() << "Found widget " << widget << " under key "
- << i.key();
-}
-//! [28multi]
+ {
+ //! [9]
+ QMutableListIterator<float> i(list);
+ i.toBack();
+ while (i.hasPrevious())
+ float f = i.previous();
+ //! [9]
+ }
+ {
+ QList<int> list = {1, 2, 3, 4, 5};
+ //! [10]
+ QMutableListIterator<int> i(list);
+ while (i.hasNext()) {
+ int val = i.next();
+ if (val < 0) {
+ i.setValue(-val);
+ } else if (val == 0) {
+ i.remove();
+ }
+ }
+ //! [10]
+ }
-//! [29]
-QHash<int, QWidget *> hash;
-...
-QHashIterator<int, QWidget *> i(hash);
-while (i.hasNext()) {
- i.next();
- qDebug() << i.key() << ": " << i.value();
-}
-//! [29]
+ {
+ //! [17]
+ QSet<float> set;
+ //...
+ QMutableSetIterator<float> i(set);
+ while (i.hasNext())
+ float f = i.next();
+ //! [17]
+ }
+ {
+ QList<int> list = {1, 2, 3, 4, 5};
+ //! [19]
+ QMutableListIterator<int> i(list);
+ while (i.hasNext()) {
+ int val = i.next();
+ if (val < -32768 || val > 32767)
+ i.remove();
+ }
+ //! [19]
+ }
-//! [31]
-QHashIterator<int, QWidget *> i(hash);
-while (i.findNext(widget)) {
- qDebug() << "Found widget " << widget << " under key "
- << i.key();
-}
-//! [31]
+ {
+ QSet<int> set;
+ //! [22]
+ QMutableSetIterator<int> i(set);
+ while (i.hasNext()) {
+ int val = i.next();
+ if (val < -32768 || val > 32767)
+ i.remove();
+ }
+ //! [22]
+ }
+ {
+ QList<double> list;
+ //! [23]
+ QMutableListIterator<double> i(list);
+ while (i.hasNext()) {
+ double val = i.next();
+ i.setValue(std::sqrt(val));
+ }
+ //! [23]
+ }
-//! [32]
-QMap<int, QWidget *> map;
-...
-QMutableMapIterator<int, QWidget *> i(map);
-while (i.hasNext()) {
- i.next();
- qDebug() << i.key() << ": " << i.value();
+ {
+ //! [25]
+ QList<int> list;
+ //...
+ QListIterator<int> i(list);
+ while (i.hasNext())
+ int val = i.next();
+ //! [25]
+ }
}
-//! [32]
-
-//! [33]
-QMutableMapIterator<int, QWidget *> i(map);
-i.toBack();
-while (i.hasPrevious()) {
- i.previous();
- qDebug() << i.key() << ": " << i.value();
-}
-//! [33]
+#if __has_include(<QWidget>)
+#include <QWidget>
+void example_widgets()
+{
+ QMap<int, QWidget *> map;
+ {
+ //! [26]
+ QMap<int, QWidget *> map;
+ //...
+ QMapIterator<int, QWidget *> i(map);
+ while (i.hasNext()) {
+ i.next();
+ qDebug() << i.key() << ": " << i.value();
+ }
+ //! [26]
+ }
+ {
+ //! [27]
+ QMapIterator<int, QWidget *> i(map);
+ i.toBack();
+ while (i.hasPrevious()) {
+ i.previous();
+ qDebug() << i.key() << ": " << i.value();
+ }
+ //! [27]
+ }
-//! [34]
-QMutableMapIterator<int, QWidget *> i(map);
-while (i.findNext(widget)) {
- qDebug() << "Found widget " << widget << " under key "
- << i.key();
-}
-//! [34]
+ QWidget *widget;
+ {
+ //! [28]
+ QMapIterator<int, QWidget *> i(map);
+ while (i.findNext(widget)) {
+ qDebug() << "Found widget " << widget << " under key "
+ << i.key();
+ }
+ //! [28]
+ }
+ {
+ //! [26multi]
+ QMultiMap<int, QWidget *> multimap;
+ //...
+ QMultiMapIterator<int, QWidget *> i(multimap);
+ while (i.hasNext()) {
+ i.next();
+ qDebug() << i.key() << ": " << i.value();
+ }
+ //! [26multi]
+ }
-//! [35]
-QMutableMapIterator<QString, QString> i(map);
-while (i.hasNext()) {
- i.next();
- if (i.key() == i.value())
- i.remove();
-}
-//! [35]
+ QMultiMap<int, QWidget *> multimap;
+ {
+ //! [27multi]
+ QMultiMapIterator<int, QWidget *> i(multimap);
+ i.toBack();
+ while (i.hasPrevious()) {
+ i.previous();
+ qDebug() << i.key() << ": " << i.value();
+ }
+ //! [27multi]
+ }
+ {
+ //! [28multi]
+ QMultiMapIterator<int, QWidget *> i(multimap);
+ while (i.findNext(widget)) {
+ qDebug() << "Found widget " << widget << " under key "
+ << i.key();
+ }
+ //! [28multi]
+ }
-//! [32multi]
-QMultiMap<int, QWidget *> multimap;
-...
-QMutableMultiMapIterator<int, QWidget *> i(multimap);
-while (i.hasNext()) {
- i.next();
- qDebug() << i.key() << ": " << i.value();
-}
-//! [32multi]
+ {
+ //! [29]
+ QHash<int, QWidget *> hash;
+ //...
+ QHashIterator<int, QWidget *> i(hash);
+ while (i.hasNext()) {
+ i.next();
+ qDebug() << i.key() << ": " << i.value();
+ }
+ //! [29]
+ }
+ QHash<int, QWidget *> hash;
+ {
+ //! [31]
+ QHashIterator<int, QWidget *> i(hash);
+ while (i.findNext(widget)) {
+ qDebug() << "Found widget " << widget << " under key "
+ << i.key();
+ }
+ //! [31]
+ }
-//! [33multi]
-QMutableMultiMapIterator<int, QWidget *> i(multimap);
-i.toBack();
-while (i.hasPrevious()) {
- i.previous();
- qDebug() << i.key() << ": " << i.value();
-}
-//! [33multi]
+ {
+ //! [32]
+ QMap<int, QWidget *> map;
+ //...
+ QMutableMapIterator<int, QWidget *> i(map);
+ while (i.hasNext()) {
+ i.next();
+ qDebug() << i.key() << ": " << i.value();
+ }
+ //! [32]
+ }
+ {
+ //! [33]
+ QMutableMapIterator<int, QWidget *> i(map);
+ i.toBack();
+ while (i.hasPrevious()) {
+ i.previous();
+ qDebug() << i.key() << ": " << i.value();
+ }
+ //! [33]
+ }
-//! [34multi]
-QMutableMultiMapIterator<int, QWidget *> i(multimap);
-while (i.findNext(widget)) {
- qDebug() << "Found widget " << widget << " under key "
- << i.key();
-}
-//! [34multi]
+ {
+ //! [34]
+ QMutableMapIterator<int, QWidget *> i(map);
+ while (i.findNext(widget)) {
+ qDebug() << "Found widget " << widget << " under key "
+ << i.key();
+ }
+ //! [34]
+ }
+ {
+ QMap<QString, QString> map;
+ //! [35]
+ QMutableMapIterator<QString, QString> i(map);
+ while (i.hasNext()) {
+ i.next();
+ if (i.key() == i.value())
+ i.remove();
+ }
+ //! [35]
+ }
-//! [35multi]
-QMutableMultiMapIterator<QString, QString> i(multimap);
-while (i.hasNext()) {
- i.next();
- if (i.key() == i.value())
- i.remove();
-}
-//! [35multi]
+ {
+ //! [32multi]
+ QMultiMap<int, QWidget *> multimap;
+ //...
+ QMutableMultiMapIterator<int, QWidget *> i(multimap);
+ while (i.hasNext()) {
+ i.next();
+ qDebug() << i.key() << ": " << i.value();
+ }
+ //! [32multi]
+ }
+ {
+ //! [33multi]
+ QMutableMultiMapIterator<int, QWidget *> i(multimap);
+ i.toBack();
+ while (i.hasPrevious()) {
+ i.previous();
+ qDebug() << i.key() << ": " << i.value();
+ }
+ //! [33multi]
+ }
-//! [36]
-QHash<int, QWidget *> hash;
-...
-QMutableHashIterator<QString, QWidget *> i(hash);
-while (i.hasNext()) {
- i.next();
- qDebug() << i.key() << ": " << i.value();
-}
-//! [36]
+ {
+ //! [34multi]
+ QMutableMultiMapIterator<int, QWidget *> i(multimap);
+ while (i.findNext(widget)) {
+ qDebug() << "Found widget " << widget << " under key "
+ << i.key();
+ }
+ //! [34multi]
+ }
+ {
+ QMultiMap<QString, QString> multimap;
+ //! [35multi]
+ QMutableMultiMapIterator<QString, QString> i(multimap);
+ while (i.hasNext()) {
+ i.next();
+ if (i.key() == i.value())
+ i.remove();
+ }
+ //! [35multi]
+ }
-//! [38]
-QMutableHashIterator<int, QWidget *> i(hash);
-while (i.findNext(widget)) {
- qDebug() << "Found widget " << widget << " under key "
- << i.key();
-}
-//! [38]
+ {
+ //! [36]
+ QHash<int, QWidget *> hash;
+ //...
+ QMutableHashIterator<int, QWidget *> i(hash);
+ while (i.hasNext()) {
+ i.next();
+ qDebug() << i.key() << ": " << i.value();
+ }
+ //! [36]
+ }
+ {
+ //! [38]
+ QMutableHashIterator<int, QWidget *> i(hash);
+ while (i.findNext(widget)) {
+ qDebug() << "Found widget " << widget << " under key "
+ << i.key();
+ }
+ //! [38]
+ }
-//! [39]
-QMutableHashIterator<QString, QString> i(hash);
-while (i.hasNext()) {
- i.next();
- if (i.key() == i.value())
- i.remove();
+ {
+ QHash<QString, QString> hash;
+ //! [39]
+ QMutableHashIterator<QString, QString> i(hash);
+ while (i.hasNext()) {
+ i.next();
+ if (i.key() == i.value())
+ i.remove();
+ }
+ //! [39]
+ }
}
-//! [39]
+#endif
diff --git a/src/corelib/doc/snippets/code/doc_src_qnamespace.cpp b/src/corelib/doc/snippets/code/doc_src_qnamespace.cpp
index 10845855840..d753874f0dd 100644
--- a/src/corelib/doc/snippets/code/doc_src_qnamespace.cpp
+++ b/src/corelib/doc/snippets/code/doc_src_qnamespace.cpp
@@ -1,6 +1,8 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+#include <QEvent>
+
//! [1]
enum CustomEventPriority
{
diff --git a/src/corelib/doc/snippets/code/doc_src_qplugin.cpp b/src/corelib/doc/snippets/code/doc_src_qplugin.cpp
index 3bca27b9661..4382d13838a 100644
--- a/src/corelib/doc/snippets/code/doc_src_qplugin.cpp
+++ b/src/corelib/doc/snippets/code/doc_src_qplugin.cpp
@@ -1,10 +1,12 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+#include <QtPlugin>
+
//! [0]
namespace Foo
{
- struct MyInterface { ... };
+ struct MyInterface { /*...*/ };
}
Q_DECLARE_INTERFACE(Foo::MyInterface, "org.examples.MyInterface")
diff --git a/src/corelib/doc/snippets/code/doc_src_qset.cpp b/src/corelib/doc/snippets/code/doc_src_qset.cpp
index 98a6f336f5a..8342e1d6f98 100644
--- a/src/corelib/doc/snippets/code/doc_src_qset.cpp
+++ b/src/corelib/doc/snippets/code/doc_src_qset.cpp
@@ -1,107 +1,134 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-//! [0]
-QSet<QString> set;
-//! [0]
+#include <QtCore>
+#include <iostream>
+using namespace std;
+void snippets_0_3()
+{
+ //! [0]
+ QSet<QString> set;
+ //! [0]
-//! [1]
-set.insert("one");
-set.insert("three");
-set.insert("seven");
-//! [1]
+ //! [1]
+ set.insert("one");
+ set.insert("three");
+ set.insert("seven");
+ //! [1]
-//! [2]
-set << "twelve" << "fifteen" << "nineteen";
-//! [2]
+ //! [2]
+ set << "twelve" << "fifteen" << "nineteen";
+ //! [2]
-//! [3]
-if (!set.contains("ninety-nine"))
- ...
-//! [3]
-
-//! [4]
-QSetIterator<QWidget *> i(set);
-while (i.hasNext()) {
- QWidget *w = i.next();
- qDebug() << w;
+ //! [3]
+ if (!set.contains("ninety-nine"))
+ {/*...*/}
+ //! [3]
}
-//! [4]
-
-//! [5]
-for (auto i = set.cbegin(), end = set.cend(); i != end; ++i)
- qDebug() << *i;
-//! [5]
+#if __has_include(<QWidget>)
+#include <QWidget>
-//! [6]
-QSet<QString> set;
-...
-for (const auto &value : set)
- qDebug() << value;
-//! [6]
+void example_widgets()
+{
+ QSet<QWidget *> set;
+ //! [4]
+ QSetIterator<QWidget *> i(set);
+ while (i.hasNext()) {
+ QWidget *w = i.next();
+ qDebug() << w;
+ }
+ //! [4]
+}
+#endif
+
+void snippets_5_12()
+{
+ QSet<QString> set;
+
+ //! [5]
+ for (auto i = set.cbegin(), end = set.cend(); i != end; ++i)
+ qDebug() << *i;
+ //! [5]
+
+ {
+ //! [6]
+ QSet<QString> set;
+ //...
+ for (const auto &value : set)
+ qDebug() << value;
+ //! [6]
+ }
+ {
+ QString values[3];
+ //! [7]
+ QSet<QString> set;
+ set.reserve(20000);
+ for (int i = 0; i < 20000; ++i)
+ set.insert(values[i]);
+ //! [7]
+ }
-//! [7]
-QSet<QString> set;
-set.reserve(20000);
-for (int i = 0; i < 20000; ++i)
- set.insert(values[i]);
-//! [7]
+ {
+ //! [8]
+ QSet<QString> set = {"January", "February", /*...*/ "December"};
+ // i is a QSet<QString>::iterator
+ for (auto i = set.begin(), end = set.end(); i != end; ++i)
+ qDebug() << *i;
+ //! [8]
+ }
-//! [8]
-QSet<QString> set = {"January", "February", ... "December"}
+ {
+ //! [9]
+ QSet<QString> set = {"January", "February", /*...*/ "December"};
+
+ auto i = set.begin();
+ while (i != set.end()) {
+ if ((*i).startsWith('J')) {
+ i = set.erase(i);
+ } else {
+ ++i;
+ }
+ }
+ //! [9]
+ }
-// i is a QSet<QString>::iterator
-for (auto i = set.begin(), end = set.end(); i != end; ++i)
- qDebug() << *i;
-//! [8]
+ {
+ //! [10]
+ QSet<QString> set;
+ //...
+ const auto predicate = [](const QString &s) { return s.compare("Jeanette", Qt::CaseInsensitive) == 0; };
+ QSet<QString>::iterator it = std::find_if(set.begin(), set.end(), predicate);
+ if (it != set.end())
+ cout << "Found Jeanette" << endl;
+ //! [10]
+ }
+ {
+ //! [11]
+ QSet<QString> set = {"January", "February", /*...*/ "December"};
-//! [9]
-QSet<QString> set = {"January", "February", ... "December"};
+ // i is QSet<QString>::const_iterator
+ for (auto i = set.cbegin(), end = set.cend(); i != end; ++i)
+ qDebug() << *i;
+ //! [11]
+ }
-auto i = set.begin();
-while (i != set.end()) {
- if ((*i).startsWith('J')) {
- i = set.erase(i);
- } else {
- ++i;
+ {
+ //! [12]
+ QSet<QString> set;
+ //...
+ const auto predicate = [](const QString &s) { return s.compare("Jeanette", Qt::CaseInsensitive) == 0; };
+ QSet<QString>::const_iterator it = std::find_if(set.cbegin(), set.cend(), predicate);
+ if (it != set.constEnd())
+ cout << "Found Jeanette" << endl;
+ //! [12]
}
}
-//! [9]
-
-
-//! [10]
-QSet<QString> set;
-...
-const auto predicate = [](const QString &s) { return s.compare("Jeanette", Qt::CaseInsensitive) == 0; };
-QSet<QString>::iterator it = std::find_if(set.begin(), set.end(), predicate);
-if (it != set.end())
- cout << "Found Jeanette" << endl;
-//! [10]
-
-
-//! [11]
-QSet<QString> set = {"January", "February", ... "December"};
-
-// i is QSet<QString>::const_iterator
-for (auto i = set.cbegin(), end = set.cend(); i != end; ++i)
- qDebug() << *i;
-//! [11]
-
-
-//! [12]
-QSet<QString> set;
-...
-const auto predicate = [](const QString &s) { return s.compare("Jeanette", Qt::CaseInsensitive) == 0; };
-QSet<QString>::const_iterator it = std::find_if(set.cbegin(), set.cend(), predicate);
-if (it != set.constEnd())
- cout << "Found Jeanette" << endl;
-//! [12]
diff --git a/src/corelib/doc/snippets/code/doc_src_qvarlengtharray.cpp b/src/corelib/doc/snippets/code/doc_src_qvarlengtharray.cpp
index 080874fc77d..4d2ccc82c2e 100644
--- a/src/corelib/doc/snippets/code/doc_src_qvarlengtharray.cpp
+++ b/src/corelib/doc/snippets/code/doc_src_qvarlengtharray.cpp
@@ -1,21 +1,24 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+#include <QVarLengthArray>
+
+#if 0
//! [0]
-int myfunc(int n)
+int myfunc_wrong(int n)
{
int table[n + 1]; // WRONG
- ...
+ //...
return table[n];
}
//! [0]
-
+#endif
//! [1]
-int myfunc(int n)
+int myfunc_correct(int n)
{
int *table = new int[n + 1];
- ...
+ //...
int ret = table[n];
delete[] table;
return ret;
@@ -24,18 +27,21 @@ int myfunc(int n)
//! [2]
-int myfunc(int n)
+int myfunc_q(int n)
{
QVarLengthArray<int, 1024> array(n + 1);
- ...
+ //...
return array[n];
}
//! [2]
-//! [3]
-QVarLengthArray<int> array(10);
-int *data = array.data();
-for (int i = 0; i < 10; ++i)
- data[i] = 2 * i;
-//! [3]
+void example()
+{
+ //! [3]
+ QVarLengthArray<int> array(10);
+ int *data = array.data();
+ for (int i = 0; i < 10; ++i)
+ data[i] = 2 * i;
+ //! [3]
+}
diff --git a/src/corelib/doc/snippets/code/doc_src_resources.cpp b/src/corelib/doc/snippets/code/doc_src_resources.cpp
index 04ecf810ec1..9a244b9239d 100644
--- a/src/corelib/doc/snippets/code/doc_src_resources.cpp
+++ b/src/corelib/doc/snippets/code/doc_src_resources.cpp
@@ -1,10 +1,25 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-//! [4]
-QResource::registerResource("/path/to/myresource.rcc");
-//! [4]
+#include <QResource>
+#include <QFile>
+void wrap()
+{
+ //! [4]
+ QResource::registerResource("/path/to/myresource.rcc");
+ //! [4]
+}
+
+class BaseClass {
+ public:
+ BaseClass() {}
+};
+
+class MyClass : BaseClass {
+ public:
+ MyClass();
+};
//! [5]
MyClass::MyClass() : BaseClass()
@@ -12,6 +27,6 @@ MyClass::MyClass() : BaseClass()
Q_INIT_RESOURCE(resources);
QFile file(":/myfile.dat");
- ...
+ //...
}
//! [5]
diff --git a/src/corelib/doc/snippets/code/src_corelib_animation_qparallelanimationgroup.cpp b/src/corelib/doc/snippets/code/src_corelib_animation_qparallelanimationgroup.cpp
index 6328cb00119..db3a9ee2dc0 100644
--- a/src/corelib/doc/snippets/code/src_corelib_animation_qparallelanimationgroup.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_animation_qparallelanimationgroup.cpp
@@ -1,10 +1,15 @@
// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-//! [0]
- QParallelAnimationGroup *group = new QParallelAnimationGroup;
- group->addAnimation(anim1);
- group->addAnimation(anim2);
+#include <QParallelAnimationGroup>
- group->start();
-//! [0]
+void example(QAbstractAnimation *anim1, QAbstractAnimation *anim2)
+{
+ //! [0]
+ QParallelAnimationGroup *group = new QParallelAnimationGroup;
+ group->addAnimation(anim1);
+ group->addAnimation(anim2);
+
+ group->start();
+ //! [0]
+}
diff --git a/src/corelib/doc/snippets/code/src_corelib_animation_qpropertyanimation.cpp b/src/corelib/doc/snippets/code/src_corelib_animation_qpropertyanimation.cpp
index 4b77ab607db..7f259e99fb8 100644
--- a/src/corelib/doc/snippets/code/src_corelib_animation_qpropertyanimation.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_animation_qpropertyanimation.cpp
@@ -1,28 +1,102 @@
// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+#include <QParallelAnimationGroup>
+#include <QSequentialAnimationGroup>
-//! [0]
+//! [includes]
#include <QApplication>
#include <QPushButton>
#include <QPropertyAnimation>
+//![includes]
+
+//! [class_decl]
class MyButtonWidget : public QWidget
{
public:
MyButtonWidget(QWidget *parent = nullptr);
};
+//! [class_decl]
+
+//! [ctor_impl]
MyButtonWidget::MyButtonWidget(QWidget *parent) : QWidget(parent)
{
- QPushButton *button = new QPushButton(tr("Animated Button"), this);
- QPropertyAnimation *anim = new QPropertyAnimation(button, "pos", this);
- anim->setDuration(10000);
- anim->setStartValue(QPoint(0, 0));
- anim->setEndValue(QPoint(100, 250));
- anim->start();
+//![ctor_impl]
+ {
+ //! [first_example]
+ QPushButton *button = new QPushButton(tr("Animated Button"), this);
+ QPropertyAnimation *anim = new QPropertyAnimation(button, "pos", this);
+ anim->setDuration(10000);
+ anim->setStartValue(QPoint(0, 0));
+ anim->setEndValue(QPoint(100, 250));
+ anim->start();
+ //! [first_example]
+ }
+
+ {
+ //! [easing-curve]
+ QPushButton *button = new QPushButton(tr("Animated Button"), this);
+ QPropertyAnimation *anim = new QPropertyAnimation(button, "pos", this);
+ anim->setDuration(10000);
+ anim->setStartValue(QPoint(0, 0));
+ anim->setEndValue(QPoint(100, 250));
+ anim->setEasingCurve(QEasingCurve::OutBounce);
+ anim->start();
+ //! [easing-curve]
+ }
+
+ {
+ //! [animation-group1]
+ QPushButton *bonnie = new QPushButton(tr("Bonnie"), this);
+ QPushButton *clyde = new QPushButton(tr("Clyde"), this);
+
+ QPropertyAnimation *anim1 = new QPropertyAnimation(bonnie, "pos", this);
+ anim1->setDuration(3000);
+ anim1->setStartValue(QPoint(0, 0));
+ anim1->setEndValue(QPoint(100, 250));
+
+ QPropertyAnimation *anim2 = new QPropertyAnimation(clyde, "pos", this);
+ anim2->setDuration(3000);
+ anim2->setStartValue(QPoint(100, 250));
+ anim2->setEndValue(QPoint(500, 500));
+
+ QParallelAnimationGroup *parallelAnim = new QParallelAnimationGroup;
+ parallelAnim->addAnimation(anim1);
+ parallelAnim->addAnimation(anim2);
+ parallelAnim->start();
+ //! [animation-group1]
+ }
+
+ {
+ //! [animation-group2]
+ QPushButton *bonnie = new QPushButton(tr("Bonnie"), this);
+ QPushButton *clyde = new QPushButton(tr("Clyde"), this);
+
+ QPropertyAnimation *anim1 = new QPropertyAnimation(bonnie, "pos", this);
+ anim1->setDuration(3000);
+ anim1->setStartValue(QPoint(0, 0));
+ anim1->setEndValue(QPoint(100, 250));
+
+ QPropertyAnimation *anim2 = new QPropertyAnimation(clyde, "pos", this);
+ anim2->setDuration(3000);
+ anim2->setStartValue(QPoint(0, 0));
+ anim2->setEndValue(QPoint(200, 250));
+
+ QSequentialAnimationGroup *sequenceAnim = new QSequentialAnimationGroup;
+ sequenceAnim->addAnimation(anim1);
+ sequenceAnim->addAnimation(anim2);
+ sequenceAnim->start();
+ //! [animation-group2]
+ }
+
+//! [ctor_close]
}
+//! [ctor_close]
+
+//! [main]
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
@@ -31,65 +105,4 @@ int main(int argc, char *argv[])
buttonAnimWidget.show();
return a.exec();
}
-//! [0]
-
-
-//! [easing-curve]
-MyButtonWidget::MyButtonWidget(QWidget *parent) : QWidget(parent)
-{
- QPushButton *button = new QPushButton(tr("Animated Button"), this);
- QPropertyAnimation *anim = new QPropertyAnimation(button, "pos", this);
- anim->setDuration(10000);
- anim->setStartValue(QPoint(0, 0));
- anim->setEndValue(QPoint(100, 250));
- anim->setEasingCurve(QEasingCurve::OutBounce);
- anim->start();
-}
-//! [easing-curve]
-
-
-//! [animation-group1]
-MyButtonWidget::MyButtonWidget(QWidget *parent) : QWidget(parent)
-{
- QPushButton *bonnie = new QPushButton(tr("Bonnie"), this);
- QPushButton *clyde = new QPushButton(tr("Clyde"), this);
-
- QPropertyAnimation *anim1 = new QPropertyAnimation(bonnie, "pos", this);
- anim1->setDuration(3000);
- anim1->setStartValue(QPoint(0, 0));
- anim1->setEndValue(QPoint(100, 250));
-
- QPropertyAnimation *anim2 = new QPropertyAnimation(clyde, "pos", this);
- anim2->setDuration(3000);
- anim2->setStartValue(QPoint(100, 250));
- anim2->setEndValue(QPoint(500, 500));
-
- QParallelAnimationGroup *parallelAnim = new QParallelAnimationGroup;
- parallelAnim->addAnimation(anim1);
- parallelAnim->addAnimation(anim2);
- parallelAnim->start();
-}
-//! [animation-group1]
-
-//! [animation-group2]
-MyButtonWidget::MyButtonWidget(QWidget *parent) : QWidget(parent)
-{
- QPushButton *bonnie = new QPushButton(tr("Bonnie"), this);
- QPushButton *clyde = new QPushButton(tr("Clyde"), this);
-
- QPropertyAnimation *anim1 = new QPropertyAnimation(bonnie, "pos", this);
- anim1->setDuration(3000);
- anim1->setStartValue(QPoint(0, 0));
- anim1->setEndValue(QPoint(100, 250));
-
- QPropertyAnimation *anim2 = new QPropertyAnimation(clyde, "pos", this);
- anim2->setDuration(3000);
- anim2->setStartValue(QPoint(0, 0));
- anim2->setEndValue(QPoint(200, 250));
-
- QSequentialAnimationGroup *sequenceAnim = new QSequentialAnimationGroup;
- sequenceAnim->addAnimation(anim1);
- sequenceAnim->addAnimation(anim2);
- sequenceAnim->start();
-}
-//! [animation-group2]
+//! [main]
diff --git a/src/corelib/doc/snippets/code/src_corelib_animation_qsequentialanimationgroup.cpp b/src/corelib/doc/snippets/code/src_corelib_animation_qsequentialanimationgroup.cpp
index a429fe20b2d..c00a723a26c 100644
--- a/src/corelib/doc/snippets/code/src_corelib_animation_qsequentialanimationgroup.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_animation_qsequentialanimationgroup.cpp
@@ -1,6 +1,10 @@
// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+#include <QSequentialAnimationGroup>
+
+void example(QAbstractAnimation *anim1, QAbstractAnimation *anim2)
+{
//! [0]
QSequentialAnimationGroup *group = new QSequentialAnimationGroup;
@@ -9,3 +13,4 @@
group->start();
//! [0]
+}
diff --git a/src/corelib/doc/snippets/code/src_corelib_animation_qvariantanimation.cpp b/src/corelib/doc/snippets/code/src_corelib_animation_qvariantanimation.cpp
index be7f549f655..be7e51e1b44 100644
--- a/src/corelib/doc/snippets/code/src_corelib_animation_qvariantanimation.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_animation_qvariantanimation.cpp
@@ -1,14 +1,22 @@
// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+#include <QVariantAnimation>
+#include <QColor>
+
//! [0]
- QVariant myColorInterpolator(const QColor &start, const QColor &end, qreal progress)
- {
- ...
- return QColor(...);
- }
- ...
+QVariant myColorInterpolator(const QColor &start, const QColor &end, qreal progress)
+{
+ // ...
+ return QColor(/*...*/);
+}
+// ...
+void someFunc()
+{
+ // ...
qRegisterAnimationInterpolator<QColor>(myColorInterpolator);
+ // ...
+}
//! [0]
//! [1]
diff --git a/src/corelib/doc/snippets/code/src_corelib_concurrent_qthreadpool.cpp b/src/corelib/doc/snippets/code/src_corelib_concurrent_qthreadpool.cpp
index 4cba70e62d4..56a0532ac21 100644
--- a/src/corelib/doc/snippets/code/src_corelib_concurrent_qthreadpool.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_concurrent_qthreadpool.cpp
@@ -1,6 +1,10 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+#include <QThreadPool>
+#include <QRunnable>
+#include <QDebug>
+
//! [0]
class HelloWorldTask : public QRunnable
{
@@ -10,7 +14,12 @@ class HelloWorldTask : public QRunnable
}
};
-HelloWorldTask *hello = new HelloWorldTask();
-// QThreadPool takes ownership and deletes 'hello' automatically
-QThreadPool::globalInstance()->start(hello);
+int main()
+{
+ //...
+ HelloWorldTask *hello = new HelloWorldTask();
+ // QThreadPool takes ownership and deletes 'hello' automatically
+ QThreadPool::globalInstance()->start(hello);
+ //...
+}
//! [0]
diff --git a/src/corelib/doc/snippets/eventfilters/CMakeLists.txt b/src/corelib/doc/snippets/eventfilters/CMakeLists.txt
index ea381e425a5..7da83cbdf6e 100644
--- a/src/corelib/doc/snippets/eventfilters/CMakeLists.txt
+++ b/src/corelib/doc/snippets/eventfilters/CMakeLists.txt
@@ -1,17 +1,19 @@
-add_library(snippets_eventfilters OBJECT)
+add_library(corelib_snippets_eventfilters OBJECT)
-target_link_libraries(snippets_eventfilters PRIVATE
+set_target_properties(corelib_snippets_eventfilters PROPERTIES COMPILE_OPTIONS "-w")
+
+target_link_libraries(corelib_snippets_eventfilters PRIVATE
Qt::Core
)
-qt_internal_extend_target(snippets_eventfilters CONDITION QT_FEATURE_widgets
+qt_internal_extend_target(corelib_snippets_eventfilters CONDITION QT_FEATURE_widgets
LIBRARIES
Qt::Widgets
SOURCE
main.cpp
)
-qt_internal_extend_target(snippets_eventfilters CONDITION QT_FEATURE_gui
+qt_internal_extend_target(corelib_snippets_eventfilters CONDITION QT_FEATURE_gui
LIBRARIES
Qt::Gui
SOURCES
diff --git a/src/corelib/doc/snippets/qmetaobject-invokable/CMakeLists.txt b/src/corelib/doc/snippets/qmetaobject-invokable/CMakeLists.txt
index 76bb79951a3..972bf43d9b1 100644
--- a/src/corelib/doc/snippets/qmetaobject-invokable/CMakeLists.txt
+++ b/src/corelib/doc/snippets/qmetaobject-invokable/CMakeLists.txt
@@ -2,13 +2,15 @@ if(NOT QT_FEATURE_widgets)
return()
endif()
-add_library(snippets_qmetaobject-invokable OBJECT)
+add_library(corelib_snippets_qmetaobject-invokable OBJECT)
-target_link_libraries(snippets_qmetaobject-invokable PRIVATE
+set_target_properties(corelib_snippets_qmetaobject-invokable PROPERTIES COMPILE_OPTIONS "-w")
+
+target_link_libraries(corelib_snippets_qmetaobject-invokable PRIVATE
Qt::Core
)
-qt_internal_extend_target(snippets_qmetaobject-invokable CONDITION QT_FEATURE_widgets
+qt_internal_extend_target(corelib_snippets_qmetaobject-invokable CONDITION QT_FEATURE_widgets
LIBRARIES
Qt::Widgets
SOURCES
diff --git a/src/corelib/doc/snippets/qmetaobject-revision/CMakeLists.txt b/src/corelib/doc/snippets/qmetaobject-revision/CMakeLists.txt
index 0cadf9380b1..369b2e15315 100644
--- a/src/corelib/doc/snippets/qmetaobject-revision/CMakeLists.txt
+++ b/src/corelib/doc/snippets/qmetaobject-revision/CMakeLists.txt
@@ -2,13 +2,15 @@ if(NOT QT_FEATURE_widgets)
return()
endif()
-add_library(snippets_qmetaobject-revision OBJECT)
+add_library(corelib_snippets_qmetaobject-revision OBJECT)
-target_link_libraries(snippets_qmetaobject-revision PRIVATE
+set_target_properties(corelib_snippets_qmetaobject-revision PROPERTIES COMPILE_OPTIONS "-w")
+
+target_link_libraries(corelib_snippets_qmetaobject-revision PRIVATE
Qt::Core
)
-qt_internal_extend_target(snippets_qmetaobject-revision CONDITION QT_FEATURE_widgets
+qt_internal_extend_target(corelib_snippets_qmetaobject-revision CONDITION QT_FEATURE_widgets
LIBRARIES
Qt::Widgets
SOURCES
diff --git a/src/corelib/doc/snippets/qprocess/CMakeLists.txt b/src/corelib/doc/snippets/qprocess/CMakeLists.txt
index 07b66d0b36b..d00e051ed9b 100644
--- a/src/corelib/doc/snippets/qprocess/CMakeLists.txt
+++ b/src/corelib/doc/snippets/qprocess/CMakeLists.txt
@@ -1,8 +1,12 @@
-add_library(snippets_qprocess OBJECT
+set(CMAKE_UNITY_BUILD OFF)
+
+add_library(corelib_snippets_qprocess OBJECT
qprocess-createprocessargumentsmodifier.cpp
qprocess-simpleexecution.cpp
)
-target_link_libraries(snippets_qprocess PRIVATE
+set_target_properties(corelib_snippets_qprocess PROPERTIES COMPILE_OPTIONS "-w")
+
+target_link_libraries(corelib_snippets_qprocess PRIVATE
Qt::Core
)
diff --git a/src/corelib/doc/snippets/qsignalmapper/CMakeLists.txt b/src/corelib/doc/snippets/qsignalmapper/CMakeLists.txt
deleted file mode 100644
index 086ddbf9c5e..00000000000
--- a/src/corelib/doc/snippets/qsignalmapper/CMakeLists.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-if(NOT TARGET Qt::Widgets)
- return()
-endif()
-
-add_library(snippets_qsignalmapper OBJECT
- buttonwidget.cpp
-)
-
-add_compile_definitions(EXAMPLE_ONE)
-
-target_link_libraries(snippets_qsignalmapper PRIVATE
- Qt::Core
-)
-
-qt_internal_extend_target(snippets_qsignalmapper CONDITION QT_FEATURE_widgets
- LIBRARIES
- Qt::Widgets
-)
diff --git a/src/corelib/doc/snippets/qsignalmapper/buttonwidget.cpp b/src/corelib/doc/snippets/qsignalmapper/buttonwidget.cpp
index 1f9e53f1385..cdbf83a977d 100644
--- a/src/corelib/doc/snippets/qsignalmapper/buttonwidget.cpp
+++ b/src/corelib/doc/snippets/qsignalmapper/buttonwidget.cpp
@@ -5,39 +5,40 @@
#include <QtWidgets>
-#ifdef EXAMPLE_ONE
-//! [0]
-ButtonWidget::ButtonWidget(const QStringList &texts, QWidget *parent)
- : QWidget(parent)
-{
- signalMapper = new QSignalMapper(this);
+ //! [OpenCtor]
+ ButtonWidget::ButtonWidget(const QStringList &texts, QWidget *parent)
+ : QWidget(parent)
+ {
+ //! [OpenCtor]
+ {
+ //![OldNotation]
+ signalMapper = new QSignalMapper(this);
- QGridLayout *gridLayout = new QGridLayout(this);
- for (int i = 0; i < texts.size(); ++i) {
- QPushButton *button = new QPushButton(texts[i]);
- connect(button, &QPushButton::clicked, signalMapper, qOverload<>(&QSignalMapper::map));
-//! [0] //! [1]
- signalMapper->setMapping(button, texts[i]);
- gridLayout->addWidget(button, i / 3, i % 3);
+ QGridLayout *gridLayout = new QGridLayout(this);
+ for (int i = 0; i < texts.size(); ++i) {
+ QPushButton *button = new QPushButton(texts[i]);
+ connect(button, &QPushButton::clicked, signalMapper, qOverload<>(&QSignalMapper::map));
+ signalMapper->setMapping(button, texts[i]);
+ gridLayout->addWidget(button, i / 3, i % 3);
+ }
+
+ connect(signalMapper, &QSignalMapper::mappedString,
+ this, &ButtonWidget::clicked);
+ //![OldNotation]
+ }
+
+ {
+ //![ModernNotation]
+ QGridLayout *gridLayout = new QGridLayout(this);
+ for (int i = 0; i < texts.size(); ++i) {
+ QString text = texts[i];
+ QPushButton *button = new QPushButton(text);
+ connect(button, &QPushButton::clicked, [this, text] { clicked(text); });
+ gridLayout->addWidget(button, i / 3, i % 3);
+ }
+ //![ModernNotation]
}
- connect(signalMapper, &QSignalMapper::mappedString,
-//! [1] //! [2]
- this, &ButtonWidget::clicked);
-}
-//! [2]
-#else
-//! [3]
-ButtonWidget::ButtonWidget(const QStringList &texts, QWidget *parent)
- : QWidget(parent)
-{
- QGridLayout *gridLayout = new QGridLayout(this);
- for (int i = 0; i < texts.size(); ++i) {
- QString text = texts[i];
- QPushButton *button = new QPushButton(text);
- connect(button, &QPushButton::clicked, [this, text] { clicked(text); });
- gridLayout->addWidget(button, i / 3, i % 3);
+ //! [CloseBrackets]
}
-}
-//! [3]
-#endif
+ //! [CloseBrackets]
diff --git a/src/corelib/doc/snippets/qsignalmapper/buttonwidget.h b/src/corelib/doc/snippets/qsignalmapper/buttonwidget.h
index 537c21c9141..cd75628dc2b 100644
--- a/src/corelib/doc/snippets/qsignalmapper/buttonwidget.h
+++ b/src/corelib/doc/snippets/qsignalmapper/buttonwidget.h
@@ -4,10 +4,8 @@
#ifndef BUTTONWIDGET_H
#define BUTTONWIDGET_H
-#include <QWidget>
+#include <QtWidgets>
-class QSignalMapper;
-class QString;
//! [0]
class ButtonWidget : public QWidget
diff --git a/src/corelib/doc/src/animation.qdoc b/src/corelib/doc/src/animation.qdoc
index d2e182f4806..ba5976f11eb 100644
--- a/src/corelib/doc/src/animation.qdoc
+++ b/src/corelib/doc/src/animation.qdoc
@@ -91,7 +91,12 @@
The following example demonstrates how you can animate a QPushButton
widget:
- \snippet code/src_corelib_animation_qpropertyanimation.cpp 0
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp includes
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp class_decl
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp ctor_impl
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp first_example
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp ctor_close
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp main
The example animates the \c pos Qt property of a QPushButton, to move
it from the top--left corner of the screen to the end position (250, 250),
@@ -174,7 +179,9 @@
path.
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp ctor_impl
\snippet code/src_corelib_animation_qpropertyanimation.cpp easing-curve
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp ctor_close
In this example, the animation follows a curve that makes the
\c button bounce like a ball. QEasingCurve offers a large collection of curves
@@ -199,13 +206,17 @@
The two following examples demonstrate the use of both
QSequentialAnimationGroup and QParallelAnimationGroup:
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp ctor_impl
\snippet code/src_corelib_animation_qpropertyanimation.cpp animation-group1
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp ctor_close
A parallel group plays more than one animation at the same time.
Its \l{QAbstractAnimation::}{start()} function starts all
animations that are part of the group.
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp ctor_impl
\snippet code/src_corelib_animation_qpropertyanimation.cpp animation-group2
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp ctor_close
As the name suggests, a QSequentialAnimationGroup plays
its animations in sequence. It starts the next animation in
@@ -225,7 +236,12 @@
independent QPropertyAnimation has the QApplication instance as its
parent:
- \snippet code/src_corelib_animation_qpropertyanimation.cpp 0
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp includes
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp class_decl
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp ctor_impl
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp first_example
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp ctor_close
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp main
\note You can also control the animation's lifespan by choosing a
\l{QAbstractAnimation::DeletionPolicy}{delete policy} while starting it.
diff --git a/src/corelib/doc/src/objectmodel/objecttrees.qdoc b/src/corelib/doc/src/objectmodel/objecttrees.qdoc
index 8939a534d40..25245fd5de8 100644
--- a/src/corelib/doc/src/objectmodel/objecttrees.qdoc
+++ b/src/corelib/doc/src/objectmodel/objecttrees.qdoc
@@ -59,7 +59,9 @@
behavior applies. Normally, the order of destruction still doesn't
present a problem. Consider the following snippet:
- \snippet code/doc_src_objecttrees.cpp 0
+ \snippet code/doc_src_objecttrees.cpp open
+ \snippet code/doc_src_objecttrees.cpp example1
+ \snippet code/doc_src_objecttrees.cpp close
The parent, \c window, and the child, \c quit, are both \l {QObject}
{QObjects} because QPushButton inherits QWidget, and QWidget inherits
@@ -73,7 +75,9 @@
But now consider what happens if we swap the order of construction, as
shown in this second snippet:
- \snippet code/doc_src_objecttrees.cpp 1
+ \snippet code/doc_src_objecttrees.cpp open
+ \snippet code/doc_src_objecttrees.cpp example2
+ \snippet code/doc_src_objecttrees.cpp close
In this case, the order of destruction causes a problem. The parent's
destructor is called first because it was created last. It then calls
diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp
index c645e57bdb6..8c22483fbfe 100644
--- a/src/corelib/io/qfile.cpp
+++ b/src/corelib/io/qfile.cpp
@@ -1,6 +1,7 @@
// Copyright (C) 2020 The Qt Company Ltd.
// Copyright (C) 2017 Intel Corporation.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:significant reason:default
#include "qplatformdefs.h"
#include "qdebug.h"
diff --git a/src/corelib/io/qfile.h b/src/corelib/io/qfile.h
index c115a6aee98..11546d87d9c 100644
--- a/src/corelib/io/qfile.h
+++ b/src/corelib/io/qfile.h
@@ -1,6 +1,7 @@
// Copyright (C) 2020 The Qt Company Ltd.
// Copyright (C) 2016 Intel Corporation.
// 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 QFILE_H
#define QFILE_H
diff --git a/src/corelib/io/qfile_p.h b/src/corelib/io/qfile_p.h
index 126da28b0f9..a50fe575f8e 100644
--- a/src/corelib/io/qfile_p.h
+++ b/src/corelib/io/qfile_p.h
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:significant reason:default
#ifndef QFILE_P_H
#define QFILE_P_H
diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp
index 6f995fe082e..5a0be1d895e 100644
--- a/src/corelib/io/qfilesystemengine_unix.cpp
+++ b/src/corelib/io/qfilesystemengine_unix.cpp
@@ -893,6 +893,12 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
{
Q_CHECK_FILE_NAME(entry, false);
+ // Detection of WasDeletedAttribute is imperfect: in general, if we can
+ // successfully stat() or access() a file, it hasn't been deleted (though
+ // there are exceptions, like /proc/XXX/fd/ entries on Linux). So we have
+ // to restore this flag in case we fail to stat() anything.
+ auto hadBeenDeleted = data.entryFlags & QFileSystemMetaData::WasDeletedAttribute;
+
#if defined(Q_OS_DARWIN)
if (what & (QFileSystemMetaData::BundleType | QFileSystemMetaData::CaseSensitive)) {
if (!data.hasFlags(QFileSystemMetaData::DirectoryType))
@@ -1103,6 +1109,11 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
if (entryErrno != 0) {
what &= ~QFileSystemMetaData::LinkType; // don't clear link: could be broken symlink
data.clearFlags(what);
+
+ // see comment at the top
+ data.entryFlags |= hadBeenDeleted;
+ data.knownFlagsMask |= hadBeenDeleted;
+
return false;
}
return true;
diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp
index 0886f63b810..9c1bb45dd2d 100644
--- a/src/corelib/io/qiodevice.cpp
+++ b/src/corelib/io/qiodevice.cpp
@@ -1309,8 +1309,11 @@ QByteArray QIODevice::readAll()
The newline character ('\\n') is included in the buffer. If a
newline is not encountered before maxSize - 1 bytes are read, a
- newline will not be inserted into the buffer. On windows newline
- characters are replaced with '\\n'.
+ newline will not be inserted into the buffer.
+
+ \note Newline translation(e.g., converting \r to \n) is performed
+ only when the device is opened for reading with QIODevice::Text
+ flag.
Note that on sequential devices, data may not be immediately available,
which may result in a partial line being returned. By calling the
diff --git a/src/corelib/io/qsavefile.cpp b/src/corelib/io/qsavefile.cpp
index 91f168f20f6..a7d101dc124 100644
--- a/src/corelib/io/qsavefile.cpp
+++ b/src/corelib/io/qsavefile.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2012 David Faure <[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:guaranteed-behavior
#include "qsavefile.h"
diff --git a/src/corelib/io/qsavefile.h b/src/corelib/io/qsavefile.h
index bf0a91bae74..5e8cffe7c38 100644
--- a/src/corelib/io/qsavefile.h
+++ b/src/corelib/io/qsavefile.h
@@ -1,5 +1,6 @@
// Copyright (C) 2012 David Faure <[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:header-decls-only
#ifndef QSAVEFILE_H
#define QSAVEFILE_H
diff --git a/src/corelib/io/qsavefile_p.h b/src/corelib/io/qsavefile_p.h
index 50ecdad2daf..e1dcc0abe23 100644
--- a/src/corelib/io/qsavefile_p.h
+++ b/src/corelib/io/qsavefile_p.h
@@ -1,5 +1,6 @@
// Copyright (C) 2013 David Faure <[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:header-decls-only
#ifndef QSAVEFILE_P_H
#define QSAVEFILE_P_H
diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp
index c1f01267949..038db4d857e 100644
--- a/src/corelib/io/qtemporaryfile.cpp
+++ b/src/corelib/io/qtemporaryfile.cpp
@@ -1,6 +1,7 @@
// Copyright (C) 2016 The Qt Company Ltd.
// Copyright (C) 2017 Intel Corporation.
// 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 "qtemporaryfile.h"
@@ -881,6 +882,11 @@ void QTemporaryFile::setFileTemplate(const QString &name)
be used for a similar purpose too, particularly if the destination file is
not temporary.
+ \note Calling rename() does not disable autoRemove. If you want the renamed
+ file to persist, you must call setAutoRemove and set it to \c false after
+ calling rename(). Otherwise, the file will be deleted when the QTemporaryFile
+ object is destroyed.
+
\sa QSaveFile, QSaveFile::commit(), QFile::rename()
*/
bool QTemporaryFile::rename(const QString &newName)
diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp
index 565ce04c6ce..a4fbf69da8b 100644
--- a/src/corelib/io/qurl.cpp
+++ b/src/corelib/io/qurl.cpp
@@ -3660,17 +3660,29 @@ QList<QUrl> QUrl::fromStringList(const QStringList &urls, ParsingMode mode)
*/
size_t qHash(const QUrl &url, size_t seed) noexcept
{
+ QtPrivate::QHashCombineWithSeed hasher(seed);
+
+ // non-commutative, we must hash the port first
if (!url.d)
- return qHash(-1, seed); // the hash of an unset port (-1)
-
- return qHash(url.d->scheme) ^
- qHash(url.d->userName) ^
- qHash(url.d->password) ^
- qHash(url.d->host) ^
- qHash(url.d->port, seed) ^
- qHash(url.d->path) ^
- qHash(url.d->query) ^
- qHash(url.d->fragment);
+ return hasher(0, -1);
+ size_t state = hasher(0, url.d->port);
+
+ if (url.d->hasScheme())
+ state = hasher(state, url.d->scheme);
+ if (url.d->hasUserInfo()) {
+ // see presentSections(), appendUserName(), etc.
+ state = hasher(state, url.d->userName);
+ state = hasher(state, url.d->password);
+ }
+ if (url.d->hasHost() || url.d->isLocalFile()) // for XDG compatibility
+ state = hasher(state, url.d->host);
+ if (url.d->hasPath())
+ state = hasher(state, url.d->path);
+ if (url.d->hasQuery())
+ state = hasher(state, url.d->query);
+ if (url.d->hasFragment())
+ state = hasher(state, url.d->fragment);
+ return state;
}
static QUrl adjustFtpPath(QUrl url)
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index 3b92c5f48f2..1b711ba16bd 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -2552,8 +2552,9 @@ static QStringList winCmdArgs()
Otherwise, the arguments() are constructed from the return value of
\l{https://docs.microsoft.com/en-us/windows/win32/api/processenv/nf-processenv-getcommandlinea}{GetCommandLine()}.
- As a result of this, the string given by arguments().at(0) might not be
- the program name on Windows, depending on how the application was started.
+ As a result of this, the string given by arguments().at(0)
+ might not be the exact program used to start the application
+ on Windows.
\sa applicationFilePath(), QCommandLineParser
*/
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp
index 2356611a5cf..de5f27f9619 100644
--- a/src/corelib/kernel/qmetaobject.cpp
+++ b/src/corelib/kernel/qmetaobject.cpp
@@ -3149,6 +3149,20 @@ bool QMetaMethod::invokeOnGadget(void *gadget,
representation. The scope() function returns the class scope this
enumerator was declared in.
+ To use QMetaEnum functionality, register the enumerator within the meta-object
+ system using the Q_ENUM macro.
+
+ \code
+ enum AppleType {
+ Big,
+ Small
+ };
+ Q_ENUM(AppleType)
+
+ QMetaEnum metaEnum = QMetaEnum::fromType<ModelApple::AppleType>();
+ qDebug() << metaEnum.valueToKey(ModelApple::Big);
+ \endcode
+
\sa QMetaObject, QMetaMethod, QMetaProperty
*/
diff --git a/src/corelib/kernel/qmetaobjectbuilder.cpp b/src/corelib/kernel/qmetaobjectbuilder.cpp
index 60bcdedba13..445009ea000 100644
--- a/src/corelib/kernel/qmetaobjectbuilder.cpp
+++ b/src/corelib/kernel/qmetaobjectbuilder.cpp
@@ -2080,6 +2080,17 @@ bool QMetaPropertyBuilder::isBindable() const
else
return false;
}
+/*!
+ Returns \c true if the property is required.
+ The default is \c false.
+ */
+bool QMetaPropertyBuilder::isRequired() const
+{
+ if (auto d = d_func())
+ return d->flag(Required);
+ else
+ return false;
+}
/*!
Sets this property to readable if \a value is true.
@@ -2236,6 +2247,15 @@ void QMetaPropertyBuilder::setBindable(bool value)
}
/*!
+ Sets the\c REQUIRED flag on this property to \a value
+ */
+void QMetaPropertyBuilder::setRequired(bool value)
+{
+ if (auto d = d_func())
+ d->setFlag(Required, value);
+}
+
+/*!
Returns the revision of this property.
\sa setRevision()
diff --git a/src/corelib/kernel/qmetaobjectbuilder_p.h b/src/corelib/kernel/qmetaobjectbuilder_p.h
index cf64e51c30c..36cd08d908c 100644
--- a/src/corelib/kernel/qmetaobjectbuilder_p.h
+++ b/src/corelib/kernel/qmetaobjectbuilder_p.h
@@ -216,6 +216,7 @@ public:
bool isFinal() const;
bool isAlias() const;
bool isBindable() const;
+ bool isRequired() const;
void setReadable(bool value);
void setWritable(bool value);
@@ -230,6 +231,7 @@ public:
void setFinal(bool value);
void setAlias(bool value);
void setBindable(bool value);
+ void setRequired(bool value);
int revision() const;
void setRevision(int revision);
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp
index 1242a40f185..45c947004f5 100644
--- a/src/corelib/kernel/qmetatype.cpp
+++ b/src/corelib/kernel/qmetatype.cpp
@@ -981,12 +981,6 @@ void QMetaType::unregisterMetaType(QMetaType type)
than the QMetaType \a rhs, otherwise returns \c false.
*/
-/*! \internal */
-bool QMetaTypeModuleHelper::convert(const void *, int, void *, int) const
-{
- return false;
-}
-
static constexpr auto createStaticTypeToIdMap()
{
#define QT_ADD_STATIC_METATYPE(MetaTypeName, MetaTypeId, RealName) \
@@ -1049,8 +1043,8 @@ static bool qIntegerConversionFromFPHelper(From from, To *to)
return true;
}
-// NOLINTNEXTLINE(cppcoreguidelines-virtual-class-destructor): this is not a base class
-static constexpr struct : QMetaTypeModuleHelper
+namespace {
+struct QCoreVariantHelper : QMetaTypeModuleHelper
{
template<typename T, typename LiteralWrapper =
std::conditional_t<std::is_same_v<T, QString>, QLatin1StringView, const char *>>
@@ -1060,7 +1054,8 @@ static constexpr struct : QMetaTypeModuleHelper
return !(str.isEmpty() || str == LiteralWrapper("0") || str == LiteralWrapper("false"));
}
- const QtPrivate::QMetaTypeInterface *interfaceForType(int type) const override {
+ static const QtPrivate::QMetaTypeInterface *interfaceForType(int type)
+ {
switch (type) {
QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(QT_METATYPE_CONVERT_ID_TO_TYPE)
QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(QT_METATYPE_CONVERT_ID_TO_TYPE)
@@ -1072,11 +1067,14 @@ static constexpr struct : QMetaTypeModuleHelper
}
}
-#ifndef QT_BOOTSTRAPPED
- bool convert(const void *from, int fromTypeId, void *to, int toTypeId) const override
+ static bool convert(const void *from, int fromTypeId, void *to, int toTypeId)
{
Q_ASSERT(fromTypeId != toTypeId);
+#ifdef QT_BOOTSTRAPPED
+ Q_UNUSED(from);
+ Q_UNUSED(to);
+#else
// canConvert calls with two nullptr
bool onlyCheck = (from == nullptr && to == nullptr);
@@ -1747,26 +1745,28 @@ QT_WARNING_DISABLE_CLANG("-Wtautological-compare")
QT_WARNING_POP
}
+#endif // !QT_BOOTSTRAPPED
return false;
}
-#endif // !QT_BOOTSTRAPPED
-} metatypeHelper = {};
+};
+} // unnamed namespace
-Q_CONSTINIT Q_CORE_EXPORT const QMetaTypeModuleHelper *qMetaTypeGuiHelper = nullptr;
-Q_CONSTINIT Q_CORE_EXPORT const QMetaTypeModuleHelper *qMetaTypeWidgetsHelper = nullptr;
+Q_CONSTINIT Q_CORE_EXPORT QMetaTypeModuleHelper qMetaTypeGuiHelper = {};
+Q_CONSTINIT Q_CORE_EXPORT QMetaTypeModuleHelper qMetaTypeWidgetsHelper = {};
-static const QMetaTypeModuleHelper *qModuleHelperForType(int type)
+#ifndef QT_BOOTSTRAPPED
+static bool tryConvertBuiltinTypes(const void *from, int fromTypeId, void *to, int toTypeId)
{
+ int type = qMax(fromTypeId, toTypeId);
if (type <= QMetaType::LastCoreType)
- return &metatypeHelper;
+ return QCoreVariantHelper::convert(from, fromTypeId, to, toTypeId);
if (type >= QMetaType::FirstGuiType && type <= QMetaType::LastGuiType)
- return qMetaTypeGuiHelper;
+ return qMetaTypeGuiHelper.convert(from, fromTypeId, to, toTypeId);
else if (type >= QMetaType::FirstWidgetsType && type <= QMetaType::LastWidgetsType)
- return qMetaTypeWidgetsHelper;
- return nullptr;
+ return qMetaTypeWidgetsHelper.convert(from, fromTypeId, to, toTypeId);
+ return false;
}
-#ifndef QT_BOOTSTRAPPED
template<typename T, typename Key>
class QMetaTypeFunctionRegistry
{
@@ -2471,10 +2471,8 @@ bool QMetaType::convert(QMetaType fromType, const void *from, QMetaType toType,
int fromTypeId = fromType.id();
int toTypeId = toType.id();
- if (auto moduleHelper = qModuleHelperForType(qMax(fromTypeId, toTypeId))) {
- if (moduleHelper->convert(from, fromTypeId, to, toTypeId))
- return true;
- }
+ if (tryConvertBuiltinTypes(from, fromTypeId, to, toTypeId))
+ return true;
const auto f = customTypesConversionRegistry()->function({fromTypeId, toTypeId});
if (f)
return (*f)(from, to);
@@ -2676,10 +2674,9 @@ bool QMetaType::canConvert(QMetaType fromType, QMetaType toType)
if (fromTypeId == toTypeId)
return true;
- if (auto moduleHelper = qModuleHelperForType(qMax(fromTypeId, toTypeId))) {
- if (moduleHelper->convert(nullptr, fromTypeId, nullptr, toTypeId))
- return true;
- }
+ if (tryConvertBuiltinTypes(nullptr, fromTypeId, nullptr, toTypeId))
+ return true;
+
const ConverterFunction * const f =
customTypesConversionRegistry()->function(std::make_pair(fromTypeId, toTypeId));
if (f)
@@ -2879,8 +2876,12 @@ void QMetaType::registerNormalizedTypedef(const NS(QByteArray) & normalizedTypeN
static const QtPrivate::QMetaTypeInterface *interfaceForStaticType(int typeId)
{
Q_ASSERT(typeId < QMetaType::User);
- if (auto moduleHelper = qModuleHelperForType(typeId))
- return moduleHelper->interfaceForType(typeId);
+ if (typeId <= QMetaType::LastCoreType)
+ return QCoreVariantHelper::interfaceForType(typeId);
+ if (typeId >= QMetaType::FirstGuiType && typeId <= QMetaType::LastGuiType)
+ return qMetaTypeGuiHelper.interfaceForType(typeId);
+ if (typeId >= QMetaType::FirstWidgetsType && typeId <= QMetaType::LastWidgetsType)
+ return qMetaTypeWidgetsHelper.interfaceForType(typeId);
return nullptr;
}
@@ -2909,40 +2910,18 @@ bool QMetaType::isRegistered(int type)
return interfaceForTypeNoWarning(type) != nullptr;
}
-namespace {
-enum NormalizeTypeMode {
- DontNormalizeType,
- TryNormalizeType
-};
-}
-template <NormalizeTypeMode tryNormalizedType> static inline
-const QtPrivate::QMetaTypeInterface *qMetaTypeTypeImpl(QByteArrayView name)
+static const QtPrivate::QMetaTypeInterface *findMetaTypeByName(QByteArrayView name)
{
- if (name.isEmpty())
- return nullptr;
-
+ Q_PRE(!name.isEmpty());
int type = qMetaTypeStaticType(name);
if (type != QMetaType::UnknownType) {
return interfaceForStaticType(type);
#ifndef QT_BOOTSTRAPPED
- } else {
- QReadLocker locker(&customTypeRegistry()->lock);
+ } else if (customTypeRegistry.exists()) {
+ QReadLocker locker(&customTypeRegistry->lock);
auto it = customTypeRegistry->aliases.constFind(name);
if (it != customTypeRegistry->aliases.constEnd())
return it.value().data();
-
-#ifndef QT_NO_QOBJECT
- if (tryNormalizedType) {
- const char *typeName = name.constData();
- const NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName);
- type = qMetaTypeStaticType(normalizedTypeName);
- if (type == QMetaType::UnknownType) {
- return customTypeRegistry->aliases.value(normalizedTypeName).data();
- } else {
- return interfaceForStaticType(type);
- }
- }
-#endif
#endif
}
return nullptr;
@@ -2969,7 +2948,9 @@ const QtPrivate::QMetaTypeInterface *qMetaTypeTypeImpl(QByteArrayView name)
*/
int qMetaTypeTypeInternal(QByteArrayView name)
{
- const QtPrivate::QMetaTypeInterface *iface = qMetaTypeTypeImpl<DontNormalizeType>(name);
+ const QtPrivate::QMetaTypeInterface *iface = nullptr;
+ if (!name.isEmpty())
+ iface = findMetaTypeByName(name);
return iface ? iface->typeId.loadRelaxed() : QMetaType::UnknownType;
}
@@ -3138,7 +3119,20 @@ QMetaType QMetaType::underlyingType() const
*/
QMetaType QMetaType::fromName(QByteArrayView typeName)
{
- return QMetaType(qMetaTypeTypeImpl<TryNormalizeType>(typeName));
+ if (typeName.isEmpty())
+ return QMetaType();
+
+ const QtPrivate::QMetaTypeInterface *iface = findMetaTypeByName(typeName);
+ if (iface)
+ return QMetaType(iface);
+
+#if !defined(QT_NO_QOBJECT)
+ const NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName.constData());
+ if (normalizedTypeName != typeName)
+ iface = findMetaTypeByName(normalizedTypeName);
+#endif
+
+ return QMetaType(iface);
}
/*!
diff --git a/src/corelib/kernel/qmetatype_p.h b/src/corelib/kernel/qmetatype_p.h
index c05bce5fc8f..b39e1de0be2 100644
--- a/src/corelib/kernel/qmetatype_p.h
+++ b/src/corelib/kernel/qmetatype_p.h
@@ -40,25 +40,29 @@ QT_BEGIN_NAMESPACE
assign_and_return \
}
-class Q_CORE_EXPORT QMetaTypeModuleHelper
+struct QMetaTypeModuleHelper
{
- Q_DISABLE_COPY_MOVE(QMetaTypeModuleHelper)
-protected:
- QMetaTypeModuleHelper() = default;
- ~QMetaTypeModuleHelper() = default;
-public:
- Q_WEAK_OVERLOAD // prevent it from entering the ABI and rendering constexpr useless
static constexpr auto makePair(int from, int to) -> quint64
{
return (quint64(from) << 32) + quint64(to);
}
- virtual const QtPrivate::QMetaTypeInterface *interfaceForType(int) const = 0;
- virtual bool convert(const void *, int, void *, int) const;
+ static const QtPrivate::QMetaTypeInterface *interfaceForType_dummy(int)
+ {
+ return nullptr;
+ }
+
+ static bool convert_dummy(const void *, int, void *, int)
+ {
+ return false;
+ }
+
+ decltype(&interfaceForType_dummy) interfaceForType = &interfaceForType_dummy;
+ decltype(&convert_dummy) convert = &convert_dummy;
};
-extern Q_CORE_EXPORT const QMetaTypeModuleHelper *qMetaTypeGuiHelper;
-extern Q_CORE_EXPORT const QMetaTypeModuleHelper *qMetaTypeWidgetsHelper;
+extern Q_CORE_EXPORT QMetaTypeModuleHelper qMetaTypeGuiHelper;
+extern Q_CORE_EXPORT QMetaTypeModuleHelper qMetaTypeWidgetsHelper;
namespace QtMetaTypePrivate {
template<typename T>
diff --git a/src/corelib/kernel/qsignalmapper.cpp b/src/corelib/kernel/qsignalmapper.cpp
index 65d766db4a9..96e909d1be7 100644
--- a/src/corelib/kernel/qsignalmapper.cpp
+++ b/src/corelib/kernel/qsignalmapper.cpp
@@ -74,9 +74,9 @@ public:
The only function that we need to implement is the constructor:
- \snippet qsignalmapper/buttonwidget.cpp 0
- \snippet qsignalmapper/buttonwidget.cpp 1
- \snippet qsignalmapper/buttonwidget.cpp 2
+ \snippet qsignalmapper/buttonwidget.cpp OpenCtor
+ \snippet qsignalmapper/buttonwidget.cpp OldNotation
+ \snippet qsignalmapper/buttonwidget.cpp CloseBrackets
A list of texts is passed to the constructor. A signal mapper is
constructed and for each text in the list a QPushButton is
@@ -92,7 +92,9 @@ public:
slots. The example above can be rewritten simpler without QSignalMapper
by connecting to a lambda function.
- \snippet qsignalmapper/buttonwidget.cpp 3
+ \snippet qsignalmapper/buttonwidget.cpp OpenCtor
+ \snippet qsignalmapper/buttonwidget.cpp ModernNotation
+ \snippet qsignalmapper/buttonwidget.cpp CloseBrackets
\sa QObject, QButtonGroup, QActionGroup
*/
diff --git a/src/corelib/kernel/qtranslator.cpp b/src/corelib/kernel/qtranslator.cpp
index 6b68cb7a513..c8348aba16a 100644
--- a/src/corelib/kernel/qtranslator.cpp
+++ b/src/corelib/kernel/qtranslator.cpp
@@ -39,6 +39,8 @@
#include <vector>
#include <memory>
+#include <QtCore/qmutex.h>
+
QT_BEGIN_NAMESPACE
Q_STATIC_LOGGING_CATEGORY(lcTranslator, "qt.core.qtranslator")
@@ -259,6 +261,8 @@ class QTranslatorPrivate : public QObjectPrivate
public:
enum { Contexts = 0x2f, Hashes = 0x42, Messages = 0x69, NumerusRules = 0x88, Dependencies = 0x96, Language = 0xa7 };
+ mutable QMutex lock;
+
QTranslatorPrivate() :
#if defined(QT_USE_MMAP)
used_mmap(0),
@@ -463,6 +467,7 @@ bool QTranslator::load(const QString & filename, const QString & directory,
const QString & suffix)
{
Q_D(QTranslator);
+ QMutexLocker locker(&d->lock);
d->clear();
QString prefix;
@@ -738,6 +743,7 @@ bool QTranslator::load(const QLocale & locale,
const QString & suffix)
{
Q_D(QTranslator);
+ QMutexLocker locker(&d->lock);
d->clear();
return d->load_translation(locale, filename, prefix, directory, suffix);
}
@@ -757,6 +763,7 @@ bool QTranslator::load(const QLocale & locale,
bool QTranslator::load(const uchar *data, int len, const QString &directory)
{
Q_D(QTranslator);
+ QMutexLocker locker(&d->lock);
d->clear();
if (!data || len < MagicLength || memcmp(data, magic, MagicLength))
@@ -1065,6 +1072,8 @@ void QTranslatorPrivate::clear()
}
/*!
+ \threadsafe
+
Returns the translation for the key (\a context, \a sourceText,
\a disambiguation). If none is found, also tries (\a context, \a
sourceText, ""). If that still fails, returns a null string.
@@ -1086,7 +1095,14 @@ QString QTranslator::translate(const char *context, const char *sourceText, cons
int n) const
{
Q_D(const QTranslator);
- return d->do_translate(context, sourceText, disambiguation, n);
+
+ // Return early to avoid a deadlock in case translate() is called
+ // from a code path triggered by QTranslator::load()
+ if (!d->lock.tryLock())
+ return QString();
+ QString result = d->do_translate(context, sourceText, disambiguation, n);
+ d->lock.unlock();
+ return result;
}
/*!
diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h
index 31f5869c9d9..e9d3ffb9ae3 100644
--- a/src/corelib/kernel/qvariant.h
+++ b/src/corelib/kernel/qvariant.h
@@ -332,7 +332,16 @@ public:
inline void swap(QVariant &other) noexcept { std::swap(d, other.d); }
int userType() const { return typeId(); }
- int typeId() const { return metaType().id(); }
+ int typeId() const
+ {
+ // QVariant types are always registered (see fromMetaType())
+ const QtPrivate::QMetaTypeInterface *mt = metaType().iface();
+ if (!mt)
+ return 0;
+ int id = mt->typeId.loadRelaxed();
+ // Q_ASSUME(id > 0);
+ return id;
+ }
const char *typeName() const;
QMetaType metaType() const;
diff --git a/src/corelib/platform/windows/qt_winrtbase_p.h b/src/corelib/platform/windows/qt_winrtbase_p.h
index fb7366f93de..79c2bdf6b1c 100644
--- a/src/corelib/platform/windows/qt_winrtbase_p.h
+++ b/src/corelib/platform/windows/qt_winrtbase_p.h
@@ -18,6 +18,7 @@
#include <QtCore/qglobal.h>
#if QT_CONFIG(cpp_winrt)
+# include <guiddef.h> // required by clang-cl: https://github.com/microsoft/cppwinrt/issues/1179
# include <winrt/base.h>
# include <QtCore/private/qfactorycacheregistration_p.h>
// Workaround for Windows SDK bug.
diff --git a/src/corelib/thread/qatomicwait.cpp b/src/corelib/thread/qatomicwait.cpp
index 3d70333ca7b..25ca771643b 100644
--- a/src/corelib/thread/qatomicwait.cpp
+++ b/src/corelib/thread/qatomicwait.cpp
@@ -4,6 +4,7 @@
#include "qatomicwait_p.h"
#include <qendian.h>
+#include "qfutex_p.h"
#include "qwaitcondition_p.h"
#include <array>
@@ -96,8 +97,21 @@ struct QAtomicWaitLocks
};
} // unnamed namespace
+static inline void checkFutexUse()
+{
+#if !defined(QATOMICWAIT_USE_FALLBACK)
+ if (QtFutex::futexAvailable()) {
+ // This will disable the code and data on systems where futexes are
+ // always available (currently: FreeBSD, Linux, Windows).
+ qFatal("Implementation should have used futex!");
+ }
+#endif
+}
+
static QAtomicWaitLocks &atomicLocks() noexcept
{
+ checkFutexUse();
+
static QAtomicWaitLocks global {};
return global;
}
diff --git a/src/corelib/thread/qmutex.cpp b/src/corelib/thread/qmutex.cpp
index bd3b269c0b7..832d87332b0 100644
--- a/src/corelib/thread/qmutex.cpp
+++ b/src/corelib/thread/qmutex.cpp
@@ -120,8 +120,8 @@ void QBasicMutex::destroyInternal(void *ptr)
Locks the mutex. If another thread has locked the mutex then this
call will block until that thread has unlocked it.
- Calling this function multiple times on the same mutex from the
- same thread will cause a \e dead-lock.
+ If the mutex was already locked by the current thread, this call will
+ never return, causing a \e dead-lock.
\sa unlock()
*/
@@ -140,9 +140,6 @@ void QBasicMutex::destroyInternal(void *ptr)
If the lock was obtained, the mutex must be unlocked with unlock()
before another thread can successfully lock it.
- Calling this function multiple times on the same mutex from the
- same thread will cause a \e dead-lock.
-
\sa lock(), unlock()
*/
@@ -157,9 +154,6 @@ void QBasicMutex::destroyInternal(void *ptr)
If the lock was obtained, the mutex must be unlocked with unlock()
before another thread can successfully lock it.
- Calling this function multiple times on the same mutex from the
- same thread will cause a \e dead-lock.
-
\sa lock(), unlock()
*/
@@ -172,9 +166,6 @@ void QBasicMutex::destroyInternal(void *ptr)
If the lock was obtained, the mutex must be unlocked with unlock()
before another thread can successfully lock it.
- Calling this function multiple times on the same mutex from the
- same thread will cause a \e dead-lock.
-
\sa lock(), unlock()
*/
@@ -202,9 +193,6 @@ void QBasicMutex::destroyInternal(void *ptr)
If the lock was obtained, the mutex must be unlocked with unlock()
before another thread can successfully lock it.
- Calling this function multiple times on the same mutex from the
- same thread will cause a \e dead-lock.
-
\sa lock(), unlock()
*/
@@ -222,9 +210,6 @@ void QBasicMutex::destroyInternal(void *ptr)
If the lock was obtained, the mutex must be unlocked with unlock()
before another thread can successfully lock it.
- Calling this function multiple times on the same mutex from the
- same thread will cause a \e dead-lock.
-
\sa lock(), unlock()
*/
diff --git a/src/corelib/tools/qarraydata.h b/src/corelib/tools/qarraydata.h
index 71e183e646e..38d1091ac1f 100644
--- a/src/corelib/tools/qarraydata.h
+++ b/src/corelib/tools/qarraydata.h
@@ -39,7 +39,7 @@ struct QArrayData
};
Q_DECLARE_FLAGS(ArrayOptions, ArrayOption)
- QBasicAtomicInt m_ref;
+ QBasicAtomicInt ref_;
ArrayOptions flags;
qsizetype alloc;
@@ -56,19 +56,19 @@ struct QArrayData
/// Returns true if sharing took place
bool ref() noexcept
{
- m_ref.ref();
+ ref_.ref();
return true;
}
/// Returns false if deallocation is necessary
bool deref() noexcept
{
- return m_ref.deref();
+ return ref_.deref();
}
bool isShared() const noexcept
{
- return m_ref.loadRelaxed() != 1;
+ return ref_.loadRelaxed() != 1;
}
// Returns true if a detach is necessary before modifying the data
@@ -76,7 +76,7 @@ struct QArrayData
// detaching is necessary, you should be in a non-const function already
bool needsDetach() noexcept
{
- return m_ref.loadRelaxed() > 1;
+ return ref_.loadRelaxed() > 1;
}
qsizetype detachCapacity(qsizetype newSize) const noexcept
diff --git a/src/corelib/tools/qarraydataops.h b/src/corelib/tools/qarraydataops.h
index 419585b0260..c20abd12c23 100644
--- a/src/corelib/tools/qarraydataops.h
+++ b/src/corelib/tools/qarraydataops.h
@@ -82,7 +82,7 @@ public:
void destroyAll() noexcept // Call from destructors, ONLY!
{
Q_ASSERT(this->d);
- Q_ASSERT(this->d->m_ref.loadRelaxed() == 0);
+ Q_ASSERT(this->d->ref_.loadRelaxed() == 0);
// As this is to be called only from destructor, it doesn't need to be
// exception safe; size not updated.
@@ -345,7 +345,7 @@ public:
// As this is to be called only from destructor, it doesn't need to be
// exception safe; size not updated.
- Q_ASSERT(this->d->m_ref.loadRelaxed() == 0);
+ Q_ASSERT(this->d->ref_.loadRelaxed() == 0);
std::destroy(this->begin(), this->end());
}
diff --git a/src/corelib/tools/qatomicscopedvaluerollback.h b/src/corelib/tools/qatomicscopedvaluerollback.h
index 8f653acba5e..929a2e2d466 100644
--- a/src/corelib/tools/qatomicscopedvaluerollback.h
+++ b/src/corelib/tools/qatomicscopedvaluerollback.h
@@ -11,6 +11,7 @@
#include <QtCore/qtconfigmacros.h>
#include <atomic>
+#include <type_traits>
QT_BEGIN_NAMESPACE
@@ -122,6 +123,33 @@ template <typename T>
QAtomicScopedValueRollback(QBasicAtomicPointer<T> &, std::memory_order)
-> QAtomicScopedValueRollback<T*>;
+template <typename T, typename V,
+ std::enable_if_t<std::is_convertible_v<V, T>, bool> = true>
+QAtomicScopedValueRollback(std::atomic<T>&, V)
+ -> QAtomicScopedValueRollback<T>;
+template <typename T, typename V,
+ std::enable_if_t<std::is_convertible_v<V, T>, bool> = true>
+QAtomicScopedValueRollback(std::atomic<T>&, V, std::memory_order)
+ -> QAtomicScopedValueRollback<T>;
+
+template <typename T, typename V,
+ std::enable_if_t<std::is_convertible_v<V, T>, bool> = true>
+QAtomicScopedValueRollback(QBasicAtomicInteger<T>&, V)
+ -> QAtomicScopedValueRollback<T>;
+template <typename T, typename V,
+ std::enable_if_t<std::is_convertible_v<V, T>, bool> = true>
+QAtomicScopedValueRollback(QBasicAtomicInteger<T>&, V, std::memory_order)
+ -> QAtomicScopedValueRollback<T>;
+
+template <typename T, typename V,
+ std::enable_if_t<std::is_convertible_v<V, T*>, bool> = true>
+QAtomicScopedValueRollback(QBasicAtomicPointer<T>&, V)
+ -> QAtomicScopedValueRollback<T*>;
+template <typename T, typename V,
+ std::enable_if_t<std::is_convertible_v<V, T*>, bool> = true>
+QAtomicScopedValueRollback(QBasicAtomicPointer<T>&, V, std::memory_order)
+ -> QAtomicScopedValueRollback<T*>;
+
QT_END_NAMESPACE
#endif // QATOMICASCOPEDVALUEROLLBACK_H
diff --git a/src/corelib/tools/qfreelist_p.h b/src/corelib/tools/qfreelist_p.h
index cc12fb9c8d0..ecefd1f55df 100644
--- a/src/corelib/tools/qfreelist_p.h
+++ b/src/corelib/tools/qfreelist_p.h
@@ -199,27 +199,27 @@ inline typename QFreeList<T, ConstantsType>::ReferenceType QFreeList<T, Constant
template <typename T, typename ConstantsType>
inline int QFreeList<T, ConstantsType>::next()
{
- int id, newid, at;
- ElementType *v;
+ int newid;
+ int id = _next.loadAcquire();
do {
- id = _next.loadAcquire();
-
- at = id & ConstantsType::IndexMask;
+ int at = id & ConstantsType::IndexMask;
const int block = blockfor(at);
- v = _v[block].loadAcquire();
+ ElementType *v = _v[block].loadAcquire();
if (!v) {
- v = allocate((id & ConstantsType::IndexMask) - at, ConstantsType::Sizes[block]);
- if (!_v[block].testAndSetRelease(nullptr, v)) {
+ ElementType* const alloced = allocate((id & ConstantsType::IndexMask) - at,
+ ConstantsType::Sizes[block]);
+ if (_v[block].testAndSetRelease(nullptr, alloced, v)) {
+ v = alloced;
+ } else {
// race with another thread lost
- delete[] v;
- v = _v[block].loadAcquire();
+ delete[] alloced;
Q_ASSERT(v != nullptr);
}
}
newid = v[at].next.loadRelaxed() | (id & ~ConstantsType::IndexMask);
- } while (!_next.testAndSetRelease(id, newid));
+ } while (!_next.testAndSetOrdered(id, newid, id));
// qDebug("QFreeList::next(): returning %d (_next now %d, serial %d)",
// id & ConstantsType::IndexMask,
// newid & ConstantsType::IndexMask,
diff --git a/src/corelib/tools/qhashfunctions.h b/src/corelib/tools/qhashfunctions.h
index cbe217db11e..3e44f5f3442 100644
--- a/src/corelib/tools/qhashfunctions.h
+++ b/src/corelib/tools/qhashfunctions.h
@@ -298,19 +298,32 @@ bool qHashEquals(const T1 &a, const T2 &b)
}
namespace QtPrivate {
-template <typename Mixer> struct QHashCombiner : private Mixer
+template <typename Mixer> struct QHashCombinerWithSeed : private Mixer
{
- using result_type = typename Mixer::result_type ;
+ using result_type = typename Mixer::result_type;
+ size_t seed;
+ constexpr QHashCombinerWithSeed(result_type s) noexcept : seed(s) {}
+
+ template <typename T>
+ constexpr result_type operator()(result_type result, const T &t) const
+ noexcept(noexcept(qHash(t, seed)))
+ {
+ return Mixer::operator()(result, qHash(t, seed));
+ }
+};
#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) || defined(QT_BOOTSTRAPPED)
- // Qt 6.x didn't use to pass the seed; bootstrap has no seed
+// Earlier Qt 6.x versions of qHashMulti() failed to pass the seed as the seed
+// argument of qHash(), so this class exists for compatibility with user and
+// inline code that relies on the old behavior. For Qt 7, we'll replace with
+// the above version, except for the bootstrapped tools (which have no seed).
+template <typename Mixer> struct QHashCombiner : private Mixer
+{
+ using result_type = typename Mixer::result_type;
+
static constexpr size_t seed = 0;
constexpr QHashCombiner(result_type) noexcept {}
Q_DECL_DEPRECATED_X("pass the seed argument") constexpr QHashCombiner() noexcept {}
-#else
- size_t seed;
- constexpr QHashCombiner(result_type s) : seed(s) noexcept {}
-#endif
template <typename T>
constexpr result_type operator()(result_type result, const T &t) const
@@ -319,6 +332,9 @@ template <typename Mixer> struct QHashCombiner : private Mixer
return Mixer::operator()(result, qHash(t, seed));
}
};
+#else
+template <typename Mixer> using QHashCombiner = QHashCombinerWithSeed<Mixer>;
+#endif
struct QHashCombineMixer
{
@@ -330,6 +346,7 @@ struct QHashCombineMixer
}
};
using QHashCombine = QHashCombiner<QHashCombineMixer>;
+using QHashCombineWithSeed = QHashCombinerWithSeed<QHashCombineMixer>;
struct QHashCombineCommutativeMixer : std::plus<size_t>
{
@@ -341,6 +358,7 @@ struct QHashCombineCommutativeMixer : std::plus<size_t>
typedef size_t result_type;
};
using QHashCombineCommutative = QHashCombiner<QHashCombineCommutativeMixer>;
+using QHashCombineCommutativeWithSeed = QHashCombinerWithSeed<QHashCombineCommutativeMixer>;
template <typename... T>
using QHashMultiReturnType = decltype(
diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h
index a9d334e28f3..e0c0110b794 100644
--- a/src/corelib/tools/qsharedpointer_impl.h
+++ b/src/corelib/tools/qsharedpointer_impl.h
@@ -592,7 +592,10 @@ class QWeakPointer
{
typedef QtSharedPointer::ExternalRefCountData Data;
template <typename X>
- using IfCompatible = typename std::enable_if<std::is_convertible<X*, T*>::value, bool>::type;
+ using IfCompatible = std::enable_if_t<std::conjunction_v<
+ std::negation<std::is_same<T, X>>, // don't make accidental copy/move SMFs
+ std::is_convertible<X*, T*>
+ >, bool>;
template <typename X>
using IfVirtualBase = typename std::enable_if<qxp::is_virtual_base_of_v<T, X>, bool>::type;
@@ -768,6 +771,11 @@ private:
{ return *this = QWeakPointer<T>(ptr, true); }
#ifndef QT_NO_QOBJECT
+ Q_NODISCARD_CTOR
+ QWeakPointer(T *ptr, bool)
+ : d{ptr ? Data::getAndRef(ptr) : nullptr}, value{ptr}
+ { }
+
template <class X, IfCompatible<X> = true>
Q_NODISCARD_CTOR
inline QWeakPointer(X *ptr, bool) : d(ptr ? Data::getAndRef(ptr) : nullptr), value(ptr)