diff --git a/CMakeLists.txt b/CMakeLists.txt
index e86afb3..9109898 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -60,7 +60,7 @@
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.15 CACHE STRING "Required macOS version")
endif()
-project(AusweisApp2 VERSION 1.26.4 LANGUAGES ${LANGUAGES})
+project(AusweisApp2 VERSION 1.26.5 LANGUAGES ${LANGUAGES})
# Set TWEAK if not defined in PROJECT_VERSION above to
# have a valid tweak version without propagating it
diff --git a/Dockerfile b/Dockerfile
index 932b382..ab32e67 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,4 @@
-ARG ALPINE_VERSION=3.17
+ARG ALPINE_VERSION=3.18
FROM alpine:$ALPINE_VERSION as builder
# Install development stuff
diff --git a/cmake/Install.cmake b/cmake/Install.cmake
index 79998b2..73dea88 100644
--- a/cmake/Install.cmake
+++ b/cmake/Install.cmake
@@ -84,13 +84,16 @@
endif()
if (QT6)
- # Workaround for QTBUG-94066
- include("${QT_INSTALL_ARCHDATA}/lib/cmake/Qt6Gui/Qt6QSvgPluginTargets.cmake")
- include("${QT_INSTALL_ARCHDATA}/lib/cmake/Qt6Gui/Qt6QGifPluginTargets.cmake")
- include("${QT_INSTALL_ARCHDATA}/lib/cmake/Qt6Gui/Qt6QJpegPluginTargets.cmake")
- include("${QT_INSTALL_ARCHDATA}/lib/cmake/Qt6Gui/Qt6QWindowsIntegrationPluginTargets.cmake")
- include("${QT_INSTALL_ARCHDATA}/lib/cmake/Qt6Widgets/Qt6QWindowsVistaStylePluginTargets.cmake")
- include("${QT_INSTALL_ARCHDATA}/lib/cmake/Qt6Network/Qt6QTlsBackendOpenSSLPluginTargets.cmake")
+ if(QT_VERSION VERSION_LESS "6.4")
+ # Workaround for QTBUG-94066
+ include("${QT_INSTALL_ARCHDATA}/lib/cmake/Qt6Gui/Qt6QSvgPluginTargets.cmake")
+ include("${QT_INSTALL_ARCHDATA}/lib/cmake/Qt6Gui/Qt6QGifPluginTargets.cmake")
+ include("${QT_INSTALL_ARCHDATA}/lib/cmake/Qt6Gui/Qt6QJpegPluginTargets.cmake")
+ include("${QT_INSTALL_ARCHDATA}/lib/cmake/Qt6Gui/Qt6QWindowsIntegrationPluginTargets.cmake")
+ include("${QT_INSTALL_ARCHDATA}/lib/cmake/Qt6Widgets/Qt6QWindowsVistaStylePluginTargets.cmake")
+ include("${QT_INSTALL_ARCHDATA}/lib/cmake/Qt6Network/Qt6QTlsBackendOpenSSLPluginTargets.cmake")
+ endif()
+
FETCH_TARGET_LOCATION(openSslBackend "${Qt}::QTlsBackendOpenSSLPlugin")
install(FILES ${openSslBackend} DESTINATION tls COMPONENT Runtime)
list(APPEND LIBS ${openSslBackend})
@@ -247,6 +250,7 @@
foreach(entry ldpi mdpi hdpi xhdpi xxhdpi xxxhdpi)
install(FILES ${RESOURCES_IMG_ANDROID_DIR}/${entry}/background_npa.png DESTINATION ${ANDROID_PACKAGE_SRC_DIR}/res/mipmap-${entry} COMPONENT Runtime RENAME npa_background.png)
install(FILES ${RESOURCES_IMG_ANDROID_DIR}/${entry}/foreground_${ANDROID_LAUNCHER_ICON} DESTINATION ${ANDROID_PACKAGE_SRC_DIR}/res/mipmap-${entry} COMPONENT Runtime RENAME npa_foreground.png)
+ install(FILES ${RESOURCES_IMG_ANDROID_DIR}/${entry}/monochrome_${ANDROID_LAUNCHER_ICON} DESTINATION ${ANDROID_PACKAGE_SRC_DIR}/res/mipmap-${entry} COMPONENT Runtime RENAME npa_monochrome.png)
install(FILES ${RESOURCES_IMG_ANDROID_DIR}/${entry}/${ANDROID_LAUNCHER_ICON} DESTINATION ${ANDROID_PACKAGE_SRC_DIR}/res/mipmap-${entry} COMPONENT Runtime RENAME npa.png)
install(FILES ${RESOURCES_IMG_ANDROID_DIR}/${entry}/${ANDROID_SPLASH_SCREEN_ICON_NAME} DESTINATION ${ANDROID_PACKAGE_SRC_DIR}/res/drawable-${entry} COMPONENT Runtime RENAME splash_npa.png)
endforeach()
@@ -269,6 +273,8 @@
set(QML_ROOT_PATH [\"${RESOURCES_DIR}/qml\"])
set(ANDROID_ROOT_LOGGER "")
configure_file(${PACKAGING_DIR}/android/fileprovider.xml ${ANDROID_PACKAGE_SRC_DIR}/res/xml/fileprovider.xml COPYONLY)
+ configure_file(${PACKAGING_DIR}/android/full_backup_content.xml ${ANDROID_PACKAGE_SRC_DIR}/res/xml/full_backup_content.xml COPYONLY)
+ configure_file(${PACKAGING_DIR}/android/data_extraction_rules.xml ${ANDROID_PACKAGE_SRC_DIR}/res/xml/data_extraction_rules.xml COPYONLY)
endif()
set(ANDROID_SO_NAME libAusweisApp2_${CMAKE_ANDROID_ARCH_ABI}.so)
diff --git a/cmake/Libraries.cmake b/cmake/Libraries.cmake
index 6ece9e5..8e47744 100644
--- a/cmake/Libraries.cmake
+++ b/cmake/Libraries.cmake
@@ -49,11 +49,8 @@
endif()
if(NOT INTEGRATED_SDK)
- list(APPEND QT_COMPONENTS Svg WebSockets Qml Quick QuickControls2 QuickTemplates2)
+ list(APPEND QT_COMPONENTS Svg WebSockets Qml Quick QuickControls2 QuickTemplates2 QmlWorkerScript)
- if(QT_VERSION VERSION_GREATER_EQUAL "5.14")
- list(APPEND QT_COMPONENTS QmlWorkerScript)
- endif()
if(NOT DESKTOP AND NOT QT6)
list(APPEND QT_COMPONENTS QuickShapes)
endif()
diff --git a/cmake/Messages.cmake b/cmake/Messages.cmake
index 0a5e4ec..e3c6319 100644
--- a/cmake/Messages.cmake
+++ b/cmake/Messages.cmake
@@ -25,7 +25,6 @@
message(STATUS "ANDROID_BUILD_TOOLS_REVISION: ${ANDROID_BUILD_TOOLS_REVISION}")
message(STATUS "ANDROID_NDK_REVISION: ${ANDROID_NDK_REVISION}")
- message(STATUS "ANDROID_SDK_REVISION: ${ANDROID_SDK_REVISION}")
endif()
diff --git a/cmake/Packaging.cmake b/cmake/Packaging.cmake
index 461c3b2..f2dfbe9 100644
--- a/cmake/Packaging.cmake
+++ b/cmake/Packaging.cmake
@@ -171,7 +171,11 @@
file(READ "${BUILD_GRADLE_APPEND}" BUILD_GRADLE)
file(APPEND "${CMAKE_INSTALL_PREFIX}/build.gradle" "${BUILD_GRADLE}")
- if(USE_SMARTEID AND NOT INTEGRATED_SDK)
+ if(INTEGRATED_SDK)
+ set(BUILD_GRADLE_APPEND "${PACKAGING_DIR}/android/build.gradle.append.aar")
+ file(READ "${BUILD_GRADLE_APPEND}" BUILD_GRADLE)
+ file(APPEND "${CMAKE_INSTALL_PREFIX}/build.gradle" "${BUILD_GRADLE}")
+ elseif(USE_SMARTEID)
set(BUILD_GRADLE_APPEND "${PACKAGING_DIR}/android/build.gradle.append.smarteid")
file(READ "${BUILD_GRADLE_APPEND}" BUILD_GRADLE)
file(APPEND "${CMAKE_INSTALL_PREFIX}/build.gradle" "${BUILD_GRADLE}")
diff --git a/cmake/Tools.Libraries.cmake b/cmake/Tools.Libraries.cmake
index 7f37aa4..9237c91 100644
--- a/cmake/Tools.Libraries.cmake
+++ b/cmake/Tools.Libraries.cmake
@@ -2,7 +2,7 @@
# So this file will be called two times and the check needs to respect that
# with a "VALIDATOR function" or "if(NOT VARIABLE)".
-if(NOT QMLFORMAT)
+if(NOT TARGET format.qml)
set(QMLFORMAT_MIN_VERSION 6)
function(qmlformat_validator validator_result binary)
execute_process(COMMAND ${binary} --version OUTPUT_VARIABLE QMLFORMAT_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
diff --git a/cmake/Tools.cmake b/cmake/Tools.cmake
index 2ee0c3e..132bfdd 100644
--- a/cmake/Tools.cmake
+++ b/cmake/Tools.cmake
@@ -226,6 +226,33 @@
COMMAND ${INKSCAPE} adaptive_foreground_preview.svg -d 320 -y 0 -o xhdpi/foreground_npa_preview.png
COMMAND ${INKSCAPE} adaptive_foreground_preview.svg -d 480 -y 0 -o xxhdpi/foreground_npa_preview.png
COMMAND ${INKSCAPE} adaptive_foreground_preview.svg -d 640 -y 0 -o xxxhdpi/foreground_npa_preview.png
+ WORKING_DIRECTORY ${RESOURCES_DIR}/images/android)
+
+ add_custom_target(npaicons.android.adaptive.monochrome
+ COMMAND ${INKSCAPE} adaptive_monochrome_release.svg -d 120 -y 0 -o ldpi/monochrome_npa.png
+ COMMAND ${INKSCAPE} adaptive_monochrome_release.svg -d 160 -y 0 -o mdpi/monochrome_npa.png
+ COMMAND ${INKSCAPE} adaptive_monochrome_release.svg -d 240 -y 0 -o hdpi/monochrome_npa.png
+ COMMAND ${INKSCAPE} adaptive_monochrome_release.svg -d 320 -y 0 -o xhdpi/monochrome_npa.png
+ COMMAND ${INKSCAPE} adaptive_monochrome_release.svg -d 480 -y 0 -o xxhdpi/monochrome_npa.png
+ COMMAND ${INKSCAPE} adaptive_monochrome_release.svg -d 640 -y 0 -o xxxhdpi/monochrome_npa.png
+ WORKING_DIRECTORY ${RESOURCES_DIR}/images/android)
+
+ add_custom_target(npaicons.android.adaptive.monochrome.beta
+ COMMAND ${INKSCAPE} adaptive_monochrome_beta.svg -d 120 -y 0 -o ldpi/monochrome_npa_beta.png
+ COMMAND ${INKSCAPE} adaptive_monochrome_beta.svg -d 160 -y 0 -o mdpi/monochrome_npa_beta.png
+ COMMAND ${INKSCAPE} adaptive_monochrome_beta.svg -d 240 -y 0 -o hdpi/monochrome_npa_beta.png
+ COMMAND ${INKSCAPE} adaptive_monochrome_beta.svg -d 320 -y 0 -o xhdpi/monochrome_npa_beta.png
+ COMMAND ${INKSCAPE} adaptive_monochrome_beta.svg -d 480 -y 0 -o xxhdpi/monochrome_npa_beta.png
+ COMMAND ${INKSCAPE} adaptive_monochrome_beta.svg -d 640 -y 0 -o xxxhdpi/monochrome_npa_beta.png
+ WORKING_DIRECTORY ${RESOURCES_DIR}/images/android)
+
+ add_custom_target(npaicons.android.adaptive.monochrome.preview
+ COMMAND ${INKSCAPE} adaptive_monochrome_preview.svg -d 120 -y 0 -o ldpi/monochrome_npa_preview.png
+ COMMAND ${INKSCAPE} adaptive_monochrome_preview.svg -d 160 -y 0 -o mdpi/monochrome_npa_preview.png
+ COMMAND ${INKSCAPE} adaptive_monochrome_preview.svg -d 240 -y 0 -o hdpi/monochrome_npa_preview.png
+ COMMAND ${INKSCAPE} adaptive_monochrome_preview.svg -d 320 -y 0 -o xhdpi/monochrome_npa_preview.png
+ COMMAND ${INKSCAPE} adaptive_monochrome_preview.svg -d 480 -y 0 -o xxhdpi/monochrome_npa_preview.png
+ COMMAND ${INKSCAPE} adaptive_monochrome_preview.svg -d 640 -y 0 -o xxxhdpi/monochrome_npa_preview.png
WORKING_DIRECTORY ${RESOURCES_DIR}/images/android)
add_custom_target(npaicons.android.launchimage
@@ -313,6 +340,9 @@
npaicons.android.adaptive.foreground
npaicons.android.adaptive.foreground.beta
npaicons.android.adaptive.foreground.preview
+ npaicons.android.adaptive.monochrome
+ npaicons.android.adaptive.monochrome.beta
+ npaicons.android.adaptive.monochrome.preview
npaicons.android.launchimage
npaicons.android.launchimage.beta
npaicons.android.launchimage.preview
@@ -405,6 +435,33 @@
COMMAND ${PNGQUANT_CMD} xhdpi/foreground_npa_preview.png -- xhdpi/foreground_npa_preview.png
COMMAND ${PNGQUANT_CMD} xxhdpi/foreground_npa_preview.png -- xxhdpi/foreground_npa_preview.png
COMMAND ${PNGQUANT_CMD} xxxhdpi/foreground_npa_preview.png -- xxxhdpi/foreground_npa_preview.png
+ WORKING_DIRECTORY ${RESOURCES_DIR}/images/android)
+
+ add_custom_target(pngquant.android.adaptive.monochrome
+ COMMAND ${PNGQUANT_CMD} ldpi/monochrome_npa.png -- ldpi/monochrome_npa.png
+ COMMAND ${PNGQUANT_CMD} mdpi/monochrome_npa.png -- mdpi/monochrome_npa.png
+ COMMAND ${PNGQUANT_CMD} hdpi/monochrome_npa.png -- hdpi/monochrome_npa.png
+ COMMAND ${PNGQUANT_CMD} xhdpi/monochrome_npa.png -- xhdpi/monochrome_npa.png
+ COMMAND ${PNGQUANT_CMD} xxhdpi/monochrome_npa.png -- xxhdpi/monochrome_npa.png
+ COMMAND ${PNGQUANT_CMD} xxxhdpi/monochrome_npa.png -- xxxhdpi/monochrome_npa.png
+ WORKING_DIRECTORY ${RESOURCES_DIR}/images/android)
+
+ add_custom_target(pngquant.android.adaptive.monochrome.beta
+ COMMAND ${PNGQUANT_CMD} ldpi/monochrome_npa_beta.png -- ldpi/monochrome_npa_beta.png
+ COMMAND ${PNGQUANT_CMD} mdpi/monochrome_npa_beta.png -- mdpi/monochrome_npa_beta.png
+ COMMAND ${PNGQUANT_CMD} hdpi/monochrome_npa_beta.png -- hdpi/monochrome_npa_beta.png
+ COMMAND ${PNGQUANT_CMD} xhdpi/monochrome_npa_beta.png -- xhdpi/monochrome_npa_beta.png
+ COMMAND ${PNGQUANT_CMD} xxhdpi/monochrome_npa_beta.png -- xxhdpi/monochrome_npa_beta.png
+ COMMAND ${PNGQUANT_CMD} xxxhdpi/monochrome_npa_beta.png -- xxxhdpi/monochrome_npa_beta.png
+ WORKING_DIRECTORY ${RESOURCES_DIR}/images/android)
+
+ add_custom_target(pngquant.android.adaptive.monochrome.preview
+ COMMAND ${PNGQUANT_CMD} ldpi/monochrome_npa_preview.png -- ldpi/monochrome_npa_preview.png
+ COMMAND ${PNGQUANT_CMD} mdpi/monochrome_npa_preview.png -- mdpi/monochrome_npa_preview.png
+ COMMAND ${PNGQUANT_CMD} hdpi/monochrome_npa_preview.png -- hdpi/monochrome_npa_preview.png
+ COMMAND ${PNGQUANT_CMD} xhdpi/monochrome_npa_preview.png -- xhdpi/monochrome_npa_preview.png
+ COMMAND ${PNGQUANT_CMD} xxhdpi/monochrome_npa_preview.png -- xxhdpi/monochrome_npa_preview.png
+ COMMAND ${PNGQUANT_CMD} xxxhdpi/monochrome_npa_preview.png -- xxxhdpi/monochrome_npa_preview.png
WORKING_DIRECTORY ${RESOURCES_DIR}/images/android)
add_custom_target(pngquant.android.launchimage
@@ -491,6 +548,9 @@
pngquant.android.adaptive.foreground
pngquant.android.adaptive.foreground.beta
pngquant.android.adaptive.foreground.preview
+ pngquant.android.adaptive.monochrome
+ pngquant.android.adaptive.monochrome.beta
+ pngquant.android.adaptive.monochrome.preview
pngquant.android.launchimage
pngquant.android.launchimage.beta
pngquant.android.launchimage.preview
diff --git a/cmake/android.toolchain.cmake b/cmake/android.toolchain.cmake
index c21ea16..a509852 100644
--- a/cmake/android.toolchain.cmake
+++ b/cmake/android.toolchain.cmake
@@ -52,7 +52,6 @@
endif()
READ_REVISION(ANDROID_NDK_REVISION ".*Revision = ([0-9|\\.]+)" "${CMAKE_ANDROID_NDK}/source.properties")
-READ_REVISION(ANDROID_SDK_REVISION ".*Revision=([0-9|\\.]+)" "${ANDROID_SDK}/cmdline-tools/latest/source.properties;${ANDROID_SDK}/tools/source.properties")
set(CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION clang)
set(CMAKE_SYSTEM_NAME Android)
@@ -73,10 +72,6 @@
set(CMAKE_ANDROID_ARM_NEON ON)
endif()
-# Emulate NDK CMake-Variable as Qt 5.14 needs this (Multi-ABI)
-set(ANDROID_ABI ${CMAKE_ANDROID_ARCH_ABI})
-
-
set(CMAKE_FIND_ROOT_PATH ${CMAKE_PREFIX_PATH} CACHE STRING "android find search path root")
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
diff --git a/docs/failurecodes/failurecodes.rst b/docs/failurecodes/failurecodes.rst
index 1a5fe20..1e880d5 100644
--- a/docs/failurecodes/failurecodes.rst
+++ b/docs/failurecodes/failurecodes.rst
@@ -157,21 +157,21 @@
the description of the service provider certificate. This condition is not met.
| **Possible Solutions:** :ref:`failure_code_inform_service_provider`.
- - | **Pre_Verfication_No_Test_Environment**
+ - | **Pre_Verification_No_Test_Environment**
| Occurs when the development mode of AusweisApp2 is activated and a genuine ID card is used.
| **Possible Solutions:** Disable developer mode. The use of genuine ID cards is not permitted with
activated developer mode, as this is only intended to facilitate the commissioning of services
with test ID cards.
- - | **Pre_Verfication_Invalid_Certificate_Chain**
+ - | **Pre_Verification_Invalid_Certificate_Chain**
| A certificate chain was sent from the server that is unknown to AusweisApp2.
| **Possible Solutions:** :ref:`failure_code_inform_service_provider`.
- - | **Pre_Verfication_Invalid_Certificate_Signature**
+ - | **Pre_Verification_Invalid_Certificate_Signature**
| At least one signature in the certificate chain used by the server is incorrect.
| **Possible Solutions:** :ref:`failure_code_inform_service_provider`.
- - | **Pre_Verfication_Certificate_Expired**
+ - | **Pre_Verification_Certificate_Expired**
| The certificate chain used by the server is currently not valid.
| **Possible Solutions:** Make sure your system time is set correctly. If the problem persists,
see :ref:`failure_code_inform_service_provider`.
@@ -262,14 +262,14 @@
- | **Generic_Send_Receive_Paos_Unhandled**
| A message was sent by the server in the PAOS communication during authentication, that
- could be completely processed.
+ could not be completely processed.
| **Possible Solutions:** :ref:`failure_code_contact_support`.
- | **Generic_Send_Receive_Network_Error**
| A network error has occurred in the PAOS communication during authentication.
| **Possible Solutions:** :ref:`failure_code_fix_connections_problems`.
- - | **Generic_Send_Receive_Ssl_Error**
+ - | **Generic_Send_Receive_Tls_Error**
| An authentication error occurred in the PAOS communication during the TLS handshake. The TLS
certificate is incorrect.
| **Possible Solutions:** :ref:`failure_code_inform_service_provider`.
@@ -318,7 +318,7 @@
did not behave as expected by the server.
| **Possible Solutions:** :ref:`failure_code_contact_support`.
- - | **Check_Refresh_Address_Fatal_Ssl_Error_Before_Reply**
+ - | **Check_Refresh_Address_Fatal_Tls_Error_Before_Reply**
| An error occurred during the TLS handshake when checking the return address after a successful
authentication. The TLS certificate is incorrect.
| **Possible Solutions:** :ref:`failure_code_inform_service_provider`.
@@ -341,7 +341,7 @@
didn't work for checking the return address.
| **Possible Solutions:** :ref:`failure_code_fix_connections_problems`.
- - | **Check_Refresh_Address_Fatal_Ssl_Error_After_Reply**
+ - | **Check_Refresh_Address_Fatal_Tls_Error_After_Reply**
| When checking the return address after successful authentication, the TLS handshake could not
be completed successfully.
| **Possible Solutions:** :ref:`failure_code_fix_connections_problems`.
@@ -413,7 +413,7 @@
self-authentication.
| **Possible Solutions:** :ref:`failure_code_inform_service_provider`.
- - | **Generic_Provider_Communication_Ssl_Error**
+ - | **Generic_Provider_Communication_Tls_Error**
| An error occurred during the TLS handshake when communicating with a service provider. The TLS
certificate is incorrect. This only applies to services that are started from AusweisApp2,
such as self-authentication.
diff --git a/docs/failurecodes/locales/de/LC_MESSAGES/failurecodes.po b/docs/failurecodes/locales/de/LC_MESSAGES/failurecodes.po
index f99714f..6f1d212 100644
--- a/docs/failurecodes/locales/de/LC_MESSAGES/failurecodes.po
+++ b/docs/failurecodes/locales/de/LC_MESSAGES/failurecodes.po
@@ -360,7 +360,7 @@
"TLS-Zertifikate in der Beschreibung des Diensteanbieterzertifikats "
"enthalten sind. Diese Bedingung ist nicht erfüllt."
-msgid "**Pre_Verfication_No_Test_Environment**"
+msgid "**Pre_Verification_No_Test_Environment**"
msgstr ""
msgid ""
@@ -380,7 +380,7 @@
"dieser nur die Inbetriebnahme von Diensten mit Testausweisen erleichtern "
"soll."
-msgid "**Pre_Verfication_Invalid_Certificate_Chain**"
+msgid "**Pre_Verification_Invalid_Certificate_Chain**"
msgstr ""
msgid ""
@@ -390,7 +390,7 @@
"Vom Server wurde eine Zertifikatskette gesendet, die der AusweisApp2 "
"nicht bekannt ist."
-msgid "**Pre_Verfication_Invalid_Certificate_Signature**"
+msgid "**Pre_Verification_Invalid_Certificate_Signature**"
msgstr ""
msgid ""
@@ -400,7 +400,7 @@
"Mindestens eine Signatur in der vom Server genutzten Zertifikatskette ist"
" nicht korrekt."
-msgid "**Pre_Verfication_Certificate_Expired**"
+msgid "**Pre_Verification_Certificate_Expired**"
msgstr ""
msgid "The certificate chain used by the server is currently not valid."
@@ -639,7 +639,7 @@
msgid ""
"A message was sent by the server in the PAOS communication during "
-"authentication, that could be completely processed."
+"authentication, that could not be completely processed."
msgstr ""
"Bei einer Authentisierung ist eine Nachricht vom Server in der PAOS-"
"Kommunikation gesendet worden, die nicht vollständig verarbeitet werden "
@@ -655,7 +655,7 @@
"Bei einer Authentisierung ist ein Netzwerkfehler in der PAOS-"
"Kommunikation aufgetreten."
-msgid "**Generic_Send_Receive_Ssl_Error**"
+msgid "**Generic_Send_Receive_Tls_Error**"
msgstr ""
msgid ""
@@ -766,7 +766,7 @@
"geliefert. Die AusweisApp2 oder die Karte hat sich nicht entsprechend der"
" Erwartung des Servers verhalten."
-msgid "**Check_Refresh_Address_Fatal_Ssl_Error_Before_Reply**"
+msgid "**Check_Refresh_Address_Fatal_Tls_Error_Before_Reply**"
msgstr ""
msgid ""
@@ -815,7 +815,7 @@
" Proxyserver konfiguriert. Dieser hat für die Überprüfung der "
"Rücksprungadresse nicht funktioniert."
-msgid "**Check_Refresh_Address_Fatal_Ssl_Error_After_Reply**"
+msgid "**Check_Refresh_Address_Fatal_Tls_Error_After_Reply**"
msgstr ""
msgid ""
@@ -976,7 +976,7 @@
"aus der AusweisApp2 heraus gestartet werden, wie zum Beispiel die "
"Selbstauskunft."
-msgid "**Generic_Provider_Communication_Ssl_Error**"
+msgid "**Generic_Provider_Communication_Tls_Error**"
msgstr ""
msgid ""
diff --git a/docs/installation/README.de.rst b/docs/installation/README.de.rst
index a1aea8e..ae07729 100644
--- a/docs/installation/README.de.rst
+++ b/docs/installation/README.de.rst
@@ -173,8 +173,8 @@
remindToClose
- showSetupAssistant
-
+ uiStartupModule
+ DEFAULT
transportPinReminder
customProxyType
@@ -183,8 +183,6 @@
proxy.example.org
customProxyPort
1337
- autoUpdateCheck
-
keylessPassword
shuffleScreenKeyboard
@@ -209,12 +207,11 @@
======================= =======================
autoCloseWindow AUTOHIDE
remindToClose REMINDTOCLOSE
-showSetupAssistant ASSISTANT
+uiStartupModule ASSISTANT
transportPinReminder TRANSPORTPINREMINDER
customProxyType CUSTOMPROXYTYPE
customProxyPort CUSTOMPROXYPORT
customProxyHost CUSTOMPROXYHOST
-autoUpdateCheck UPDATECHECK
keylessPassword ONSCREENKEYBOARD
shuffleScreenKeyboard SHUFFLESCREENKEYBOARD
visualPrivacy SECURESCREENKEYBOARD
diff --git a/docs/installation/README.en.rst b/docs/installation/README.en.rst
index 2f03af3..4ab2cd5 100644
--- a/docs/installation/README.en.rst
+++ b/docs/installation/README.en.rst
@@ -160,8 +160,8 @@
remindToClose
- showSetupAssistant
-
+ uiStartupModule
+ DEFAULT
transportPinReminder
customProxyType
@@ -170,8 +170,6 @@
proxy.example.org
customProxyPort
1337
- autoUpdateCheck
-
keylessPassword
shuffleScreenKeyboard
@@ -195,12 +193,11 @@
======================= =======================
autoCloseWindow AUTOHIDE
remindToClose REMINDTOCLOSE
-showSetupAssistant ASSISTANT
+uiStartupModule ASSISTANT
transportPinReminder TRANSPORTPINREMINDER
customProxyType CUSTOMPROXYTYPE
customProxyPort CUSTOMPROXYPORT
customProxyHost CUSTOMPROXYHOST
-autoUpdateCheck UPDATECHECK
keylessPassword ONSCREENKEYBOARD
shuffleScreenKeyboard SHUFFLESCREENKEYBOARD
visualPrivacy SECURESCREENKEYBOARD
@@ -251,7 +248,7 @@
Broadcast on UDP port 24727 in the local subnet have to be receivable by the
AusweisApp2 to use the "Smartphone as Card Reader" functionality.
-It may be necessary to deactive AP isolation on your router.
+It may be necessary to deactivate AP isolation on your router.
.. _communicationmodel_en:
.. figure:: CommunicationModel_en.pdf
diff --git a/docs/releasenotes/1.26.5.rst b/docs/releasenotes/1.26.5.rst
new file mode 100644
index 0000000..450f414
--- /dev/null
+++ b/docs/releasenotes/1.26.5.rst
@@ -0,0 +1,36 @@
+AusweisApp2 1.26.5
+^^^^^^^^^^^^^^^^^^
+
+**Releasedatum:** 25. Juli 2023
+
+
+Anwender
+""""""""
+- Überarbeitung des Kopplungsprozesses der Funktion Smartphone als Kartenleser.
+ Beide an der Kopplung beteiligten Geräte müssen auf Version 1.26.5 aktualisiert werden.
+ Versionen kleiner als 1.26.5 lassen sich nicht mit einer AusweisApp2 1.26.5 koppeln.
+
+- Die Anzeige des Fortschritts erfolgt jetzt auch auf einem Smartphone als Kartenleser.
+
+- Der Tastaturmodus auf einem Smartphone als Kartenleser ist jetzt standardmäßig aktiviert.
+
+- Bei Nutzung des Tastaturmodus auf einem Smartphone als Kartenleser kann in den Einstellungen eine
+ erneute Anzeige der Berechtigungen aktiviert werden.
+
+- Ergänzung eines monochromen Icons unter Android.
+
+- Berücksichtigung von Command + W unter macOS.
+
+- Entfernung der Updatefunktion auf macOS zugunsten des Mac App Store.
+
+- Kleinere Fehlerbehebungen und Optimierungen.
+
+
+Entwickler
+""""""""""
+- Die Dokumentation für die Installation in Firmennetzwerken unter macOS für die Einstellung zum
+ Einrichtungsassistenten wurde korrigiert.
+
+- Optimierung der Größe des Android SDK.
+
+- Aktualisierung von OpenSSL auf die Version 3.0.9.
diff --git a/docs/releasenotes/announce.rst b/docs/releasenotes/announce.rst
index 13d2566..f8b914e 100644
--- a/docs/releasenotes/announce.rst
+++ b/docs/releasenotes/announce.rst
@@ -5,6 +5,8 @@
folgender Systeme und Funktionen eingestellt.
- macOS Catalina 10.15
+- Android 7
+- iOS 13
- Online-Hilfe
- PDF-Export-Funktion der Selbstauskunft
diff --git a/docs/releasenotes/appcast.rst b/docs/releasenotes/appcast.rst
index 682bc05..5aee357 100644
--- a/docs/releasenotes/appcast.rst
+++ b/docs/releasenotes/appcast.rst
@@ -4,6 +4,7 @@
.. toctree::
:maxdepth: 1
+ 1.26.5
1.26.4
1.26.3
1.26.2
diff --git a/docs/releasenotes/issues.rst b/docs/releasenotes/issues.rst
index 0ca9b1b..9f6d822 100644
--- a/docs/releasenotes/issues.rst
+++ b/docs/releasenotes/issues.rst
@@ -38,11 +38,6 @@
- Die visuelle Hervorhebung des aktiven Elements wird an einigen Stellen
fälschlicherwiese auch aktiviert, wenn die Maus benutzt wurde.
-- Unter macOS werden im System hinterlegte Proxy-Server nicht erkannt und
- damit auch nicht automatisch verwendet. Um manuell einen Proxy-Server in
- der AusweisApp2 zu hinterlegen beachten Sie die Anleitung zur Installation
- in Firmennetzwerken.
-
Android / iOS
"""""""""""""
diff --git a/docs/releasenotes/support.rst b/docs/releasenotes/support.rst
index 6a5f4bf..88faee3 100644
--- a/docs/releasenotes/support.rst
+++ b/docs/releasenotes/support.rst
@@ -54,13 +54,13 @@
Im Rahmen der Qualitätssicherung werden die folgenden Browserversionen
getestet.
-- Chrome 112
+- Chrome 115
-- Firefox 112
+- Firefox 115
-- Safari 16.4 (macOS)
+- Safari 16.5 (macOS)
-- Edge 112
+- Edge 115
@@ -118,13 +118,13 @@
Anbieter umgesetzten Aktivierung. Daher empfehlen wir einen der
folgenden Browser zu verwenden.
-- Chrome 112 (iOS/Android)
+- Chrome 115 (iOS/Android)
-- Firefox 112 (iOS/Android)
+- Firefox 115 (iOS/Android)
-- Samsung Internet 20 (Android)
+- Samsung Internet 22 (Android)
-- Safari 16.4 (iOS)
+- Safari 16.5 (iOS)
Kartenleser
diff --git a/docs/releasenotes/versions.rst b/docs/releasenotes/versions.rst
index 67040af..2eeb000 100644
--- a/docs/releasenotes/versions.rst
+++ b/docs/releasenotes/versions.rst
@@ -6,6 +6,7 @@
.. toctree::
:maxdepth: 1
+ 1.26.5
1.26.4
1.26.3
1.26.2
diff --git a/docs/sdk/messages.rst b/docs/sdk/messages.rst
index 8187f07..d091862 100644
--- a/docs/sdk/messages.rst
+++ b/docs/sdk/messages.rst
@@ -810,6 +810,8 @@
to unblock the PIN.
- **deactivated**: True if eID function is deactivated, otherwise false.
+ The scan dialog on iOS won't be closed if this is True. You need to
+ send :ref:`interrupt` yourself to show an error message.
- **retryCounter**: Count of possible retries for the PIN. If you enter a PIN
with command :ref:`set_pin` it will be decreased if PIN was incorrect.
diff --git a/docs/sdk/workflow.rst b/docs/sdk/workflow.rst
index b5cc878..a55a977 100644
--- a/docs/sdk/workflow.rst
+++ b/docs/sdk/workflow.rst
@@ -24,7 +24,7 @@
.. code-block:: json
- {"cmd": "RUN_AUTH", "tcTokenURL": "https://test.governikus-eid.de/DEMO"}
+ {"cmd": "RUN_AUTH", "tcTokenURL": "https://test.governikus-eid.de/AusweisAuskunft/WebServiceRequesterServlet"}
{"msg": "AUTH"}
diff --git a/libs/CMakeLists.txt b/libs/CMakeLists.txt
index 4af45b2..77505ba 100644
--- a/libs/CMakeLists.txt
+++ b/libs/CMakeLists.txt
@@ -109,11 +109,7 @@
endif()
################################## Versions
-set(QT 6.4.1)
-set(QT_HASH e20b850b6134098a7f2e7701cfddfb213c6cf394b9e848e6fbc5b0e89dcfcc09)
-
-set(OPENSSL 3.0.8)
-set(OPENSSL_HASH 6c13d2bf38fdf31eac3ce2a347073673f5d63263398f1f69d0df4a41253e4b3e)
+include(Versions.cmake)
################################## Files
set(QT_FILE qt-everywhere-src-${QT}.tar.xz)
diff --git a/libs/Versions.cmake b/libs/Versions.cmake
new file mode 100644
index 0000000..56bc6c0
--- /dev/null
+++ b/libs/Versions.cmake
@@ -0,0 +1,5 @@
+set(QT 6.4.1)
+set(QT_HASH e20b850b6134098a7f2e7701cfddfb213c6cf394b9e848e6fbc5b0e89dcfcc09)
+
+set(OPENSSL 3.0.9)
+set(OPENSSL_HASH eb1ab04781474360f77c318ab89d8c5a03abc38e63d65a603cabbf1b00a1dc90)
diff --git a/libs/patch.cmake.in b/libs/patch.cmake.in
index 6f5ded1..adec3a6 100644
--- a/libs/patch.cmake.in
+++ b/libs/patch.cmake.in
@@ -15,11 +15,11 @@
function(PATCH_SOURCES _component)
set(PATCHES_DIR @PROJECT_SOURCE_DIR@/patches)
- file(GLOB PATCHES "${PATCHES_DIR}/${_component}-*.patch")
+ file(GLOB PATCHES "${PATCHES_DIR}/${_component}*.patch")
PATCH_SOURCES_EXECUTE("${PATCHES}")
if("@CMAKE_BUILD_TYPE@" STREQUAL "DEBUG")
- file(GLOB PATCHES_DEBUG "${PATCHES_DIR}/debug/${_component}-*.patch")
+ file(GLOB PATCHES_DEBUG "${PATCHES_DIR}/debug/${_component}*.patch")
PATCH_SOURCES_EXECUTE("${PATCHES_DEBUG}")
endif()
endfunction()
diff --git a/libs/patches/openssl-0001-Adjust-iOS-target.patch b/libs/patches/openssl-0001-Adjust-iOS-target.patch
index c2345ef..6f9fcdc 100644
--- a/libs/patches/openssl-0001-Adjust-iOS-target.patch
+++ b/libs/patches/openssl-0001-Adjust-iOS-target.patch
@@ -1,4 +1,4 @@
-From a16972bcfd33b694fd27d19e85754be74daa4430 Mon Sep 17 00:00:00 2001
+From c97e9531a9da0ad5ae3bfb7cec90b03475a58a76 Mon Sep 17 00:00:00 2001
From: Lars Schmertmann
Date: Fri, 12 Feb 2021 13:15:00 +0100
Subject: Adjust iOS target
@@ -8,7 +8,7 @@
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git x/Configurations/15-ios.conf y/Configurations/15-ios.conf
-index 54d37f63f4..a4ade8d209 100644
+index 54d37f63f4..7e411b2e3a 100644
--- x/Configurations/15-ios.conf
+++ y/Configurations/15-ios.conf
@@ -25,7 +25,7 @@ my %targets = (
@@ -20,5 +20,3 @@
bn_ops => "SIXTY_FOUR_BIT_LONG RC4_CHAR",
asm_arch => 'aarch64',
perlasm_scheme => "ios64",
---
-2.35.1
diff --git a/libs/patches/openssl-0002-android-shlib_variant.patch b/libs/patches/openssl-0002-android-shlib_variant.patch
index 24f251f..d562c10 100644
--- a/libs/patches/openssl-0002-android-shlib_variant.patch
+++ b/libs/patches/openssl-0002-android-shlib_variant.patch
@@ -1,4 +1,4 @@
-From 8e011194bf8b4e4275f51f76b75a1b22e45e9564 Mon Sep 17 00:00:00 2001
+From 8353ce61f188109953e327b4bddf65c95e4baf92 Mon Sep 17 00:00:00 2001
From: Lars Schmertmann
Date: Tue, 19 Jan 2021 17:07:51 +0100
Subject: android shlib_variant
@@ -41,6 +41,3 @@
},
####################################################################
---
-2.35.1
-
diff --git a/libs/patches/openssl-0003-Do-not-ignore-empty-associated-data-with-AES-SIV-mod.patch b/libs/patches/openssl-0003-Do-not-ignore-empty-associated-data-with-AES-SIV-mod.patch
new file mode 100644
index 0000000..914498e
--- /dev/null
+++ b/libs/patches/openssl-0003-Do-not-ignore-empty-associated-data-with-AES-SIV-mod.patch
@@ -0,0 +1,55 @@
+From 9faa80071777b8a0b9eca1ab59bf69adb4621d9f Mon Sep 17 00:00:00 2001
+From: Tomas Mraz
+Date: Tue, 4 Jul 2023 17:30:35 +0200
+Subject: Do not ignore empty associated data with AES-SIV mode
+
+The AES-SIV mode allows for multiple associated data items
+authenticated separately with any of these being 0 length.
+
+The provided implementation ignores such empty associated data
+which is incorrect in regards to the RFC 5297 and is also
+a security issue because such empty associated data then become
+unauthenticated if an application expects to authenticate them.
+
+Fixes CVE-2023-2975
+
+Reviewed-by: Matt Caswell
+Reviewed-by: Paul Dale
+(Merged from https://github.com/openssl/openssl/pull/21384)
+
+(cherry picked from commit c426c281cfc23ab182f7d7d7a35229e7db1494d9)
+(cherry picked from commit 00e2f5eea29994d19293ec4e8c8775ba73678598)
+---
+ .../implementations/ciphers/cipher_aes_siv.c | 18 +++++++++++-------
+ 1 file changed, 11 insertions(+), 7 deletions(-)
+
+diff --git x/providers/implementations/ciphers/cipher_aes_siv.c y/providers/implementations/ciphers/cipher_aes_siv.c
+index 45010b90db..b396c8651a 100644
+--- x/providers/implementations/ciphers/cipher_aes_siv.c
++++ y/providers/implementations/ciphers/cipher_aes_siv.c
+@@ -120,14 +120,18 @@ static int siv_cipher(void *vctx, unsigned char *out, size_t *outl,
+ if (!ossl_prov_is_running())
+ return 0;
+
+- if (inl == 0) {
+- *outl = 0;
+- return 1;
+- }
++ /* Ignore just empty encryption/decryption call and not AAD. */
++ if (out != NULL) {
++ if (inl == 0) {
++ if (outl != NULL)
++ *outl = 0;
++ return 1;
++ }
+
+- if (outsize < inl) {
+- ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+- return 0;
++ if (outsize < inl) {
++ ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
++ return 0;
++ }
+ }
+
+ if (ctx->hw->cipher(ctx, out, in, inl) <= 0)
diff --git a/libs/patches/openssl-0004-Fix-DH_check-excessive-time-with-over-sized-modulus.patch b/libs/patches/openssl-0004-Fix-DH_check-excessive-time-with-over-sized-modulus.patch
new file mode 100644
index 0000000..4582d53
--- /dev/null
+++ b/libs/patches/openssl-0004-Fix-DH_check-excessive-time-with-over-sized-modulus.patch
@@ -0,0 +1,72 @@
+From c012334ed713416cc30d6b2ff4dbeca97d1503c3 Mon Sep 17 00:00:00 2001
+From: Matt Caswell
+Date: Thu, 6 Jul 2023 16:36:35 +0100
+Subject: Fix DH_check() excessive time with over sized modulus
+
+The DH_check() function checks numerous aspects of the key or parameters
+that have been supplied. Some of those checks use the supplied modulus
+value even if it is excessively large.
+
+There is already a maximum DH modulus size (10,000 bits) over which
+OpenSSL will not generate or derive keys. DH_check() will however still
+perform various tests for validity on such a large modulus. We introduce a
+new maximum (32,768) over which DH_check() will just fail.
+
+An application that calls DH_check() and supplies a key or parameters
+obtained from an untrusted source could be vulnerable to a Denial of
+Service attack.
+
+The function DH_check() is itself called by a number of other OpenSSL
+functions. An application calling any of those other functions may
+similarly be affected. The other functions affected by this are
+DH_check_ex() and EVP_PKEY_param_check().
+
+CVE-2023-3446
+
+Reviewed-by: Paul Dale
+Reviewed-by: Tom Cosgrove
+Reviewed-by: Bernd Edlinger
+Reviewed-by: Tomas Mraz
+(Merged from https://github.com/openssl/openssl/pull/21451)
+
+(cherry picked from commit 9e0094e2aa1b3428a12d5095132f133c078d3c3d)
+(cherry picked from commit 1fa20cf2f506113c761777127a38bce5068740eb)
+---
+ crypto/dh/dh_check.c | 6 ++++++
+ include/openssl/dh.h | 6 +++++-
+ 2 files changed, 11 insertions(+), 1 deletion(-)
+
+diff --git x/crypto/dh/dh_check.c y/crypto/dh/dh_check.c
+index 0b391910d6..84a926998e 100644
+--- x/crypto/dh/dh_check.c
++++ y/crypto/dh/dh_check.c
+@@ -152,6 +152,12 @@ int DH_check(const DH *dh, int *ret)
+ if (nid != NID_undef)
+ return 1;
+
++ /* Don't do any checks at all with an excessively large modulus */
++ if (BN_num_bits(dh->params.p) > OPENSSL_DH_CHECK_MAX_MODULUS_BITS) {
++ ERR_raise(ERR_LIB_DH, DH_R_MODULUS_TOO_LARGE);
++ return 0;
++ }
++
+ if (!DH_check_params(dh, ret))
+ return 0;
+
+diff --git x/include/openssl/dh.h y/include/openssl/dh.h
+index b97871eca7..36420f51d8 100644
+--- x/include/openssl/dh.h
++++ y/include/openssl/dh.h
+@@ -89,7 +89,11 @@ int EVP_PKEY_CTX_get0_dh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char **ukm);
+ # include
+
+ # ifndef OPENSSL_DH_MAX_MODULUS_BITS
+-# define OPENSSL_DH_MAX_MODULUS_BITS 10000
++# define OPENSSL_DH_MAX_MODULUS_BITS 10000
++# endif
++
++# ifndef OPENSSL_DH_CHECK_MAX_MODULUS_BITS
++# define OPENSSL_DH_CHECK_MAX_MODULUS_BITS 32768
+ # endif
+
+ # define OPENSSL_DH_FIPS_MIN_MODULUS_BITS 1024
diff --git a/libs/patches/qt-base-0001-Revert-Fix-usage-of-logging-category-on-Android.patch b/libs/patches/qt-base-0001-Revert-Fix-usage-of-logging-category-on-Android.patch
deleted file mode 100644
index 23f53c9..0000000
--- a/libs/patches/qt-base-0001-Revert-Fix-usage-of-logging-category-on-Android.patch
+++ /dev/null
@@ -1,43 +0,0 @@
-From ca3a694221c62131a384cbabd7dc34f91add9eae Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Andr=C3=A9=20Klitzing?=
-Date: Mon, 25 Jul 2022 17:08:54 +0200
-Subject: Revert "Fix usage of logging category on Android"
-
-This reverts commit 87d8ee755bfdef8e72a122789c2e3ed382881a12.
-
-Change-Id: If19a9d615e01d61c79955cda4789ba1646520ee1
----
- src/corelib/global/qlogging.cpp | 9 +--------
- 1 file changed, 1 insertion(+), 8 deletions(-)
-
-diff --git x/qtbase/src/corelib/global/qlogging.cpp y/qtbase/src/corelib/global/qlogging.cpp
-index 9ac70b3340..737a91dc6e 100644
---- x/qtbase/src/corelib/global/qlogging.cpp
-+++ y/qtbase/src/corelib/global/qlogging.cpp
-@@ -1450,10 +1450,7 @@ QString qFormatLogMessage(QtMsgType type, const QMessageLogContext &context, con
- } else if (token == messageTokenC) {
- message.append(str);
- } else if (token == categoryTokenC) {
--#ifndef Q_OS_ANDROID
-- // Don't add the category to the message on Android
- message.append(QLatin1StringView(context.category));
--#endif
- } else if (token == typeTokenC) {
- switch (type) {
- case QtDebugMsg: message.append("debug"_L1); break;
-@@ -1701,11 +1698,7 @@ static bool android_default_message_handler(QtMsgType type,
- break;
- };
-
-- // If application name is a tag ensure it has no spaces
-- // If a category is defined, use it as an Android logging tag
-- __android_log_print(priority, isDefaultCategory(context.category) ?
-- qPrintable(QCoreApplication::applicationName().replace(u' ', u'_')) : context.category,
-- "%s\n", qPrintable(formattedMessage));
-+ __android_log_print(priority, qPrintable(QCoreApplication::applicationName()), "%s\n", qPrintable(formattedMessage));
-
- return true; // Prevent further output to stderr
- }
---
-2.38.1
-
diff --git a/libs/patches/qt-base-0002-Revert-Android-Fix-QSettings-when-using-content-URL.patch b/libs/patches/qt-base-0002-Revert-Android-Fix-QSettings-when-using-content-URL.patch
deleted file mode 100644
index 86f8eb0..0000000
--- a/libs/patches/qt-base-0002-Revert-Android-Fix-QSettings-when-using-content-URL.patch
+++ /dev/null
@@ -1,66 +0,0 @@
-From c6818d0c25f067bc13198b9aa2ca82776a40ad3b Mon Sep 17 00:00:00 2001
-From: Lars Schmertmann
-Date: Wed, 14 Dec 2022 11:52:12 +0100
-Subject: Revert "Android: Fix QSettings when using content URL"
-
-This reverts commit 140ca89a3c2b8d78889d27217f977cd4de10041b.
----
- src/corelib/io/qsettings.cpp | 21 +++------------------
- 1 file changed, 3 insertions(+), 18 deletions(-)
-
-diff --git x/qtbase/src/corelib/io/qsettings.cpp y/qtbase/src/corelib/io/qsettings.cpp
-index 60622e3aaa..a999aa6996 100644
---- x/qtbase/src/corelib/io/qsettings.cpp
-+++ y/qtbase/src/corelib/io/qsettings.cpp
-@@ -48,9 +48,8 @@
- #define Q_XDG_PLATFORM
- #endif
-
--#if !defined(QT_NO_STANDARDPATHS) \
-- && (defined(Q_XDG_PLATFORM) || defined(QT_PLATFORM_UIKIT) || defined(Q_OS_ANDROID))
--# define QSETTINGS_USE_QSTANDARDPATHS
-+#if !defined(QT_NO_STANDARDPATHS) && (defined(Q_XDG_PLATFORM) || defined(QT_PLATFORM_UIKIT))
-+#define QSETTINGS_USE_QSTANDARDPATHS
- #endif
-
- // ************************************************************************
-@@ -1332,15 +1331,6 @@ void QConfFileSettingsPrivate::syncConfFile(QConfFile *confFile)
- }
-
- #ifndef QT_BOOTSTRAPPED
-- QString lockFileName = confFile->name + ".lock"_L1;
--
--# if defined(Q_OS_ANDROID) && defined(QSETTINGS_USE_QSTANDARDPATHS)
-- // On android and if it is a content URL put the lock file in a
-- // writable location to prevent permissions issues and invalid paths.
-- if (confFile->name.startsWith("content:"_L1))
-- lockFileName = QStandardPaths::writableLocation(QStandardPaths::CacheLocation)
-- + QFileInfo(lockFileName).fileName();
--# endif
- /*
- Use a lockfile in order to protect us against other QSettings instances
- trying to write the same settings at the same time.
-@@ -1348,7 +1338,7 @@ void QConfFileSettingsPrivate::syncConfFile(QConfFile *confFile)
- We only need to lock if we are actually writing as only concurrent writes are a problem.
- Concurrent read and write are not a problem because the writing operation is atomic.
- */
-- QLockFile lockFile(lockFileName);
-+ QLockFile lockFile(confFile->name + ".lock"_L1);
- if (!readOnly && !lockFile.lock() && atomicSyncOnly) {
- setStatus(QSettings::AccessError);
- return;
-@@ -1426,11 +1416,6 @@ void QConfFileSettingsPrivate::syncConfFile(QConfFile *confFile)
- #if !defined(QT_BOOTSTRAPPED) && QT_CONFIG(temporaryfile)
- QSaveFile sf(confFile->name);
- sf.setDirectWriteFallback(!atomicSyncOnly);
--# ifdef Q_OS_ANDROID
-- // QSaveFile requires direct write when using content scheme URL in Android
-- if (confFile->name.startsWith("content:"_L1))
-- sf.setDirectWriteFallback(true);
--# endif
- #else
- QFile sf(confFile->name);
- #endif
---
-2.39.0
-
diff --git a/libs/patches/qt-base-0003-Android-A11Y-Only-access-the-main-thread-when-it-is-.patch b/libs/patches/qt-base-0003-Android-A11Y-Only-access-the-main-thread-when-it-is-.patch
deleted file mode 100644
index ea17cb1..0000000
--- a/libs/patches/qt-base-0003-Android-A11Y-Only-access-the-main-thread-when-it-is-.patch
+++ /dev/null
@@ -1,66 +0,0 @@
-From 97d4394f85f120724a9cbe518ba2233b87e48c68 Mon Sep 17 00:00:00 2001
-From: Julian Greilich
-Date: Wed, 4 Jan 2023 16:32:28 +0100
-Subject: Android A11Y: Only access the main thread when it is not blocked
-
-When the qtMainLoopThread calls QSGThreadedRenderLoop::polishAndSync(),
-it waits for the QSGRenderThread.
-
-In the QSGRenderThread, QAndroidPlatformOpenGLWindow::eglSurface()
-calls QtAndroid::createSurface() and waits for the "android main
-thread" to return a valid surface.
-When the "android main thread" now calls "runInObjectContext" (e.g. by
-calling QtAndroidAccessibility::childIdListForAccessibleObject()) it
-waits for the qtMainLoopThread and the program is stuck in a deadlock.
-
-To prevent this, we protect all BlockedQueuedConnection from the
-"android main thread" to the qtMainLoopThread by acquiring the
-AndroidDeadlockProtector.
-When QAndroidPlatformOpenGLWindow::eglSurface() already acquired the
-AndroidDeadlockProtector we abort the current A11y call with an emtpy
-or default value.
-
-Note: b8a95275440b8a143ee648466fd8b5401ee1e839 already tried to fix
-this by checking "getSurfaceCount() != 0", but there are situations,
-where a new surface is being created while an old surface is still
-present.
-
-Task-number: QTBUG-105958
-Pick-to: 6.5 6.4 6.3 6.2 5.15
-Change-Id: Ie40e8654c99aace9e69b0b8412952fa22c89f071
-Reviewed-by: Assam Boudjelthia
-(cherry picked from commit b832a5ac72c6015b6509d60b75b2ce5d5e570800)
----
- .../platforms/android/androidjniaccessibility.cpp | 9 +++++++++
- 1 file changed, 9 insertions(+)
-
-diff --git x/qtbase/src/plugins/platforms/android/androidjniaccessibility.cpp y/qtbase/src/plugins/platforms/android/androidjniaccessibility.cpp
-index 3067cb178a..8990289dc4 100644
---- x/qtbase/src/plugins/platforms/android/androidjniaccessibility.cpp
-+++ y/qtbase/src/plugins/platforms/android/androidjniaccessibility.cpp
-@@ -1,6 +1,7 @@
- // Copyright (C) 2021 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
-
-+#include "androiddeadlockprotector.h"
- #include "androidjniaccessibility.h"
- #include "androidjnimain.h"
- #include "qandroidplatformintegration.h"
-@@ -61,6 +62,14 @@ namespace QtAndroidAccessibility
- template
- void runInObjectContext(QObject *context, Func &&func, Ret *retVal)
- {
-+ AndroidDeadlockProtector protector;
-+ if (!protector.acquire()) {
-+ __android_log_print(ANDROID_LOG_WARN, m_qtTag,
-+ "Could not run accessibility call in object context, accessing "
-+ "main thread could lead to deadlock");
-+ return;
-+ }
-+
- if (!QtAndroid::blockEventLoopsWhenSuspended()
- || QGuiApplication::applicationState() != Qt::ApplicationSuspended) {
- QMetaObject::invokeMethod(context, func, Qt::BlockingQueuedConnection, retVal);
---
-2.39.0
-
diff --git a/libs/patches/qt-base-0004-Fix-warning-in-q20algorithm.h-when-xcodebuild-is-use.patch b/libs/patches/qt-base-0004-Fix-warning-in-q20algorithm.h-when-xcodebuild-is-use.patch
deleted file mode 100644
index 29a7037..0000000
--- a/libs/patches/qt-base-0004-Fix-warning-in-q20algorithm.h-when-xcodebuild-is-use.patch
+++ /dev/null
@@ -1,49 +0,0 @@
-From bc1b984a5b1a53c0c9eccc44763aaf0c94294fb7 Mon Sep 17 00:00:00 2001
-From: Lars Schmertmann
-Date: Mon, 9 Jan 2023 06:54:53 +0100
-Subject: Fix warning in q20algorithm.h when xcodebuild is used
-
-q20algorithm.h:150:20: error: unused function template 'operator()'
-q20algorithm.h:163:20: error: unused function template 'operator()'
-q20algorithm.h:176:20: error: unused function template 'operator()'
-
-Fixes: QTBUG-109874
-Change-Id: If5ccbfffd0b6a53f73f221b45033dab7e4775d89
----
- src/corelib/global/q20algorithm.h | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
-diff --git x/qtbase/src/corelib/global/q20algorithm.h y/qtbase/src/corelib/global/q20algorithm.h
-index 69dc2d2446..88e8ab08d2 100644
---- x/qtbase/src/corelib/global/q20algorithm.h
-+++ y/qtbase/src/corelib/global/q20algorithm.h
-@@ -147,7 +147,7 @@ using std::ranges::none_of;
- [[maybe_unused]] inline constexpr struct { // Niebloid
- template
-- constexpr bool operator()(InputIterator first, Sentinel last, Predicate pred, Projection proj = {}) const
-+ [[maybe_unused]] constexpr bool operator()(InputIterator first, Sentinel last, Predicate pred, Projection proj = {}) const
- {
- while (first != last) {
- if (std::invoke(pred, std::invoke(proj, *first)))
-@@ -160,7 +160,7 @@ using std::ranges::none_of;
- [[maybe_unused]] inline constexpr struct { // Niebloid
- template
-- constexpr bool operator()(InputIterator first, Sentinel last, Predicate pred, Projection proj = {}) const
-+ [[maybe_unused]] constexpr bool operator()(InputIterator first, Sentinel last, Predicate pred, Projection proj = {}) const
- {
- while (first != last) {
- if (!std::invoke(pred, std::invoke(proj, *first)))
-@@ -173,7 +173,7 @@ using std::ranges::none_of;
- [[maybe_unused]] inline constexpr struct { // Niebloid
- template
-- constexpr bool operator()(InputIterator first, Sentinel last, Predicate pred, Projection proj = {}) const
-+ [[maybe_unused]] constexpr bool operator()(InputIterator first, Sentinel last, Predicate pred, Projection proj = {}) const
- {
- while (first != last) {
- if (std::invoke(pred, std::invoke(proj, *first)))
---
-2.39.0
-
diff --git a/libs/patches/qt-base-0005-macOS-Use-NSStatusItem.menu-to-manage-system-tray-me.patch b/libs/patches/qt-base-0005-macOS-Use-NSStatusItem.menu-to-manage-system-tray-me.patch
deleted file mode 100644
index 737430d..0000000
--- a/libs/patches/qt-base-0005-macOS-Use-NSStatusItem.menu-to-manage-system-tray-me.patch
+++ /dev/null
@@ -1,130 +0,0 @@
-From d5555d3c62cbc8c061de0ae9e1f0c20374b4004e Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?=
-Date: Mon, 12 Dec 2022 14:33:41 +0100
-Subject: macOS: Use NSStatusItem.menu to manage system tray menu
-
-Using [NSStatusItem popUpStatusItemMenu:] to manually show the menu is
-deprecated, and was causing various issues when right clicking the menu,
-such as not unhighlighting the menu item when dismissing the menu, or
-worse, not quitting the application if a 'Quit' item was triggered from
-a right click.
-
-The reason we were using popUpStatusItemMenu instead of the menu
-property of NSStatusItem was that the latter prevented us from seeing
-the action message of the NSStatusItem button, which we used to emit
-the system tray's activated signal, but this can be solved by listing
-for the menu's tracking state starting.
-
-Fixes: QTBUG-103515
-Pick-to: 6.4
-Change-Id: I686550ebac7d94d8d11b2e3c49ed16a8240cb214
-Reviewed-by: Volker Hilsheimer
-(cherry picked from commit da754d5b6589c9877f0325edb3da5cbc64d966c7)
----
- .../platforms/cocoa/qcocoasystemtrayicon.h | 3 +-
- .../platforms/cocoa/qcocoasystemtrayicon.mm | 36 ++++++++++++-------
- 2 files changed, 24 insertions(+), 15 deletions(-)
-
-diff --git x/qtbase/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h y/qtbase/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h
-index 414560e1192..75c33cc5a3f 100644
---- x/qtbase/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h
-+++ y/qtbase/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h
-@@ -45,12 +45,11 @@ public:
- bool isSystemTrayAvailable() const override;
- bool supportsMessages() const override;
-
-- void statusItemClicked();
-+ void emitActivated();
-
- private:
- NSStatusItem *m_statusItem = nullptr;
- QStatusItemDelegate *m_delegate = nullptr;
-- QCocoaMenu *m_menu = nullptr;
- };
-
- QT_END_NAMESPACE
-diff --git x/qtbase/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm y/qtbase/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
-index c004cd69b57..2f7f73b4813 100644
---- x/qtbase/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
-+++ y/qtbase/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
-@@ -64,6 +64,8 @@ void QCocoaSystemTrayIcon::init()
-
- m_delegate = [[QStatusItemDelegate alloc] initWithSysTray:this];
-
-+ // In case the status item does not have a menu assigned to it
-+ // we fall back to the item's button to detect activation.
- m_statusItem.button.target = m_delegate;
- m_statusItem.button.action = @selector(statusItemClicked);
- [m_statusItem.button sendActionOn:NSEventMaskLeftMouseDown | NSEventMaskRightMouseDown | NSEventMaskOtherMouseDown];
-@@ -81,8 +83,6 @@ void QCocoaSystemTrayIcon::cleanup()
-
- [m_delegate release];
- m_delegate = nil;
--
-- m_menu = nullptr;
- }
-
- QRect QCocoaSystemTrayIcon::geometry() const
-@@ -178,12 +178,20 @@ void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon)
-
- void QCocoaSystemTrayIcon::updateMenu(QPlatformMenu *menu)
- {
-- // We don't set the menu property of the NSStatusItem here,
-- // as that would prevent us from receiving the action for the
-- // click, and we wouldn't be able to emit the activated signal.
-- // Instead we show the menu manually when the status item is
-- // clicked.
-- m_menu = static_cast(menu);
-+ m_statusItem.menu = menu ? static_cast(menu)->nsMenu() : nil;
-+
-+ if (m_statusItem.menu) {
-+ // When a menu is assigned, NSStatusBarButtonCell will intercept the mouse
-+ // down to pop up the menu, and we never see the NSStatusBarButton action.
-+ // To ensure we emit the 'activated' signal in both cases we detect when
-+ // menu starts tracking, which happens before the menu delegate is sent
-+ // the menuWillOpen callback we use to emit aboutToShow for the menu.
-+ [NSNotificationCenter.defaultCenter addObserver:m_delegate
-+ selector:@selector(statusItemMenuBeganTracking:)
-+ name:NSMenuDidBeginTrackingNotification
-+ object:m_statusItem.menu
-+ ];
-+ }
- }
-
- void QCocoaSystemTrayIcon::updateToolTip(const QString &toolTip)
-@@ -226,7 +234,7 @@ void QCocoaSystemTrayIcon::showMessage(const QString &title, const QString &mess
- }
- }
-
--void QCocoaSystemTrayIcon::statusItemClicked()
-+void QCocoaSystemTrayIcon::emitActivated()
- {
- auto *mouseEvent = NSApp.currentEvent;
-
-@@ -245,9 +253,6 @@ void QCocoaSystemTrayIcon::statusItemClicked()
- }
-
- emit activated(activationReason);
--
-- if (NSMenu *menu = m_menu ? m_menu->nsMenu() : nil)
-- QT_IGNORE_DEPRECATIONS([m_statusItem popUpStatusItemMenu:menu]);
- }
-
- QT_END_NAMESPACE
-@@ -270,7 +275,12 @@ QT_END_NAMESPACE
-
- - (void)statusItemClicked
- {
-- self.platformSystemTray->statusItemClicked();
-+ self.platformSystemTray->emitActivated();
-+}
-+
-+- (void)statusItemMenuBeganTracking:(NSNotification*)notification
-+{
-+ self.platformSystemTray->emitActivated();
- }
-
- - (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center shouldPresentNotification:(NSUserNotification *)notification
---
-2.39.2
-
diff --git a/libs/patches/qt-base-0006-iOS-Don-t-assume-screens-will-not-be-connected-befor.patch b/libs/patches/qt-base-0006-iOS-Don-t-assume-screens-will-not-be-connected-befor.patch
deleted file mode 100644
index b5c1ff9..0000000
--- a/libs/patches/qt-base-0006-iOS-Don-t-assume-screens-will-not-be-connected-befor.patch
+++ /dev/null
@@ -1,44 +0,0 @@
-From e28710e3f175663b030c00d75ee899a9a7b0cdd2 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?=
-Date: Thu, 15 Dec 2022 16:40:34 +0100
-Subject: iOS: Don't assume screens will not be connected before
- QIOSIntegration
-
-When an external screen is connected to an iPad, and the application is
-starting up on that screen, we will get a connection notification about
-that screen as part of the initial bootstrap of UIApplicationMain,
-before we call the user's main().
-
-Since we initialize and add all available screen on QIOSIntegration
-creation, we can just ignore the early connection notification.
-
-This avoids a crash, but the window will not show anything on the
-external screen, which is a separate issue.
-
-Pick-to: 6.5 6.4 6.2
-Fixes: QTBUG-106701
-Change-Id: I9e0a9736bf602277316bd004e0d01c640feaf319
-Reviewed-by: Volker Hilsheimer
-(cherry picked from commit dd49793bc3b4dd3808f0f24b717c442a5095db14)
----
- src/plugins/platforms/ios/qiosscreen.mm | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git x/qtbase/src/plugins/platforms/ios/qiosscreen.mm y/qtbase/src/plugins/platforms/ios/qiosscreen.mm
-index f144c00fb0a..3d660189af4 100644
---- x/qtbase/src/plugins/platforms/ios/qiosscreen.mm
-+++ y/qtbase/src/plugins/platforms/ios/qiosscreen.mm
-@@ -72,8 +72,8 @@ static QIOSScreen* qtPlatformScreenFor(UIScreen *uiScreen)
-
- + (void)screenConnected:(NSNotification*)notification
- {
-- Q_ASSERT_X(QIOSIntegration::instance(), Q_FUNC_INFO,
-- "Screen connected before QIOSIntegration creation");
-+ if (!QIOSIntegration::instance())
-+ return; // Will be added when QIOSIntegration is created
-
- QWindowSystemInterface::handleScreenAdded(new QIOSScreen([notification object]));
- }
---
-2.39.2
-
diff --git a/libs/patches/qt-base-0007-Ignore-removed-changed-screens-if-no-QIOSIntegration.patch b/libs/patches/qt-base-0007-Ignore-removed-changed-screens-if-no-QIOSIntegration.patch
deleted file mode 100644
index 5489207..0000000
--- a/libs/patches/qt-base-0007-Ignore-removed-changed-screens-if-no-QIOSIntegration.patch
+++ /dev/null
@@ -1,57 +0,0 @@
-From ae857fcf8415daafa6b77999dc8a44cd0e5ede7b Mon Sep 17 00:00:00 2001
-From: Jan Moeller
-Date: Thu, 6 Apr 2023 09:27:16 +0200
-Subject: Ignore removed/changed screens if no QIOSIntegration instance exists
-
-QIOSTracker registers itself as handlers for system notifications about
-changes of the screen environment. If no QIOSIntegration instance
-exists, newly detected screens are not added to the list of known
-screens (see screenConnected()). This, in turn, will result in a crash
-if a screen is disconnected and removed in screenDisconnected() as it
-is not known to qtPlatformScreenFor() and the function returns a
-nullptr.
-
-Consider the QIOSIntegration also whenever a screen is "changed". This
-is more of a safety measure do avoid crashes for unknown screens.
-
-This situation occurs if an iOS device is used to mirror the display
-via AirPlay and no actual QGuiApplication exists, e.g. Qt is only
-embedded in a Framework.
-
-Pick-to: 6.5 6.2
-Fixes: QTBUG-106701
-Change-Id: Id778fc5afa7c284b0536ee02b1ba2c10321cc5b1
-Reviewed-by: Volker Hilsheimer
-Reviewed-by: Lars Schmertmann
-(cherry picked from commit ffdfafc4b47b8267395370199073c292da33dd42)
----
- src/plugins/platforms/ios/qiosscreen.mm | 6 ++++++
- 1 file changed, 6 insertions(+)
-
-diff --git x/qtbase/src/plugins/platforms/ios/qiosscreen.mm y/qtbase/src/plugins/platforms/ios/qiosscreen.mm
-index 3d660189af4..e0216ce6526 100644
---- x/qtbase/src/plugins/platforms/ios/qiosscreen.mm
-+++ y/qtbase/src/plugins/platforms/ios/qiosscreen.mm
-@@ -80,6 +80,9 @@ static QIOSScreen* qtPlatformScreenFor(UIScreen *uiScreen)
-
- + (void)screenDisconnected:(NSNotification*)notification
- {
-+ if (!QIOSIntegration::instance())
-+ return;
-+
- QIOSScreen *screen = qtPlatformScreenFor([notification object]);
- Q_ASSERT_X(screen, Q_FUNC_INFO, "Screen disconnected that we didn't know about");
-
-@@ -88,6 +91,9 @@ static QIOSScreen* qtPlatformScreenFor(UIScreen *uiScreen)
-
- + (void)screenModeChanged:(NSNotification*)notification
- {
-+ if (!QIOSIntegration::instance())
-+ return;
-+
- QIOSScreen *screen = qtPlatformScreenFor([notification object]);
- Q_ASSERT_X(screen, Q_FUNC_INFO, "Screen changed that we didn't know about");
-
---
-2.39.2
-
diff --git a/libs/patches/qt-connectivity-0001-iOS-NFC-Always-ensure-timeout-after-session-invalida.patch b/libs/patches/qt-connectivity-0001-iOS-NFC-Always-ensure-timeout-after-session-invalida.patch
deleted file mode 100644
index f7da165..0000000
--- a/libs/patches/qt-connectivity-0001-iOS-NFC-Always-ensure-timeout-after-session-invalida.patch
+++ /dev/null
@@ -1,140 +0,0 @@
-From 720768b715d432aa084c9c15b994a396a89968a8 Mon Sep 17 00:00:00 2001
-From: Julian Greilich
-Date: Thu, 26 Jan 2023 19:19:21 +0100
-Subject: iOS NFC: Always ensure timeout after session invalidation
-
-iOS needs some time after invalidating a session before a new session
-can be started. Otherwise the NFC dialog of iOS will not show up.
-
-For restarting a session inside the iOS NearfieldManager, this was
-already solved with a timeout of 2 seconds.
-
-This commit fixes the case, that a user of the Nearfieldmanager
-restarts a session manually too fast.
-
-Change-Id: Ic91ad225a9cab13ba92523f33a19f44af68575a0
-Reviewed-by: Timur Pocheptsov
-(cherry picked from commit 849ba86ba9a073a266219b6a39786e20f4f3ed7b)
-(cherry picked from commit 5052cd14c28bbf0ff93c465a4e33bf1dbd48c7dd)
----
- src/nfc/qnearfieldmanager_ios.mm | 44 +++++++++++++++++++++----------
- src/nfc/qnearfieldmanager_ios_p.h | 5 +++-
- 2 files changed, 34 insertions(+), 15 deletions(-)
-
-diff --git x/qtconnectivity/src/nfc/qnearfieldmanager_ios.mm y/qtconnectivity/src/nfc/qnearfieldmanager_ios.mm
-index 6fd71451..a0651626 100644
---- x/qtconnectivity/src/nfc/qnearfieldmanager_ios.mm
-+++ y/qtconnectivity/src/nfc/qnearfieldmanager_ios.mm
-@@ -25,6 +25,10 @@ QNearFieldManagerPrivateImpl::QNearFieldManagerPrivateImpl()
- connect(this, &QNearFieldManagerPrivateImpl::didInvalidateWithError,
- this, &QNearFieldManagerPrivateImpl::onDidInvalidateWithError,
- Qt::QueuedConnection);
-+
-+ sessionTimer.setInterval(2000);
-+ sessionTimer.setSingleShot(true);
-+ connect(&sessionTimer, &QTimer::timeout, this, &QNearFieldManagerPrivateImpl::onSessionTimer);
- }
-
- QNearFieldManagerPrivateImpl::~QNearFieldManagerPrivateImpl()
-@@ -62,7 +66,7 @@ bool QNearFieldManagerPrivateImpl::startTargetDetection(QNearFieldTarget::Access
- if (@available(iOS 13, *))
- if (NFCTagReaderSession.readingAvailable) {
- detectionRunning = true;
-- startSession();
-+ scheduleSession();
- return true;
- }
- return false;
-@@ -71,16 +75,28 @@ bool QNearFieldManagerPrivateImpl::startTargetDetection(QNearFieldTarget::Access
-
- void QNearFieldManagerPrivateImpl::stopTargetDetection(const QString &errorMessage)
- {
-- if (detectionRunning) {
-- stopSession(errorMessage);
-- detectionRunning = false;
-- Q_EMIT targetDetectionStopped();
-- }
-+ if (!detectionRunning)
-+ return;
-+
-+ isSessionScheduled = false;
-+ stopSession(errorMessage);
-+ detectionRunning = false;
-+ Q_EMIT targetDetectionStopped();
- }
-
-+void QNearFieldManagerPrivateImpl::scheduleSession()
-+{
-+ if (sessionTimer.isActive()) {
-+ isSessionScheduled = true;
-+ return;
-+ }
-+
-+ startSession();
-+}
-
- void QNearFieldManagerPrivateImpl::startSession()
- {
-+ isSessionScheduled = false;
- if (detectionRunning)
- if (@available(iOS 13, *))
- [delegate startSession];
-@@ -132,17 +148,11 @@ void QNearFieldManagerPrivateImpl::onTargetLost(QNearFieldTargetPrivateImpl *tar
- void QNearFieldManagerPrivateImpl::onDidInvalidateWithError(bool doRestart)
- {
- clearTargets();
-+ sessionTimer.start();
-
- if (detectionRunning && doRestart)
- {
-- if (!isRestarting) {
-- isRestarting = true;
-- using namespace std::chrono_literals;
-- QTimer::singleShot(2s, this, [this](){
-- isRestarting = false;
-- startSession();
-- });
-- }
-+ scheduleSession();
- return;
- }
-
-@@ -150,4 +160,10 @@ void QNearFieldManagerPrivateImpl::onDidInvalidateWithError(bool doRestart)
- Q_EMIT targetDetectionStopped();
- }
-
-+void QNearFieldManagerPrivateImpl::onSessionTimer()
-+{
-+ if (isSessionScheduled)
-+ scheduleSession();
-+}
-+
- QT_END_NAMESPACE
-diff --git x/qtconnectivity/src/nfc/qnearfieldmanager_ios_p.h y/qtconnectivity/src/nfc/qnearfieldmanager_ios_p.h
-index 6aa1574e..b3668ff6 100644
---- x/qtconnectivity/src/nfc/qnearfieldmanager_ios_p.h
-+++ y/qtconnectivity/src/nfc/qnearfieldmanager_ios_p.h
-@@ -54,9 +54,11 @@ Q_SIGNALS:
- private:
- QT_MANGLE_NAMESPACE(QIosTagReaderDelegate) *delegate API_AVAILABLE(ios(13.0)) = nullptr;
- bool detectionRunning = false;
-- bool isRestarting = false;
-+ bool isSessionScheduled = false;
-+ QTimer sessionTimer;
- QList detectedTargets;
-
-+ void scheduleSession();
- void startSession();
- void stopSession(const QString &error);
- void clearTargets();
-@@ -65,6 +67,7 @@ private Q_SLOTS:
- void onTagDiscovered(void *target);
- void onTargetLost(QNearFieldTargetPrivateImpl *target);
- void onDidInvalidateWithError(bool doRestart);
-+ void onSessionTimer();
- };
-
-
---
-2.39.1
-
diff --git a/libs/patches/qt-declarative-0001-qmlformat-fix-omitting-some-comments-while-reformatt.patch b/libs/patches/qt-declarative-0001-qmlformat-fix-omitting-some-comments-while-reformatt.patch
deleted file mode 100644
index 7ad14c8..0000000
--- a/libs/patches/qt-declarative-0001-qmlformat-fix-omitting-some-comments-while-reformatt.patch
+++ /dev/null
@@ -1,102 +0,0 @@
-From f5b5a974f6ad854008c587c9494ae46785e21899 Mon Sep 17 00:00:00 2001
-From: Semih Yavuz
-Date: Wed, 18 Jan 2023 15:36:23 +0100
-Subject: qmlformat: fix omitting some comments while reformatting
-
-We rewrite comments associated to a node on the preVisit call
-(if they were marked as preComment), or postVisit( if comments were
-marked as postComments) of the reformatter. If the comment
-associated with a patternProperty kind of node, neither of these
-functions are called. Add missing call to previsit/postVist
-in the pattern property node visit.
-
-Pick-to: 6.4 6.5
-Fixes: QTBUG-109074
-Change-Id: If57968b3f5dbd83aa23dc2cd2bca3608ee841d49
-Reviewed-by: Sami Shalayel
-Reviewed-by: Ulf Hermann
-(cherry picked from commit 444d4f1f3f27a81996d9cbcc0642040b68728260)
----
- src/qmldom/qqmldomreformatter.cpp | 2 ++
- .../qmlformat/data/dontRemoveComments.formatted.qml | 13 +++++++++++++
- .../auto/qml/qmlformat/data/dontRemoveComments.qml | 13 +++++++++++++
- tests/auto/qml/qmlformat/tst_qmlformat.cpp | 3 +++
- 4 files changed, 31 insertions(+)
- create mode 100644 tests/auto/qml/qmlformat/data/dontRemoveComments.formatted.qml
- create mode 100644 tests/auto/qml/qmlformat/data/dontRemoveComments.qml
-
-diff --git x/qtdeclarative/src/qmldom/qqmldomreformatter.cpp y/qtdeclarative/src/qmldom/qqmldomreformatter.cpp
-index bb76f8f772..3dfacfc84e 100644
---- x/qtdeclarative/src/qmldom/qqmldomreformatter.cpp
-+++ y/qtdeclarative/src/qmldom/qqmldomreformatter.cpp
-@@ -301,6 +301,7 @@ protected:
- for (PatternPropertyList *it = ast; it; it = it->next) {
- PatternProperty *assignment = AST::cast(it->property);
- if (assignment) {
-+ preVisit(assignment);
- bool isStringLike = AST::cast(assignment->name)
- || cast(assignment->name);
- if (isStringLike)
-@@ -316,6 +317,7 @@ protected:
- accept(assignment->initializer);
- if (it->next)
- newLine();
-+ postVisit(assignment);
- continue;
- }
- PatternPropertyList *getterSetter = AST::cast(it->next);
-diff --git x/qtdeclarative/tests/auto/qml/qmlformat/data/dontRemoveComments.formatted.qml y/qtdeclarative/tests/auto/qml/qmlformat/data/dontRemoveComments.formatted.qml
-new file mode 100644
-index 0000000000..0c7a2829c9
---- /dev/null
-+++ y/qtdeclarative/tests/auto/qml/qmlformat/data/dontRemoveComments.formatted.qml
-@@ -0,0 +1,13 @@
-+Item {
-+ property var test: [{
-+ // Testing
-+ "foo": "bar"
-+ }]
-+
-+ onTestChanged: {
-+ fooBar(test, {
-+ // Testing
-+ "foo": "bar"
-+ });
-+ }
-+}
-diff --git x/qtdeclarative/tests/auto/qml/qmlformat/data/dontRemoveComments.qml y/qtdeclarative/tests/auto/qml/qmlformat/data/dontRemoveComments.qml
-new file mode 100644
-index 0000000000..1797834879
---- /dev/null
-+++ y/qtdeclarative/tests/auto/qml/qmlformat/data/dontRemoveComments.qml
-@@ -0,0 +1,13 @@
-+Item {
-+ property var test: [{
-+// Testing
-+ "foo": "bar"
-+ }]
-+
-+ onTestChanged: {
-+ fooBar(test, {
-+ // Testing
-+ "foo": "bar"
-+ });
-+ }
-+}
-diff --git x/qtdeclarative/tests/auto/qml/qmlformat/tst_qmlformat.cpp y/qtdeclarative/tests/auto/qml/qmlformat/tst_qmlformat.cpp
-index 9d7beb23a7..7755095acd 100644
---- x/qtdeclarative/tests/auto/qml/qmlformat/tst_qmlformat.cpp
-+++ y/qtdeclarative/tests/auto/qml/qmlformat/tst_qmlformat.cpp
-@@ -276,6 +276,9 @@ void TestQmlformat::testFormat_data()
- QTest::newRow("forWithLet")
- << "forWithLet.qml"
- << "forWithLet.formatted.qml" << QStringList {} << RunOption::OnCopy;
-+ QTest::newRow("dontRemoveComments")
-+ << "dontRemoveComments.qml"
-+ << "dontRemoveComments.formatted.qml" << QStringList {} << RunOption::OnCopy;
- }
-
- void TestQmlformat::testFormat()
---
-2.39.1
-
diff --git a/libs/patches/qt-scxml-0001-Make-qtdeclarative-optional-for-CONTAINER_SDK.patch b/libs/patches/qt-scxml-0001-Make-qtdeclarative-optional-for-CONTAINER_SDK.patch
deleted file mode 100644
index d345633..0000000
--- a/libs/patches/qt-scxml-0001-Make-qtdeclarative-optional-for-CONTAINER_SDK.patch
+++ /dev/null
@@ -1,23 +0,0 @@
-From 5a844a0c1b5e9c1b9fb94831afc0724f5deaa7dd Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Andr=C3=A9=20Klitzing?=
-Date: Tue, 12 Apr 2022 10:21:19 +0200
-Subject: Make qtdeclarative optional for CONTAINER_SDK
-
-Change-Id: Ia25b91ea5e3716aef4cb096de1052267b70e343d
----
- dependencies.yaml | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git x/qtscxml/dependencies.yaml y/qtscxml/dependencies.yaml
-index ee6f92e..7375551 100644
---- x/qtscxml/dependencies.yaml
-+++ y/qtscxml/dependencies.yaml
-@@ -4,4 +4,4 @@ dependencies:
- required: true
- ../qtdeclarative:
- ref: a514640b2a38391fceaaac3ca01b390ad3d62f31
-- required: true
-+ required: false
---
-2.38.1
-
diff --git a/libs/patches/qt-scxml-0002-Disable-qtscxml-library.patch b/libs/patches/qt-scxml-0002-Disable-qtscxml-library.patch
deleted file mode 100644
index c311a71..0000000
--- a/libs/patches/qt-scxml-0002-Disable-qtscxml-library.patch
+++ /dev/null
@@ -1,38 +0,0 @@
-From ee68d7d67358f92c87720c2f740322fb03ad8299 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Andr=C3=A9=20Klitzing?=
-Date: Tue, 12 Apr 2022 11:39:12 +0200
-Subject: Disable qtscxml library
-
----
- src/CMakeLists.txt | 4 ++--
- tools/CMakeLists.txt | 2 +-
- 2 files changed, 3 insertions(+), 3 deletions(-)
-
-diff --git x/qtscxml/src/CMakeLists.txt y/qtscxml/src/CMakeLists.txt
-index f1b7c2b..7e28acc 100644
---- x/qtscxml/src/CMakeLists.txt
-+++ y/qtscxml/src/CMakeLists.txt
-@@ -1,8 +1,8 @@
-
--add_subdirectory(scxml)
-+#add_subdirectory(scxml)
- add_subdirectory(statemachine)
- if(TARGET Qt::Qml)
- add_subdirectory(statemachineqml)
-- add_subdirectory(scxmlqml)
-+# add_subdirectory(scxmlqml)
- endif()
- add_subdirectory(plugins)
-diff --git x/qtscxml/tools/CMakeLists.txt y/qtscxml/tools/CMakeLists.txt
-index 9726a78..956f904 100644
---- x/qtscxml/tools/CMakeLists.txt
-+++ y/qtscxml/tools/CMakeLists.txt
-@@ -1,4 +1,4 @@
-
- if(QT_FEATURE_commandlineparser)
-- add_subdirectory(qscxmlc)
-+ #add_subdirectory(qscxmlc)
- endif()
---
-2.38.1
-
diff --git a/libs/patches/qt-tools-0001-Disable-linguist-but-keep-translation-tools.patch b/libs/patches/qt-tools-0001-Disable-linguist-but-keep-translation-tools.patch
deleted file mode 100644
index 54eda29..0000000
--- a/libs/patches/qt-tools-0001-Disable-linguist-but-keep-translation-tools.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-From 125584904a64497ae50b227ef326e0fc12683a4b Mon Sep 17 00:00:00 2001
-From: Jan Moeller
-Date: Mon, 14 Feb 2022 13:46:46 +0100
-Subject: Disable linguist but keep translation tools
-
-Change-Id: I1c54eb0e7bb86ec0861b54b5abe753c86bb57dd9
----
- src/linguist/CMakeLists.txt | 3 ---
- 1 file changed, 3 deletions(-)
-
-diff --git x/qttools/src/linguist/CMakeLists.txt y/qttools/src/linguist/CMakeLists.txt
-index 16ff9f559..fde23b0c4 100644
---- x/qttools/src/linguist/CMakeLists.txt
-+++ y/qttools/src/linguist/CMakeLists.txt
-@@ -14,9 +14,6 @@ add_subdirectory(lrelease)
- add_subdirectory(lrelease-pro)
- add_subdirectory(lupdate)
- add_subdirectory(lupdate-pro)
--if(QT_FEATURE_process AND QT_FEATURE_pushbutton AND QT_FEATURE_toolbutton AND TARGET Qt::Widgets AND NOT no-png)
-- add_subdirectory(linguist)
--endif()
-
- # special case begin
- # Create a fake module that would emulate the Qt5::LinguistTools CMake Config package
---
-2.38.1
-
diff --git a/libs/patches/qt-tools-0002-Revert-Move-UiTools-and-UiPlugin-modules-to-a-upper-.patch b/libs/patches/qt-tools-0002-Revert-Move-UiTools-and-UiPlugin-modules-to-a-upper-.patch
deleted file mode 100644
index ef7852d..0000000
--- a/libs/patches/qt-tools-0002-Revert-Move-UiTools-and-UiPlugin-modules-to-a-upper-.patch
+++ /dev/null
@@ -1,3235 +0,0 @@
-From d6c550d3ef01a50e100acd4fa44a2d6fbd376cbb Mon Sep 17 00:00:00 2001
-From: Lars Schmertmann
-Date: Wed, 9 Nov 2022 09:49:38 +0100
-Subject: Revert "Move UiTools and UiPlugin modules to a upper level
- sub-directory"
-
-This partially reverts commit 6af882fa2f45f73ec2ba4066d5ae3ad072d0c5ee.
-
-Change-Id: I247e2189577b74d813a210ace0b49d672a90975e
----
- src/CMakeLists.txt | 5 -
- src/designer/src/CMakeLists.txt | 2 +
- .../src/designer/doc/qtdesigner.qdocconf | 4 +-
- src/designer/src/uiplugin/CMakeLists.txt | 27 +
- src/designer/src/uiplugin/customwidget.h | 62 ++
- src/designer/src/uiplugin/customwidget.qdoc | 269 ++++++
- .../src/uiplugin/qdesignerexportwidget.h | 24 +
- src/designer/src/uitools/CMakeLists.txt | 47 +
- src/designer/src/uitools/qtuitoolsglobal.h | 24 +
- src/designer/src/uitools/quiloader.cpp | 914 ++++++++++++++++++
- src/designer/src/uitools/quiloader.h | 61 ++
- src/designer/src/uitools/quiloader_p.h | 77 ++
- src/uiplugin/CMakeLists.txt | 27 -
- src/uiplugin/customwidget.h | 62 --
- src/uiplugin/customwidget.qdoc | 269 ------
- src/uiplugin/qdesignerexportwidget.h | 24 -
- src/uitools/CMakeLists.txt | 47 -
- src/uitools/qtuitoolsglobal.h | 24 -
- src/uitools/quiloader.cpp | 914 ------------------
- src/uitools/quiloader.h | 61 --
- src/uitools/quiloader_p.h | 77 --
- sync.profile | 4 +-
- 22 files changed, 1511 insertions(+), 1514 deletions(-)
- create mode 100644 src/designer/src/uiplugin/CMakeLists.txt
- create mode 100644 src/designer/src/uiplugin/customwidget.h
- create mode 100644 src/designer/src/uiplugin/customwidget.qdoc
- create mode 100644 src/designer/src/uiplugin/qdesignerexportwidget.h
- create mode 100644 src/designer/src/uitools/CMakeLists.txt
- create mode 100644 src/designer/src/uitools/qtuitoolsglobal.h
- create mode 100644 src/designer/src/uitools/quiloader.cpp
- create mode 100644 src/designer/src/uitools/quiloader.h
- create mode 100644 src/designer/src/uitools/quiloader_p.h
- delete mode 100644 src/uiplugin/CMakeLists.txt
- delete mode 100644 src/uiplugin/customwidget.h
- delete mode 100644 src/uiplugin/customwidget.qdoc
- delete mode 100644 src/uiplugin/qdesignerexportwidget.h
- delete mode 100644 src/uitools/CMakeLists.txt
- delete mode 100644 src/uitools/qtuitoolsglobal.h
- delete mode 100644 src/uitools/quiloader.cpp
- delete mode 100644 src/uitools/quiloader.h
- delete mode 100644 src/uitools/quiloader_p.h
-
-diff --git x/qttools/src/CMakeLists.txt y/qttools/src/CMakeLists.txt
-index b42cd4946..cb0c21a70 100644
---- x/qttools/src/CMakeLists.txt
-+++ y/qttools/src/CMakeLists.txt
-@@ -21,11 +21,6 @@ qt_exclude_tool_directories_from_default_target(
- qt_feature_evaluate_features("${CMAKE_CURRENT_SOURCE_DIR}/../configure.cmake")
- # special case end
-
--if(TARGET Qt::Widgets)
-- add_subdirectory(uiplugin)
-- add_subdirectory(uitools)
--endif()
--
- add_subdirectory(global) # special case add as first directory
- if(QT_FEATURE_linguist)
- add_subdirectory(linguist)
-diff --git x/qttools/src/designer/src/CMakeLists.txt y/qttools/src/designer/src/CMakeLists.txt
-index 31fc1734e..32fb45160 100644
---- x/qttools/src/designer/src/CMakeLists.txt
-+++ y/qttools/src/designer/src/CMakeLists.txt
-@@ -8,6 +8,8 @@ qt_exclude_tool_directories_from_default_target(
- plugins
- )
-
-+add_subdirectory(uiplugin)
-+add_subdirectory(uitools)
- if(QT_FEATURE_process)
- add_subdirectory(lib)
- add_subdirectory(components)
-diff --git x/qttools/src/designer/src/designer/doc/qtdesigner.qdocconf y/qttools/src/designer/src/designer/doc/qtdesigner.qdocconf
-index 75c8c78dd..964fb47ed 100644
---- x/qttools/src/designer/src/designer/doc/qtdesigner.qdocconf
-+++ y/qttools/src/designer/src/designer/doc/qtdesigner.qdocconf
-@@ -28,11 +28,11 @@ qhp.QtDesigner.subprojects.classes.sortPages = true
- language = Cpp
-
- headerdirs += .. \
-- ../../../../uiplugin \
-+ ../../uiplugin \
- ../../lib
-
- sourcedirs = .. \
-- ../../../../uiplugin \
-+ ../../uiplugin \
- ../../lib
-
- exampledirs = ../../../../../examples/designer \
-diff --git x/qttools/src/designer/src/uiplugin/CMakeLists.txt y/qttools/src/designer/src/uiplugin/CMakeLists.txt
-new file mode 100644
-index 000000000..4fedf8e33
---- /dev/null
-+++ y/qttools/src/designer/src/uiplugin/CMakeLists.txt
-@@ -0,0 +1,27 @@
-+# Generated from uiplugin.pro.
-+
-+#####################################################################
-+## UiPlugin Module:
-+#####################################################################
-+
-+qt_internal_add_module(UiPlugin
-+ NO_PRIVATE_MODULE
-+ HEADER_MODULE
-+ QMAKE_MODULE_CONFIG designer_defines
-+ PUBLIC_LIBRARIES
-+ Qt::Core
-+ Qt::Gui
-+ Qt::Widgets
-+)
-+
-+# special case begin
-+set(is_plugin "$")
-+target_compile_definitions(
-+ UiPlugin
-+ INTERFACE
-+ $<$:QDESIGNER_EXPORT_WIDGETS>
-+)
-+# special case end
-+
-+#### Keys ignored in scope 1:.:.:uiplugin.pro::
-+# MODULE_CONFIG = "designer_defines"
-diff --git x/qttools/src/designer/src/uiplugin/customwidget.h y/qttools/src/designer/src/uiplugin/customwidget.h
-new file mode 100644
-index 000000000..2a47a32f8
---- /dev/null
-+++ y/qttools/src/designer/src/uiplugin/customwidget.h
-@@ -0,0 +1,62 @@
-+// Copyright (C) 2016 The Qt Company Ltd.
-+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-+
-+#ifndef CUSTOMWIDGET_H
-+#define CUSTOMWIDGET_H
-+
-+#include
-+#include
-+#include
-+
-+QT_BEGIN_NAMESPACE
-+
-+class QWidget;
-+class QDesignerFormEditorInterface;
-+
-+class QDesignerCustomWidgetInterface
-+{
-+public:
-+ virtual ~QDesignerCustomWidgetInterface() = default; // ### FIXME: weak vtable
-+
-+ virtual QString name() const = 0;
-+ virtual QString group() const = 0;
-+ virtual QString toolTip() const = 0;
-+ virtual QString whatsThis() const = 0;
-+ virtual QString includeFile() const = 0;
-+ virtual QIcon icon() const = 0;
-+
-+ virtual bool isContainer() const = 0;
-+
-+ virtual QWidget *createWidget(QWidget *parent) = 0;
-+
-+ virtual bool isInitialized() const { return false; }
-+ virtual void initialize(QDesignerFormEditorInterface *core) { Q_UNUSED(core); }
-+
-+ virtual QString domXml() const
-+ {
-+ return QString::fromUtf8("")
-+ .arg(name()).arg(name().toLower());
-+ }
-+
-+ virtual QString codeTemplate() const { return QString(); }
-+};
-+
-+#define QDesignerCustomWidgetInterface_iid "org.qt-project.QDesignerCustomWidgetInterface"
-+
-+Q_DECLARE_INTERFACE(QDesignerCustomWidgetInterface, QDesignerCustomWidgetInterface_iid)
-+
-+class QDesignerCustomWidgetCollectionInterface
-+{
-+public:
-+ virtual ~QDesignerCustomWidgetCollectionInterface() = default; // ### FIXME: weak vtable
-+
-+ virtual QList customWidgets() const = 0;
-+};
-+
-+#define QDesignerCustomWidgetCollectionInterface_iid "org.qt-project.Qt.QDesignerCustomWidgetCollectionInterface"
-+
-+Q_DECLARE_INTERFACE(QDesignerCustomWidgetCollectionInterface, QDesignerCustomWidgetCollectionInterface_iid)
-+
-+QT_END_NAMESPACE
-+
-+#endif // CUSTOMWIDGET_H
-diff --git x/qttools/src/designer/src/uiplugin/customwidget.qdoc y/qttools/src/designer/src/uiplugin/customwidget.qdoc
-new file mode 100644
-index 000000000..557e9a454
---- /dev/null
-+++ y/qttools/src/designer/src/uiplugin/customwidget.qdoc
-@@ -0,0 +1,269 @@
-+// Copyright (C) 2016 The Qt Company Ltd.
-+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
-+
-+/*!
-+ \class QDesignerCustomWidgetInterface
-+
-+ \brief The QDesignerCustomWidgetInterface class enables Qt Designer
-+ to access and construct custom widgets.
-+
-+ \inmodule QtDesigner
-+
-+ QDesignerCustomWidgetInterface provides a custom widget with an
-+ interface. The class contains a set of functions that must be subclassed
-+ to return basic information about the widget, such as its class name and
-+ the name of its header file. Other functions must be implemented to
-+ initialize the plugin when it is loaded, and to construct instances of
-+ the custom widget for \QD to use.
-+
-+ When implementing a custom widget you must subclass
-+ QDesignerCustomWidgetInterface to expose your widget to \QD. For
-+ example, this is the declaration for the plugin used in the
-+ \l{Custom Widget Plugin Example}{Custom Widget Plugin example} that
-+ enables an analog clock custom widget to be used by \QD:
-+
-+ \snippet customwidgetplugin/customwidgetplugin.h 0
-+
-+ Note that the only part of the class definition that is specific
-+ to this particular custom widget is the class name. In addition,
-+ since we are implementing an interface, we must ensure that it's
-+ made known to the meta object system using the Q_INTERFACES()
-+ macro. This enables \QD to use the qobject_cast() function to
-+ query for supported interfaces using nothing but a QObject
-+ pointer.
-+
-+ After \QD loads a custom widget plugin, it calls the interface's
-+ initialize() function to enable it to set up any resources that it
-+ may need. This function is called with a QDesignerFormEditorInterface
-+ parameter that provides the plugin with a gateway to all of \QD's API.
-+
-+ \QD constructs instances of the custom widget by calling the plugin's
-+ createWidget() function with a suitable parent widget. Plugins must
-+ construct and return an instance of a custom widget with the specified
-+ parent widget.
-+
-+ Exporting your custom widget plugin to \QD using the Q_PLUGIN_METADATA()
-+ macro. For example, if a library called \c libcustomwidgetplugin.so
-+ (on Unix) or \c libcustomwidget.dll (on Windows) contains a widget
-+ class called \c MyCustomWidget, we can export it by adding the
-+ following line to the file containing the plugin header:
-+
-+ \snippet plugins/doc_src_qtdesigner.cpp 14
-+
-+ This macro ensures that \QD can access and construct the custom widget.
-+ Without this macro, there is no way for \QD to use it.
-+
-+ When implementing a custom widget plugin, you build it as a
-+ separate library. If you want to include several custom widget
-+ plugins in the same library, you must in addition subclass
-+ QDesignerCustomWidgetCollectionInterface.
-+
-+ \warning If your custom widget plugin contains QVariant
-+ properties, be aware that only the following \l
-+ {QVariant::Type}{types} are supported:
-+
-+ \list
-+ \li QVariant::ByteArray
-+ \li QVariant::Bool
-+ \li QVariant::Color
-+ \li QVariant::Cursor
-+ \li QVariant::Date
-+ \li QVariant::DateTime
-+ \li QVariant::Double
-+ \li QVariant::Int
-+ \li QVariant::Point
-+ \li QVariant::Rect
-+ \li QVariant::Size
-+ \li QVariant::SizePolicy
-+ \li QVariant::String
-+ \li QVariant::Time
-+ \li QVariant::UInt
-+ \endlist
-+
-+ For a complete example using the QDesignerCustomWidgetInterface
-+ class, see the \l {customwidgetplugin}{Custom Widget
-+ Example}. The example shows how to create a custom widget plugin
-+ for \QD.
-+
-+ \sa QDesignerCustomWidgetCollectionInterface, {Creating Custom Widgets for Qt Designer}
-+*/
-+
-+/*!
-+ \fn QDesignerCustomWidgetInterface::~QDesignerCustomWidgetInterface()
-+
-+ Destroys the custom widget interface.
-+*/
-+
-+/*!
-+ \fn QString QDesignerCustomWidgetInterface::name() const
-+
-+ Returns the class name of the custom widget supplied by the interface.
-+
-+ The name returned \e must be identical to the class name used for the
-+ custom widget.
-+*/
-+
-+/*!
-+ \fn QString QDesignerCustomWidgetInterface::group() const
-+
-+ Returns the name of the group to which the custom widget belongs.
-+*/
-+
-+/*!
-+ \fn QString QDesignerCustomWidgetInterface::toolTip() const
-+
-+ Returns a short description of the widget that can be used by \QD
-+ in a tool tip.
-+*/
-+
-+/*!
-+ \fn QString QDesignerCustomWidgetInterface::whatsThis() const
-+
-+ Returns a description of the widget that can be used by \QD in
-+ "What's This?" help for the widget.
-+*/
-+
-+/*!
-+ \fn QString QDesignerCustomWidgetInterface::includeFile() const
-+
-+ Returns the path to the include file that \l uic uses when
-+ creating code for the custom widget.
-+*/
-+
-+/*!
-+ \fn QIcon QDesignerCustomWidgetInterface::icon() const
-+
-+ Returns the icon used to represent the custom widget in \QD's
-+ widget box.
-+*/
-+
-+/*!
-+ \fn bool QDesignerCustomWidgetInterface::isContainer() const
-+
-+ Returns true if the custom widget is intended to be used as a
-+ container; otherwise returns false.
-+
-+ Most custom widgets are not used to hold other widgets, so their
-+ implementations of this function will return false, but custom
-+ containers will return true to ensure that they behave correctly
-+ in \QD.
-+*/
-+
-+/*!
-+ \fn QWidget *QDesignerCustomWidgetInterface::createWidget(QWidget *parent)
-+
-+ Returns a new instance of the custom widget, with the given \a
-+ parent.
-+*/
-+
-+/*!
-+ \fn bool QDesignerCustomWidgetInterface::isInitialized() const
-+
-+ Returns true if the widget has been initialized; otherwise returns
-+ false.
-+
-+ \sa initialize()
-+*/
-+
-+/*!
-+ \fn void QDesignerCustomWidgetInterface::initialize(QDesignerFormEditorInterface *formEditor)
-+
-+ Initializes the widget for use with the specified \a formEditor
-+ interface.
-+
-+ \sa isInitialized()
-+*/
-+
-+/*!
-+ \fn QString QDesignerCustomWidgetInterface::domXml() const
-+
-+ Returns the XML that is used to describe the custom widget's
-+ properties to \QD.
-+*/
-+
-+/*!
-+ \fn QString QDesignerCustomWidgetInterface::codeTemplate() const
-+
-+ This function is reserved for future use by \QD.
-+
-+ \omit
-+ Returns the code template that \QD includes in forms that contain
-+ the custom widget when they are saved.
-+ \endomit
-+*/
-+
-+/*!
-+ \macro QDESIGNER_WIDGET_EXPORT
-+ \relates QDesignerCustomWidgetInterface
-+ \since 4.1
-+
-+ This macro is used when defining custom widgets to ensure that they are
-+ correctly exported from plugins for use with \QD.
-+
-+ On some platforms, the symbols required by \QD to create new widgets
-+ are removed from plugins by the build system, making them unusable.
-+ Using this macro ensures that the symbols are retained on those platforms,
-+ and has no side effects on other platforms.
-+
-+ For example, the \l{worldtimeclockplugin}{World Time Clock Plugin}
-+ example exports a custom widget class with the following declaration:
-+
-+ \snippet worldtimeclockplugin/worldtimeclock.h 0
-+ \dots
-+ \snippet worldtimeclockplugin/worldtimeclock.h 2
-+
-+ \sa {Creating Custom Widgets for Qt Designer}
-+*/
-+
-+
-+
-+
-+
-+/*!
-+ \class QDesignerCustomWidgetCollectionInterface
-+
-+ \brief The QDesignerCustomWidgetCollectionInterface class allows
-+ you to include several custom widgets in one single library.
-+
-+ \inmodule QtDesigner
-+
-+ When implementing a custom widget plugin, you build it as a
-+ separate library. If you want to include several custom widget
-+ plugins in the same library, you must in addition subclass
-+ QDesignerCustomWidgetCollectionInterface.
-+
-+ QDesignerCustomWidgetCollectionInterface contains one single
-+ function returning a list of the collection's
-+ QDesignerCustomWidgetInterface objects. For example, if you have
-+ several custom widgets \c CustomWidgetOne, \c CustomWidgetTwo and
-+ \c CustomWidgetThree, the class definition may look like this:
-+
-+ \snippet plugins/doc_src_qtdesigner.cpp 12
-+
-+ In the class constructor you add the interfaces to your custom
-+ widgets to the list which you return in the customWidgets()
-+ function:
-+
-+ \snippet plugins/doc_src_qtdesigner.cpp 13
-+
-+ Note that instead of exporting each custom widget plugin using the
-+ Q_PLUGIN_METADATA() macro, you export the entire collection. The
-+ Q_PLUGIN_METADATA() macro ensures that \QD can access and construct
-+ the custom widgets. Without this macro, there is no way for \QD to
-+ use them.
-+
-+ \sa QDesignerCustomWidgetInterface, {Creating Custom Widgets for
-+ Qt Designer}
-+*/
-+
-+/*!
-+ \fn QDesignerCustomWidgetCollectionInterface::~QDesignerCustomWidgetCollectionInterface() {
-+
-+ Destroys the custom widget collection interface.
-+*/
-+
-+/*!
-+ \fn QList QDesignerCustomWidgetCollectionInterface::customWidgets() const
-+
-+ Returns a list of interfaces to the collection's custom widgets.
-+*/
-diff --git x/qttools/src/designer/src/uiplugin/qdesignerexportwidget.h y/qttools/src/designer/src/uiplugin/qdesignerexportwidget.h
-new file mode 100644
-index 000000000..d90e9b217
---- /dev/null
-+++ y/qttools/src/designer/src/uiplugin/qdesignerexportwidget.h
-@@ -0,0 +1,24 @@
-+// Copyright (C) 2016 The Qt Company Ltd.
-+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-+
-+#ifndef QDESIGNEREXPORTWIDGET_H
-+#define QDESIGNEREXPORTWIDGET_H
-+
-+#include
-+
-+QT_BEGIN_NAMESPACE
-+
-+#if 0
-+// pragma for syncqt, don't remove.
-+#pragma qt_class(QDesignerExportWidget)
-+#endif
-+
-+#if defined(QDESIGNER_EXPORT_WIDGETS)
-+# define QDESIGNER_WIDGET_EXPORT Q_DECL_EXPORT
-+#else
-+# define QDESIGNER_WIDGET_EXPORT Q_DECL_IMPORT
-+#endif
-+
-+QT_END_NAMESPACE
-+
-+#endif //QDESIGNEREXPORTWIDGET_H
-diff --git x/qttools/src/designer/src/uitools/CMakeLists.txt y/qttools/src/designer/src/uitools/CMakeLists.txt
-new file mode 100644
-index 000000000..5306fcbd5
---- /dev/null
-+++ y/qttools/src/designer/src/uitools/CMakeLists.txt
-@@ -0,0 +1,47 @@
-+# Generated from uitools.pro.
-+
-+#####################################################################
-+## UiTools Module:
-+#####################################################################
-+
-+qt_internal_add_module(UiTools
-+ SOURCES
-+ ../lib/uilib/abstractformbuilder.cpp ../lib/uilib/abstractformbuilder.h
-+ ../lib/uilib/formbuilder.cpp ../lib/uilib/formbuilder.h
-+ ../lib/uilib/formbuilderextra.cpp ../lib/uilib/formbuilderextra_p.h
-+ ../lib/uilib/properties.cpp ../lib/uilib/properties_p.h
-+ ../lib/uilib/resourcebuilder.cpp ../lib/uilib/resourcebuilder_p.h
-+ ../lib/uilib/textbuilder.cpp ../lib/uilib/textbuilder_p.h
-+ ../lib/uilib/ui4.cpp ../lib/uilib/ui4_p.h
-+ quiloader.cpp quiloader.h
-+ DEFINES
-+ QFORMINTERNAL_NAMESPACE
-+ QT_DESIGNER
-+ QT_DESIGNER_STATIC
-+ QT_USE_QSTRINGBUILDER
-+ INCLUDE_DIRECTORIES
-+ ../lib/uilib
-+ LIBRARIES
-+ Qt::UiPlugin
-+ PUBLIC_LIBRARIES
-+ Qt::Core
-+ Qt::Gui
-+ Qt::Widgets
-+)
-+
-+## Scopes:
-+#####################################################################
-+
-+qt_internal_extend_target(UiTools CONDITION TARGET Qt::OpenGLWidgets
-+ PUBLIC_LIBRARIES
-+ Qt::OpenGLWidgets
-+)
-+
-+qt_internal_extend_target(UiTools CONDITION QT_FEATURE_opengl
-+ LIBRARIES
-+ Qt::OpenGL
-+)
-+qt_internal_add_docs(UiTools
-+ doc/qtuitools.qdocconf
-+)
-+
-diff --git x/qttools/src/designer/src/uitools/qtuitoolsglobal.h y/qttools/src/designer/src/uitools/qtuitoolsglobal.h
-new file mode 100644
-index 000000000..a2f967dee
---- /dev/null
-+++ y/qttools/src/designer/src/uitools/qtuitoolsglobal.h
-@@ -0,0 +1,24 @@
-+// Copyright (C) 2020 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
-+
-+#ifndef QTUITOOLSGLOBAL_H
-+#define QTUITOOLSGLOBAL_H
-+
-+#include
-+
-+QT_BEGIN_NAMESPACE
-+
-+#ifndef QT_STATIC
-+# if defined(QT_BUILD_UITOOLS_LIB)
-+# define Q_UITOOLS_EXPORT Q_DECL_EXPORT
-+# else
-+# define Q_UITOOLS_EXPORT Q_DECL_IMPORT
-+# endif
-+#else
-+# define Q_UITOOLS_EXPORT
-+#endif
-+
-+QT_END_NAMESPACE
-+
-+#endif // QTUITOOLSGLOBAL_H
-+
-diff --git x/qttools/src/designer/src/uitools/quiloader.cpp y/qttools/src/designer/src/uitools/quiloader.cpp
-new file mode 100644
-index 000000000..a06d4717b
---- /dev/null
-+++ y/qttools/src/designer/src/uitools/quiloader.cpp
-@@ -0,0 +1,914 @@
-+// Copyright (C) 2020 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
-+
-+
-+#include "quiloader.h"
-+#include "quiloader_p.h"
-+
-+#include
-+
-+#include
-+#include
-+#include
-+#include
-+
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+
-+#include
-+#include
-+
-+#include
-+#include
-+#include
-+#include
-+#include
-+
-+QT_BEGIN_NAMESPACE
-+
-+typedef QMap widget_map;
-+Q_GLOBAL_STATIC(widget_map, g_widgets)
-+
-+class QUiLoader;
-+class QUiLoaderPrivate;
-+
-+#ifndef QT_NO_DATASTREAM
-+// QUiTranslatableStringValue must be streamable since they become part of the QVariant-based
-+// mime data when dragging items in views with QAbstractItemView::InternalMove.
-+QDataStream &operator<<(QDataStream &out, const QUiTranslatableStringValue &s)
-+{
-+ out << s.qualifier() << s.value();
-+ return out;
-+}
-+
-+QDataStream &operator>>(QDataStream &in, QUiTranslatableStringValue &s)
-+{
-+ QByteArray qualifier, value;
-+ in >> qualifier >> value;
-+ s.setQualifier(qualifier);
-+ s.setValue(value);
-+ return in;
-+}
-+#endif // QT_NO_DATASTREAM
-+
-+QString QUiTranslatableStringValue::translate(const QByteArray &className, bool idBased) const
-+{
-+ return idBased
-+ ? qtTrId(m_qualifier.constData())
-+ : QCoreApplication::translate(className.constData(), m_value.constData(), m_qualifier.constData());
-+}
-+
-+#ifdef QFORMINTERNAL_NAMESPACE
-+namespace QFormInternal
-+{
-+#endif
-+
-+class TranslatingTextBuilder : public QTextBuilder
-+{
-+public:
-+ explicit TranslatingTextBuilder(bool idBased, bool trEnabled, const QByteArray &className) :
-+ m_idBased(idBased), m_trEnabled(trEnabled), m_className(className) {}
-+
-+ QVariant loadText(const DomProperty *icon) const override;
-+
-+ QVariant toNativeValue(const QVariant &value) const override;
-+
-+ bool idBased() const { return m_idBased; }
-+
-+private:
-+ bool m_idBased;
-+ bool m_trEnabled;
-+ QByteArray m_className;
-+};
-+
-+QVariant TranslatingTextBuilder::loadText(const DomProperty *text) const
-+{
-+ const DomString *str = text->elementString();
-+ if (!str)
-+ return QVariant();
-+ if (str->hasAttributeNotr()) {
-+ const QString notr = str->attributeNotr();
-+ if (notr == QStringLiteral("true") || notr == QStringLiteral("yes"))
-+ return QVariant::fromValue(str->text());
-+ }
-+ QUiTranslatableStringValue strVal;
-+ strVal.setValue(str->text().toUtf8());
-+ if (m_idBased)
-+ strVal.setQualifier(str->attributeId().toUtf8());
-+ else if (str->hasAttributeComment())
-+ strVal.setQualifier(str->attributeComment().toUtf8());
-+ return QVariant::fromValue(strVal);
-+}
-+
-+QVariant TranslatingTextBuilder::toNativeValue(const QVariant &value) const
-+{
-+ if (value.canConvert()) {
-+ QUiTranslatableStringValue tsv = qvariant_cast(value);
-+ if (!m_trEnabled)
-+ return QString::fromUtf8(tsv.value().constData());
-+ return QVariant::fromValue(tsv.translate(m_className, m_idBased));
-+ }
-+ if (value.canConvert())
-+ return QVariant::fromValue(qvariant_cast(value));
-+ return value;
-+}
-+
-+// This is "exported" to linguist
-+const QUiItemRolePair qUiItemRoles[] = {
-+ { Qt::DisplayRole, Qt::DisplayPropertyRole },
-+#if QT_CONFIG(tooltip)
-+ { Qt::ToolTipRole, Qt::ToolTipPropertyRole },
-+#endif
-+#if QT_CONFIG(statustip)
-+ { Qt::StatusTipRole, Qt::StatusTipPropertyRole },
-+#endif
-+#if QT_CONFIG(whatsthis)
-+ { Qt::WhatsThisRole, Qt::WhatsThisPropertyRole },
-+#endif
-+ { -1 , -1 }
-+};
-+
-+static void recursiveReTranslate(QTreeWidgetItem *item, const QByteArray &class_name, bool idBased)
-+{
-+ const QUiItemRolePair *irs = qUiItemRoles;
-+
-+ int cnt = item->columnCount();
-+ for (int i = 0; i < cnt; ++i) {
-+ for (unsigned j = 0; irs[j].shadowRole >= 0; j++) {
-+ QVariant v = item->data(i, irs[j].shadowRole);
-+ if (v.isValid()) {
-+ QUiTranslatableStringValue tsv = qvariant_cast(v);
-+ item->setData(i, irs[j].realRole, tsv.translate(class_name, idBased));
-+ }
-+ }
-+ }
-+
-+ cnt = item->childCount();
-+ for (int i = 0; i < cnt; ++i)
-+ recursiveReTranslate(item->child(i), class_name, idBased);
-+}
-+
-+template
-+static void reTranslateWidgetItem(T *item, const QByteArray &class_name, bool idBased)
-+{
-+ const QUiItemRolePair *irs = qUiItemRoles;
-+
-+ for (unsigned j = 0; irs[j].shadowRole >= 0; j++) {
-+ QVariant v = item->data(irs[j].shadowRole);
-+ if (v.isValid()) {
-+ QUiTranslatableStringValue tsv = qvariant_cast(v);
-+ item->setData(irs[j].realRole, tsv.translate(class_name, idBased));
-+ }
-+ }
-+}
-+
-+static void reTranslateTableItem(QTableWidgetItem *item, const QByteArray &class_name, bool idBased)
-+{
-+ if (item)
-+ reTranslateWidgetItem(item, class_name, idBased);
-+}
-+
-+#define RETRANSLATE_SUBWIDGET_PROP(mainWidget, setter, propName) \
-+ do { \
-+ QVariant v = mainWidget->widget(i)->property(propName); \
-+ if (v.isValid()) { \
-+ QUiTranslatableStringValue tsv = qvariant_cast(v); \
-+ mainWidget->setter(i, tsv.translate(m_className, m_idBased)); \
-+ } \
-+ } while (0)
-+
-+class TranslationWatcher: public QObject
-+{
-+ Q_OBJECT
-+
-+public:
-+ explicit TranslationWatcher(QObject *parent, const QByteArray &className, bool idBased):
-+ QObject(parent),
-+ m_className(className),
-+ m_idBased(idBased)
-+ {
-+ }
-+
-+ bool eventFilter(QObject *o, QEvent *event) override
-+ {
-+ if (event->type() == QEvent::LanguageChange) {
-+ const auto &dynamicPropertyNames = o->dynamicPropertyNames();
-+ for (const QByteArray &prop : dynamicPropertyNames) {
-+ if (prop.startsWith(PROP_GENERIC_PREFIX)) {
-+ const QByteArray propName = prop.mid(sizeof(PROP_GENERIC_PREFIX) - 1);
-+ const QUiTranslatableStringValue tsv =
-+ qvariant_cast(o->property(prop));
-+ o->setProperty(propName, tsv.translate(m_className, m_idBased));
-+ }
-+ }
-+ if (0) {
-+#if QT_CONFIG(tabwidget)
-+ } else if (QTabWidget *tabw = qobject_cast(o)) {
-+ const int cnt = tabw->count();
-+ for (int i = 0; i < cnt; ++i) {
-+ RETRANSLATE_SUBWIDGET_PROP(tabw, setTabText, PROP_TABPAGETEXT);
-+#if QT_CONFIG(tooltip)
-+ RETRANSLATE_SUBWIDGET_PROP(tabw, setTabToolTip, PROP_TABPAGETOOLTIP);
-+# endif
-+#if QT_CONFIG(whatsthis)
-+ RETRANSLATE_SUBWIDGET_PROP(tabw, setTabWhatsThis, PROP_TABPAGEWHATSTHIS);
-+# endif
-+ }
-+#endif
-+#if QT_CONFIG(listwidget)
-+ } else if (QListWidget *listw = qobject_cast(o)) {
-+ const int cnt = listw->count();
-+ for (int i = 0; i < cnt; ++i)
-+ reTranslateWidgetItem(listw->item(i), m_className, m_idBased);
-+#endif
-+#if QT_CONFIG(treewidget)
-+ } else if (QTreeWidget *treew = qobject_cast(o)) {
-+ if (QTreeWidgetItem *item = treew->headerItem())
-+ recursiveReTranslate(item, m_className, m_idBased);
-+ const int cnt = treew->topLevelItemCount();
-+ for (int i = 0; i < cnt; ++i) {
-+ QTreeWidgetItem *item = treew->topLevelItem(i);
-+ recursiveReTranslate(item, m_className, m_idBased);
-+ }
-+#endif
-+#if QT_CONFIG(tablewidget)
-+ } else if (QTableWidget *tablew = qobject_cast(o)) {
-+ const int row_cnt = tablew->rowCount();
-+ const int col_cnt = tablew->columnCount();
-+ for (int j = 0; j < col_cnt; ++j)
-+ reTranslateTableItem(tablew->horizontalHeaderItem(j), m_className, m_idBased);
-+ for (int i = 0; i < row_cnt; ++i) {
-+ reTranslateTableItem(tablew->verticalHeaderItem(i), m_className, m_idBased);
-+ for (int j = 0; j < col_cnt; ++j)
-+ reTranslateTableItem(tablew->item(i, j), m_className, m_idBased);
-+ }
-+#endif
-+#if QT_CONFIG(combobox)
-+ } else if (QComboBox *combow = qobject_cast(o)) {
-+ if (!qobject_cast(o)) {
-+ const int cnt = combow->count();
-+ for (int i = 0; i < cnt; ++i) {
-+ const QVariant v = combow->itemData(i, Qt::DisplayPropertyRole);
-+ if (v.isValid()) {
-+ QUiTranslatableStringValue tsv = qvariant_cast(v);
-+ combow->setItemText(i, tsv.translate(m_className, m_idBased));
-+ }
-+ }
-+ }
-+#endif
-+#if QT_CONFIG(toolbox)
-+ } else if (QToolBox *toolw = qobject_cast(o)) {
-+ const int cnt = toolw->count();
-+ for (int i = 0; i < cnt; ++i) {
-+ RETRANSLATE_SUBWIDGET_PROP(toolw, setItemText, PROP_TOOLITEMTEXT);
-+#if QT_CONFIG(tooltip)
-+ RETRANSLATE_SUBWIDGET_PROP(toolw, setItemToolTip, PROP_TOOLITEMTOOLTIP);
-+# endif
-+ }
-+#endif
-+ }
-+ }
-+ return false;
-+ }
-+
-+private:
-+ QByteArray m_className;
-+ bool m_idBased;
-+};
-+
-+class FormBuilderPrivate: public QFormBuilder
-+{
-+ friend class QT_PREPEND_NAMESPACE(QUiLoader);
-+ friend class QT_PREPEND_NAMESPACE(QUiLoaderPrivate);
-+ using ParentClass = QFormBuilder;
-+
-+public:
-+ QUiLoader *loader = nullptr;
-+
-+ bool dynamicTr = false;
-+ bool trEnabled = true;
-+
-+ FormBuilderPrivate() = default;
-+
-+ QWidget *defaultCreateWidget(const QString &className, QWidget *parent, const QString &name)
-+ {
-+ return ParentClass::createWidget(className, parent, name);
-+ }
-+
-+ QLayout *defaultCreateLayout(const QString &className, QObject *parent, const QString &name)
-+ {
-+ return ParentClass::createLayout(className, parent, name);
-+ }
-+
-+ QAction *defaultCreateAction(QObject *parent, const QString &name)
-+ {
-+ return ParentClass::createAction(parent, name);
-+ }
-+
-+ QActionGroup *defaultCreateActionGroup(QObject *parent, const QString &name)
-+ {
-+ return ParentClass::createActionGroup(parent, name);
-+ }
-+
-+ QWidget *createWidget(const QString &className, QWidget *parent, const QString &name) override
-+ {
-+ if (QWidget *widget = loader->createWidget(className, parent, name)) {
-+ widget->setObjectName(name);
-+ return widget;
-+ }
-+
-+ return nullptr;
-+ }
-+
-+ QLayout *createLayout(const QString &className, QObject *parent, const QString &name) override
-+ {
-+ if (QLayout *layout = loader->createLayout(className, parent, name)) {
-+ layout->setObjectName(name);
-+ return layout;
-+ }
-+
-+ return nullptr;
-+ }
-+
-+ QActionGroup *createActionGroup(QObject *parent, const QString &name) override
-+ {
-+ if (QActionGroup *actionGroup = loader->createActionGroup(parent, name)) {
-+ actionGroup->setObjectName(name);
-+ return actionGroup;
-+ }
-+
-+ return nullptr;
-+ }
-+
-+ QAction *createAction(QObject *parent, const QString &name) override
-+ {
-+ if (QAction *action = loader->createAction(parent, name)) {
-+ action->setObjectName(name);
-+ return action;
-+ }
-+
-+ return nullptr;
-+ }
-+
-+ void applyProperties(QObject *o, const QList &properties) override;
-+ QWidget *create(DomUI *ui, QWidget *parentWidget) override;
-+ QWidget *create(DomWidget *ui_widget, QWidget *parentWidget) override;
-+ bool addItem(DomWidget *ui_widget, QWidget *widget, QWidget *parentWidget) override;
-+
-+private:
-+ QByteArray m_class;
-+ TranslationWatcher *m_trwatch = nullptr;
-+ bool m_idBased = false;
-+};
-+
-+static QString convertTranslatable(const DomProperty *p, const QByteArray &className,
-+ bool idBased, QUiTranslatableStringValue *strVal)
-+{
-+ if (p->kind() != DomProperty::String)
-+ return QString();
-+ const DomString *dom_str = p->elementString();
-+ if (!dom_str)
-+ return QString();
-+ if (dom_str->hasAttributeNotr()) {
-+ const QString notr = dom_str->attributeNotr();
-+ if (notr == QStringLiteral("yes") || notr == QStringLiteral("true"))
-+ return QString();
-+ }
-+ strVal->setValue(dom_str->text().toUtf8());
-+ strVal->setQualifier(idBased ? dom_str->attributeId().toUtf8() : dom_str->attributeComment().toUtf8());
-+ if (strVal->value().isEmpty() && strVal->qualifier().isEmpty())
-+ return QString();
-+ return strVal->translate(className, idBased);
-+}
-+
-+void FormBuilderPrivate::applyProperties(QObject *o, const QList &properties)
-+{
-+ QFormBuilder::applyProperties(o, properties);
-+
-+ if (!m_trwatch)
-+ m_trwatch = new TranslationWatcher(o, m_class, m_idBased);
-+
-+ if (properties.isEmpty())
-+ return;
-+
-+ // Unlike string item roles, string properties are not loaded via the textBuilder
-+ // (as they are "shadowed" by the property sheets in designer). So do the initial
-+ // translation here.
-+ bool anyTrs = false;
-+ for (const DomProperty *p : properties) {
-+ QUiTranslatableStringValue strVal;
-+ const QString text = convertTranslatable(p, m_class, m_idBased, &strVal);
-+ if (text.isEmpty())
-+ continue;
-+ const QByteArray name = p->attributeName().toUtf8();
-+ if (dynamicTr) {
-+ const QByteArray dynname = QByteArray(PROP_GENERIC_PREFIX + name);
-+ o->setProperty(dynname, QVariant::fromValue(strVal));
-+ anyTrs = trEnabled;
-+ }
-+ if (p->elementString()->text() != text)
-+ o->setProperty(name, text);
-+ }
-+ if (anyTrs)
-+ o->installEventFilter(m_trwatch);
-+}
-+
-+QWidget *FormBuilderPrivate::create(DomUI *ui, QWidget *parentWidget)
-+{
-+ m_class = ui->elementClass().toUtf8();
-+ m_trwatch = nullptr;
-+ m_idBased = ui->attributeIdbasedtr();
-+ setTextBuilder(new TranslatingTextBuilder(m_idBased, trEnabled, m_class));
-+ return QFormBuilder::create(ui, parentWidget);
-+}
-+
-+QWidget *FormBuilderPrivate::create(DomWidget *ui_widget, QWidget *parentWidget)
-+{
-+ QWidget *w = QFormBuilder::create(ui_widget, parentWidget);
-+ if (w == nullptr)
-+ return nullptr;
-+
-+ if (0) {
-+#if QT_CONFIG(tabwidget)
-+ } else if (qobject_cast(w)) {
-+#endif
-+#if QT_CONFIG(listwidget)
-+ } else if (qobject_cast(w)) {
-+#endif
-+#if QT_CONFIG(treewidget)
-+ } else if (qobject_cast(w)) {
-+#endif
-+#if QT_CONFIG(tablewidget)
-+ } else if (qobject_cast(w)) {
-+#endif
-+#if QT_CONFIG(combobox)
-+ } else if (qobject_cast(w)) {
-+ if (qobject_cast(w))
-+ return w;
-+#endif
-+#if QT_CONFIG(toolbox)
-+ } else if (qobject_cast(w)) {
-+#endif
-+ } else {
-+ return w;
-+ }
-+ if (dynamicTr && trEnabled)
-+ w->installEventFilter(m_trwatch);
-+ return w;
-+}
-+
-+#define TRANSLATE_SUBWIDGET_PROP(mainWidget, attribute, setter, propName) \
-+ do { \
-+ if (const DomProperty *p##attribute = attributes.value(strings.attribute)) { \
-+ QUiTranslatableStringValue strVal; \
-+ const QString text = convertTranslatable(p##attribute, m_class, m_idBased, &strVal); \
-+ if (!text.isEmpty()) { \
-+ if (dynamicTr) \
-+ mainWidget->widget(i)->setProperty(propName, QVariant::fromValue(strVal)); \
-+ mainWidget->setter(i, text); \
-+ } \
-+ } \
-+ } while (0)
-+
-+bool FormBuilderPrivate::addItem(DomWidget *ui_widget, QWidget *widget, QWidget *parentWidget)
-+{
-+ if (parentWidget == nullptr)
-+ return true;
-+
-+ if (!ParentClass::addItem(ui_widget, widget, parentWidget))
-+ return false;
-+
-+ // Check special cases. First: Custom container
-+ const QString className = QLatin1String(parentWidget->metaObject()->className());
-+ if (!d->customWidgetAddPageMethod(className).isEmpty())
-+ return true;
-+
-+ const QFormBuilderStrings &strings = QFormBuilderStrings::instance();
-+
-+ if (0) {
-+#if QT_CONFIG(tabwidget)
-+ } else if (QTabWidget *tabWidget = qobject_cast(parentWidget)) {
-+ const DomPropertyHash attributes = propertyMap(ui_widget->elementAttribute());
-+ const int i = tabWidget->count() - 1;
-+ TRANSLATE_SUBWIDGET_PROP(tabWidget, titleAttribute, setTabText, PROP_TABPAGETEXT);
-+#if QT_CONFIG(tooltip)
-+ TRANSLATE_SUBWIDGET_PROP(tabWidget, toolTipAttribute, setTabToolTip, PROP_TABPAGETOOLTIP);
-+# endif
-+#if QT_CONFIG(whatsthis)
-+ TRANSLATE_SUBWIDGET_PROP(tabWidget, whatsThisAttribute, setTabWhatsThis, PROP_TABPAGEWHATSTHIS);
-+# endif
-+#endif
-+#if QT_CONFIG(toolbox)
-+ } else if (QToolBox *toolBox = qobject_cast(parentWidget)) {
-+ const DomPropertyHash attributes = propertyMap(ui_widget->elementAttribute());
-+ const int i = toolBox->count() - 1;
-+ TRANSLATE_SUBWIDGET_PROP(toolBox, labelAttribute, setItemText, PROP_TOOLITEMTEXT);
-+#if QT_CONFIG(tooltip)
-+ TRANSLATE_SUBWIDGET_PROP(toolBox, toolTipAttribute, setItemToolTip, PROP_TOOLITEMTOOLTIP);
-+# endif
-+#endif
-+ }
-+
-+ return true;
-+}
-+
-+#ifdef QFORMINTERNAL_NAMESPACE
-+}
-+#endif
-+
-+class QUiLoaderPrivate
-+{
-+public:
-+#ifdef QFORMINTERNAL_NAMESPACE
-+ QFormInternal::FormBuilderPrivate builder;
-+#else
-+ FormBuilderPrivate builder;
-+#endif
-+
-+ void setupWidgetMap() const;
-+};
-+
-+void QUiLoaderPrivate::setupWidgetMap() const
-+{
-+ if (!g_widgets()->isEmpty())
-+ return;
-+
-+#define DECLARE_WIDGET(a, b) g_widgets()->insert(QLatin1String(#a), true);
-+#define DECLARE_LAYOUT(a, b)
-+
-+#include "widgets.table"
-+
-+#undef DECLARE_WIDGET
-+#undef DECLARE_WIDGET_1
-+#undef DECLARE_LAYOUT
-+}
-+
-+/*!
-+ \class QUiLoader
-+ \inmodule QtUiTools
-+
-+ \brief The QUiLoader class enables standalone applications to
-+ dynamically create user interfaces at run-time using the
-+ information stored in UI files or specified in plugin paths.
-+
-+ In addition, you can customize or create your own user interface by
-+ deriving your own loader class.
-+
-+ If you have a custom component or an application that embeds \QD, you can
-+ also use the QFormBuilder class provided by the QtDesigner module to create
-+ user interfaces from UI files.
-+
-+ The QUiLoader class provides a collection of functions allowing you to
-+ create widgets based on the information stored in UI files (created
-+ with \QD) or available in the specified plugin paths. The specified plugin
-+ paths can be retrieved using the pluginPaths() function. Similarly, the
-+ contents of a UI file can be retrieved using the load() function. For
-+ example:
-+
-+ \snippet quiloader/mywidget.cpp 0
-+
-+ \if !defined(qtforpython)
-+ By including the user interface in the form's resources (\c myform.qrc), we
-+ ensure that it will be present at run-time:
-+
-+ \quotefile quiloader/mywidget.qrc
-+ \endif
-+
-+ The availableWidgets() function returns a QStringList with the class names
-+ of the widgets available in the specified plugin paths. To create these
-+ widgets, simply use the createWidget() function. For example:
-+
-+ \snippet quiloader/main.cpp 0
-+
-+ To make a custom widget available to the loader, you can use the
-+ addPluginPath() function; to remove all available widgets, you can call
-+ the clearPluginPaths() function.
-+
-+ The createAction(), createActionGroup(), createLayout(), and createWidget()
-+ functions are used internally by the QUiLoader class whenever it has to
-+ create an action, action group, layout, or widget respectively. For that
-+ reason, you can subclass the QUiLoader class and reimplement these
-+ functions to intervene the process of constructing a user interface. For
-+ example, you might want to have a list of the actions created when loading
-+ a form or creating a custom widget.
-+
-+ For a complete example using the QUiLoader class, see the
-+ \l{Calculator Builder Example}.
-+
-+ \sa {Qt UI Tools}, QFormBuilder
-+*/
-+
-+/*!
-+ Creates a form loader with the given \a parent.
-+*/
-+QUiLoader::QUiLoader(QObject *parent)
-+ : QObject(parent), d_ptr(new QUiLoaderPrivate)
-+{
-+ Q_D(QUiLoader);
-+
-+#ifndef QT_NO_DATASTREAM
-+ static int metaTypeId = 0;
-+ if (!metaTypeId) {
-+ metaTypeId = qRegisterMetaType("QUiTranslatableStringValue");
-+ }
-+#endif // QT_NO_DATASTREAM
-+ d->builder.loader = this;
-+
-+#if QT_CONFIG(library)
-+ QStringList paths;
-+ const QStringList &libraryPaths = QApplication::libraryPaths();
-+ for (const QString &path : libraryPaths) {
-+ QString libPath = path;
-+ libPath += QDir::separator();
-+ libPath += QStringLiteral("designer");
-+ paths.append(libPath);
-+ }
-+
-+ d->builder.setPluginPath(paths);
-+#endif // QT_CONFIG(library)
-+}
-+
-+/*!
-+ Destroys the loader.
-+*/
-+QUiLoader::~QUiLoader() = default;
-+
-+/*!
-+ Loads a form from the given \a device and creates a new widget with the
-+ given \a parentWidget to hold its contents.
-+
-+ \sa createWidget(), errorString()
-+*/
-+QWidget *QUiLoader::load(QIODevice *device, QWidget *parentWidget)
-+{
-+ Q_D(QUiLoader);
-+ // QXmlStreamReader will report errors on open failure.
-+ if (!device->isOpen())
-+ device->open(QIODevice::ReadOnly|QIODevice::Text);
-+ return d->builder.load(device, parentWidget);
-+}
-+
-+/*!
-+ Returns a list naming the paths in which the loader will search when
-+ locating custom widget plugins.
-+
-+ \sa addPluginPath(), clearPluginPaths()
-+*/
-+QStringList QUiLoader::pluginPaths() const
-+{
-+ Q_D(const QUiLoader);
-+ return d->builder.pluginPaths();
-+}
-+
-+/*!
-+ Clears the list of paths in which the loader will search when locating
-+ plugins.
-+
-+ \sa addPluginPath(), pluginPaths()
-+*/
-+void QUiLoader::clearPluginPaths()
-+{
-+ Q_D(QUiLoader);
-+ d->builder.clearPluginPaths();
-+}
-+
-+/*!
-+ Adds the given \a path to the list of paths in which the loader will search
-+ when locating plugins.
-+
-+ \sa pluginPaths(), clearPluginPaths()
-+*/
-+void QUiLoader::addPluginPath(const QString &path)
-+{
-+ Q_D(QUiLoader);
-+ d->builder.addPluginPath(path);
-+}
-+
-+/*!
-+ Creates a new widget with the given \a parent and \a name using the class
-+ specified by \a className. You can use this function to create any of the
-+ widgets returned by the availableWidgets() function.
-+
-+ The function is also used internally by the QUiLoader class whenever it
-+ creates a widget. Hence, you can subclass QUiLoader and reimplement this
-+ function to intervene process of constructing a user interface or widget.
-+ However, in your implementation, ensure that you call QUiLoader's version
-+ first.
-+
-+ \sa availableWidgets(), load()
-+*/
-+QWidget *QUiLoader::createWidget(const QString &className, QWidget *parent, const QString &name)
-+{
-+ Q_D(QUiLoader);
-+ return d->builder.defaultCreateWidget(className, parent, name);
-+}
-+
-+/*!
-+ Creates a new layout with the given \a parent and \a name using the class
-+ specified by \a className.
-+
-+ The function is also used internally by the QUiLoader class whenever it
-+ creates a widget. Hence, you can subclass QUiLoader and reimplement this
-+ function to intervene process of constructing a user interface or widget.
-+ However, in your implementation, ensure that you call QUiLoader's version
-+ first.
-+
-+ \sa createWidget(), load()
-+*/
-+QLayout *QUiLoader::createLayout(const QString &className, QObject *parent, const QString &name)
-+{
-+ Q_D(QUiLoader);
-+ return d->builder.defaultCreateLayout(className, parent, name);
-+}
-+
-+/*!
-+ Creates a new action group with the given \a parent and \a name.
-+
-+ The function is also used internally by the QUiLoader class whenever it
-+ creates a widget. Hence, you can subclass QUiLoader and reimplement this
-+ function to intervene process of constructing a user interface or widget.
-+ However, in your implementation, ensure that you call QUiLoader's version
-+ first.
-+
-+ \sa createAction(), createWidget(), load()
-+ */
-+QActionGroup *QUiLoader::createActionGroup(QObject *parent, const QString &name)
-+{
-+ Q_D(QUiLoader);
-+ return d->builder.defaultCreateActionGroup(parent, name);
-+}
-+
-+/*!
-+ Creates a new action with the given \a parent and \a name.
-+
-+ The function is also used internally by the QUiLoader class whenever it
-+ creates a widget. Hence, you can subclass QUiLoader and reimplement this
-+ function to intervene process of constructing a user interface or widget.
-+ However, in your implementation, ensure that you call QUiLoader's version
-+ first.
-+
-+ \sa createActionGroup(), createWidget(), load()
-+*/
-+QAction *QUiLoader::createAction(QObject *parent, const QString &name)
-+{
-+ Q_D(QUiLoader);
-+ return d->builder.defaultCreateAction(parent, name);
-+}
-+
-+/*!
-+ Returns a list naming all available widgets that can be built using the
-+ createWidget() function, i.e all the widgets specified within the given
-+ plugin paths.
-+
-+ \sa pluginPaths(), createWidget()
-+
-+*/
-+QStringList QUiLoader::availableWidgets() const
-+{
-+ Q_D(const QUiLoader);
-+
-+ d->setupWidgetMap();
-+ widget_map available = *g_widgets();
-+
-+ const auto &customWidgets = d->builder.customWidgets();
-+ for (QDesignerCustomWidgetInterface *plugin : customWidgets)
-+ available.insert(plugin->name(), true);
-+
-+ return available.keys();
-+}
-+
-+
-+/*!
-+ \since 4.5
-+ Returns a list naming all available layouts that can be built using the
-+ createLayout() function
-+
-+ \sa createLayout()
-+*/
-+
-+QStringList QUiLoader::availableLayouts() const
-+{
-+ QStringList rc;
-+#define DECLARE_WIDGET(a, b)
-+#define DECLARE_LAYOUT(a, b) rc.push_back(QLatin1String(#a));
-+
-+#include "widgets.table"
-+
-+#undef DECLARE_WIDGET
-+#undef DECLARE_LAYOUT
-+ return rc;
-+}
-+
-+/*!
-+ Sets the working directory of the loader to \a dir. The loader will look
-+ for other resources, such as icons and resource files, in paths relative to
-+ this directory.
-+
-+ \sa workingDirectory()
-+*/
-+
-+void QUiLoader::setWorkingDirectory(const QDir &dir)
-+{
-+ Q_D(QUiLoader);
-+ d->builder.setWorkingDirectory(dir);
-+}
-+
-+/*!
-+ Returns the working directory of the loader.
-+
-+ \sa setWorkingDirectory()
-+*/
-+
-+QDir QUiLoader::workingDirectory() const
-+{
-+ Q_D(const QUiLoader);
-+ return d->builder.workingDirectory();
-+}
-+/*!
-+ \since 4.5
-+
-+ If \a enabled is true, user interfaces loaded by this loader will
-+ automatically retranslate themselves upon receiving a language change
-+ event. Otherwise, the user interfaces will not be retranslated.
-+
-+ \sa isLanguageChangeEnabled()
-+*/
-+
-+void QUiLoader::setLanguageChangeEnabled(bool enabled)
-+{
-+ Q_D(QUiLoader);
-+ d->builder.dynamicTr = enabled;
-+}
-+
-+/*!
-+ \since 4.5
-+
-+ Returns true if dynamic retranslation on language change is enabled;
-+ returns false otherwise.
-+
-+ \sa setLanguageChangeEnabled()
-+*/
-+
-+bool QUiLoader::isLanguageChangeEnabled() const
-+{
-+ Q_D(const QUiLoader);
-+ return d->builder.dynamicTr;
-+}
-+
-+/*!
-+ \internal
-+ \since 4.5
-+
-+ If \a enabled is true, user interfaces loaded by this loader will be
-+ translated. Otherwise, the user interfaces will not be translated.
-+
-+ \note This is orthogonal to languageChangeEnabled.
-+
-+ \sa isLanguageChangeEnabled(), setLanguageChangeEnabled()
-+*/
-+
-+void QUiLoader::setTranslationEnabled(bool enabled)
-+{
-+ Q_D(QUiLoader);
-+ d->builder.trEnabled = enabled;
-+}
-+
-+/*!
-+ \internal
-+ \since 4.5
-+
-+ Returns true if translation is enabled; returns false otherwise.
-+
-+ \sa setTranslationEnabled()
-+*/
-+
-+bool QUiLoader::isTranslationEnabled() const
-+{
-+ Q_D(const QUiLoader);
-+ return d->builder.trEnabled;
-+}
-+
-+/*!
-+ Returns a human-readable description of the last error occurred in load().
-+
-+ \since 5.0
-+ \sa load()
-+*/
-+
-+QString QUiLoader::errorString() const
-+{
-+ Q_D(const QUiLoader);
-+ return d->builder.errorString();
-+}
-+
-+QT_END_NAMESPACE
-+
-+#include "quiloader.moc"
-diff --git x/qttools/src/designer/src/uitools/quiloader.h y/qttools/src/designer/src/uitools/quiloader.h
-new file mode 100644
-index 000000000..742b5606f
---- /dev/null
-+++ y/qttools/src/designer/src/uitools/quiloader.h
-@@ -0,0 +1,61 @@
-+// Copyright (C) 2020 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
-+
-+#ifndef QUILOADER_H
-+#define QUILOADER_H
-+
-+#include
-+#include
-+#include
-+
-+QT_BEGIN_NAMESPACE
-+
-+class QWidget;
-+class QLayout;
-+class QAction;
-+class QActionGroup;
-+class QString;
-+class QIODevice;
-+class QDir;
-+
-+class QUiLoaderPrivate;
-+class Q_UITOOLS_EXPORT QUiLoader : public QObject
-+{
-+ Q_OBJECT
-+public:
-+ explicit QUiLoader(QObject *parent = nullptr);
-+ ~QUiLoader() override;
-+
-+ QStringList pluginPaths() const;
-+ void clearPluginPaths();
-+ void addPluginPath(const QString &path);
-+
-+ QWidget *load(QIODevice *device, QWidget *parentWidget = nullptr);
-+ QStringList availableWidgets() const;
-+ QStringList availableLayouts() const;
-+
-+ virtual QWidget *createWidget(const QString &className, QWidget *parent = nullptr, const QString &name = QString());
-+ virtual QLayout *createLayout(const QString &className, QObject *parent = nullptr, const QString &name = QString());
-+ virtual QActionGroup *createActionGroup(QObject *parent = nullptr, const QString &name = QString());
-+ virtual QAction *createAction(QObject *parent = nullptr, const QString &name = QString());
-+
-+ void setWorkingDirectory(const QDir &dir);
-+ QDir workingDirectory() const;
-+
-+ void setLanguageChangeEnabled(bool enabled);
-+ bool isLanguageChangeEnabled() const;
-+
-+ void setTranslationEnabled(bool enabled);
-+ bool isTranslationEnabled() const;
-+
-+ QString errorString() const;
-+
-+private:
-+ QScopedPointer d_ptr;
-+ Q_DECLARE_PRIVATE(QUiLoader)
-+ Q_DISABLE_COPY_MOVE(QUiLoader)
-+};
-+
-+QT_END_NAMESPACE
-+
-+#endif // QUILOADER_H
-diff --git x/qttools/src/designer/src/uitools/quiloader_p.h y/qttools/src/designer/src/uitools/quiloader_p.h
-new file mode 100644
-index 000000000..efd943217
---- /dev/null
-+++ y/qttools/src/designer/src/uitools/quiloader_p.h
-@@ -0,0 +1,77 @@
-+// Copyright (C) 2020 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
-+
-+#ifndef QUILOADER_P_H
-+#define QUILOADER_P_H
-+
-+//
-+// W A R N I N G
-+// -------------
-+//
-+// This file is not part of the Qt API. It exists purely as an
-+// implementation detail. This header file may change from version to
-+// version without notice, or even be removed.
-+//
-+// We mean it.
-+//
-+
-+#include
-+#include
-+#include
-+
-+QT_FORWARD_DECLARE_CLASS(QDataStream)
-+
-+// This file is here for use by the form preview in Linguist. If you change anything
-+// here or in the code which uses it, remember to adapt Linguist accordingly.
-+
-+#define PROP_GENERIC_PREFIX "_q_notr_"
-+#define PROP_TOOLITEMTEXT "_q_toolItemText_notr"
-+#define PROP_TOOLITEMTOOLTIP "_q_toolItemToolTip_notr"
-+#define PROP_TABPAGETEXT "_q_tabPageText_notr"
-+#define PROP_TABPAGETOOLTIP "_q_tabPageToolTip_notr"
-+#define PROP_TABPAGEWHATSTHIS "_q_tabPageWhatsThis_notr"
-+
-+QT_BEGIN_NAMESPACE
-+
-+class Q_UITOOLS_EXPORT QUiTranslatableStringValue
-+{
-+public:
-+ QByteArray value() const { return m_value; }
-+ void setValue(const QByteArray &value) { m_value = value; }
-+ QByteArray qualifier() const { return m_qualifier; }
-+ void setQualifier(const QByteArray &qualifier) { m_qualifier = qualifier; }
-+
-+ QString translate(const QByteArray &className, bool idBased) const;
-+
-+private:
-+ QByteArray m_value;
-+ QByteArray m_qualifier; // Comment or ID for id-based tr().
-+};
-+
-+#ifndef QT_NO_DATASTREAM
-+Q_UITOOLS_EXPORT QDataStream &operator<<(QDataStream &out, const QUiTranslatableStringValue &s);
-+Q_UITOOLS_EXPORT QDataStream &operator>>(QDataStream &in, QUiTranslatableStringValue &s);
-+#endif // QT_NO_DATASTREAM
-+
-+struct QUiItemRolePair {
-+ int realRole;
-+ int shadowRole;
-+};
-+
-+#ifdef QFORMINTERNAL_NAMESPACE
-+namespace QFormInternal
-+{
-+#endif
-+
-+extern const Q_UITOOLS_EXPORT QUiItemRolePair qUiItemRoles[];
-+
-+#ifdef QFORMINTERNAL_NAMESPACE
-+}
-+#endif
-+
-+QT_END_NAMESPACE
-+
-+Q_DECLARE_METATYPE(QUiTranslatableStringValue)
-+
-+
-+#endif // QUILOADER_P_H
-diff --git x/qttools/src/uiplugin/CMakeLists.txt y/qttools/src/uiplugin/CMakeLists.txt
-deleted file mode 100644
-index 4fedf8e33..000000000
---- x/qttools/src/uiplugin/CMakeLists.txt
-+++ /dev/null
-@@ -1,27 +0,0 @@
--# Generated from uiplugin.pro.
--
--#####################################################################
--## UiPlugin Module:
--#####################################################################
--
--qt_internal_add_module(UiPlugin
-- NO_PRIVATE_MODULE
-- HEADER_MODULE
-- QMAKE_MODULE_CONFIG designer_defines
-- PUBLIC_LIBRARIES
-- Qt::Core
-- Qt::Gui
-- Qt::Widgets
--)
--
--# special case begin
--set(is_plugin "$")
--target_compile_definitions(
-- UiPlugin
-- INTERFACE
-- $<$:QDESIGNER_EXPORT_WIDGETS>
--)
--# special case end
--
--#### Keys ignored in scope 1:.:.:uiplugin.pro::
--# MODULE_CONFIG = "designer_defines"
-diff --git x/qttools/src/uiplugin/customwidget.h y/qttools/src/uiplugin/customwidget.h
-deleted file mode 100644
-index 2a47a32f8..000000000
---- x/qttools/src/uiplugin/customwidget.h
-+++ /dev/null
-@@ -1,62 +0,0 @@
--// Copyright (C) 2016 The Qt Company Ltd.
--// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
--
--#ifndef CUSTOMWIDGET_H
--#define CUSTOMWIDGET_H
--
--#include
--#include
--#include
--
--QT_BEGIN_NAMESPACE
--
--class QWidget;
--class QDesignerFormEditorInterface;
--
--class QDesignerCustomWidgetInterface
--{
--public:
-- virtual ~QDesignerCustomWidgetInterface() = default; // ### FIXME: weak vtable
--
-- virtual QString name() const = 0;
-- virtual QString group() const = 0;
-- virtual QString toolTip() const = 0;
-- virtual QString whatsThis() const = 0;
-- virtual QString includeFile() const = 0;
-- virtual QIcon icon() const = 0;
--
-- virtual bool isContainer() const = 0;
--
-- virtual QWidget *createWidget(QWidget *parent) = 0;
--
-- virtual bool isInitialized() const { return false; }
-- virtual void initialize(QDesignerFormEditorInterface *core) { Q_UNUSED(core); }
--
-- virtual QString domXml() const
-- {
-- return QString::fromUtf8("")
-- .arg(name()).arg(name().toLower());
-- }
--
-- virtual QString codeTemplate() const { return QString(); }
--};
--
--#define QDesignerCustomWidgetInterface_iid "org.qt-project.QDesignerCustomWidgetInterface"
--
--Q_DECLARE_INTERFACE(QDesignerCustomWidgetInterface, QDesignerCustomWidgetInterface_iid)
--
--class QDesignerCustomWidgetCollectionInterface
--{
--public:
-- virtual ~QDesignerCustomWidgetCollectionInterface() = default; // ### FIXME: weak vtable
--
-- virtual QList customWidgets() const = 0;
--};
--
--#define QDesignerCustomWidgetCollectionInterface_iid "org.qt-project.Qt.QDesignerCustomWidgetCollectionInterface"
--
--Q_DECLARE_INTERFACE(QDesignerCustomWidgetCollectionInterface, QDesignerCustomWidgetCollectionInterface_iid)
--
--QT_END_NAMESPACE
--
--#endif // CUSTOMWIDGET_H
-diff --git x/qttools/src/uiplugin/customwidget.qdoc y/qttools/src/uiplugin/customwidget.qdoc
-deleted file mode 100644
-index 557e9a454..000000000
---- x/qttools/src/uiplugin/customwidget.qdoc
-+++ /dev/null
-@@ -1,269 +0,0 @@
--// Copyright (C) 2016 The Qt Company Ltd.
--// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
--
--/*!
-- \class QDesignerCustomWidgetInterface
--
-- \brief The QDesignerCustomWidgetInterface class enables Qt Designer
-- to access and construct custom widgets.
--
-- \inmodule QtDesigner
--
-- QDesignerCustomWidgetInterface provides a custom widget with an
-- interface. The class contains a set of functions that must be subclassed
-- to return basic information about the widget, such as its class name and
-- the name of its header file. Other functions must be implemented to
-- initialize the plugin when it is loaded, and to construct instances of
-- the custom widget for \QD to use.
--
-- When implementing a custom widget you must subclass
-- QDesignerCustomWidgetInterface to expose your widget to \QD. For
-- example, this is the declaration for the plugin used in the
-- \l{Custom Widget Plugin Example}{Custom Widget Plugin example} that
-- enables an analog clock custom widget to be used by \QD:
--
-- \snippet customwidgetplugin/customwidgetplugin.h 0
--
-- Note that the only part of the class definition that is specific
-- to this particular custom widget is the class name. In addition,
-- since we are implementing an interface, we must ensure that it's
-- made known to the meta object system using the Q_INTERFACES()
-- macro. This enables \QD to use the qobject_cast() function to
-- query for supported interfaces using nothing but a QObject
-- pointer.
--
-- After \QD loads a custom widget plugin, it calls the interface's
-- initialize() function to enable it to set up any resources that it
-- may need. This function is called with a QDesignerFormEditorInterface
-- parameter that provides the plugin with a gateway to all of \QD's API.
--
-- \QD constructs instances of the custom widget by calling the plugin's
-- createWidget() function with a suitable parent widget. Plugins must
-- construct and return an instance of a custom widget with the specified
-- parent widget.
--
-- Exporting your custom widget plugin to \QD using the Q_PLUGIN_METADATA()
-- macro. For example, if a library called \c libcustomwidgetplugin.so
-- (on Unix) or \c libcustomwidget.dll (on Windows) contains a widget
-- class called \c MyCustomWidget, we can export it by adding the
-- following line to the file containing the plugin header:
--
-- \snippet plugins/doc_src_qtdesigner.cpp 14
--
-- This macro ensures that \QD can access and construct the custom widget.
-- Without this macro, there is no way for \QD to use it.
--
-- When implementing a custom widget plugin, you build it as a
-- separate library. If you want to include several custom widget
-- plugins in the same library, you must in addition subclass
-- QDesignerCustomWidgetCollectionInterface.
--
-- \warning If your custom widget plugin contains QVariant
-- properties, be aware that only the following \l
-- {QVariant::Type}{types} are supported:
--
-- \list
-- \li QVariant::ByteArray
-- \li QVariant::Bool
-- \li QVariant::Color
-- \li QVariant::Cursor
-- \li QVariant::Date
-- \li QVariant::DateTime
-- \li QVariant::Double
-- \li QVariant::Int
-- \li QVariant::Point
-- \li QVariant::Rect
-- \li QVariant::Size
-- \li QVariant::SizePolicy
-- \li QVariant::String
-- \li QVariant::Time
-- \li QVariant::UInt
-- \endlist
--
-- For a complete example using the QDesignerCustomWidgetInterface
-- class, see the \l {customwidgetplugin}{Custom Widget
-- Example}. The example shows how to create a custom widget plugin
-- for \QD.
--
-- \sa QDesignerCustomWidgetCollectionInterface, {Creating Custom Widgets for Qt Designer}
--*/
--
--/*!
-- \fn QDesignerCustomWidgetInterface::~QDesignerCustomWidgetInterface()
--
-- Destroys the custom widget interface.
--*/
--
--/*!
-- \fn QString QDesignerCustomWidgetInterface::name() const
--
-- Returns the class name of the custom widget supplied by the interface.
--
-- The name returned \e must be identical to the class name used for the
-- custom widget.
--*/
--
--/*!
-- \fn QString QDesignerCustomWidgetInterface::group() const
--
-- Returns the name of the group to which the custom widget belongs.
--*/
--
--/*!
-- \fn QString QDesignerCustomWidgetInterface::toolTip() const
--
-- Returns a short description of the widget that can be used by \QD
-- in a tool tip.
--*/
--
--/*!
-- \fn QString QDesignerCustomWidgetInterface::whatsThis() const
--
-- Returns a description of the widget that can be used by \QD in
-- "What's This?" help for the widget.
--*/
--
--/*!
-- \fn QString QDesignerCustomWidgetInterface::includeFile() const
--
-- Returns the path to the include file that \l uic uses when
-- creating code for the custom widget.
--*/
--
--/*!
-- \fn QIcon QDesignerCustomWidgetInterface::icon() const
--
-- Returns the icon used to represent the custom widget in \QD's
-- widget box.
--*/
--
--/*!
-- \fn bool QDesignerCustomWidgetInterface::isContainer() const
--
-- Returns true if the custom widget is intended to be used as a
-- container; otherwise returns false.
--
-- Most custom widgets are not used to hold other widgets, so their
-- implementations of this function will return false, but custom
-- containers will return true to ensure that they behave correctly
-- in \QD.
--*/
--
--/*!
-- \fn QWidget *QDesignerCustomWidgetInterface::createWidget(QWidget *parent)
--
-- Returns a new instance of the custom widget, with the given \a
-- parent.
--*/
--
--/*!
-- \fn bool QDesignerCustomWidgetInterface::isInitialized() const
--
-- Returns true if the widget has been initialized; otherwise returns
-- false.
--
-- \sa initialize()
--*/
--
--/*!
-- \fn void QDesignerCustomWidgetInterface::initialize(QDesignerFormEditorInterface *formEditor)
--
-- Initializes the widget for use with the specified \a formEditor
-- interface.
--
-- \sa isInitialized()
--*/
--
--/*!
-- \fn QString QDesignerCustomWidgetInterface::domXml() const
--
-- Returns the XML that is used to describe the custom widget's
-- properties to \QD.
--*/
--
--/*!
-- \fn QString QDesignerCustomWidgetInterface::codeTemplate() const
--
-- This function is reserved for future use by \QD.
--
-- \omit
-- Returns the code template that \QD includes in forms that contain
-- the custom widget when they are saved.
-- \endomit
--*/
--
--/*!
-- \macro QDESIGNER_WIDGET_EXPORT
-- \relates QDesignerCustomWidgetInterface
-- \since 4.1
--
-- This macro is used when defining custom widgets to ensure that they are
-- correctly exported from plugins for use with \QD.
--
-- On some platforms, the symbols required by \QD to create new widgets
-- are removed from plugins by the build system, making them unusable.
-- Using this macro ensures that the symbols are retained on those platforms,
-- and has no side effects on other platforms.
--
-- For example, the \l{worldtimeclockplugin}{World Time Clock Plugin}
-- example exports a custom widget class with the following declaration:
--
-- \snippet worldtimeclockplugin/worldtimeclock.h 0
-- \dots
-- \snippet worldtimeclockplugin/worldtimeclock.h 2
--
-- \sa {Creating Custom Widgets for Qt Designer}
--*/
--
--
--
--
--
--/*!
-- \class QDesignerCustomWidgetCollectionInterface
--
-- \brief The QDesignerCustomWidgetCollectionInterface class allows
-- you to include several custom widgets in one single library.
--
-- \inmodule QtDesigner
--
-- When implementing a custom widget plugin, you build it as a
-- separate library. If you want to include several custom widget
-- plugins in the same library, you must in addition subclass
-- QDesignerCustomWidgetCollectionInterface.
--
-- QDesignerCustomWidgetCollectionInterface contains one single
-- function returning a list of the collection's
-- QDesignerCustomWidgetInterface objects. For example, if you have
-- several custom widgets \c CustomWidgetOne, \c CustomWidgetTwo and
-- \c CustomWidgetThree, the class definition may look like this:
--
-- \snippet plugins/doc_src_qtdesigner.cpp 12
--
-- In the class constructor you add the interfaces to your custom
-- widgets to the list which you return in the customWidgets()
-- function:
--
-- \snippet plugins/doc_src_qtdesigner.cpp 13
--
-- Note that instead of exporting each custom widget plugin using the
-- Q_PLUGIN_METADATA() macro, you export the entire collection. The
-- Q_PLUGIN_METADATA() macro ensures that \QD can access and construct
-- the custom widgets. Without this macro, there is no way for \QD to
-- use them.
--
-- \sa QDesignerCustomWidgetInterface, {Creating Custom Widgets for
-- Qt Designer}
--*/
--
--/*!
-- \fn QDesignerCustomWidgetCollectionInterface::~QDesignerCustomWidgetCollectionInterface() {
--
-- Destroys the custom widget collection interface.
--*/
--
--/*!
-- \fn QList QDesignerCustomWidgetCollectionInterface::customWidgets() const
--
-- Returns a list of interfaces to the collection's custom widgets.
--*/
-diff --git x/qttools/src/uiplugin/qdesignerexportwidget.h y/qttools/src/uiplugin/qdesignerexportwidget.h
-deleted file mode 100644
-index d90e9b217..000000000
---- x/qttools/src/uiplugin/qdesignerexportwidget.h
-+++ /dev/null
-@@ -1,24 +0,0 @@
--// Copyright (C) 2016 The Qt Company Ltd.
--// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
--
--#ifndef QDESIGNEREXPORTWIDGET_H
--#define QDESIGNEREXPORTWIDGET_H
--
--#include
--
--QT_BEGIN_NAMESPACE
--
--#if 0
--// pragma for syncqt, don't remove.
--#pragma qt_class(QDesignerExportWidget)
--#endif
--
--#if defined(QDESIGNER_EXPORT_WIDGETS)
--# define QDESIGNER_WIDGET_EXPORT Q_DECL_EXPORT
--#else
--# define QDESIGNER_WIDGET_EXPORT Q_DECL_IMPORT
--#endif
--
--QT_END_NAMESPACE
--
--#endif //QDESIGNEREXPORTWIDGET_H
-diff --git x/qttools/src/uitools/CMakeLists.txt y/qttools/src/uitools/CMakeLists.txt
-deleted file mode 100644
-index 448bd1840..000000000
---- x/qttools/src/uitools/CMakeLists.txt
-+++ /dev/null
-@@ -1,47 +0,0 @@
--# Generated from uitools.pro.
--
--#####################################################################
--## UiTools Module:
--#####################################################################
--
--qt_internal_add_module(UiTools
-- SOURCES
-- ../designer/src/lib/uilib/abstractformbuilder.cpp ../designer/src/lib/uilib/abstractformbuilder.h
-- ../designer/src/lib/uilib/formbuilder.cpp ../designer/src/lib/uilib/formbuilder.h
-- ../designer/src/lib/uilib/formbuilderextra.cpp ../designer/src/lib/uilib/formbuilderextra_p.h
-- ../designer/src/lib/uilib/properties.cpp ../designer/src/lib/uilib/properties_p.h
-- ../designer/src/lib/uilib/resourcebuilder.cpp ../designer/src/lib/uilib/resourcebuilder_p.h
-- ../designer/src/lib/uilib/textbuilder.cpp ../designer/src/lib/uilib/textbuilder_p.h
-- ../designer/src/lib/uilib/ui4.cpp ../designer/src/lib/uilib/ui4_p.h
-- quiloader.cpp quiloader.h
-- DEFINES
-- QFORMINTERNAL_NAMESPACE
-- QT_DESIGNER
-- QT_DESIGNER_STATIC
-- QT_USE_QSTRINGBUILDER
-- INCLUDE_DIRECTORIES
-- ../designer/src/lib/uilib
-- LIBRARIES
-- Qt::UiPlugin
-- PUBLIC_LIBRARIES
-- Qt::Core
-- Qt::Gui
-- Qt::Widgets
--)
--
--## Scopes:
--#####################################################################
--
--qt_internal_extend_target(UiTools CONDITION TARGET Qt::OpenGLWidgets
-- PUBLIC_LIBRARIES
-- Qt::OpenGLWidgets
--)
--
--qt_internal_extend_target(UiTools CONDITION TARGET Qt::OpenGL
-- LIBRARIES
-- Qt::OpenGL
--)
--qt_internal_add_docs(UiTools
-- doc/qtuitools.qdocconf
--)
--
-diff --git x/qttools/src/uitools/qtuitoolsglobal.h y/qttools/src/uitools/qtuitoolsglobal.h
-deleted file mode 100644
-index a2f967dee..000000000
---- x/qttools/src/uitools/qtuitoolsglobal.h
-+++ /dev/null
-@@ -1,24 +0,0 @@
--// Copyright (C) 2020 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
--
--#ifndef QTUITOOLSGLOBAL_H
--#define QTUITOOLSGLOBAL_H
--
--#include
--
--QT_BEGIN_NAMESPACE
--
--#ifndef QT_STATIC
--# if defined(QT_BUILD_UITOOLS_LIB)
--# define Q_UITOOLS_EXPORT Q_DECL_EXPORT
--# else
--# define Q_UITOOLS_EXPORT Q_DECL_IMPORT
--# endif
--#else
--# define Q_UITOOLS_EXPORT
--#endif
--
--QT_END_NAMESPACE
--
--#endif // QTUITOOLSGLOBAL_H
--
-diff --git x/qttools/src/uitools/quiloader.cpp y/qttools/src/uitools/quiloader.cpp
-deleted file mode 100644
-index a06d4717b..000000000
---- x/qttools/src/uitools/quiloader.cpp
-+++ /dev/null
-@@ -1,914 +0,0 @@
--// Copyright (C) 2020 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
--
--
--#include "quiloader.h"
--#include "quiloader_p.h"
--
--#include
--
--#include
--#include
--#include
--#include
--
--#include
--#include
--#include
--#include
--#include
--#include
--#include
--#include
--#include
--#include
--
--#include
--#include
--
--#include
--#include
--#include
--#include
--#include
--
--QT_BEGIN_NAMESPACE
--
--typedef QMap widget_map;
--Q_GLOBAL_STATIC(widget_map, g_widgets)
--
--class QUiLoader;
--class QUiLoaderPrivate;
--
--#ifndef QT_NO_DATASTREAM
--// QUiTranslatableStringValue must be streamable since they become part of the QVariant-based
--// mime data when dragging items in views with QAbstractItemView::InternalMove.
--QDataStream &operator<<(QDataStream &out, const QUiTranslatableStringValue &s)
--{
-- out << s.qualifier() << s.value();
-- return out;
--}
--
--QDataStream &operator>>(QDataStream &in, QUiTranslatableStringValue &s)
--{
-- QByteArray qualifier, value;
-- in >> qualifier >> value;
-- s.setQualifier(qualifier);
-- s.setValue(value);
-- return in;
--}
--#endif // QT_NO_DATASTREAM
--
--QString QUiTranslatableStringValue::translate(const QByteArray &className, bool idBased) const
--{
-- return idBased
-- ? qtTrId(m_qualifier.constData())
-- : QCoreApplication::translate(className.constData(), m_value.constData(), m_qualifier.constData());
--}
--
--#ifdef QFORMINTERNAL_NAMESPACE
--namespace QFormInternal
--{
--#endif
--
--class TranslatingTextBuilder : public QTextBuilder
--{
--public:
-- explicit TranslatingTextBuilder(bool idBased, bool trEnabled, const QByteArray &className) :
-- m_idBased(idBased), m_trEnabled(trEnabled), m_className(className) {}
--
-- QVariant loadText(const DomProperty *icon) const override;
--
-- QVariant toNativeValue(const QVariant &value) const override;
--
-- bool idBased() const { return m_idBased; }
--
--private:
-- bool m_idBased;
-- bool m_trEnabled;
-- QByteArray m_className;
--};
--
--QVariant TranslatingTextBuilder::loadText(const DomProperty *text) const
--{
-- const DomString *str = text->elementString();
-- if (!str)
-- return QVariant();
-- if (str->hasAttributeNotr()) {
-- const QString notr = str->attributeNotr();
-- if (notr == QStringLiteral("true") || notr == QStringLiteral("yes"))
-- return QVariant::fromValue(str->text());
-- }
-- QUiTranslatableStringValue strVal;
-- strVal.setValue(str->text().toUtf8());
-- if (m_idBased)
-- strVal.setQualifier(str->attributeId().toUtf8());
-- else if (str->hasAttributeComment())
-- strVal.setQualifier(str->attributeComment().toUtf8());
-- return QVariant::fromValue(strVal);
--}
--
--QVariant TranslatingTextBuilder::toNativeValue(const QVariant &value) const
--{
-- if (value.canConvert()) {
-- QUiTranslatableStringValue tsv = qvariant_cast(value);
-- if (!m_trEnabled)
-- return QString::fromUtf8(tsv.value().constData());
-- return QVariant::fromValue(tsv.translate(m_className, m_idBased));
-- }
-- if (value.canConvert())
-- return QVariant::fromValue(qvariant_cast(value));
-- return value;
--}
--
--// This is "exported" to linguist
--const QUiItemRolePair qUiItemRoles[] = {
-- { Qt::DisplayRole, Qt::DisplayPropertyRole },
--#if QT_CONFIG(tooltip)
-- { Qt::ToolTipRole, Qt::ToolTipPropertyRole },
--#endif
--#if QT_CONFIG(statustip)
-- { Qt::StatusTipRole, Qt::StatusTipPropertyRole },
--#endif
--#if QT_CONFIG(whatsthis)
-- { Qt::WhatsThisRole, Qt::WhatsThisPropertyRole },
--#endif
-- { -1 , -1 }
--};
--
--static void recursiveReTranslate(QTreeWidgetItem *item, const QByteArray &class_name, bool idBased)
--{
-- const QUiItemRolePair *irs = qUiItemRoles;
--
-- int cnt = item->columnCount();
-- for (int i = 0; i < cnt; ++i) {
-- for (unsigned j = 0; irs[j].shadowRole >= 0; j++) {
-- QVariant v = item->data(i, irs[j].shadowRole);
-- if (v.isValid()) {
-- QUiTranslatableStringValue tsv = qvariant_cast(v);
-- item->setData(i, irs[j].realRole, tsv.translate(class_name, idBased));
-- }
-- }
-- }
--
-- cnt = item->childCount();
-- for (int i = 0; i < cnt; ++i)
-- recursiveReTranslate(item->child(i), class_name, idBased);
--}
--
--template
--static void reTranslateWidgetItem(T *item, const QByteArray &class_name, bool idBased)
--{
-- const QUiItemRolePair *irs = qUiItemRoles;
--
-- for (unsigned j = 0; irs[j].shadowRole >= 0; j++) {
-- QVariant v = item->data(irs[j].shadowRole);
-- if (v.isValid()) {
-- QUiTranslatableStringValue tsv = qvariant_cast(v);
-- item->setData(irs[j].realRole, tsv.translate(class_name, idBased));
-- }
-- }
--}
--
--static void reTranslateTableItem(QTableWidgetItem *item, const QByteArray &class_name, bool idBased)
--{
-- if (item)
-- reTranslateWidgetItem(item, class_name, idBased);
--}
--
--#define RETRANSLATE_SUBWIDGET_PROP(mainWidget, setter, propName) \
-- do { \
-- QVariant v = mainWidget->widget(i)->property(propName); \
-- if (v.isValid()) { \
-- QUiTranslatableStringValue tsv = qvariant_cast(v); \
-- mainWidget->setter(i, tsv.translate(m_className, m_idBased)); \
-- } \
-- } while (0)
--
--class TranslationWatcher: public QObject
--{
-- Q_OBJECT
--
--public:
-- explicit TranslationWatcher(QObject *parent, const QByteArray &className, bool idBased):
-- QObject(parent),
-- m_className(className),
-- m_idBased(idBased)
-- {
-- }
--
-- bool eventFilter(QObject *o, QEvent *event) override
-- {
-- if (event->type() == QEvent::LanguageChange) {
-- const auto &dynamicPropertyNames = o->dynamicPropertyNames();
-- for (const QByteArray &prop : dynamicPropertyNames) {
-- if (prop.startsWith(PROP_GENERIC_PREFIX)) {
-- const QByteArray propName = prop.mid(sizeof(PROP_GENERIC_PREFIX) - 1);
-- const QUiTranslatableStringValue tsv =
-- qvariant_cast(o->property(prop));
-- o->setProperty(propName, tsv.translate(m_className, m_idBased));
-- }
-- }
-- if (0) {
--#if QT_CONFIG(tabwidget)
-- } else if (QTabWidget *tabw = qobject_cast(o)) {
-- const int cnt = tabw->count();
-- for (int i = 0; i < cnt; ++i) {
-- RETRANSLATE_SUBWIDGET_PROP(tabw, setTabText, PROP_TABPAGETEXT);
--#if QT_CONFIG(tooltip)
-- RETRANSLATE_SUBWIDGET_PROP(tabw, setTabToolTip, PROP_TABPAGETOOLTIP);
--# endif
--#if QT_CONFIG(whatsthis)
-- RETRANSLATE_SUBWIDGET_PROP(tabw, setTabWhatsThis, PROP_TABPAGEWHATSTHIS);
--# endif
-- }
--#endif
--#if QT_CONFIG(listwidget)
-- } else if (QListWidget *listw = qobject_cast(o)) {
-- const int cnt = listw->count();
-- for (int i = 0; i < cnt; ++i)
-- reTranslateWidgetItem(listw->item(i), m_className, m_idBased);
--#endif
--#if QT_CONFIG(treewidget)
-- } else if (QTreeWidget *treew = qobject_cast(o)) {
-- if (QTreeWidgetItem *item = treew->headerItem())
-- recursiveReTranslate(item, m_className, m_idBased);
-- const int cnt = treew->topLevelItemCount();
-- for (int i = 0; i < cnt; ++i) {
-- QTreeWidgetItem *item = treew->topLevelItem(i);
-- recursiveReTranslate(item, m_className, m_idBased);
-- }
--#endif
--#if QT_CONFIG(tablewidget)
-- } else if (QTableWidget *tablew = qobject_cast(o)) {
-- const int row_cnt = tablew->rowCount();
-- const int col_cnt = tablew->columnCount();
-- for (int j = 0; j < col_cnt; ++j)
-- reTranslateTableItem(tablew->horizontalHeaderItem(j), m_className, m_idBased);
-- for (int i = 0; i < row_cnt; ++i) {
-- reTranslateTableItem(tablew->verticalHeaderItem(i), m_className, m_idBased);
-- for (int j = 0; j < col_cnt; ++j)
-- reTranslateTableItem(tablew->item(i, j), m_className, m_idBased);
-- }
--#endif
--#if QT_CONFIG(combobox)
-- } else if (QComboBox *combow = qobject_cast(o)) {
-- if (!qobject_cast(o)) {
-- const int cnt = combow->count();
-- for (int i = 0; i < cnt; ++i) {
-- const QVariant v = combow->itemData(i, Qt::DisplayPropertyRole);
-- if (v.isValid()) {
-- QUiTranslatableStringValue tsv = qvariant_cast(v);
-- combow->setItemText(i, tsv.translate(m_className, m_idBased));
-- }
-- }
-- }
--#endif
--#if QT_CONFIG(toolbox)
-- } else if (QToolBox *toolw = qobject_cast(o)) {
-- const int cnt = toolw->count();
-- for (int i = 0; i < cnt; ++i) {
-- RETRANSLATE_SUBWIDGET_PROP(toolw, setItemText, PROP_TOOLITEMTEXT);
--#if QT_CONFIG(tooltip)
-- RETRANSLATE_SUBWIDGET_PROP(toolw, setItemToolTip, PROP_TOOLITEMTOOLTIP);
--# endif
-- }
--#endif
-- }
-- }
-- return false;
-- }
--
--private:
-- QByteArray m_className;
-- bool m_idBased;
--};
--
--class FormBuilderPrivate: public QFormBuilder
--{
-- friend class QT_PREPEND_NAMESPACE(QUiLoader);
-- friend class QT_PREPEND_NAMESPACE(QUiLoaderPrivate);
-- using ParentClass = QFormBuilder;
--
--public:
-- QUiLoader *loader = nullptr;
--
-- bool dynamicTr = false;
-- bool trEnabled = true;
--
-- FormBuilderPrivate() = default;
--
-- QWidget *defaultCreateWidget(const QString &className, QWidget *parent, const QString &name)
-- {
-- return ParentClass::createWidget(className, parent, name);
-- }
--
-- QLayout *defaultCreateLayout(const QString &className, QObject *parent, const QString &name)
-- {
-- return ParentClass::createLayout(className, parent, name);
-- }
--
-- QAction *defaultCreateAction(QObject *parent, const QString &name)
-- {
-- return ParentClass::createAction(parent, name);
-- }
--
-- QActionGroup *defaultCreateActionGroup(QObject *parent, const QString &name)
-- {
-- return ParentClass::createActionGroup(parent, name);
-- }
--
-- QWidget *createWidget(const QString &className, QWidget *parent, const QString &name) override
-- {
-- if (QWidget *widget = loader->createWidget(className, parent, name)) {
-- widget->setObjectName(name);
-- return widget;
-- }
--
-- return nullptr;
-- }
--
-- QLayout *createLayout(const QString &className, QObject *parent, const QString &name) override
-- {
-- if (QLayout *layout = loader->createLayout(className, parent, name)) {
-- layout->setObjectName(name);
-- return layout;
-- }
--
-- return nullptr;
-- }
--
-- QActionGroup *createActionGroup(QObject *parent, const QString &name) override
-- {
-- if (QActionGroup *actionGroup = loader->createActionGroup(parent, name)) {
-- actionGroup->setObjectName(name);
-- return actionGroup;
-- }
--
-- return nullptr;
-- }
--
-- QAction *createAction(QObject *parent, const QString &name) override
-- {
-- if (QAction *action = loader->createAction(parent, name)) {
-- action->setObjectName(name);
-- return action;
-- }
--
-- return nullptr;
-- }
--
-- void applyProperties(QObject *o, const QList &properties) override;
-- QWidget *create(DomUI *ui, QWidget *parentWidget) override;
-- QWidget *create(DomWidget *ui_widget, QWidget *parentWidget) override;
-- bool addItem(DomWidget *ui_widget, QWidget *widget, QWidget *parentWidget) override;
--
--private:
-- QByteArray m_class;
-- TranslationWatcher *m_trwatch = nullptr;
-- bool m_idBased = false;
--};
--
--static QString convertTranslatable(const DomProperty *p, const QByteArray &className,
-- bool idBased, QUiTranslatableStringValue *strVal)
--{
-- if (p->kind() != DomProperty::String)
-- return QString();
-- const DomString *dom_str = p->elementString();
-- if (!dom_str)
-- return QString();
-- if (dom_str->hasAttributeNotr()) {
-- const QString notr = dom_str->attributeNotr();
-- if (notr == QStringLiteral("yes") || notr == QStringLiteral("true"))
-- return QString();
-- }
-- strVal->setValue(dom_str->text().toUtf8());
-- strVal->setQualifier(idBased ? dom_str->attributeId().toUtf8() : dom_str->attributeComment().toUtf8());
-- if (strVal->value().isEmpty() && strVal->qualifier().isEmpty())
-- return QString();
-- return strVal->translate(className, idBased);
--}
--
--void FormBuilderPrivate::applyProperties(QObject *o, const QList &properties)
--{
-- QFormBuilder::applyProperties(o, properties);
--
-- if (!m_trwatch)
-- m_trwatch = new TranslationWatcher(o, m_class, m_idBased);
--
-- if (properties.isEmpty())
-- return;
--
-- // Unlike string item roles, string properties are not loaded via the textBuilder
-- // (as they are "shadowed" by the property sheets in designer). So do the initial
-- // translation here.
-- bool anyTrs = false;
-- for (const DomProperty *p : properties) {
-- QUiTranslatableStringValue strVal;
-- const QString text = convertTranslatable(p, m_class, m_idBased, &strVal);
-- if (text.isEmpty())
-- continue;
-- const QByteArray name = p->attributeName().toUtf8();
-- if (dynamicTr) {
-- const QByteArray dynname = QByteArray(PROP_GENERIC_PREFIX + name);
-- o->setProperty(dynname, QVariant::fromValue(strVal));
-- anyTrs = trEnabled;
-- }
-- if (p->elementString()->text() != text)
-- o->setProperty(name, text);
-- }
-- if (anyTrs)
-- o->installEventFilter(m_trwatch);
--}
--
--QWidget *FormBuilderPrivate::create(DomUI *ui, QWidget *parentWidget)
--{
-- m_class = ui->elementClass().toUtf8();
-- m_trwatch = nullptr;
-- m_idBased = ui->attributeIdbasedtr();
-- setTextBuilder(new TranslatingTextBuilder(m_idBased, trEnabled, m_class));
-- return QFormBuilder::create(ui, parentWidget);
--}
--
--QWidget *FormBuilderPrivate::create(DomWidget *ui_widget, QWidget *parentWidget)
--{
-- QWidget *w = QFormBuilder::create(ui_widget, parentWidget);
-- if (w == nullptr)
-- return nullptr;
--
-- if (0) {
--#if QT_CONFIG(tabwidget)
-- } else if (qobject_cast(w)) {
--#endif
--#if QT_CONFIG(listwidget)
-- } else if (qobject_cast(w)) {
--#endif
--#if QT_CONFIG(treewidget)
-- } else if (qobject_cast(w)) {
--#endif
--#if QT_CONFIG(tablewidget)
-- } else if (qobject_cast(w)) {
--#endif
--#if QT_CONFIG(combobox)
-- } else if (qobject_cast(w)) {
-- if (qobject_cast(w))
-- return w;
--#endif
--#if QT_CONFIG(toolbox)
-- } else if (qobject_cast(w)) {
--#endif
-- } else {
-- return w;
-- }
-- if (dynamicTr && trEnabled)
-- w->installEventFilter(m_trwatch);
-- return w;
--}
--
--#define TRANSLATE_SUBWIDGET_PROP(mainWidget, attribute, setter, propName) \
-- do { \
-- if (const DomProperty *p##attribute = attributes.value(strings.attribute)) { \
-- QUiTranslatableStringValue strVal; \
-- const QString text = convertTranslatable(p##attribute, m_class, m_idBased, &strVal); \
-- if (!text.isEmpty()) { \
-- if (dynamicTr) \
-- mainWidget->widget(i)->setProperty(propName, QVariant::fromValue(strVal)); \
-- mainWidget->setter(i, text); \
-- } \
-- } \
-- } while (0)
--
--bool FormBuilderPrivate::addItem(DomWidget *ui_widget, QWidget *widget, QWidget *parentWidget)
--{
-- if (parentWidget == nullptr)
-- return true;
--
-- if (!ParentClass::addItem(ui_widget, widget, parentWidget))
-- return false;
--
-- // Check special cases. First: Custom container
-- const QString className = QLatin1String(parentWidget->metaObject()->className());
-- if (!d->customWidgetAddPageMethod(className).isEmpty())
-- return true;
--
-- const QFormBuilderStrings &strings = QFormBuilderStrings::instance();
--
-- if (0) {
--#if QT_CONFIG(tabwidget)
-- } else if (QTabWidget *tabWidget = qobject_cast(parentWidget)) {
-- const DomPropertyHash attributes = propertyMap(ui_widget->elementAttribute());
-- const int i = tabWidget->count() - 1;
-- TRANSLATE_SUBWIDGET_PROP(tabWidget, titleAttribute, setTabText, PROP_TABPAGETEXT);
--#if QT_CONFIG(tooltip)
-- TRANSLATE_SUBWIDGET_PROP(tabWidget, toolTipAttribute, setTabToolTip, PROP_TABPAGETOOLTIP);
--# endif
--#if QT_CONFIG(whatsthis)
-- TRANSLATE_SUBWIDGET_PROP(tabWidget, whatsThisAttribute, setTabWhatsThis, PROP_TABPAGEWHATSTHIS);
--# endif
--#endif
--#if QT_CONFIG(toolbox)
-- } else if (QToolBox *toolBox = qobject_cast(parentWidget)) {
-- const DomPropertyHash attributes = propertyMap(ui_widget->elementAttribute());
-- const int i = toolBox->count() - 1;
-- TRANSLATE_SUBWIDGET_PROP(toolBox, labelAttribute, setItemText, PROP_TOOLITEMTEXT);
--#if QT_CONFIG(tooltip)
-- TRANSLATE_SUBWIDGET_PROP(toolBox, toolTipAttribute, setItemToolTip, PROP_TOOLITEMTOOLTIP);
--# endif
--#endif
-- }
--
-- return true;
--}
--
--#ifdef QFORMINTERNAL_NAMESPACE
--}
--#endif
--
--class QUiLoaderPrivate
--{
--public:
--#ifdef QFORMINTERNAL_NAMESPACE
-- QFormInternal::FormBuilderPrivate builder;
--#else
-- FormBuilderPrivate builder;
--#endif
--
-- void setupWidgetMap() const;
--};
--
--void QUiLoaderPrivate::setupWidgetMap() const
--{
-- if (!g_widgets()->isEmpty())
-- return;
--
--#define DECLARE_WIDGET(a, b) g_widgets()->insert(QLatin1String(#a), true);
--#define DECLARE_LAYOUT(a, b)
--
--#include "widgets.table"
--
--#undef DECLARE_WIDGET
--#undef DECLARE_WIDGET_1
--#undef DECLARE_LAYOUT
--}
--
--/*!
-- \class QUiLoader
-- \inmodule QtUiTools
--
-- \brief The QUiLoader class enables standalone applications to
-- dynamically create user interfaces at run-time using the
-- information stored in UI files or specified in plugin paths.
--
-- In addition, you can customize or create your own user interface by
-- deriving your own loader class.
--
-- If you have a custom component or an application that embeds \QD, you can
-- also use the QFormBuilder class provided by the QtDesigner module to create
-- user interfaces from UI files.
--
-- The QUiLoader class provides a collection of functions allowing you to
-- create widgets based on the information stored in UI files (created
-- with \QD) or available in the specified plugin paths. The specified plugin
-- paths can be retrieved using the pluginPaths() function. Similarly, the
-- contents of a UI file can be retrieved using the load() function. For
-- example:
--
-- \snippet quiloader/mywidget.cpp 0
--
-- \if !defined(qtforpython)
-- By including the user interface in the form's resources (\c myform.qrc), we
-- ensure that it will be present at run-time:
--
-- \quotefile quiloader/mywidget.qrc
-- \endif
--
-- The availableWidgets() function returns a QStringList with the class names
-- of the widgets available in the specified plugin paths. To create these
-- widgets, simply use the createWidget() function. For example:
--
-- \snippet quiloader/main.cpp 0
--
-- To make a custom widget available to the loader, you can use the
-- addPluginPath() function; to remove all available widgets, you can call
-- the clearPluginPaths() function.
--
-- The createAction(), createActionGroup(), createLayout(), and createWidget()
-- functions are used internally by the QUiLoader class whenever it has to
-- create an action, action group, layout, or widget respectively. For that
-- reason, you can subclass the QUiLoader class and reimplement these
-- functions to intervene the process of constructing a user interface. For
-- example, you might want to have a list of the actions created when loading
-- a form or creating a custom widget.
--
-- For a complete example using the QUiLoader class, see the
-- \l{Calculator Builder Example}.
--
-- \sa {Qt UI Tools}, QFormBuilder
--*/
--
--/*!
-- Creates a form loader with the given \a parent.
--*/
--QUiLoader::QUiLoader(QObject *parent)
-- : QObject(parent), d_ptr(new QUiLoaderPrivate)
--{
-- Q_D(QUiLoader);
--
--#ifndef QT_NO_DATASTREAM
-- static int metaTypeId = 0;
-- if (!metaTypeId) {
-- metaTypeId = qRegisterMetaType("QUiTranslatableStringValue");
-- }
--#endif // QT_NO_DATASTREAM
-- d->builder.loader = this;
--
--#if QT_CONFIG(library)
-- QStringList paths;
-- const QStringList &libraryPaths = QApplication::libraryPaths();
-- for (const QString &path : libraryPaths) {
-- QString libPath = path;
-- libPath += QDir::separator();
-- libPath += QStringLiteral("designer");
-- paths.append(libPath);
-- }
--
-- d->builder.setPluginPath(paths);
--#endif // QT_CONFIG(library)
--}
--
--/*!
-- Destroys the loader.
--*/
--QUiLoader::~QUiLoader() = default;
--
--/*!
-- Loads a form from the given \a device and creates a new widget with the
-- given \a parentWidget to hold its contents.
--
-- \sa createWidget(), errorString()
--*/
--QWidget *QUiLoader::load(QIODevice *device, QWidget *parentWidget)
--{
-- Q_D(QUiLoader);
-- // QXmlStreamReader will report errors on open failure.
-- if (!device->isOpen())
-- device->open(QIODevice::ReadOnly|QIODevice::Text);
-- return d->builder.load(device, parentWidget);
--}
--
--/*!
-- Returns a list naming the paths in which the loader will search when
-- locating custom widget plugins.
--
-- \sa addPluginPath(), clearPluginPaths()
--*/
--QStringList QUiLoader::pluginPaths() const
--{
-- Q_D(const QUiLoader);
-- return d->builder.pluginPaths();
--}
--
--/*!
-- Clears the list of paths in which the loader will search when locating
-- plugins.
--
-- \sa addPluginPath(), pluginPaths()
--*/
--void QUiLoader::clearPluginPaths()
--{
-- Q_D(QUiLoader);
-- d->builder.clearPluginPaths();
--}
--
--/*!
-- Adds the given \a path to the list of paths in which the loader will search
-- when locating plugins.
--
-- \sa pluginPaths(), clearPluginPaths()
--*/
--void QUiLoader::addPluginPath(const QString &path)
--{
-- Q_D(QUiLoader);
-- d->builder.addPluginPath(path);
--}
--
--/*!
-- Creates a new widget with the given \a parent and \a name using the class
-- specified by \a className. You can use this function to create any of the
-- widgets returned by the availableWidgets() function.
--
-- The function is also used internally by the QUiLoader class whenever it
-- creates a widget. Hence, you can subclass QUiLoader and reimplement this
-- function to intervene process of constructing a user interface or widget.
-- However, in your implementation, ensure that you call QUiLoader's version
-- first.
--
-- \sa availableWidgets(), load()
--*/
--QWidget *QUiLoader::createWidget(const QString &className, QWidget *parent, const QString &name)
--{
-- Q_D(QUiLoader);
-- return d->builder.defaultCreateWidget(className, parent, name);
--}
--
--/*!
-- Creates a new layout with the given \a parent and \a name using the class
-- specified by \a className.
--
-- The function is also used internally by the QUiLoader class whenever it
-- creates a widget. Hence, you can subclass QUiLoader and reimplement this
-- function to intervene process of constructing a user interface or widget.
-- However, in your implementation, ensure that you call QUiLoader's version
-- first.
--
-- \sa createWidget(), load()
--*/
--QLayout *QUiLoader::createLayout(const QString &className, QObject *parent, const QString &name)
--{
-- Q_D(QUiLoader);
-- return d->builder.defaultCreateLayout(className, parent, name);
--}
--
--/*!
-- Creates a new action group with the given \a parent and \a name.
--
-- The function is also used internally by the QUiLoader class whenever it
-- creates a widget. Hence, you can subclass QUiLoader and reimplement this
-- function to intervene process of constructing a user interface or widget.
-- However, in your implementation, ensure that you call QUiLoader's version
-- first.
--
-- \sa createAction(), createWidget(), load()
-- */
--QActionGroup *QUiLoader::createActionGroup(QObject *parent, const QString &name)
--{
-- Q_D(QUiLoader);
-- return d->builder.defaultCreateActionGroup(parent, name);
--}
--
--/*!
-- Creates a new action with the given \a parent and \a name.
--
-- The function is also used internally by the QUiLoader class whenever it
-- creates a widget. Hence, you can subclass QUiLoader and reimplement this
-- function to intervene process of constructing a user interface or widget.
-- However, in your implementation, ensure that you call QUiLoader's version
-- first.
--
-- \sa createActionGroup(), createWidget(), load()
--*/
--QAction *QUiLoader::createAction(QObject *parent, const QString &name)
--{
-- Q_D(QUiLoader);
-- return d->builder.defaultCreateAction(parent, name);
--}
--
--/*!
-- Returns a list naming all available widgets that can be built using the
-- createWidget() function, i.e all the widgets specified within the given
-- plugin paths.
--
-- \sa pluginPaths(), createWidget()
--
--*/
--QStringList QUiLoader::availableWidgets() const
--{
-- Q_D(const QUiLoader);
--
-- d->setupWidgetMap();
-- widget_map available = *g_widgets();
--
-- const auto &customWidgets = d->builder.customWidgets();
-- for (QDesignerCustomWidgetInterface *plugin : customWidgets)
-- available.insert(plugin->name(), true);
--
-- return available.keys();
--}
--
--
--/*!
-- \since 4.5
-- Returns a list naming all available layouts that can be built using the
-- createLayout() function
--
-- \sa createLayout()
--*/
--
--QStringList QUiLoader::availableLayouts() const
--{
-- QStringList rc;
--#define DECLARE_WIDGET(a, b)
--#define DECLARE_LAYOUT(a, b) rc.push_back(QLatin1String(#a));
--
--#include "widgets.table"
--
--#undef DECLARE_WIDGET
--#undef DECLARE_LAYOUT
-- return rc;
--}
--
--/*!
-- Sets the working directory of the loader to \a dir. The loader will look
-- for other resources, such as icons and resource files, in paths relative to
-- this directory.
--
-- \sa workingDirectory()
--*/
--
--void QUiLoader::setWorkingDirectory(const QDir &dir)
--{
-- Q_D(QUiLoader);
-- d->builder.setWorkingDirectory(dir);
--}
--
--/*!
-- Returns the working directory of the loader.
--
-- \sa setWorkingDirectory()
--*/
--
--QDir QUiLoader::workingDirectory() const
--{
-- Q_D(const QUiLoader);
-- return d->builder.workingDirectory();
--}
--/*!
-- \since 4.5
--
-- If \a enabled is true, user interfaces loaded by this loader will
-- automatically retranslate themselves upon receiving a language change
-- event. Otherwise, the user interfaces will not be retranslated.
--
-- \sa isLanguageChangeEnabled()
--*/
--
--void QUiLoader::setLanguageChangeEnabled(bool enabled)
--{
-- Q_D(QUiLoader);
-- d->builder.dynamicTr = enabled;
--}
--
--/*!
-- \since 4.5
--
-- Returns true if dynamic retranslation on language change is enabled;
-- returns false otherwise.
--
-- \sa setLanguageChangeEnabled()
--*/
--
--bool QUiLoader::isLanguageChangeEnabled() const
--{
-- Q_D(const QUiLoader);
-- return d->builder.dynamicTr;
--}
--
--/*!
-- \internal
-- \since 4.5
--
-- If \a enabled is true, user interfaces loaded by this loader will be
-- translated. Otherwise, the user interfaces will not be translated.
--
-- \note This is orthogonal to languageChangeEnabled.
--
-- \sa isLanguageChangeEnabled(), setLanguageChangeEnabled()
--*/
--
--void QUiLoader::setTranslationEnabled(bool enabled)
--{
-- Q_D(QUiLoader);
-- d->builder.trEnabled = enabled;
--}
--
--/*!
-- \internal
-- \since 4.5
--
-- Returns true if translation is enabled; returns false otherwise.
--
-- \sa setTranslationEnabled()
--*/
--
--bool QUiLoader::isTranslationEnabled() const
--{
-- Q_D(const QUiLoader);
-- return d->builder.trEnabled;
--}
--
--/*!
-- Returns a human-readable description of the last error occurred in load().
--
-- \since 5.0
-- \sa load()
--*/
--
--QString QUiLoader::errorString() const
--{
-- Q_D(const QUiLoader);
-- return d->builder.errorString();
--}
--
--QT_END_NAMESPACE
--
--#include "quiloader.moc"
-diff --git x/qttools/src/uitools/quiloader.h y/qttools/src/uitools/quiloader.h
-deleted file mode 100644
-index 742b5606f..000000000
---- x/qttools/src/uitools/quiloader.h
-+++ /dev/null
-@@ -1,61 +0,0 @@
--// Copyright (C) 2020 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
--
--#ifndef QUILOADER_H
--#define QUILOADER_H
--
--#include
--#include
--#include
--
--QT_BEGIN_NAMESPACE
--
--class QWidget;
--class QLayout;
--class QAction;
--class QActionGroup;
--class QString;
--class QIODevice;
--class QDir;
--
--class QUiLoaderPrivate;
--class Q_UITOOLS_EXPORT QUiLoader : public QObject
--{
-- Q_OBJECT
--public:
-- explicit QUiLoader(QObject *parent = nullptr);
-- ~QUiLoader() override;
--
-- QStringList pluginPaths() const;
-- void clearPluginPaths();
-- void addPluginPath(const QString &path);
--
-- QWidget *load(QIODevice *device, QWidget *parentWidget = nullptr);
-- QStringList availableWidgets() const;
-- QStringList availableLayouts() const;
--
-- virtual QWidget *createWidget(const QString &className, QWidget *parent = nullptr, const QString &name = QString());
-- virtual QLayout *createLayout(const QString &className, QObject *parent = nullptr, const QString &name = QString());
-- virtual QActionGroup *createActionGroup(QObject *parent = nullptr, const QString &name = QString());
-- virtual QAction *createAction(QObject *parent = nullptr, const QString &name = QString());
--
-- void setWorkingDirectory(const QDir &dir);
-- QDir workingDirectory() const;
--
-- void setLanguageChangeEnabled(bool enabled);
-- bool isLanguageChangeEnabled() const;
--
-- void setTranslationEnabled(bool enabled);
-- bool isTranslationEnabled() const;
--
-- QString errorString() const;
--
--private:
-- QScopedPointer d_ptr;
-- Q_DECLARE_PRIVATE(QUiLoader)
-- Q_DISABLE_COPY_MOVE(QUiLoader)
--};
--
--QT_END_NAMESPACE
--
--#endif // QUILOADER_H
-diff --git x/qttools/src/uitools/quiloader_p.h y/qttools/src/uitools/quiloader_p.h
-deleted file mode 100644
-index efd943217..000000000
---- x/qttools/src/uitools/quiloader_p.h
-+++ /dev/null
-@@ -1,77 +0,0 @@
--// Copyright (C) 2020 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
--
--#ifndef QUILOADER_P_H
--#define QUILOADER_P_H
--
--//
--// W A R N I N G
--// -------------
--//
--// This file is not part of the Qt API. It exists purely as an
--// implementation detail. This header file may change from version to
--// version without notice, or even be removed.
--//
--// We mean it.
--//
--
--#include
--#include
--#include
--
--QT_FORWARD_DECLARE_CLASS(QDataStream)
--
--// This file is here for use by the form preview in Linguist. If you change anything
--// here or in the code which uses it, remember to adapt Linguist accordingly.
--
--#define PROP_GENERIC_PREFIX "_q_notr_"
--#define PROP_TOOLITEMTEXT "_q_toolItemText_notr"
--#define PROP_TOOLITEMTOOLTIP "_q_toolItemToolTip_notr"
--#define PROP_TABPAGETEXT "_q_tabPageText_notr"
--#define PROP_TABPAGETOOLTIP "_q_tabPageToolTip_notr"
--#define PROP_TABPAGEWHATSTHIS "_q_tabPageWhatsThis_notr"
--
--QT_BEGIN_NAMESPACE
--
--class Q_UITOOLS_EXPORT QUiTranslatableStringValue
--{
--public:
-- QByteArray value() const { return m_value; }
-- void setValue(const QByteArray &value) { m_value = value; }
-- QByteArray qualifier() const { return m_qualifier; }
-- void setQualifier(const QByteArray &qualifier) { m_qualifier = qualifier; }
--
-- QString translate(const QByteArray &className, bool idBased) const;
--
--private:
-- QByteArray m_value;
-- QByteArray m_qualifier; // Comment or ID for id-based tr().
--};
--
--#ifndef QT_NO_DATASTREAM
--Q_UITOOLS_EXPORT QDataStream &operator<<(QDataStream &out, const QUiTranslatableStringValue &s);
--Q_UITOOLS_EXPORT QDataStream &operator>>(QDataStream &in, QUiTranslatableStringValue &s);
--#endif // QT_NO_DATASTREAM
--
--struct QUiItemRolePair {
-- int realRole;
-- int shadowRole;
--};
--
--#ifdef QFORMINTERNAL_NAMESPACE
--namespace QFormInternal
--{
--#endif
--
--extern const Q_UITOOLS_EXPORT QUiItemRolePair qUiItemRoles[];
--
--#ifdef QFORMINTERNAL_NAMESPACE
--}
--#endif
--
--QT_END_NAMESPACE
--
--Q_DECLARE_METATYPE(QUiTranslatableStringValue)
--
--
--#endif // QUILOADER_P_H
-diff --git x/qttools/sync.profile y/qttools/sync.profile
-index caa7ed5ad..de4261afc 100644
---- x/qttools/sync.profile
-+++ y/qttools/sync.profile
-@@ -1,8 +1,8 @@
- %modules = ( # path to module name map
- "QtTools" => "$basedir/src/global",
- "QtHelp" => "$basedir/src/assistant/help",
-- "QtUiTools" => "$basedir/src/uitools",
-- "QtUiPlugin" => "$basedir/src/uiplugin",
-+ "QtUiTools" => "$basedir/src/designer/src/uitools",
-+ "QtUiPlugin" => "$basedir/src/designer/src/uiplugin",
- "QtDesigner" => "$basedir/src/designer/src/lib",
- "QtDesignerComponents" => "$basedir/src/designer/src/components/lib",
- );
---
-2.38.1
-
diff --git a/libs/patches/qt-webengine-0001-Fix-Linux-build-with-CMake-versions-3.25.patch b/libs/patches/qt-webengine-0001-Fix-Linux-build-with-CMake-versions-3.25.patch
deleted file mode 100644
index 0ded83d..0000000
--- a/libs/patches/qt-webengine-0001-Fix-Linux-build-with-CMake-versions-3.25.patch
+++ /dev/null
@@ -1,39 +0,0 @@
-From dfc2918f8d635edf9300512fc5c1a067a89707d1 Mon Sep 17 00:00:00 2001
-From: Alexey Edelev
-Date: Wed, 23 Nov 2022 12:40:45 +0100
-Subject: Fix Linux build with CMake versions >= 3.25
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-The 'LINUX' variable exists in CMake since the version 3.25. This
-variable previously was undefined while preparsing the configure.cmake
-files. Since the CMake script that defines the 'check_for_ulimit'
-function is not included while evaluating configure.cmake first time
-we need to add a stub.
-
-Change-Id: I25bdec4f4a1b6af23174507a8f0f9cbf01f0c398
-Reviewed-by: Jörg Bornemann
-(cherry picked from commit 240e71877865ed07e4c8d5bd4553aa0772c2adf4)
-Reviewed-by: Qt Cherry-pick Bot
-(cherry picked from commit 517d0890f9e95c841bea3421f2455651ca0d8070)
----
- configure.cmake | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git x/qtwebengine/configure.cmake y/qtwebengine/configure.cmake
-index f485c1b4b..fff76d54a 100644
---- x/qtwebengine/configure.cmake
-+++ y/qtwebengine/configure.cmake
-@@ -3,6 +3,8 @@ if(QT_CONFIGURE_RUNNING)
- endfunction()
- function(add_check_for_support)
- endfunction()
-+ function(check_for_ulimit)
-+ endfunction()
- else()
- find_package(Ninja 1.7.2)
- find_package(Gn ${QT_REPO_MODULE_VERSION} EXACT)
---
-2.38.1
-
diff --git a/libs/patches/qtbase-0001-Revert-Fix-usage-of-logging-category-on-Android.patch b/libs/patches/qtbase-0001-Revert-Fix-usage-of-logging-category-on-Android.patch
new file mode 100644
index 0000000..8a73295
--- /dev/null
+++ b/libs/patches/qtbase-0001-Revert-Fix-usage-of-logging-category-on-Android.patch
@@ -0,0 +1,40 @@
+From 68bc2e3fae6480d6315f524c2ee9acf3a33a435a Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Andr=C3=A9=20Klitzing?=
+Date: Mon, 25 Jul 2022 17:08:54 +0200
+Subject: Revert "Fix usage of logging category on Android"
+
+This reverts commit 87d8ee755bfdef8e72a122789c2e3ed382881a12.
+
+Change-Id: If19a9d615e01d61c79955cda4789ba1646520ee1
+---
+ src/corelib/global/qlogging.cpp | 9 +--------
+ 1 file changed, 1 insertion(+), 8 deletions(-)
+
+diff --git x/qtbase/src/corelib/global/qlogging.cpp y/qtbase/src/corelib/global/qlogging.cpp
+index 9ac70b3340..737a91dc6e 100644
+--- x/qtbase/src/corelib/global/qlogging.cpp
++++ y/qtbase/src/corelib/global/qlogging.cpp
+@@ -1450,10 +1450,7 @@ QString qFormatLogMessage(QtMsgType type, const QMessageLogContext &context, con
+ } else if (token == messageTokenC) {
+ message.append(str);
+ } else if (token == categoryTokenC) {
+-#ifndef Q_OS_ANDROID
+- // Don't add the category to the message on Android
+ message.append(QLatin1StringView(context.category));
+-#endif
+ } else if (token == typeTokenC) {
+ switch (type) {
+ case QtDebugMsg: message.append("debug"_L1); break;
+@@ -1701,11 +1698,7 @@ static bool android_default_message_handler(QtMsgType type,
+ break;
+ };
+
+- // If application name is a tag ensure it has no spaces
+- // If a category is defined, use it as an Android logging tag
+- __android_log_print(priority, isDefaultCategory(context.category) ?
+- qPrintable(QCoreApplication::applicationName().replace(u' ', u'_')) : context.category,
+- "%s\n", qPrintable(formattedMessage));
++ __android_log_print(priority, qPrintable(QCoreApplication::applicationName()), "%s\n", qPrintable(formattedMessage));
+
+ return true; // Prevent further output to stderr
+ }
diff --git a/libs/patches/qtbase-0002-Android-Restore-the-default-QSettings-path-to-the-.c.patch b/libs/patches/qtbase-0002-Android-Restore-the-default-QSettings-path-to-the-.c.patch
new file mode 100644
index 0000000..13641dc
--- /dev/null
+++ b/libs/patches/qtbase-0002-Android-Restore-the-default-QSettings-path-to-the-.c.patch
@@ -0,0 +1,89 @@
+From bdd9f0e3a243977858df6691b734b7f596a9729b Mon Sep 17 00:00:00 2001
+From: Bartlomiej Moskal
+Date: Tue, 30 May 2023 14:17:19 +0200
+Subject: Android: Restore the default QSettings path to the .config directory
+
+After 140ca89a3c2b8d78889d27217f977cd4de10041b commit, the path of the
+QSettings default file location changed. That caused the problem with
+updating the app (old settings file is not used anymore). That is why we
+should still use old (.config) directory for QSettings file if the file
+exists.
+
+Pick-to: 6.2 6.5 6.6
+Fixes: QTBUG-109405
+Fixes: QTBUG-109369
+Change-Id: I8ce53e0a80e4c2d16802b27b000ab3fbed198628
+Reviewed-by: Assam Boudjelthia
+(cherry picked from commit beaaa0bf02fee696b03f2839bea8e0e6bc685a62)
+---
+ src/corelib/io/qsettings.cpp | 40 +++++++++++++++++++++++++-----------
+ 1 file changed, 28 insertions(+), 12 deletions(-)
+
+diff --git x/qtbase/src/corelib/io/qsettings.cpp y/qtbase/src/corelib/io/qsettings.cpp
+index 60622e3aaa..9fb2e0b522 100644
+--- x/qtbase/src/corelib/io/qsettings.cpp
++++ y/qtbase/src/corelib/io/qsettings.cpp
+@@ -954,26 +954,43 @@ static inline int pathHashKey(QSettings::Format format, QSettings::Scope scope)
+ }
+
+ #ifndef Q_OS_WIN
+-static QString make_user_path()
++static constexpr QChar sep = u'/';
++
++#if !defined(QSETTINGS_USE_QSTANDARDPATHS) || defined(Q_OS_ANDROID)
++static QString make_user_path_without_qstandard_paths()
+ {
+- static constexpr QChar sep = u'/';
+-#ifndef QSETTINGS_USE_QSTANDARDPATHS
+- // Non XDG platforms (OS X, iOS, Android...) have used this code path erroneously
+- // for some time now. Moving away from that would require migrating existing settings.
+ QByteArray env = qgetenv("XDG_CONFIG_HOME");
+ if (env.isEmpty()) {
+ return QDir::homePath() + "/.config/"_L1;
+ } else if (env.startsWith('/')) {
+ return QFile::decodeName(env) + sep;
+- } else {
+- return QDir::homePath() + sep + QFile::decodeName(env) + sep;
+ }
++
++ return QDir::homePath() + sep + QFile::decodeName(env) + sep;
++}
++#endif // !QSETTINGS_USE_QSTANDARDPATHS || Q_OS_ANDROID
++
++static QString make_user_path()
++{
++#ifndef QSETTINGS_USE_QSTANDARDPATHS
++ // Non XDG platforms (OS X, iOS, Android...) have used this code path erroneously
++ // for some time now. Moving away from that would require migrating existing settings.
++ // The migration has already been done for Android.
++ return make_user_path_without_qstandard_paths();
+ #else
+- // When using a proper XDG platform, use QStandardPaths rather than the above hand-written code;
+- // it makes the use of test mode from unit tests possible.
++
++#ifdef Q_OS_ANDROID
++ // If an old settings path exists, use it instead of creating a new one
++ QString ret = make_user_path_without_qstandard_paths();
++ if (QFile(ret).exists())
++ return ret;
++#endif // Q_OS_ANDROID
++
++ // When using a proper XDG platform or Android platform, use QStandardPaths rather than the
++ // above hand-written code. It makes the use of test mode from unit tests possible.
+ // Ideally all platforms should use this, but see above for the migration issue.
+ return QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + sep;
+-#endif
++#endif // !QSETTINGS_USE_QSTANDARDPATHS
+ }
+ #endif // !Q_OS_WIN
+
+@@ -1338,8 +1355,7 @@ void QConfFileSettingsPrivate::syncConfFile(QConfFile *confFile)
+ // On android and if it is a content URL put the lock file in a
+ // writable location to prevent permissions issues and invalid paths.
+ if (confFile->name.startsWith("content:"_L1))
+- lockFileName = QStandardPaths::writableLocation(QStandardPaths::CacheLocation)
+- + QFileInfo(lockFileName).fileName();
++ lockFileName = make_user_path() + QFileInfo(lockFileName).fileName();
+ # endif
+ /*
+ Use a lockfile in order to protect us against other QSettings instances
diff --git a/libs/patches/qtbase-0003-Android-A11Y-Only-access-the-main-thread-when-it-is-.patch b/libs/patches/qtbase-0003-Android-A11Y-Only-access-the-main-thread-when-it-is-.patch
new file mode 100644
index 0000000..df11194
--- /dev/null
+++ b/libs/patches/qtbase-0003-Android-A11Y-Only-access-the-main-thread-when-it-is-.patch
@@ -0,0 +1,63 @@
+From a7490023e8f11906b30013c93ff991d941efc622 Mon Sep 17 00:00:00 2001
+From: Julian Greilich
+Date: Wed, 4 Jan 2023 16:32:28 +0100
+Subject: Android A11Y: Only access the main thread when it is not blocked
+
+When the qtMainLoopThread calls QSGThreadedRenderLoop::polishAndSync(),
+it waits for the QSGRenderThread.
+
+In the QSGRenderThread, QAndroidPlatformOpenGLWindow::eglSurface()
+calls QtAndroid::createSurface() and waits for the "android main
+thread" to return a valid surface.
+When the "android main thread" now calls "runInObjectContext" (e.g. by
+calling QtAndroidAccessibility::childIdListForAccessibleObject()) it
+waits for the qtMainLoopThread and the program is stuck in a deadlock.
+
+To prevent this, we protect all BlockedQueuedConnection from the
+"android main thread" to the qtMainLoopThread by acquiring the
+AndroidDeadlockProtector.
+When QAndroidPlatformOpenGLWindow::eglSurface() already acquired the
+AndroidDeadlockProtector we abort the current A11y call with an emtpy
+or default value.
+
+Note: b8a95275440b8a143ee648466fd8b5401ee1e839 already tried to fix
+this by checking "getSurfaceCount() != 0", but there are situations,
+where a new surface is being created while an old surface is still
+present.
+
+Task-number: QTBUG-105958
+Pick-to: 6.5 6.4 6.3 6.2 5.15
+Change-Id: Ie40e8654c99aace9e69b0b8412952fa22c89f071
+Reviewed-by: Assam Boudjelthia
+(cherry picked from commit b832a5ac72c6015b6509d60b75b2ce5d5e570800)
+---
+ .../platforms/android/androidjniaccessibility.cpp | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git x/qtbase/src/plugins/platforms/android/androidjniaccessibility.cpp y/qtbase/src/plugins/platforms/android/androidjniaccessibility.cpp
+index 3067cb178a..8990289dc4 100644
+--- x/qtbase/src/plugins/platforms/android/androidjniaccessibility.cpp
++++ y/qtbase/src/plugins/platforms/android/androidjniaccessibility.cpp
+@@ -1,6 +1,7 @@
+ // Copyright (C) 2021 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
+
++#include "androiddeadlockprotector.h"
+ #include "androidjniaccessibility.h"
+ #include "androidjnimain.h"
+ #include "qandroidplatformintegration.h"
+@@ -61,6 +62,14 @@ namespace QtAndroidAccessibility
+ template
+ void runInObjectContext(QObject *context, Func &&func, Ret *retVal)
+ {
++ AndroidDeadlockProtector protector;
++ if (!protector.acquire()) {
++ __android_log_print(ANDROID_LOG_WARN, m_qtTag,
++ "Could not run accessibility call in object context, accessing "
++ "main thread could lead to deadlock");
++ return;
++ }
++
+ if (!QtAndroid::blockEventLoopsWhenSuspended()
+ || QGuiApplication::applicationState() != Qt::ApplicationSuspended) {
+ QMetaObject::invokeMethod(context, func, Qt::BlockingQueuedConnection, retVal);
diff --git a/libs/patches/qtbase-0004-Fix-warning-in-q20algorithm.h-when-xcodebuild-is-use.patch b/libs/patches/qtbase-0004-Fix-warning-in-q20algorithm.h-when-xcodebuild-is-use.patch
new file mode 100644
index 0000000..e9761b1
--- /dev/null
+++ b/libs/patches/qtbase-0004-Fix-warning-in-q20algorithm.h-when-xcodebuild-is-use.patch
@@ -0,0 +1,46 @@
+From 03485e0ca36c615b87b82c6711fbacf0493d02bc Mon Sep 17 00:00:00 2001
+From: Lars Schmertmann
+Date: Mon, 9 Jan 2023 06:54:53 +0100
+Subject: Fix warning in q20algorithm.h when xcodebuild is used
+
+q20algorithm.h:150:20: error: unused function template 'operator()'
+q20algorithm.h:163:20: error: unused function template 'operator()'
+q20algorithm.h:176:20: error: unused function template 'operator()'
+
+Fixes: QTBUG-109874
+Change-Id: If5ccbfffd0b6a53f73f221b45033dab7e4775d89
+---
+ src/corelib/global/q20algorithm.h | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git x/qtbase/src/corelib/global/q20algorithm.h y/qtbase/src/corelib/global/q20algorithm.h
+index 69dc2d2446..88e8ab08d2 100644
+--- x/qtbase/src/corelib/global/q20algorithm.h
++++ y/qtbase/src/corelib/global/q20algorithm.h
+@@ -147,7 +147,7 @@ using std::ranges::none_of;
+ [[maybe_unused]] inline constexpr struct { // Niebloid
+ template
+- constexpr bool operator()(InputIterator first, Sentinel last, Predicate pred, Projection proj = {}) const
++ [[maybe_unused]] constexpr bool operator()(InputIterator first, Sentinel last, Predicate pred, Projection proj = {}) const
+ {
+ while (first != last) {
+ if (std::invoke(pred, std::invoke(proj, *first)))
+@@ -160,7 +160,7 @@ using std::ranges::none_of;
+ [[maybe_unused]] inline constexpr struct { // Niebloid
+ template
+- constexpr bool operator()(InputIterator first, Sentinel last, Predicate pred, Projection proj = {}) const
++ [[maybe_unused]] constexpr bool operator()(InputIterator first, Sentinel last, Predicate pred, Projection proj = {}) const
+ {
+ while (first != last) {
+ if (!std::invoke(pred, std::invoke(proj, *first)))
+@@ -173,7 +173,7 @@ using std::ranges::none_of;
+ [[maybe_unused]] inline constexpr struct { // Niebloid
+ template
+- constexpr bool operator()(InputIterator first, Sentinel last, Predicate pred, Projection proj = {}) const
++ [[maybe_unused]] constexpr bool operator()(InputIterator first, Sentinel last, Predicate pred, Projection proj = {}) const
+ {
+ while (first != last) {
+ if (std::invoke(pred, std::invoke(proj, *first)))
diff --git a/libs/patches/qtbase-0005-macOS-Use-NSStatusItem.menu-to-manage-system-tray-me.patch b/libs/patches/qtbase-0005-macOS-Use-NSStatusItem.menu-to-manage-system-tray-me.patch
new file mode 100644
index 0000000..85819c9
--- /dev/null
+++ b/libs/patches/qtbase-0005-macOS-Use-NSStatusItem.menu-to-manage-system-tray-me.patch
@@ -0,0 +1,127 @@
+From e2402debef95b7ccc2050f331ee9f5076332ae91 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?=
+Date: Mon, 12 Dec 2022 14:33:41 +0100
+Subject: macOS: Use NSStatusItem.menu to manage system tray menu
+
+Using [NSStatusItem popUpStatusItemMenu:] to manually show the menu is
+deprecated, and was causing various issues when right clicking the menu,
+such as not unhighlighting the menu item when dismissing the menu, or
+worse, not quitting the application if a 'Quit' item was triggered from
+a right click.
+
+The reason we were using popUpStatusItemMenu instead of the menu
+property of NSStatusItem was that the latter prevented us from seeing
+the action message of the NSStatusItem button, which we used to emit
+the system tray's activated signal, but this can be solved by listing
+for the menu's tracking state starting.
+
+Fixes: QTBUG-103515
+Pick-to: 6.4
+Change-Id: I686550ebac7d94d8d11b2e3c49ed16a8240cb214
+Reviewed-by: Volker Hilsheimer
+(cherry picked from commit da754d5b6589c9877f0325edb3da5cbc64d966c7)
+---
+ .../platforms/cocoa/qcocoasystemtrayicon.h | 3 +-
+ .../platforms/cocoa/qcocoasystemtrayicon.mm | 36 ++++++++++++-------
+ 2 files changed, 24 insertions(+), 15 deletions(-)
+
+diff --git x/qtbase/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h y/qtbase/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h
+index 414560e119..75c33cc5a3 100644
+--- x/qtbase/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h
++++ y/qtbase/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h
+@@ -45,12 +45,11 @@ public:
+ bool isSystemTrayAvailable() const override;
+ bool supportsMessages() const override;
+
+- void statusItemClicked();
++ void emitActivated();
+
+ private:
+ NSStatusItem *m_statusItem = nullptr;
+ QStatusItemDelegate *m_delegate = nullptr;
+- QCocoaMenu *m_menu = nullptr;
+ };
+
+ QT_END_NAMESPACE
+diff --git x/qtbase/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm y/qtbase/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
+index c004cd69b5..2f7f73b481 100644
+--- x/qtbase/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
++++ y/qtbase/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
+@@ -64,6 +64,8 @@ void QCocoaSystemTrayIcon::init()
+
+ m_delegate = [[QStatusItemDelegate alloc] initWithSysTray:this];
+
++ // In case the status item does not have a menu assigned to it
++ // we fall back to the item's button to detect activation.
+ m_statusItem.button.target = m_delegate;
+ m_statusItem.button.action = @selector(statusItemClicked);
+ [m_statusItem.button sendActionOn:NSEventMaskLeftMouseDown | NSEventMaskRightMouseDown | NSEventMaskOtherMouseDown];
+@@ -81,8 +83,6 @@ void QCocoaSystemTrayIcon::cleanup()
+
+ [m_delegate release];
+ m_delegate = nil;
+-
+- m_menu = nullptr;
+ }
+
+ QRect QCocoaSystemTrayIcon::geometry() const
+@@ -178,12 +178,20 @@ void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon)
+
+ void QCocoaSystemTrayIcon::updateMenu(QPlatformMenu *menu)
+ {
+- // We don't set the menu property of the NSStatusItem here,
+- // as that would prevent us from receiving the action for the
+- // click, and we wouldn't be able to emit the activated signal.
+- // Instead we show the menu manually when the status item is
+- // clicked.
+- m_menu = static_cast(menu);
++ m_statusItem.menu = menu ? static_cast(menu)->nsMenu() : nil;
++
++ if (m_statusItem.menu) {
++ // When a menu is assigned, NSStatusBarButtonCell will intercept the mouse
++ // down to pop up the menu, and we never see the NSStatusBarButton action.
++ // To ensure we emit the 'activated' signal in both cases we detect when
++ // menu starts tracking, which happens before the menu delegate is sent
++ // the menuWillOpen callback we use to emit aboutToShow for the menu.
++ [NSNotificationCenter.defaultCenter addObserver:m_delegate
++ selector:@selector(statusItemMenuBeganTracking:)
++ name:NSMenuDidBeginTrackingNotification
++ object:m_statusItem.menu
++ ];
++ }
+ }
+
+ void QCocoaSystemTrayIcon::updateToolTip(const QString &toolTip)
+@@ -226,7 +234,7 @@ void QCocoaSystemTrayIcon::showMessage(const QString &title, const QString &mess
+ }
+ }
+
+-void QCocoaSystemTrayIcon::statusItemClicked()
++void QCocoaSystemTrayIcon::emitActivated()
+ {
+ auto *mouseEvent = NSApp.currentEvent;
+
+@@ -245,9 +253,6 @@ void QCocoaSystemTrayIcon::statusItemClicked()
+ }
+
+ emit activated(activationReason);
+-
+- if (NSMenu *menu = m_menu ? m_menu->nsMenu() : nil)
+- QT_IGNORE_DEPRECATIONS([m_statusItem popUpStatusItemMenu:menu]);
+ }
+
+ QT_END_NAMESPACE
+@@ -270,7 +275,12 @@ QT_END_NAMESPACE
+
+ - (void)statusItemClicked
+ {
+- self.platformSystemTray->statusItemClicked();
++ self.platformSystemTray->emitActivated();
++}
++
++- (void)statusItemMenuBeganTracking:(NSNotification*)notification
++{
++ self.platformSystemTray->emitActivated();
+ }
+
+ - (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center shouldPresentNotification:(NSUserNotification *)notification
diff --git a/libs/patches/qtbase-0006-iOS-Don-t-assume-screens-will-not-be-connected-befor.patch b/libs/patches/qtbase-0006-iOS-Don-t-assume-screens-will-not-be-connected-befor.patch
new file mode 100644
index 0000000..63c2ce9
--- /dev/null
+++ b/libs/patches/qtbase-0006-iOS-Don-t-assume-screens-will-not-be-connected-befor.patch
@@ -0,0 +1,41 @@
+From d967022bcd7061771f10e4d36d38ab8ffe5aef98 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?=
+Date: Thu, 15 Dec 2022 16:40:34 +0100
+Subject: iOS: Don't assume screens will not be connected before
+ QIOSIntegration
+
+When an external screen is connected to an iPad, and the application is
+starting up on that screen, we will get a connection notification about
+that screen as part of the initial bootstrap of UIApplicationMain,
+before we call the user's main().
+
+Since we initialize and add all available screen on QIOSIntegration
+creation, we can just ignore the early connection notification.
+
+This avoids a crash, but the window will not show anything on the
+external screen, which is a separate issue.
+
+Pick-to: 6.5 6.4 6.2
+Fixes: QTBUG-106701
+Change-Id: I9e0a9736bf602277316bd004e0d01c640feaf319
+Reviewed-by: Volker Hilsheimer
+(cherry picked from commit dd49793bc3b4dd3808f0f24b717c442a5095db14)
+---
+ src/plugins/platforms/ios/qiosscreen.mm | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git x/qtbase/src/plugins/platforms/ios/qiosscreen.mm y/qtbase/src/plugins/platforms/ios/qiosscreen.mm
+index f144c00fb0..3d660189af 100644
+--- x/qtbase/src/plugins/platforms/ios/qiosscreen.mm
++++ y/qtbase/src/plugins/platforms/ios/qiosscreen.mm
+@@ -72,8 +72,8 @@ static QIOSScreen* qtPlatformScreenFor(UIScreen *uiScreen)
+
+ + (void)screenConnected:(NSNotification*)notification
+ {
+- Q_ASSERT_X(QIOSIntegration::instance(), Q_FUNC_INFO,
+- "Screen connected before QIOSIntegration creation");
++ if (!QIOSIntegration::instance())
++ return; // Will be added when QIOSIntegration is created
+
+ QWindowSystemInterface::handleScreenAdded(new QIOSScreen([notification object]));
+ }
diff --git a/libs/patches/qtbase-0007-Ignore-removed-changed-screens-if-no-QIOSIntegration.patch b/libs/patches/qtbase-0007-Ignore-removed-changed-screens-if-no-QIOSIntegration.patch
new file mode 100644
index 0000000..ff42334
--- /dev/null
+++ b/libs/patches/qtbase-0007-Ignore-removed-changed-screens-if-no-QIOSIntegration.patch
@@ -0,0 +1,54 @@
+From 6d6832fc530c9296d92dd924f6f6bca0effa6412 Mon Sep 17 00:00:00 2001
+From: Jan Moeller
+Date: Thu, 6 Apr 2023 09:27:16 +0200
+Subject: Ignore removed/changed screens if no QIOSIntegration instance exists
+
+QIOSTracker registers itself as handlers for system notifications about
+changes of the screen environment. If no QIOSIntegration instance
+exists, newly detected screens are not added to the list of known
+screens (see screenConnected()). This, in turn, will result in a crash
+if a screen is disconnected and removed in screenDisconnected() as it
+is not known to qtPlatformScreenFor() and the function returns a
+nullptr.
+
+Consider the QIOSIntegration also whenever a screen is "changed". This
+is more of a safety measure do avoid crashes for unknown screens.
+
+This situation occurs if an iOS device is used to mirror the display
+via AirPlay and no actual QGuiApplication exists, e.g. Qt is only
+embedded in a Framework.
+
+Pick-to: 6.5 6.2
+Fixes: QTBUG-106701
+Change-Id: Id778fc5afa7c284b0536ee02b1ba2c10321cc5b1
+Reviewed-by: Volker Hilsheimer
+Reviewed-by: Lars Schmertmann
+(cherry picked from commit ffdfafc4b47b8267395370199073c292da33dd42)
+---
+ src/plugins/platforms/ios/qiosscreen.mm | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git x/qtbase/src/plugins/platforms/ios/qiosscreen.mm y/qtbase/src/plugins/platforms/ios/qiosscreen.mm
+index 3d660189af..e0216ce652 100644
+--- x/qtbase/src/plugins/platforms/ios/qiosscreen.mm
++++ y/qtbase/src/plugins/platforms/ios/qiosscreen.mm
+@@ -80,6 +80,9 @@ static QIOSScreen* qtPlatformScreenFor(UIScreen *uiScreen)
+
+ + (void)screenDisconnected:(NSNotification*)notification
+ {
++ if (!QIOSIntegration::instance())
++ return;
++
+ QIOSScreen *screen = qtPlatformScreenFor([notification object]);
+ Q_ASSERT_X(screen, Q_FUNC_INFO, "Screen disconnected that we didn't know about");
+
+@@ -88,6 +91,9 @@ static QIOSScreen* qtPlatformScreenFor(UIScreen *uiScreen)
+
+ + (void)screenModeChanged:(NSNotification*)notification
+ {
++ if (!QIOSIntegration::instance())
++ return;
++
+ QIOSScreen *screen = qtPlatformScreenFor([notification object]);
+ Q_ASSERT_X(screen, Q_FUNC_INFO, "Screen changed that we didn't know about");
+
diff --git a/libs/patches/qtbase-0008-Fix-specific-overflow-in-qtextlayout.patch b/libs/patches/qtbase-0008-Fix-specific-overflow-in-qtextlayout.patch
new file mode 100644
index 0000000..ba82d24
--- /dev/null
+++ b/libs/patches/qtbase-0008-Fix-specific-overflow-in-qtextlayout.patch
@@ -0,0 +1,75 @@
+From 25b9264bd6e5a547db3692032dd5c49cb2db0bfd Mon Sep 17 00:00:00 2001
+From: Allan Sandfeld Jensen
+Date: Fri, 5 May 2023 09:51:32 +0200
+Subject: Fix specific overflow in qtextlayout
+
+Adds qAddOverflow and qMulOverflow definitions to QFixed
+
+Fixes: QTBUG-113337
+Pick-to: 6.5 6.5.1 6.2 5.15
+Change-Id: I13579306defceaccdc0fbb1ec0e9b77c6f8d1af9
+Reviewed-by: Eirik Aavitsland
+Reviewed-by: Thiago Macieira
+(cherry picked from commit 7b7a01c266b507636eab51a36328c7c72d82d93c)
+---
+ src/gui/painting/qfixed_p.h | 17 +++++++++++++++++
+ src/gui/text/qtextlayout.cpp | 9 ++++++---
+ 2 files changed, 23 insertions(+), 3 deletions(-)
+
+diff --git x/qtbase/src/gui/painting/qfixed_p.h y/qtbase/src/gui/painting/qfixed_p.h
+index f3718a097e..c0a13d057f 100644
+--- x/qtbase/src/gui/painting/qfixed_p.h
++++ y/qtbase/src/gui/painting/qfixed_p.h
+@@ -18,6 +18,7 @@
+ #include
+ #include "QtCore/qdebug.h"
+ #include "QtCore/qpoint.h"
++#include "QtCore/qnumeric.h"
+ #include "QtCore/qsize.h"
+
+ QT_BEGIN_NAMESPACE
+@@ -136,6 +137,22 @@ constexpr inline QFixed operator+(uint i, QFixed d) { return d+i; }
+ constexpr inline QFixed operator-(uint i, QFixed d) { return -(d-i); }
+ // constexpr inline QFixed operator*(qreal d, QFixed d2) { return d2*d; }
+
++inline bool qAddOverflow(QFixed v1, QFixed v2, QFixed *r)
++{
++ int val;
++ bool result = qAddOverflow(v1.value(), v2.value(), &val);
++ r->setValue(val);
++ return result;
++}
++
++inline bool qMulOverflow(QFixed v1, QFixed v2, QFixed *r)
++{
++ int val;
++ bool result = qMulOverflow(v1.value(), v2.value(), &val);
++ r->setValue(val);
++ return result;
++}
++
+ #ifndef QT_NO_DEBUG_STREAM
+ inline QDebug &operator<<(QDebug &dbg, QFixed f)
+ { return dbg << f.toReal(); }
+diff --git x/qtbase/src/gui/text/qtextlayout.cpp y/qtbase/src/gui/text/qtextlayout.cpp
+index 365131f508..6a36b2458a 100644
+--- x/qtbase/src/gui/text/qtextlayout.cpp
++++ y/qtbase/src/gui/text/qtextlayout.cpp
+@@ -2105,11 +2105,14 @@ found:
+ eng->maxWidth = qMax(eng->maxWidth, line.textWidth);
+ } else {
+ eng->minWidth = qMax(eng->minWidth, lbh.minw);
+- eng->maxWidth += line.textWidth;
++ if (qAddOverflow(eng->maxWidth, line.textWidth, &eng->maxWidth))
++ eng->maxWidth = QFIXED_MAX;
+ }
+
+- if (line.textWidth > 0 && item < eng->layoutData->items.size())
+- eng->maxWidth += lbh.spaceData.textWidth;
++ if (line.textWidth > 0 && item < eng->layoutData->items.size()) {
++ if (qAddOverflow(eng->maxWidth, lbh.spaceData.textWidth, &eng->maxWidth))
++ eng->maxWidth = QFIXED_MAX;
++ }
+
+ line.textWidth += trailingSpace;
+ if (lbh.spaceData.length) {
diff --git a/libs/patches/qtbase-0009-Schannel-Reject-certificate-not-signed-by-a-configur.patch b/libs/patches/qtbase-0009-Schannel-Reject-certificate-not-signed-by-a-configur.patch
new file mode 100644
index 0000000..9f1a1ec
--- /dev/null
+++ b/libs/patches/qtbase-0009-Schannel-Reject-certificate-not-signed-by-a-configur.patch
@@ -0,0 +1,289 @@
+From 550172c8a2f5e7195e2255bc50cffb2a64b8701c Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?M=C3=A5rten=20Nordheim?=
+Date: Wed, 10 May 2023 16:43:41 +0200
+Subject: Schannel: Reject certificate not signed by a configured CA
+ certificate
+
+Not entirely clear why, but when building the certificate chain for a
+peer the system certificate store is searched for root certificates.
+General expectation is that after calling
+`sslConfiguration.setCaCertificates()` the system certificates will
+not be taken into consideration.
+
+To work around this behavior, we do a manual check that the root of the
+chain is part of the configured CA certificates.
+
+Pick-to: 6.5 6.2 5.15
+Change-Id: I03666a4d9b0eac39ae97e150b4743120611a11b3
+Reviewed-by: Edward Welbourne
+Reviewed-by: Volker Hilsheimer
+(cherry picked from commit ada2c573c1a25f8d96577734968fe317ddfa292a)
+---
+ src/plugins/tls/schannel/qtls_schannel.cpp | 21 ++++
+ .../network/ssl/client-auth/CMakeLists.txt | 24 ++++
+ .../network/ssl/client-auth/certs/.gitignore | 4 +
+ .../client-auth/certs/accepted-client.conf | 14 +++
+ .../network/ssl/client-auth/certs/generate.sh | 33 +++++
+ .../tst_manual_ssl_client_auth.cpp | 118 ++++++++++++++++++
+ 6 files changed, 214 insertions(+)
+ create mode 100644 tests/manual/network/ssl/client-auth/CMakeLists.txt
+ create mode 100644 tests/manual/network/ssl/client-auth/certs/.gitignore
+ create mode 100644 tests/manual/network/ssl/client-auth/certs/accepted-client.conf
+ create mode 100755 tests/manual/network/ssl/client-auth/certs/generate.sh
+ create mode 100644 tests/manual/network/ssl/client-auth/tst_manual_ssl_client_auth.cpp
+
+diff --git x/qtbase/src/plugins/tls/schannel/qtls_schannel.cpp y/qtbase/src/plugins/tls/schannel/qtls_schannel.cpp
+index 58e74357d8..c15eab8796 100644
+--- x/qtbase/src/plugins/tls/schannel/qtls_schannel.cpp
++++ y/qtbase/src/plugins/tls/schannel/qtls_schannel.cpp
+@@ -2106,6 +2106,27 @@ bool TlsCryptographSchannel::verifyCertContext(CERT_CONTEXT *certContext)
+ verifyDepth = DWORD(q->peerVerifyDepth());
+
+ const auto &caCertificates = q->sslConfiguration().caCertificates();
++
++ if (!rootCertOnDemandLoadingAllowed()
++ && !(chain->TrustStatus.dwErrorStatus & CERT_TRUST_IS_PARTIAL_CHAIN)
++ && (q->peerVerifyMode() == QSslSocket::VerifyPeer
++ || (isClient && q->peerVerifyMode() == QSslSocket::AutoVerifyPeer))) {
++ // When verifying a peer Windows "helpfully" builds a chain that
++ // may include roots from the system store. But we don't want that if
++ // the user has set their own CA certificates.
++ // Since Windows claims this is not a partial chain the root is included
++ // and we have to check that it is one of our configured CAs.
++ CERT_CHAIN_ELEMENT *element = chain->rgpElement[chain->cElement - 1];
++ QSslCertificate certificate = getCertificateFromChainElement(element);
++ if (!caCertificates.contains(certificate)) {
++ auto error = QSslError(QSslError::CertificateUntrusted, certificate);
++ sslErrors += error;
++ emit q->peerVerifyError(error);
++ if (q->state() != QAbstractSocket::ConnectedState)
++ return false;
++ }
++ }
++
+ QList peerCertificateChain;
+ for (DWORD i = 0; i < verifyDepth; i++) {
+ CERT_CHAIN_ELEMENT *element = chain->rgpElement[i];
+diff --git x/qtbase/tests/manual/network/ssl/client-auth/CMakeLists.txt y/qtbase/tests/manual/network/ssl/client-auth/CMakeLists.txt
+new file mode 100644
+index 0000000000..67ecc20bf4
+--- /dev/null
++++ y/qtbase/tests/manual/network/ssl/client-auth/CMakeLists.txt
+@@ -0,0 +1,24 @@
++# Copyright (C) 2023 The Qt Company Ltd.
++# SPDX-License-Identifier: BSD-3-Clause
++
++qt_internal_add_manual_test(tst_manual_ssl_client_auth
++ SOURCES
++ tst_manual_ssl_client_auth.cpp
++ LIBRARIES
++ Qt::Network
++)
++
++qt_internal_add_resource(tst_manual_ssl_client_auth "tst_manual_ssl_client_auth"
++ PREFIX
++ "/"
++ FILES
++ "certs/127.0.0.1.pem"
++ "certs/127.0.0.1-key.pem"
++ "certs/127.0.0.1-client.pem"
++ "certs/127.0.0.1-client-key.pem"
++ "certs/accepted-client.pem"
++ "certs/accepted-client-key.pem"
++ "certs/rootCA.pem"
++ BASE
++ "certs"
++)
+diff --git x/qtbase/tests/manual/network/ssl/client-auth/certs/.gitignore y/qtbase/tests/manual/network/ssl/client-auth/certs/.gitignore
+new file mode 100644
+index 0000000000..5866f7b609
+--- /dev/null
++++ y/qtbase/tests/manual/network/ssl/client-auth/certs/.gitignore
+@@ -0,0 +1,4 @@
++*
++!/.gitignore
++!/generate.sh
++!/accepted-client.conf
+diff --git x/qtbase/tests/manual/network/ssl/client-auth/certs/accepted-client.conf y/qtbase/tests/manual/network/ssl/client-auth/certs/accepted-client.conf
+new file mode 100644
+index 0000000000..a88b276efe
+--- /dev/null
++++ y/qtbase/tests/manual/network/ssl/client-auth/certs/accepted-client.conf
+@@ -0,0 +1,14 @@
++[req]
++default_md = sha512
++basicConstraints = CA:FALSE
++extendedKeyUsage = clientAuth
++[req]
++distinguished_name = client_distinguished_name
++prompt = no
++[client_distinguished_name]
++C = NO
++ST = Oslo
++L = Oslo
++O = The Qt Project
++OU = The Qt Project
++CN = Fake Qt Project Client Certificate
+diff --git x/qtbase/tests/manual/network/ssl/client-auth/certs/generate.sh y/qtbase/tests/manual/network/ssl/client-auth/certs/generate.sh
+new file mode 100755
+index 0000000000..5dbe3b3712
+--- /dev/null
++++ y/qtbase/tests/manual/network/ssl/client-auth/certs/generate.sh
+@@ -0,0 +1,33 @@
++#!/bin/bash
++# Copyright (C) 2023 The Qt Company Ltd.
++# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
++
++# Requires mkcert and openssl
++
++warn () { echo "$@" >&2; }
++die () { warn "$@"; exit 1; }
++
++
++command -v mkcert 1>/dev/null 2>&1 || die "Failed to find mkcert"
++command -v openssl 1>/dev/null 2>&1 || die "Failed to find openssl"
++
++SCRIPT=$(realpath "$0")
++SCRIPTPATH=$(dirname "$SCRIPT")
++
++pushd "$SCRIPTPATH" || die "Unable to pushd to $SCRIPTPATH"
++mkcert 127.0.0.1
++mkcert -client 127.0.0.1
++warn "Remember to run mkcert -install if you haven't already"
++
++# Generate CA
++openssl genrsa -out ca-key.pem 2048
++openssl req -new -x509 -noenc -days 365 -key ca-key.pem -out rootCA.pem
++
++# Generate accepted client certificate
++openssl genrsa -out accepted-client-key.pem 2048
++openssl req -new -sha512 -nodes -key accepted-client-key.pem -out accepted-client.csr -config accepted-client.conf
++openssl x509 -req -sha512 -days 45 -in accepted-client.csr -CA rootCA.pem -CAkey ca-key.pem -CAcreateserial -out accepted-client.pem
++rm accepted-client.csr
++rm rootCA.srl
++
++popd || die "Unable to popd"
+diff --git x/qtbase/tests/manual/network/ssl/client-auth/tst_manual_ssl_client_auth.cpp y/qtbase/tests/manual/network/ssl/client-auth/tst_manual_ssl_client_auth.cpp
+new file mode 100644
+index 0000000000..2307cbb191
+--- /dev/null
++++ y/qtbase/tests/manual/network/ssl/client-auth/tst_manual_ssl_client_auth.cpp
+@@ -0,0 +1,118 @@
++// Copyright (C) 2023 The Qt Company Ltd.
++// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
++
++#include
++
++#include
++#include
++#include
++
++#include
++#include
++#include
++#include
++
++// Client and/or server presents a certificate signed by a system-trusted CA
++// but the other side presents a certificate signed by a different CA.
++constexpr bool TestServerPresentsIncorrectCa = false;
++constexpr bool TestClientPresentsIncorrectCa = true;
++
++class ServerThread : public QThread
++{
++ Q_OBJECT
++public:
++ void run() override
++ {
++ QSslServer server;
++
++ QSslConfiguration config = server.sslConfiguration();
++ QList certs = QSslCertificate::fromPath(QStringLiteral(":/rootCA.pem"));
++ config.setCaCertificates(certs);
++ config.setLocalCertificate(QSslCertificate::fromPath(QStringLiteral(":/127.0.0.1.pem"))
++ .first());
++ QFile keyFile(QStringLiteral(":/127.0.0.1-key.pem"));
++ if (!keyFile.open(QIODevice::ReadOnly))
++ qFatal("Failed to open key file");
++ config.setPrivateKey(QSslKey(&keyFile, QSsl::Rsa));
++ config.setPeerVerifyMode(QSslSocket::VerifyPeer);
++ server.setSslConfiguration(config);
++
++ connect(&server, &QSslServer::pendingConnectionAvailable, [&server]() {
++ QSslSocket *socket = static_cast(server.nextPendingConnection());
++ qDebug() << "[s] newConnection" << socket->peerAddress() << socket->peerPort();
++ socket->disconnectFromHost();
++ qApp->quit();
++ });
++ connect(&server, &QSslServer::startedEncryptionHandshake, [](QSslSocket *socket) {
++ qDebug() << "[s] new handshake" << socket->peerAddress() << socket->peerPort();
++ });
++ connect(&server, &QSslServer::errorOccurred,
++ [](QSslSocket *socket, QAbstractSocket::SocketError error) {
++ qDebug() << "[s] errorOccurred" << socket->peerAddress() << socket->peerPort()
++ << error << socket->errorString();
++ });
++ connect(&server, &QSslServer::peerVerifyError,
++ [](QSslSocket *socket, const QSslError &error) {
++ qDebug() << "[s] peerVerifyError" << socket->peerAddress() << socket->peerPort()
++ << error;
++ });
++ server.listen(QHostAddress::LocalHost, 24242);
++
++ exec();
++
++ server.close();
++ }
++};
++
++int main(int argc, char **argv)
++{
++ QCoreApplication app(argc, argv);
++
++ using namespace Qt::StringLiterals;
++
++ if (!QFileInfo(u":/rootCA.pem"_s).exists())
++ qFatal("rootCA.pem not found. Did you run generate.sh in the certs directory?");
++
++ ServerThread serverThread;
++ serverThread.start();
++
++ QSslSocket socket;
++ QSslConfiguration config = socket.sslConfiguration();
++ QString certificatePath;
++ QString keyFileName;
++ if constexpr (TestClientPresentsIncorrectCa) { // true: Present cert signed with incorrect CA: should fail
++ certificatePath = u":/127.0.0.1-client.pem"_s;
++ keyFileName = u":/127.0.0.1-client-key.pem"_s;
++ } else { // false: Use correct CA: should succeed
++ certificatePath = u":/accepted-client.pem"_s;
++ keyFileName = u":/accepted-client-key.pem"_s;
++ }
++ config.setLocalCertificate(QSslCertificate::fromPath(certificatePath).first());
++ if (TestServerPresentsIncorrectCa) // true: Verify server using incorrect CA: should fail
++ config.setCaCertificates(QSslCertificate::fromPath(u":/rootCA.pem"_s));
++ QFile keyFile(keyFileName);
++ if (!keyFile.open(QIODevice::ReadOnly))
++ qFatal("Failed to open key file");
++ config.setPrivateKey(QSslKey(&keyFile, QSsl::Rsa));
++ socket.setSslConfiguration(config);
++
++ QObject::connect(&socket, &QSslSocket::encrypted, []() { qDebug() << "[c] encrypted"; });
++ QObject::connect(&socket, &QSslSocket::errorOccurred,
++ [&socket](QAbstractSocket::SocketError error) {
++ qDebug() << "[c] errorOccurred" << error << socket.errorString();
++ qApp->quit();
++ });
++ QObject::connect(&socket, &QSslSocket::sslErrors, [](const QList &errors) {
++ qDebug() << "[c] sslErrors" << errors;
++ });
++ QObject::connect(&socket, &QSslSocket::connected, []() { qDebug() << "[c] connected"; });
++
++ socket.connectToHostEncrypted(QStringLiteral("127.0.0.1"), 24242);
++
++ const int res = app.exec();
++ serverThread.quit();
++ serverThread.wait();
++ return res;
++}
++
++#include "tst_manual_ssl_client_auth.moc"
diff --git a/libs/patches/qtbase-0010-Ssl-Copy-the-on-demand-cert-loading-bool-from-defaul.patch b/libs/patches/qtbase-0010-Ssl-Copy-the-on-demand-cert-loading-bool-from-defaul.patch
new file mode 100644
index 0000000..84724d3
--- /dev/null
+++ b/libs/patches/qtbase-0010-Ssl-Copy-the-on-demand-cert-loading-bool-from-defaul.patch
@@ -0,0 +1,110 @@
+From d13e70c1d56a94d64eb68d2f3cba670e58a1a73f Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?M=C3=A5rten=20Nordheim?=
+Date: Thu, 25 May 2023 14:40:29 +0200
+Subject: Ssl: Copy the on-demand cert loading bool from default config
+
+Otherwise individual sockets will still load system certificates when
+a chain doesn't match against the configured CA certificates.
+That's not intended behavior, since specifically setting the CA
+certificates means you don't want the system certificates to be used.
+
+Follow-up to/amends ada2c573c1a25f8d96577734968fe317ddfa292a
+
+This is potentially a breaking change because now, if you ever add a
+CA to the default config, it will disable loading system certificates
+on demand for all sockets. And the only way to re-enable it is to
+create a null-QSslConfiguration and set it as the new default.
+
+Pick-to: 6.5 6.2 5.15
+Change-Id: Ic3b2ab125c0cdd58ad654af1cb36173960ce2d1e
+Reviewed-by: Timur Pocheptsov
+(cherry picked from commit 57ba6260c0801055b7188fdaa1818b940590f5f1)
+---
+ src/network/ssl/qsslsocket.cpp | 5 ++++
+ .../tst_manual_ssl_client_auth.cpp | 24 ++++++++++++++++---
+ 2 files changed, 26 insertions(+), 3 deletions(-)
+
+diff --git x/qtbase/src/network/ssl/qsslsocket.cpp y/qtbase/src/network/ssl/qsslsocket.cpp
+index cd76517c25..a94f2b79c3 100644
+--- x/qtbase/src/network/ssl/qsslsocket.cpp
++++ y/qtbase/src/network/ssl/qsslsocket.cpp
+@@ -1973,6 +1973,10 @@ QSslSocketPrivate::QSslSocketPrivate()
+ , flushTriggered(false)
+ {
+ QSslConfigurationPrivate::deepCopyDefaultConfiguration(&configuration);
++ // If the global configuration doesn't allow root certificates to be loaded
++ // on demand then we have to disable it for this socket as well.
++ if (!configuration.allowRootCertOnDemandLoading)
++ allowRootCertOnDemandLoading = false;
+
+ const auto *tlsBackend = tlsBackendInUse();
+ if (!tlsBackend) {
+@@ -2281,6 +2285,7 @@ void QSslConfigurationPrivate::deepCopyDefaultConfiguration(QSslConfigurationPri
+ ptr->sessionProtocol = global->sessionProtocol;
+ ptr->ciphers = global->ciphers;
+ ptr->caCertificates = global->caCertificates;
++ ptr->allowRootCertOnDemandLoading = global->allowRootCertOnDemandLoading;
+ ptr->protocol = global->protocol;
+ ptr->peerVerifyMode = global->peerVerifyMode;
+ ptr->peerVerifyDepth = global->peerVerifyDepth;
+diff --git x/qtbase/tests/manual/network/ssl/client-auth/tst_manual_ssl_client_auth.cpp y/qtbase/tests/manual/network/ssl/client-auth/tst_manual_ssl_client_auth.cpp
+index 2307cbb191..4d4aaca7e3 100644
+--- x/qtbase/tests/manual/network/ssl/client-auth/tst_manual_ssl_client_auth.cpp
++++ y/qtbase/tests/manual/network/ssl/client-auth/tst_manual_ssl_client_auth.cpp
+@@ -16,6 +16,9 @@
+ // but the other side presents a certificate signed by a different CA.
+ constexpr bool TestServerPresentsIncorrectCa = false;
+ constexpr bool TestClientPresentsIncorrectCa = true;
++// Decides whether or not to put the root CA into the global ssl configuration
++// or into the socket's specific ssl configuration.
++constexpr bool UseGlobalConfiguration = true;
+
+ class ServerThread : public QThread
+ {
+@@ -26,8 +29,10 @@ public:
+ QSslServer server;
+
+ QSslConfiguration config = server.sslConfiguration();
+- QList certs = QSslCertificate::fromPath(QStringLiteral(":/rootCA.pem"));
+- config.setCaCertificates(certs);
++ if (!UseGlobalConfiguration) {
++ QList certs = QSslCertificate::fromPath(QStringLiteral(":/rootCA.pem"));
++ config.setCaCertificates(certs);
++ }
+ config.setLocalCertificate(QSslCertificate::fromPath(QStringLiteral(":/127.0.0.1.pem"))
+ .first());
+ QFile keyFile(QStringLiteral(":/127.0.0.1-key.pem"));
+@@ -73,6 +78,12 @@ int main(int argc, char **argv)
+ if (!QFileInfo(u":/rootCA.pem"_s).exists())
+ qFatal("rootCA.pem not found. Did you run generate.sh in the certs directory?");
+
++ if (UseGlobalConfiguration) {
++ QSslConfiguration config = QSslConfiguration::defaultConfiguration();
++ config.setCaCertificates(QSslCertificate::fromPath(u":/rootCA.pem"_s));
++ QSslConfiguration::setDefaultConfiguration(config);
++ }
++
+ ServerThread serverThread;
+ serverThread.start();
+
+@@ -88,12 +99,19 @@ int main(int argc, char **argv)
+ keyFileName = u":/accepted-client-key.pem"_s;
+ }
+ config.setLocalCertificate(QSslCertificate::fromPath(certificatePath).first());
+- if (TestServerPresentsIncorrectCa) // true: Verify server using incorrect CA: should fail
++ if (!UseGlobalConfiguration && TestServerPresentsIncorrectCa) {
++ // Verify server using incorrect CA: should fail
+ config.setCaCertificates(QSslCertificate::fromPath(u":/rootCA.pem"_s));
++ } else if (UseGlobalConfiguration && !TestServerPresentsIncorrectCa) {
++ // Verify server using correct CA, we need to explicitly set the
++ // system CAs when the global config is overridden.
++ config.setCaCertificates(QSslConfiguration::systemCaCertificates());
++ }
+ QFile keyFile(keyFileName);
+ if (!keyFile.open(QIODevice::ReadOnly))
+ qFatal("Failed to open key file");
+ config.setPrivateKey(QSslKey(&keyFile, QSsl::Rsa));
++
+ socket.setSslConfiguration(config);
+
+ QObject::connect(&socket, &QSslSocket::encrypted, []() { qDebug() << "[c] encrypted"; });
diff --git a/libs/patches/qtbase-0011-Improve-Intent-source-app-detection.patch b/libs/patches/qtbase-0011-Improve-Intent-source-app-detection.patch
new file mode 100644
index 0000000..4dcdca6
--- /dev/null
+++ b/libs/patches/qtbase-0011-Improve-Intent-source-app-detection.patch
@@ -0,0 +1,51 @@
+From bdc4845cd844e674f17161435a11e60dde2769cc Mon Sep 17 00:00:00 2001
+From: Jens Trillmann
+Date: Wed, 5 Jul 2023 09:33:03 +0200
+Subject: Improve Intent source app detection
+
+Activity.getReferrer does not only return app IDs but also URLs if
+Intent.EXTRA_REFERRER is set on the Intent. In the case of Chrome the referrer
+is set to the website triggering the Intent. To improve the detection of the
+calling app we check first if the browser specific
+Browser.EXTRAS_APPLICATION_ID is set. If it is not set we fall back to
+Intent.getReferrer.
+
+Pick-to: 6.6
+Change-Id: I33d1edd52de98486d9616713e531ea20ada87bcb
+---
+ .../qtproject/qt/android/bindings/QtActivity.java | 15 ++++++++++++---
+ 1 file changed, 12 insertions(+), 3 deletions(-)
+
+diff --git x/qtbase/src/android/java/src/org/qtproject/qt/android/bindings/QtActivity.java y/qtbase/src/android/java/src/org/qtproject/qt/android/bindings/QtActivity.java
+index 9cef8146fd..f862f6aaee 100644
+--- x/qtbase/src/android/java/src/org/qtproject/qt/android/bindings/QtActivity.java
++++ y/qtbase/src/android/java/src/org/qtproject/qt/android/bindings/QtActivity.java
+@@ -16,6 +16,7 @@ import android.graphics.Canvas;
+ import android.net.Uri;
+ import android.os.Build;
+ import android.os.Bundle;
++import android.provider.Browser;
+ import android.util.AttributeSet;
+ import android.view.ActionMode;
+ import android.view.ActionMode.Callback;
+@@ -237,9 +238,17 @@ public class QtActivity extends Activity
+ return;
+
+ String sourceInformation = "";
+- Uri referrer = getReferrer();
+- if (referrer != null)
+- sourceInformation = referrer.toString().replaceFirst("android-app://", "");
++ String browserApplicationId = intent.getExtras() == null ? "" : intent.getExtras().getString(Browser.EXTRA_APPLICATION_ID);
++ if (!browserApplicationId.isEmpty())
++ {
++ sourceInformation = browserApplicationId;
++ }
++ else
++ {
++ Uri referrer = getReferrer();
++ if (referrer != null)
++ sourceInformation = referrer.toString().replaceFirst("android-app://", "");
++ }
+
+ intent.putExtra(EXTRA_SOURCE_INFO, sourceInformation);
+ }
diff --git a/libs/patches/qtbase-0012-QXmlStreamReader-change-fastScanName-to-take-a-Value.patch b/libs/patches/qtbase-0012-QXmlStreamReader-change-fastScanName-to-take-a-Value.patch
new file mode 100644
index 0000000..5602a02
--- /dev/null
+++ b/libs/patches/qtbase-0012-QXmlStreamReader-change-fastScanName-to-take-a-Value.patch
@@ -0,0 +1,105 @@
+From f9a1c8668e5f4787e9b0b3136076138f4fda5563 Mon Sep 17 00:00:00 2001
+From: Ahmad Samir
+Date: Wed, 12 Apr 2023 13:10:26 +0200
+Subject: QXmlStreamReader: change fastScanName() to take a Value*
+
+For easier debugging, e.g. to print out value.len and value.prefix.
+
+Pick-to: 6.6 6.5 6.5.2 6.2 5.15
+Change-Id: Ib0eed38772f899502962f578775d34ea2744fdde
+Reviewed-by: Marc Mutz
+(cherry picked from commit 1a423ce4372d18a779f3c0d746d5283d9a425839)
+---
+ src/corelib/serialization/qxmlstream.cpp | 16 ++++++++--------
+ src/corelib/serialization/qxmlstream.g | 3 ++-
+ src/corelib/serialization/qxmlstream_p.h | 2 +-
+ src/corelib/serialization/qxmlstreamparser_p.h | 3 ++-
+ 4 files changed, 13 insertions(+), 11 deletions(-)
+
+diff --git x/qtbase/src/corelib/serialization/qxmlstream.cpp y/qtbase/src/corelib/serialization/qxmlstream.cpp
+index a6a2bc41af..f64db47867 100644
+--- x/qtbase/src/corelib/serialization/qxmlstream.cpp
++++ y/qtbase/src/corelib/serialization/qxmlstream.cpp
+@@ -1243,7 +1243,7 @@ inline qsizetype QXmlStreamReaderPrivate::fastScanContentCharList()
+ return n;
+ }
+
+-inline qsizetype QXmlStreamReaderPrivate::fastScanName(qint16 *prefix)
++inline qsizetype QXmlStreamReaderPrivate::fastScanName(Value *val)
+ {
+ qsizetype n = 0;
+ uint c;
+@@ -1280,16 +1280,16 @@ inline qsizetype QXmlStreamReaderPrivate::fastScanName(qint16 *prefix)
+ case '+':
+ case '*':
+ putChar(c);
+- if (prefix && *prefix == n+1) {
+- *prefix = 0;
++ if (val && val->prefix == n + 1) {
++ val->prefix = 0;
+ putChar(':');
+ --n;
+ }
+ return n;
+ case ':':
+- if (prefix) {
+- if (*prefix == 0) {
+- *prefix = qint16(n + 2);
++ if (val) {
++ if (val->prefix == 0) {
++ val->prefix = qint16(n + 2);
+ } else { // only one colon allowed according to the namespace spec.
+ putChar(c);
+ return n;
+@@ -1305,8 +1305,8 @@ inline qsizetype QXmlStreamReaderPrivate::fastScanName(qint16 *prefix)
+ }
+ }
+
+- if (prefix)
+- *prefix = 0;
++ if (val)
++ val->prefix = 0;
+ qsizetype pos = textBuffer.size() - n;
+ putString(textBuffer, pos);
+ textBuffer.resize(pos);
+diff --git x/qtbase/src/corelib/serialization/qxmlstream.g y/qtbase/src/corelib/serialization/qxmlstream.g
+index d06c371eb8..f3152bff37 100644
+--- x/qtbase/src/corelib/serialization/qxmlstream.g
++++ y/qtbase/src/corelib/serialization/qxmlstream.g
+@@ -1419,7 +1419,8 @@ space_opt ::= space;
+ qname ::= LETTER;
+ /.
+ case $rule_number: {
+- sym(1).len += fastScanName(&sym(1).prefix);
++ Value &val = sym(1);
++ val.len += fastScanName(&val);
+ if (atEnd) {
+ resume($rule_number);
+ return false;
+diff --git x/qtbase/src/corelib/serialization/qxmlstream_p.h y/qtbase/src/corelib/serialization/qxmlstream_p.h
+index 8e523f9c67..5da1f4aa5a 100644
+--- x/qtbase/src/corelib/serialization/qxmlstream_p.h
++++ y/qtbase/src/corelib/serialization/qxmlstream_p.h
+@@ -471,7 +471,7 @@ public:
+ qsizetype fastScanLiteralContent();
+ qsizetype fastScanSpace();
+ qsizetype fastScanContentCharList();
+- qsizetype fastScanName(qint16 *prefix = nullptr);
++ qsizetype fastScanName(Value *val = nullptr);
+ inline qsizetype fastScanNMTOKEN();
+
+
+diff --git x/qtbase/src/corelib/serialization/qxmlstreamparser_p.h y/qtbase/src/corelib/serialization/qxmlstreamparser_p.h
+index e3ae6faa44..59370a9310 100644
+--- x/qtbase/src/corelib/serialization/qxmlstreamparser_p.h
++++ y/qtbase/src/corelib/serialization/qxmlstreamparser_p.h
+@@ -947,7 +947,8 @@ bool QXmlStreamReaderPrivate::parse()
+ break;
+
+ case 262: {
+- sym(1).len += fastScanName(&sym(1).prefix);
++ Value &val = sym(1);
++ val.len += fastScanName(&val);
+ if (atEnd) {
+ resume(262);
+ return false;
diff --git a/libs/patches/qtbase-0013-QXmlStreamReader-make-fastScanName-indicate-parsing-.patch b/libs/patches/qtbase-0013-QXmlStreamReader-make-fastScanName-indicate-parsing-.patch
new file mode 100644
index 0000000..375a274
--- /dev/null
+++ b/libs/patches/qtbase-0013-QXmlStreamReader-make-fastScanName-indicate-parsing-.patch
@@ -0,0 +1,270 @@
+From 836d7df23ec9b6cb3dea1bb68b7c8bc75090702e Mon Sep 17 00:00:00 2001
+From: Ahmad Samir
+Date: Thu, 22 Jun 2023 15:56:07 +0300
+Subject: QXmlStreamReader: make fastScanName() indicate parsing status to
+ callers
+
+This fixes a crash while parsing an XML file with garbage data, the file
+starts with '<' then garbage data:
+- The loop in the parse() keeps iterating until it hits "case 262:",
+ which calls fastScanName()
+- fastScanName() iterates over the text buffer scanning for the
+ attribute name (e.g. "xml:lang"), until it finds ':'
+- Consider a Value val, fastScanName() is called on it, it would set
+ val.prefix to a number > val.len, then it would hit the 4096 condition
+ and return (returned 0, now it returns the equivalent of
+ std::null_opt), which means that val.len doesn't get modified, making
+ it smaller than val.prefix
+- The code would try constructing an XmlStringRef with negative length,
+ which would hit an assert in one of QStringView's constructors
+
+Add an assert to the XmlStringRef constructor.
+
+Add unittest based on the file from the bug report.
+
+Later on I will replace FastScanNameResult with std::optional
+(std::optional is C++17, which isn't required by Qt 5.15, and we want to
+backport this fix).
+
+Credit to OSS-Fuzz.
+
+Fixes: QTBUG-109781
+Fixes: QTBUG-114829
+Pick-to: 6.6 6.5 6.2 5.15
+Change-Id: I455a5eeb47870c2ac9ffd0cbcdcd99c1ae2dd374
+Reviewed-by: Allan Sandfeld Jensen
+(cherry picked from commit 6326bec46a618c72feba4a2bb994c4d475050aed)
+---
+ src/corelib/serialization/qxmlstream.cpp | 23 ++++++++---
+ src/corelib/serialization/qxmlstream.g | 12 +++++-
+ src/corelib/serialization/qxmlstream_p.h | 14 ++++++-
+ .../serialization/qxmlstreamparser_p.h | 12 +++++-
+ .../qxmlstream/tst_qxmlstream.cpp | 39 +++++++++++++++++++
+ 5 files changed, 88 insertions(+), 12 deletions(-)
+
+diff --git x/qtbase/src/corelib/serialization/qxmlstream.cpp y/qtbase/src/corelib/serialization/qxmlstream.cpp
+index f64db47867..34568b7351 100644
+--- x/qtbase/src/corelib/serialization/qxmlstream.cpp
++++ y/qtbase/src/corelib/serialization/qxmlstream.cpp
+@@ -1243,7 +1243,9 @@ inline qsizetype QXmlStreamReaderPrivate::fastScanContentCharList()
+ return n;
+ }
+
+-inline qsizetype QXmlStreamReaderPrivate::fastScanName(Value *val)
++// Fast scan an XML attribute name (e.g. "xml:lang").
++inline QXmlStreamReaderPrivate::FastScanNameResult
++QXmlStreamReaderPrivate::fastScanName(Value *val)
+ {
+ qsizetype n = 0;
+ uint c;
+@@ -1251,7 +1253,8 @@ inline qsizetype QXmlStreamReaderPrivate::fastScanName(Value *val)
+ if (n >= 4096) {
+ // This is too long to be a sensible name, and
+ // can exhaust memory, or the range of decltype(*prefix)
+- return 0;
++ raiseNamePrefixTooLongError();
++ return {};
+ }
+ switch (c) {
+ case '\n':
+@@ -1285,18 +1288,18 @@ inline qsizetype QXmlStreamReaderPrivate::fastScanName(Value *val)
+ putChar(':');
+ --n;
+ }
+- return n;
++ return FastScanNameResult(n);
+ case ':':
+ if (val) {
+ if (val->prefix == 0) {
+ val->prefix = qint16(n + 2);
+ } else { // only one colon allowed according to the namespace spec.
+ putChar(c);
+- return n;
++ return FastScanNameResult(n);
+ }
+ } else {
+ putChar(c);
+- return n;
++ return FastScanNameResult(n);
+ }
+ Q_FALLTHROUGH();
+ default:
+@@ -1310,7 +1313,7 @@ inline qsizetype QXmlStreamReaderPrivate::fastScanName(Value *val)
+ qsizetype pos = textBuffer.size() - n;
+ putString(textBuffer, pos);
+ textBuffer.resize(pos);
+- return 0;
++ return FastScanNameResult(0);
+ }
+
+ enum NameChar { NameBeginning, NameNotBeginning, NotName };
+@@ -1791,6 +1794,14 @@ void QXmlStreamReaderPrivate::raiseWellFormedError(const QString &message)
+ raiseError(QXmlStreamReader::NotWellFormedError, message);
+ }
+
++void QXmlStreamReaderPrivate::raiseNamePrefixTooLongError()
++{
++ // TODO: add a ImplementationLimitsExceededError and use it instead
++ raiseError(QXmlStreamReader::NotWellFormedError,
++ QXmlStream::tr("Length of XML attribute name exceeds implemnetation limits (4KiB "
++ "characters)."));
++}
++
+ void QXmlStreamReaderPrivate::parseError()
+ {
+
+diff --git x/qtbase/src/corelib/serialization/qxmlstream.g y/qtbase/src/corelib/serialization/qxmlstream.g
+index f3152bff37..fc122e6681 100644
+--- x/qtbase/src/corelib/serialization/qxmlstream.g
++++ y/qtbase/src/corelib/serialization/qxmlstream.g
+@@ -1420,7 +1420,11 @@ qname ::= LETTER;
+ /.
+ case $rule_number: {
+ Value &val = sym(1);
+- val.len += fastScanName(&val);
++ if (auto res = fastScanName(&val))
++ val.len += *res;
++ else
++ return false;
++
+ if (atEnd) {
+ resume($rule_number);
+ return false;
+@@ -1431,7 +1435,11 @@ qname ::= LETTER;
+ name ::= LETTER;
+ /.
+ case $rule_number:
+- sym(1).len += fastScanName();
++ if (auto res = fastScanName())
++ sym(1).len += *res;
++ else
++ return false;
++
+ if (atEnd) {
+ resume($rule_number);
+ return false;
+diff --git x/qtbase/src/corelib/serialization/qxmlstream_p.h y/qtbase/src/corelib/serialization/qxmlstream_p.h
+index 5da1f4aa5a..7925e59014 100644
+--- x/qtbase/src/corelib/serialization/qxmlstream_p.h
++++ y/qtbase/src/corelib/serialization/qxmlstream_p.h
+@@ -38,7 +38,7 @@ public:
+
+ constexpr XmlStringRef() = default;
+ constexpr inline XmlStringRef(const QString *string, qsizetype pos, qsizetype length)
+- : m_string(string), m_pos(pos), m_size(length)
++ : m_string(string), m_pos(pos), m_size((Q_ASSERT(length >= 0), length))
+ {
+ }
+ XmlStringRef(const QString *string)
+@@ -471,7 +471,16 @@ public:
+ qsizetype fastScanLiteralContent();
+ qsizetype fastScanSpace();
+ qsizetype fastScanContentCharList();
+- qsizetype fastScanName(Value *val = nullptr);
++
++ struct FastScanNameResult {
++ FastScanNameResult() : ok(false) {}
++ explicit FastScanNameResult(qsizetype len) : addToLen(len), ok(true) { }
++ operator bool() { return ok; }
++ qsizetype operator*() { Q_ASSERT(ok); return addToLen; }
++ qsizetype addToLen;
++ bool ok;
++ };
++ FastScanNameResult fastScanName(Value *val = nullptr);
+ inline qsizetype fastScanNMTOKEN();
+
+
+@@ -480,6 +489,7 @@ public:
+
+ void raiseError(QXmlStreamReader::Error error, const QString& message = QString());
+ void raiseWellFormedError(const QString &message);
++ void raiseNamePrefixTooLongError();
+
+ QXmlStreamEntityResolver *entityResolver;
+
+diff --git x/qtbase/src/corelib/serialization/qxmlstreamparser_p.h y/qtbase/src/corelib/serialization/qxmlstreamparser_p.h
+index 59370a9310..afd83381b3 100644
+--- x/qtbase/src/corelib/serialization/qxmlstreamparser_p.h
++++ y/qtbase/src/corelib/serialization/qxmlstreamparser_p.h
+@@ -948,7 +948,11 @@ bool QXmlStreamReaderPrivate::parse()
+
+ case 262: {
+ Value &val = sym(1);
+- val.len += fastScanName(&val);
++ if (auto res = fastScanName(&val))
++ val.len += *res;
++ else
++ return false;
++
+ if (atEnd) {
+ resume(262);
+ return false;
+@@ -956,7 +960,11 @@ bool QXmlStreamReaderPrivate::parse()
+ } break;
+
+ case 263:
+- sym(1).len += fastScanName();
++ if (auto res = fastScanName())
++ sym(1).len += *res;
++ else
++ return false;
++
+ if (atEnd) {
+ resume(263);
+ return false;
+diff --git x/qtbase/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp y/qtbase/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp
+index 2799e7a999..7eb0aac5cc 100644
+--- x/qtbase/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp
++++ y/qtbase/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp
+@@ -581,6 +581,8 @@ private slots:
+ void readBack() const;
+ void roundTrip() const;
+ void roundTrip_data() const;
++ void test_fastScanName_data() const;
++ void test_fastScanName() const;
+
+ void entityExpansionLimit() const;
+
+@@ -1753,5 +1755,42 @@ void tst_QXmlStream::roundTrip() const
+ QCOMPARE(out, in);
+ }
+
++void tst_QXmlStream::test_fastScanName_data() const
++{
++ QTest::addColumn("data");
++ QTest::addColumn("errorType");
++
++ // 4096 is the limit in QXmlStreamReaderPrivate::fastScanName()
++
++ QByteArray arr = "
+Date: Fri, 2 Sep 2022 16:52:04 +0200
+Subject: QXmlStreamReader: use qOffsetStringArray for storing token types
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Change-Id: I9e58c17d97c44e1b13899d30396f65b452d8600f
+Reviewed-by: Mårten Nordheim
+(cherry picked from commit d674f3f5454fb39de9405484a8c01fb928523f67)
+---
+ src/corelib/serialization/qxmlstream.cpp | 67 ++++++------------------
+ 1 file changed, 16 insertions(+), 51 deletions(-)
+
+diff --git x/qtbase/src/corelib/serialization/qxmlstream.cpp y/qtbase/src/corelib/serialization/qxmlstream.cpp
+index 34568b7351..535f98a215 100644
+--- x/qtbase/src/corelib/serialization/qxmlstream.cpp
++++ y/qtbase/src/corelib/serialization/qxmlstream.cpp
+@@ -15,6 +15,8 @@
+ #include
+ #include
+
++#include
++
+ #include
+ #include "qxmlstream_p.h"
+ #include "qxmlstreamparser_p.h"
+@@ -640,55 +642,19 @@ void QXmlStreamReader::skipCurrentElement()
+ }
+ }
+
+-/*
+- * Use the following Perl script to generate the error string index list:
+-===== PERL SCRIPT ====
+-print "static const char QXmlStreamReader_tokenTypeString_string[] =\n";
+-$counter = 0;
+-$i = 0;
+-while () {
+- chomp;
+- print " \"$_\\0\"\n";
+- $sizes[$i++] = $counter;
+- $counter += length 1 + $_;
+-}
+-print " \"\\0\";\n\nstatic const short QXmlStreamReader_tokenTypeString_indices[] = {\n ";
+-for ($j = 0; $j < $i; ++$j) {
+- printf "$sizes[$j], ";
+-}
+-print "0\n};\n";
+-===== PERL SCRIPT ====
+-
+- * The input data is as follows (copied from qxmlstream.h):
+-NoToken
+-Invalid
+-StartDocument
+-EndDocument
+-StartElement
+-EndElement
+-Characters
+-Comment
+-DTD
+-EntityReference
+-ProcessingInstruction
+-*/
+-static const char QXmlStreamReader_tokenTypeString_string[] =
+- "NoToken\0"
+- "Invalid\0"
+- "StartDocument\0"
+- "EndDocument\0"
+- "StartElement\0"
+- "EndElement\0"
+- "Characters\0"
+- "Comment\0"
+- "DTD\0"
+- "EntityReference\0"
+- "ProcessingInstruction\0";
+-
+-static const short QXmlStreamReader_tokenTypeString_indices[] = {
+- 0, 8, 16, 30, 42, 55, 66, 77, 85, 89, 105, 0
+-};
+-
++static constexpr auto QXmlStreamReader_tokenTypeString = qOffsetStringArray(
++ "NoToken",
++ "Invalid",
++ "StartDocument",
++ "EndDocument",
++ "StartElement",
++ "EndElement",
++ "Characters",
++ "Comment",
++ "DTD",
++ "EntityReference",
++ "ProcessingInstruction"
++);
+
+ /*!
+ \property QXmlStreamReader::namespaceProcessing
+@@ -721,8 +687,7 @@ bool QXmlStreamReader::namespaceProcessing() const
+ QString QXmlStreamReader::tokenString() const
+ {
+ Q_D(const QXmlStreamReader);
+- return QLatin1StringView(QXmlStreamReader_tokenTypeString_string +
+- QXmlStreamReader_tokenTypeString_indices[d->type]);
++ return QLatin1StringView(QXmlStreamReader_tokenTypeString.at(d->type));
+ }
+
+ #endif // QT_NO_XMLSTREAMREADER
diff --git a/libs/patches/qtbase-0015-QXmlStreamReader-Raise-error-on-unexpected-tokens.patch b/libs/patches/qtbase-0015-QXmlStreamReader-Raise-error-on-unexpected-tokens.patch
new file mode 100644
index 0000000..b9fd729
--- /dev/null
+++ b/libs/patches/qtbase-0015-QXmlStreamReader-Raise-error-on-unexpected-tokens.patch
@@ -0,0 +1,394 @@
+From ce9ffbc726f7a0d90561db7206f3061371126190 Mon Sep 17 00:00:00 2001
+From: Axel Spoerl
+Date: Fri, 30 Jun 2023 12:43:59 +0200
+Subject: QXmlStreamReader: Raise error on unexpected tokens
+
+QXmlStreamReader accepted multiple DOCTYPE elements, containing DTD
+fragments in the XML prolog, and in the XML body.
+Well-formed but invalid XML files - with multiple DTD fragments in
+prolog and body, combined with recursive entity expansions - have
+caused infinite loops in QXmlStreamReader.
+
+This patch implements a token check in QXmlStreamReader.
+A stream is allowed to start with an XML prolog. StartDocument
+and DOCTYPE elements are only allowed in this prolog, which
+may also contain ProcessingInstruction and Comment elements.
+As soon as anything else is seen, the prolog ends.
+After that, the prolog-specific elements are treated as unexpected.
+Furthermore, the prolog can contain at most one DOCTYPE element.
+
+Update the documentation to reflect the new behavior.
+Add an autotest that checks the new error cases are correctly detected,
+and no error is raised for legitimate input.
+
+The original OSS-Fuzz files (see bug reports) are not included in this
+patch for file size reasons. They have been tested manually. Each of
+them has more than one DOCTYPE element, causing infinite loops in
+recursive entity expansions. The newly implemented functionality
+detects those invalid DTD fragments. By raising an error, it aborts
+stream reading before an infinite loop occurs.
+
+Thanks to OSS-Fuzz for finding this.
+
+Fixes: QTBUG-92113
+Fixes: QTBUG-95188
+Change-Id: I0a082b9188b2eee50b396c4d5b1c9e1fd237bbdd
+Reviewed-by: Volker Hilsheimer
+(cherry picked from commit c4301be7d5f94852e1b17f2c2989d5ca807855d4)
+(cherry picked from commit c216c3d9859a20b3aeec985512e89316423fc3a8)
+---
+ src/corelib/serialization/qxmlstream.cpp | 140 +++++++++++++++++-
+ src/corelib/serialization/qxmlstream_p.h | 11 ++
+ .../qxmlstream/tokenError/dtdInBody.xml | 20 +++
+ .../qxmlstream/tokenError/multipleDtd.xml | 20 +++
+ .../qxmlstream/tokenError/wellFormed.xml | 15 ++
+ .../qxmlstream/tst_qxmlstream.cpp | 39 +++++
+ 6 files changed, 237 insertions(+), 8 deletions(-)
+ create mode 100644 tests/auto/corelib/serialization/qxmlstream/tokenError/dtdInBody.xml
+ create mode 100644 tests/auto/corelib/serialization/qxmlstream/tokenError/multipleDtd.xml
+ create mode 100644 tests/auto/corelib/serialization/qxmlstream/tokenError/wellFormed.xml
+
+diff --git x/qtbase/src/corelib/serialization/qxmlstream.cpp y/qtbase/src/corelib/serialization/qxmlstream.cpp
+index 535f98a215..050556f463 100644
+--- x/qtbase/src/corelib/serialization/qxmlstream.cpp
++++ y/qtbase/src/corelib/serialization/qxmlstream.cpp
+@@ -128,7 +128,7 @@ void reversed(const Range &&) = delete;
+ addData() or by waiting for it to arrive on the device().
+
+ \value UnexpectedElementError The parser encountered an element
+- that was different to those it expected.
++ or token that was different to those it expected.
+
+ */
+
+@@ -263,13 +263,34 @@ QXmlStreamEntityResolver *QXmlStreamReader::entityResolver() const
+
+ QXmlStreamReader is a well-formed XML 1.0 parser that does \e not
+ include external parsed entities. As long as no error occurs, the
+- application code can thus be assured that the data provided by the
+- stream reader satisfies the W3C's criteria for well-formed XML. For
+- example, you can be certain that all tags are indeed nested and
+- closed properly, that references to internal entities have been
+- replaced with the correct replacement text, and that attributes have
+- been normalized or added according to the internal subset of the
+- DTD.
++ application code can thus be assured, that
++ \list
++ \li the data provided by the stream reader satisfies the W3C's
++ criteria for well-formed XML,
++ \li tokens are provided in a valid order.
++ \endlist
++
++ Unless QXmlStreamReader raises an error, it guarantees the following:
++ \list
++ \li All tags are nested and closed properly.
++ \li References to internal entities have been replaced with the
++ correct replacement text.
++ \li Attributes have been normalized or added according to the
++ internal subset of the \l DTD.
++ \li Tokens of type \l StartDocument happen before all others,
++ aside from comments and processing instructions.
++ \li At most one DOCTYPE element (a token of type \l DTD) is present.
++ \li If present, the DOCTYPE appears before all other elements,
++ aside from StartDocument, comments and processing instructions.
++ \endlist
++
++ In particular, once any token of type \l StartElement, \l EndElement,
++ \l Characters, \l EntityReference or \l EndDocument is seen, no
++ tokens of type StartDocument or DTD will be seen. If one is present in
++ the input stream, out of order, an error is raised.
++
++ \note The token types \l Comment and \l ProcessingInstruction may appear
++ anywhere in the stream.
+
+ If an error occurs while parsing, atEnd() and hasError() return
+ true, and error() returns the error that occurred. The functions
+@@ -572,6 +593,7 @@ QXmlStreamReader::TokenType QXmlStreamReader::readNext()
+ d->token = -1;
+ return readNext();
+ }
++ d->checkToken();
+ return d->type;
+ }
+
+@@ -656,6 +678,11 @@ static constexpr auto QXmlStreamReader_tokenTypeString = qOffsetStringArray(
+ "ProcessingInstruction"
+ );
+
++static constexpr auto QXmlStreamReader_XmlContextString = qOffsetStringArray(
++ "Prolog",
++ "Body"
++);
++
+ /*!
+ \property QXmlStreamReader::namespaceProcessing
+ \brief the namespace-processing flag of the stream reader.
+@@ -690,6 +717,15 @@ QString QXmlStreamReader::tokenString() const
+ return QLatin1StringView(QXmlStreamReader_tokenTypeString.at(d->type));
+ }
+
++/*!
++ \internal
++ \return \param loc (Prolog/Body) as a string.
++ */
++static constexpr QLatin1StringView contextString(QXmlStreamReaderPrivate::XmlContext ctxt)
++{
++ return QLatin1StringView(QXmlStreamReader_XmlContextString.at(static_cast(ctxt)));
++}
++
+ #endif // QT_NO_XMLSTREAMREADER
+
+ QXmlStreamPrivateTagStack::QXmlStreamPrivateTagStack()
+@@ -776,6 +812,8 @@ void QXmlStreamReaderPrivate::init()
+
+ type = QXmlStreamReader::NoToken;
+ error = QXmlStreamReader::NoError;
++ currentContext = XmlContext::Prolog;
++ foundDTD = false;
+ }
+
+ /*
+@@ -3692,6 +3730,92 @@ void QXmlStreamWriter::writeCurrentToken(const QXmlStreamReader &reader)
+ }
+ }
+
++static constexpr bool isTokenAllowedInContext(QXmlStreamReader::TokenType type,
++ QXmlStreamReaderPrivate::XmlContext loc)
++{
++ switch (type) {
++ case QXmlStreamReader::StartDocument:
++ case QXmlStreamReader::DTD:
++ return loc == QXmlStreamReaderPrivate::XmlContext::Prolog;
++
++ case QXmlStreamReader::StartElement:
++ case QXmlStreamReader::EndElement:
++ case QXmlStreamReader::Characters:
++ case QXmlStreamReader::EntityReference:
++ case QXmlStreamReader::EndDocument:
++ return loc == QXmlStreamReaderPrivate::XmlContext::Body;
++
++ case QXmlStreamReader::Comment:
++ case QXmlStreamReader::ProcessingInstruction:
++ return true;
++
++ case QXmlStreamReader::NoToken:
++ case QXmlStreamReader::Invalid:
++ return false;
++ }
++
++ return false;
++}
++
++/*!
++ \internal
++ \brief QXmlStreamReader::isValidToken
++ \return \c true if \param type is a valid token type.
++ \return \c false if \param type is an unexpected token,
++ which indicates a non-well-formed or invalid XML stream.
++ */
++bool QXmlStreamReaderPrivate::isValidToken(QXmlStreamReader::TokenType type)
++{
++ // Don't change currentContext, if Invalid or NoToken occur in the prolog
++ if (type == QXmlStreamReader::Invalid || type == QXmlStreamReader::NoToken)
++ return false;
++
++ // If a token type gets rejected in the body, there is no recovery
++ const bool result = isTokenAllowedInContext(type, currentContext);
++ if (result || currentContext == XmlContext::Body)
++ return result;
++
++ // First non-Prolog token observed => switch context to body and check again.
++ currentContext = XmlContext::Body;
++ return isTokenAllowedInContext(type, currentContext);
++}
++
++/*!
++ \internal
++ Checks token type and raises an error, if it is invalid
++ in the current context (prolog/body).
++ */
++void QXmlStreamReaderPrivate::checkToken()
++{
++ Q_Q(QXmlStreamReader);
++
++ // The token type must be consumed, to keep track if the body has been reached.
++ const XmlContext context = currentContext;
++ const bool ok = isValidToken(type);
++
++ // Do nothing if an error has been raised already (going along with an unexpected token)
++ if (error != QXmlStreamReader::Error::NoError)
++ return;
++
++ if (!ok) {
++ raiseError(QXmlStreamReader::UnexpectedElementError,
++ QObject::tr("Unexpected token type %1 in %2.")
++ .arg(q->tokenString(), contextString(context)));
++ return;
++ }
++
++ if (type != QXmlStreamReader::DTD)
++ return;
++
++ // Raise error on multiple DTD tokens
++ if (foundDTD) {
++ raiseError(QXmlStreamReader::UnexpectedElementError,
++ QObject::tr("Found second DTD token in %1.").arg(contextString(context)));
++ } else {
++ foundDTD = true;
++ }
++}
++
+ /*!
+ \fn bool QXmlStreamAttributes::hasAttribute(const QString &qualifiedName) const
+ \since 4.5
+diff --git x/qtbase/src/corelib/serialization/qxmlstream_p.h y/qtbase/src/corelib/serialization/qxmlstream_p.h
+index 7925e59014..c24c74d5c9 100644
+--- x/qtbase/src/corelib/serialization/qxmlstream_p.h
++++ y/qtbase/src/corelib/serialization/qxmlstream_p.h
+@@ -270,6 +270,17 @@ public:
+ QStringDecoder decoder;
+ bool atEnd;
+
++ enum class XmlContext
++ {
++ Prolog,
++ Body,
++ };
++
++ XmlContext currentContext = XmlContext::Prolog;
++ bool foundDTD = false;
++ bool isValidToken(QXmlStreamReader::TokenType type);
++ void checkToken();
++
+ /*!
+ \sa setType()
+ */
+diff --git x/qtbase/tests/auto/corelib/serialization/qxmlstream/tokenError/dtdInBody.xml y/qtbase/tests/auto/corelib/serialization/qxmlstream/tokenError/dtdInBody.xml
+new file mode 100644
+index 0000000000..1c3ca4e271
+--- /dev/null
++++ y/qtbase/tests/auto/corelib/serialization/qxmlstream/tokenError/dtdInBody.xml
+@@ -0,0 +1,20 @@
++
++
++
++
++
++
++
++
++]>
++
++
++ tst_QXmlStream
++
++
++
++
++ ]>
++
+diff --git x/qtbase/tests/auto/corelib/serialization/qxmlstream/tokenError/multipleDtd.xml y/qtbase/tests/auto/corelib/serialization/qxmlstream/tokenError/multipleDtd.xml
+new file mode 100644
+index 0000000000..cd398c0f9f
+--- /dev/null
++++ y/qtbase/tests/auto/corelib/serialization/qxmlstream/tokenError/multipleDtd.xml
+@@ -0,0 +1,20 @@
++
++
++
++
++
++
++
++
++]>
++
++
++
++]>
++
++
++ tst_QXmlStream
++
++
+diff --git x/qtbase/tests/auto/corelib/serialization/qxmlstream/tokenError/wellFormed.xml y/qtbase/tests/auto/corelib/serialization/qxmlstream/tokenError/wellFormed.xml
+new file mode 100644
+index 0000000000..1b61a3f062
+--- /dev/null
++++ y/qtbase/tests/auto/corelib/serialization/qxmlstream/tokenError/wellFormed.xml
+@@ -0,0 +1,15 @@
++
++
++
++
++
++
++
++
++]>
++
++
++ tst_QXmlStream
++
++
+diff --git x/qtbase/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp y/qtbase/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp
+index 7eb0aac5cc..ee962d3870 100644
+--- x/qtbase/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp
++++ y/qtbase/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp
+@@ -586,6 +586,9 @@ private slots:
+
+ void entityExpansionLimit() const;
+
++ void tokenErrorHandling_data() const;
++ void tokenErrorHandling() const;
++
+ private:
+ static QByteArray readFile(const QString &filename);
+
+@@ -1792,5 +1795,41 @@ void tst_QXmlStream::test_fastScanName() const
+ QCOMPARE(reader.error(), errorType);
+ }
+
++void tst_QXmlStream::tokenErrorHandling_data() const
++{
++ QTest::addColumn("fileName");
++ QTest::addColumn("expectedError");
++ QTest::addColumn("errorKeyWord");
++
++ constexpr auto invalid = QXmlStreamReader::Error::UnexpectedElementError;
++ constexpr auto valid = QXmlStreamReader::Error::NoError;
++ QTest::newRow("DtdInBody") << "dtdInBody.xml" << invalid << "DTD";
++ QTest::newRow("multipleDTD") << "multipleDtd.xml" << invalid << "second DTD";
++ QTest::newRow("wellFormed") << "wellFormed.xml" << valid << "";
++}
++
++void tst_QXmlStream::tokenErrorHandling() const
++{
++ QFETCH(const QString, fileName);
++ QFETCH(const QXmlStreamReader::Error, expectedError);
++ QFETCH(const QString, errorKeyWord);
++
++ const QDir dir(QFINDTESTDATA("tokenError"));
++ QFile file(dir.absoluteFilePath(fileName));
++
++ // Cross-compiling: File will be on host only
++ if (!file.exists())
++ QSKIP("Testfile not found.");
++
++ file.open(QIODevice::ReadOnly);
++ QXmlStreamReader reader(&file);
++ while (!reader.atEnd())
++ reader.readNext();
++
++ QCOMPARE(reader.error(), expectedError);
++ if (expectedError != QXmlStreamReader::Error::NoError)
++ QVERIFY(reader.errorString().contains(errorKeyWord));
++}
++
+ #include "tst_qxmlstream.moc"
+ // vim: et:ts=4:sw=4:sts=4
diff --git a/libs/patches/qtbase-0016-QOffsetStringArray-fix-ambiguous-qOffsetStringArray-.patch b/libs/patches/qtbase-0016-QOffsetStringArray-fix-ambiguous-qOffsetStringArray-.patch
new file mode 100644
index 0000000..9f06617
--- /dev/null
+++ b/libs/patches/qtbase-0016-QOffsetStringArray-fix-ambiguous-qOffsetStringArray-.patch
@@ -0,0 +1,42 @@
+From e6d25e8d3b67cf7d9601d3fdd07131280f8ff056 Mon Sep 17 00:00:00 2001
+From: Marc Mutz
+Date: Sun, 4 Sep 2022 12:31:10 +0200
+Subject: QOffsetStringArray: fix ambiguous qOffsetStringArray overloads
+
+There are two qOffsetStringArray overloads: one in QT_NAMESPACE, the
+other in QT_PREPEND_NAMESPACE(QtPrivate). In TUs which use using
+namespace QtPrivate, a call to qOffsetStringArray() may become
+ambiguous.
+
+Fix by renaming the qOffsetStringArray() to makeOffsetStringArray().
+
+Pick-to: 6.4 6.3 6.2
+Change-Id: I242a969f363e230d6a8dfb048601a0c024724f6a
+Reviewed-by: Thiago Macieira
+(cherry picked from commit 21c5eeba673694f865badfd137ee9fc474177ae0)
+---
+ src/corelib/tools/qoffsetstringarray_p.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git x/qtbase/src/corelib/tools/qoffsetstringarray_p.h y/qtbase/src/corelib/tools/qoffsetstringarray_p.h
+index 3afb5cb731..68afef57d5 100644
+--- x/qtbase/src/corelib/tools/qoffsetstringarray_p.h
++++ y/qtbase/src/corelib/tools/qoffsetstringarray_p.h
+@@ -116,7 +116,7 @@ template struct StaticMapEntry
+ };
+
+ template
+-constexpr auto qOffsetStringArray(StringExtractor extractString, const T &... entries)
++constexpr auto makeOffsetStringArray(StringExtractor extractString, const T &... entries)
+ {
+ constexpr size_t Count = sizeof...(T);
+ constexpr qsizetype StringLength = (sizeof(extractString(T{})) + ...);
+@@ -140,7 +140,7 @@ template
+ constexpr auto qOffsetStringArray(const char (&...strings)[Nx]) noexcept
+ {
+ auto extractString = [](const auto &s) -> decltype(auto) { return s; };
+- return QtPrivate::qOffsetStringArray(extractString, QtPrivate::StaticString(strings)...);
++ return QtPrivate::makeOffsetStringArray(extractString, QtPrivate::StaticString(strings)...);
+ }
+
+ QT_WARNING_POP
diff --git a/libs/patches/qtbase-0017-QOffsetStringArray-fix-size_t-qsizetype-mismatch.patch b/libs/patches/qtbase-0017-QOffsetStringArray-fix-size_t-qsizetype-mismatch.patch
new file mode 100644
index 0000000..5f23bbb
--- /dev/null
+++ b/libs/patches/qtbase-0017-QOffsetStringArray-fix-size_t-qsizetype-mismatch.patch
@@ -0,0 +1,31 @@
+From 72533c561d6952e63f86f11d9e4f0c6ffe8ed5a1 Mon Sep 17 00:00:00 2001
+From: Marc Mutz