summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmake/FindWrapBrotli.cmake7
-rw-r--r--cmake/FindWrapSystemHarfbuzz.cmake7
-rw-r--r--cmake/FindWrapSystemPCRE2.cmake7
-rw-r--r--cmake/FindWrapZSTD.cmake7
-rw-r--r--cmake/QtAppHelpers.cmake2
-rw-r--r--cmake/QtAutoDetectHelpers.cmake6
-rw-r--r--cmake/QtFlagHandlingHelpers.cmake23
-rw-r--r--cmake/QtFrameworkHelpers.cmake10
-rw-r--r--cmake/QtHeadersClean.cmake3
-rw-r--r--cmake/QtModuleHelpers.cmake2
-rw-r--r--cmake/QtPluginHelpers.cmake2
-rw-r--r--cmake/QtPostProcessHelpers.cmake10
-rw-r--r--cmake/QtPriHelpers.cmake2
-rw-r--r--cmake/QtProcessConfigureArgs.cmake1
-rw-r--r--cmake/QtPublicWasmToolchainHelpers.cmake4
-rw-r--r--cmake/QtTargetHelpers.cmake1
-rw-r--r--cmake/QtTestHelpers.cmake12
-rw-r--r--cmake/QtToolHelpers.cmake2
-rw-r--r--cmake/README.md2
-rw-r--r--cmake/configure-cmake-mapping.md5
-rw-r--r--cmake/visionos/Info.plist.app.in8
-rw-r--r--coin/instructions/cmake_module_build_instructions.yaml3
-rw-r--r--coin/instructions/cmake_qtbase_build_instructions.yaml3
-rw-r--r--config.tests/no_direct_extern_access/CMakeLists.txt2
-rw-r--r--config_help.txt6
-rw-r--r--doc/global/externalsites/external-resources.qdoc4
-rw-r--r--doc/global/macros.qdocconf10
-rw-r--r--examples/corelib/platform/androidnotifier/android/AndroidManifest.xml5
-rw-r--r--examples/opengl/cube/fshader.glsl2
-rw-r--r--examples/opengl/cube/vshader.glsl2
-rw-r--r--examples/widgets/animation/CMakeLists.txt2
-rw-r--r--examples/widgets/desktop/CMakeLists.txt2
-rw-r--r--examples/widgets/doc/src/simpletreemodel.qdoc8
-rw-r--r--examples/widgets/itemviews/editabletreemodel/default.txt10
-rw-r--r--examples/widgets/itemviews/simpletreemodel/default.txt10
-rw-r--r--examples/widgets/widgets/shortcuteditor/CMakeLists.txt2
-rw-r--r--qmake/CMakeLists.txt3
-rw-r--r--src/3rdparty/gradle/gradle/wrapper/gradle-wrapper.properties2
-rw-r--r--src/3rdparty/gradle/qt_attribution.json6
-rw-r--r--src/3rdparty/libjpeg/LICENSE31
-rwxr-xr-xsrc/3rdparty/libjpeg/import_from_libjpeg_tarball.sh2
-rw-r--r--src/3rdparty/libjpeg/qt_attribution.json10
-rw-r--r--src/3rdparty/libjpeg/src/ChangeLog.md24
-rw-r--r--src/3rdparty/libjpeg/src/jcmaster.c122
-rw-r--r--src/3rdparty/libjpeg/src/jconfig.h4
-rw-r--r--src/3rdparty/libjpeg/src/jconfigint.h2
-rw-r--r--src/3rdparty/libjpeg/src/jerror.c14
-rw-r--r--src/3rdparty/libjpeg/src/jversion.h7
-rw-r--r--src/3rdparty/libjpeg/zlib-license.txt15
-rw-r--r--src/android/CMakeLists.txt1
-rw-r--r--src/android/jar/CMakeLists.txt8
-rw-r--r--src/android/jar/build.gradle4
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/BackendRegister.java9
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtAccessibilityDelegate.java2
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtAccessibilityInterface.java14
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtActivityBase.java13
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java129
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtActivityDelegateBase.java90
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtEmbeddedDelegate.java63
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtEmbeddedDelegateFactory.java37
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtEmbeddedLoader.java2
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtEmbeddedViewInterfaceFactory.java34
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtInputConnection.java9
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java261
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtInputInterface.java21
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtLayoutInterface.java8
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtMenuInterface.java11
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtServiceEmbeddedDelegate.java10
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtView.java52
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtWindow.java5
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtWindowInterface.java11
-rw-r--r--src/android/templates/build.gradle8
-rw-r--r--src/android/templates/doc/src/android-manifest-file-configuration.qdoc6
-rw-r--r--src/android/templates_aar/AndroidManifest.xml9
-rw-r--r--src/android/templates_aar/CMakeLists.txt24
-rw-r--r--src/assets/CMakeLists.txt2
-rw-r--r--src/corelib/CMakeLists.txt38
-rw-r--r--src/corelib/Qt6AndroidMacros.cmake50
-rw-r--r--src/corelib/Qt6CoreConfigExtras.cmake.in2
-rw-r--r--src/corelib/compat/removed_api.cpp48
-rw-r--r--src/corelib/configure.cmake3
-rw-r--r--src/corelib/doc/src/cmake/cmake-properties.qdoc50
-rw-r--r--src/corelib/doc/src/cmake/qt_android_generate_deployment_settings.qdoc1
-rw-r--r--src/corelib/global/qcompare.cpp56
-rw-r--r--src/corelib/global/qcomparehelpers.h96
-rw-r--r--src/corelib/global/qlibraryinfo.cpp96
-rw-r--r--src/corelib/global/qnamespace.h6
-rw-r--r--src/corelib/global/qnamespace.qdoc12
-rw-r--r--src/corelib/global/qtconfigmacros.h1
-rw-r--r--src/corelib/global/qtdeprecationdefinitions.h.in28
-rw-r--r--src/corelib/global/qtdeprecationmarkers.h23
-rw-r--r--src/corelib/io/qdir.cpp5
-rw-r--r--src/corelib/io/qdirlisting.cpp51
-rw-r--r--src/corelib/io/qfile.cpp2
-rw-r--r--src/corelib/io/qfilesystemengine_unix.cpp34
-rw-r--r--src/corelib/io/qurl.cpp21
-rw-r--r--src/corelib/itemmodels/qabstractitemmodel.cpp100
-rw-r--r--src/corelib/itemmodels/qabstractitemmodel.h42
-rw-r--r--src/corelib/itemmodels/qitemselectionmodel.h2
-rw-r--r--src/corelib/kernel/qapplicationstatic.h4
-rw-r--r--src/corelib/kernel/qcore_mac.mm2
-rw-r--r--src/corelib/kernel/qcore_mac_p.h5
-rw-r--r--src/corelib/kernel/qelapsedtimer.cpp5
-rw-r--r--src/corelib/kernel/qelapsedtimer.h39
-rw-r--r--src/corelib/kernel/qjniobject.cpp4
-rw-r--r--src/corelib/kernel/qmetatype.cpp50
-rw-r--r--src/corelib/kernel/qmetatype.h24
-rw-r--r--src/corelib/kernel/qproperty_p.h5
-rw-r--r--src/corelib/kernel/qvariant.h1
-rw-r--r--src/corelib/mimetypes/mime/packages/freedesktop.org.xml62
-rw-r--r--src/corelib/platform/android/qandroidnativeinterface.cpp2
-rw-r--r--src/corelib/plugin/quuid.cpp64
-rw-r--r--src/corelib/plugin/quuid.h71
-rw-r--r--src/corelib/text/qbytearray.cpp66
-rw-r--r--src/corelib/text/qbytearraymatcher.cpp61
-rw-r--r--src/corelib/text/qlocale.cpp5
-rw-r--r--src/corelib/text/qlocale_tools.cpp86
-rw-r--r--src/corelib/text/qlocale_tools_p.h17
-rw-r--r--src/corelib/text/qstring.cpp17
-rw-r--r--src/corelib/thread/qfutureinterface.h5
-rw-r--r--src/corelib/thread/qresultstore.cpp10
-rw-r--r--src/corelib/thread/qresultstore.h9
-rw-r--r--src/corelib/thread/qthread_unix.cpp6
-rw-r--r--src/corelib/time/qtimezone.cpp11
-rw-r--r--src/corelib/time/qtimezonelocale.cpp99
-rw-r--r--src/corelib/time/qtimezonelocale_p.h13
-rw-r--r--src/corelib/time/qtimezoneprivate.cpp124
-rw-r--r--src/corelib/time/qtimezoneprivate_data_p.h364
-rw-r--r--src/corelib/time/qtimezoneprivate_icu.cpp73
-rw-r--r--src/corelib/time/qtimezoneprivate_p.h36
-rw-r--r--src/corelib/time/qtimezoneprivate_tz.cpp150
-rw-r--r--src/corelib/tools/qcryptographichash.cpp2
-rw-r--r--src/corelib/tools/qsize.cpp33
-rw-r--r--src/corelib/tools/qsize.h23
-rw-r--r--src/corelib/tools/qspan.h23
-rw-r--r--src/corelib/tools/qspan.qdoc36
-rw-r--r--src/gui/CMakeLists.txt20
-rw-r--r--src/gui/accessible/linux/atspiadaptor.cpp75
-rw-r--r--src/gui/accessible/linux/atspiadaptor_p.h6
-rw-r--r--src/gui/accessible/qaccessible.cpp83
-rw-r--r--src/gui/accessible/qaccessible.h32
-rw-r--r--src/gui/accessible/qaccessible_base.h7
-rw-r--r--src/gui/accessible/qaccessiblebridge.cpp2
-rw-r--r--src/gui/accessible/qaccessiblebridge.h4
-rw-r--r--src/gui/image/qicon.cpp28
-rw-r--r--src/gui/image/qicon_p.h20
-rw-r--r--src/gui/image/qiconengine.h1
-rw-r--r--src/gui/kernel/qguiapplication.cpp12
-rw-r--r--src/gui/kernel/qguiapplication_p.h2
-rw-r--r--src/gui/kernel/qguiapplication_platform.h30
-rw-r--r--src/gui/kernel/qhighdpiscaling_p.h4
-rw-r--r--src/gui/kernel/qpalette.cpp5
-rw-r--r--src/gui/kernel/qstylehints.cpp34
-rw-r--r--src/gui/kernel/qstylehints.h5
-rw-r--r--src/gui/kernel/qstylehints_p.h1
-rw-r--r--src/gui/kernel/qwindow.cpp8
-rw-r--r--src/gui/painting/qbackingstore.cpp29
-rw-r--r--src/gui/painting/qbackingstorerhisupport.cpp4
-rw-r--r--src/gui/painting/qcolorspace.cpp8
-rw-r--r--src/gui/painting/qcolortransform.cpp116
-rw-r--r--src/gui/painting/qcolortransform_p.h6
-rw-r--r--src/gui/painting/qicc.cpp6
-rw-r--r--src/gui/painting/qpdf.cpp1
-rw-r--r--src/gui/painting/qregion.cpp64
-rw-r--r--src/gui/painting/qregion.h4
-rw-r--r--src/gui/platform/ios/qiosnativeinterface.cpp26
-rw-r--r--src/gui/platform/unix/qgenericunixthemes.cpp266
-rw-r--r--src/gui/qt_cmdline.cmake3
-rw-r--r--src/gui/text/qcssparser.cpp50
-rw-r--r--src/gui/text/qcssparser_p.h14
-rw-r--r--src/gui/text/qfontdatabase.cpp31
-rw-r--r--src/gui/text/qtextdocument.cpp48
-rw-r--r--src/gui/text/qtextdocument.h6
-rw-r--r--src/gui/text/qtexthtmlparser.cpp55
-rw-r--r--src/gui/util/qdesktopservices.cpp33
-rw-r--r--src/network/access/http2/http2protocol_p.h2
-rw-r--r--src/network/access/qhttpnetworkconnection.cpp67
-rw-r--r--src/network/access/qhttpnetworkconnection_p.h7
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel.cpp147
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel_p.h5
-rw-r--r--src/network/access/qhttpnetworkrequest.cpp10
-rw-r--r--src/network/access/qhttpnetworkrequest_p.h4
-rw-r--r--src/network/access/qhttpthreaddelegate.cpp36
-rw-r--r--src/network/access/qnetworkaccessmanager.cpp15
-rw-r--r--src/network/access/qnetworkreplyhttpimpl.cpp19
-rw-r--r--src/network/access/qnetworkrequest.cpp10
-rw-r--r--src/network/access/qnetworkrequest.h1
-rw-r--r--src/network/android/jar/build.gradle4
-rw-r--r--src/network/kernel/qnetworkinterface_unix.cpp26
-rw-r--r--src/plugins/networkinformation/android/jar/build.gradle4
-rw-r--r--src/plugins/platforms/android/CMakeLists.txt3
-rw-r--r--src/plugins/platforms/android/androidbackendregister.cpp52
-rw-r--r--src/plugins/platforms/android/androidbackendregister.h67
-rw-r--r--src/plugins/platforms/android/androidjniaccessibility.cpp2
-rw-r--r--src/plugins/platforms/android/androidjniinput.cpp52
-rw-r--r--src/plugins/platforms/android/androidjnimain.cpp78
-rw-r--r--src/plugins/platforms/android/androidjnimain.h6
-rw-r--r--src/plugins/platforms/android/androidjnimenu.cpp18
-rw-r--r--src/plugins/platforms/android/qandroidplatformscreen.cpp20
-rw-r--r--src/plugins/platforms/android/qandroidplatformwindow.cpp13
-rw-r--r--src/plugins/platforms/cocoa/CMakeLists.txt2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibility.mm17
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm2
-rw-r--r--src/plugins/platforms/eglfs/CMakeLists.txt2
-rw-r--r--src/plugins/platforms/ios/CMakeLists.txt19
-rw-r--r--src/plugins/platforms/ios/SwiftIntegration.cmake78
-rw-r--r--src/plugins/platforms/ios/module.modulemap4
-rw-r--r--src/plugins/platforms/ios/qiosapplication.swift82
-rw-r--r--src/plugins/platforms/ios/qiosapplicationdelegate.h5
-rw-r--r--src/plugins/platforms/ios/qioseventdispatcher.h2
-rw-r--r--src/plugins/platforms/ios/qioseventdispatcher.mm21
-rw-r--r--src/plugins/platforms/ios/qiosglobal.mm20
-rw-r--r--src/plugins/platforms/ios/qiosintegration.h30
-rw-r--r--src/plugins/platforms/ios/qiosintegration.mm37
-rw-r--r--src/plugins/platforms/linuxfb/CMakeLists.txt2
-rw-r--r--src/plugins/platforms/minimal/CMakeLists.txt2
-rw-r--r--src/plugins/platforms/minimalegl/CMakeLists.txt2
-rw-r--r--src/plugins/platforms/offscreen/CMakeLists.txt2
-rw-r--r--src/plugins/platforms/qnx/CMakeLists.txt2
-rw-r--r--src/plugins/platforms/qnx/qqnxintegration.cpp16
-rw-r--r--src/plugins/platforms/vkkhrdisplay/CMakeLists.txt2
-rw-r--r--src/plugins/platforms/vnc/CMakeLists.txt2
-rw-r--r--src/plugins/platforms/wasm/CMakeLists.txt2
-rw-r--r--src/plugins/platforms/wasm/qwasmevent.cpp2
-rw-r--r--src/plugins/platforms/wasm/qwasmevent.h1
-rw-r--r--src/plugins/platforms/wasm/qwasmwindow.cpp2
-rw-r--r--src/plugins/platforms/wasm/wasm_shell.html5
-rw-r--r--src/plugins/platforms/windows/CMakeLists.txt2
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.cpp6
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.h1
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.h1
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp6
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp3
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp111
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h5
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiautomation.cpp8
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiautomation.h11
-rw-r--r--src/plugins/platforms/xcb/CMakeLists.txt2
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp5
-rw-r--r--src/plugins/sqldrivers/ibase/qsql_ibase.cpp140
-rw-r--r--src/plugins/styles/modernwindows/qwindows11style.cpp22
-rw-r--r--src/printsupport/CMakeLists.txt2
-rw-r--r--src/printsupport/kernel/qprintengine.cpp15
-rw-r--r--src/printsupport/kernel/qprintengine.h3
-rw-r--r--src/sql/kernel/qsqldatabase.cpp2
-rw-r--r--src/sql/kernel/qsqldatabase.h2
-rw-r--r--src/sql/models/qsqlquerymodel.cpp7
-rw-r--r--src/sql/models/qsqlrelationaltablemodel.cpp18
-rw-r--r--src/sql/models/qsqltablemodel.cpp33
-rw-r--r--src/sql/models/qsqltablemodel_p.h6
-rw-r--r--src/testlib/qsignalspy.cpp7
-rw-r--r--src/testlib/qsignalspy.h5
-rw-r--r--src/testlib/qtestevent.h15
-rw-r--r--src/tools/androiddeployqt/main.cpp332
-rw-r--r--src/tools/moc/main.cpp69
-rw-r--r--src/tools/rcc/rcc.cpp2
-rw-r--r--src/tools/rcc/rcc.h2
-rw-r--r--src/tools/syncqt/CMakeLists.txt2
-rw-r--r--src/tools/syncqt/main.cpp15
-rw-r--r--src/tools/uic/cpp/cppwriteinitialization.cpp2
-rw-r--r--src/tools/uic/uic.cpp4
-rw-r--r--src/tools/windeployqt/main.cpp22
-rw-r--r--src/widgets/kernel/qwidget.cpp102
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp9
-rw-r--r--src/widgets/styles/images/standardbutton-apply-128.pngbin5395 -> 5298 bytes
-rw-r--r--src/widgets/styles/images/standardbutton-apply-16.pngbin611 -> 567 bytes
-rw-r--r--src/widgets/styles/images/standardbutton-apply-32.pngbin1279 -> 1219 bytes
-rw-r--r--src/widgets/styles/images/standardbutton-no-128.pngbin6520 -> 6437 bytes
-rw-r--r--src/widgets/styles/images/standardbutton-no-16.pngbin701 -> 673 bytes
-rw-r--r--src/widgets/styles/images/standardbutton-no-32.pngbin1445 -> 1476 bytes
-rw-r--r--src/widgets/styles/images/standardbutton-ok-128.pngbin4232 -> 4414 bytes
-rw-r--r--src/widgets/styles/images/standardbutton-yes-128.pngbin6554 -> 6484 bytes
-rw-r--r--src/widgets/styles/images/standardbutton-yes-16.pngbin687 -> 661 bytes
-rw-r--r--src/widgets/styles/images/standardbutton-yes-32.pngbin1504 -> 1529 bytes
-rw-r--r--src/widgets/styles/qstylehelper.cpp2
-rw-r--r--src/widgets/widgets/qdialogbuttonbox.cpp54
-rw-r--r--src/widgets/widgets/qdialogbuttonbox_p.h5
-rw-r--r--src/widgets/widgets/qframe.cpp6
-rw-r--r--tests/auto/cmake/test_moc_macro_target/check_moc_parameters.cmake2
-rw-r--r--tests/auto/cmake/test_qt_add_resources_rebuild/sample/CMakeLists.txt2
-rw-r--r--tests/auto/corelib/global/CMakeLists.txt1
-rw-r--r--tests/auto/corelib/global/q20/CMakeLists.txt2
-rw-r--r--tests/auto/corelib/global/qcomparehelpers/tst_qcomparehelpers.cpp2
-rw-r--r--tests/auto/corelib/global/qlibraryinfo/CMakeLists.txt17
-rw-r--r--tests/auto/corelib/global/qlibraryinfo/empty.qt.conf0
-rw-r--r--tests/auto/corelib/global/qlibraryinfo/partial.qt.conf2
-rw-r--r--tests/auto/corelib/global/qlibraryinfo/tst_qlibraryinfo.cpp66
-rw-r--r--tests/auto/corelib/global/qxp/CMakeLists.txt2
-rw-r--r--tests/auto/corelib/io/CMakeLists.txt2
-rw-r--r--tests/auto/corelib/io/largefile/tst_largefile.cpp8
-rw-r--r--tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp9
-rw-r--r--tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp10
-rwxr-xr-xtests/auto/corelib/io/qresourceengine/generateResources.sh2
-rw-r--r--tests/auto/corelib/io/qurl/tst_qurl.cpp8
-rw-r--r--tests/auto/corelib/itemmodels/qabstractitemmodel/tst_qabstractitemmodel.cpp21
-rw-r--r--tests/auto/corelib/kernel/qelapsedtimer/CMakeLists.txt2
-rw-r--r--tests/auto/corelib/kernel/qelapsedtimer/tst_qelapsedtimer.cpp22
-rw-r--r--tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp2
-rw-r--r--tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp3
-rw-r--r--tests/auto/corelib/platform/windows/qcomobject/tst_qcomobject.cpp3
-rw-r--r--tests/auto/corelib/plugin/qpluginloader/machtest/CMakeLists.txt2
-rw-r--r--tests/auto/corelib/plugin/quuid/test/CMakeLists.txt2
-rw-r--r--tests/auto/corelib/plugin/quuid/tst_quuid.cpp105
-rw-r--r--tests/auto/corelib/text/qbytearrayview/CMakeLists.txt7
-rw-r--r--tests/auto/corelib/text/qbytearrayview/tst_qbytearrayview.cpp8
-rw-r--r--tests/auto/corelib/text/qlocale/tst_qlocale.cpp2
-rw-r--r--tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp13
-rw-r--r--tests/auto/corelib/text/qstringview/CMakeLists.txt7
-rw-r--r--tests/auto/corelib/text/qstringview/tst_qstringview.cpp26
-rw-r--r--tests/auto/corelib/thread/qresultstore/CMakeLists.txt1
-rw-r--r--tests/auto/corelib/thread/qresultstore/tst_qresultstore.cpp33
-rw-r--r--tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp6
-rw-r--r--tests/auto/corelib/tools/qcryptographichash/tst_qcryptographichash.cpp22
-rw-r--r--tests/auto/corelib/tools/qsize/CMakeLists.txt2
-rw-r--r--tests/auto/corelib/tools/qsize/tst_qsize.cpp37
-rw-r--r--tests/auto/corelib/tools/qsizef/CMakeLists.txt2
-rw-r--r--tests/auto/corelib/tools/qsizef/tst_qsizef.cpp96
-rw-r--r--tests/auto/corelib/tools/qspan/tst_qspan.cpp35
-rw-r--r--tests/auto/gui/painting/qregion/tst_qregion.cpp24
-rw-r--r--tests/auto/gui/text/qcssparser/tst_qcssparser.cpp55
-rw-r--r--tests/auto/gui/text/qfontdatabase/CMakeLists.txt2
-rw-r--r--tests/auto/gui/text/qfontdatabase/QtTestFallbackFont-Regular.ttfbin0 -> 5664 bytes
-rw-r--r--tests/auto/gui/text/qfontdatabase/QtTestLimitedFont-Regular.ttfbin0 -> 5280 bytes
-rw-r--r--tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp135
-rw-r--r--tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp109
-rw-r--r--tests/auto/gui/text/qtextmarkdownwriter/data/example.md4
-rw-r--r--tests/auto/gui/util/qdesktopservices/tst_qdesktopservices.cpp15
-rw-r--r--tests/auto/network/access/CMakeLists.txt1
-rw-r--r--tests/auto/network/access/http2/tst_http2.cpp2
-rw-r--r--tests/auto/network/access/qnetworkreply_local/CMakeLists.txt9
-rw-r--r--tests/auto/network/access/qnetworkreply_local/minihttpserver.h246
-rw-r--r--tests/auto/network/access/qnetworkreply_local/tst_qnetworkreply_local.cpp177
-rw-r--r--tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp8
-rw-r--r--tests/auto/other/android_deployment_settings/CMakeLists.txt2
-rw-r--r--tests/auto/other/android_deployment_settings/tst_android_deployment_settings.cpp2
-rw-r--r--tests/auto/other/qaccessibility/tst_qaccessibility.cpp7
-rw-r--r--tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp103
-rw-r--r--tests/auto/testlib/selftests/eventloop/CMakeLists.txt2
-rw-r--r--tests/auto/testlib/selftests/failcleanup/CMakeLists.txt2
-rw-r--r--tests/auto/testlib/selftests/failcleanuptestcase/CMakeLists.txt2
-rw-r--r--tests/auto/testlib/selftests/skipblacklisted/CMakeLists.txt2
-rw-r--r--tests/auto/testlib/selftests/skipcleanuptestcase/CMakeLists.txt2
-rw-r--r--tests/auto/wasm/selenium/CMakeLists.txt2
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp5
-rw-r--r--tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp45
-rw-r--r--tests/auto/xml/CMakeLists.txt2
-rw-r--r--tests/benchmarks/corelib/io/qdir/CMakeLists.txt2
-rw-r--r--tests/benchmarks/corelib/itemmodels/CMakeLists.txt2
-rw-r--r--tests/benchmarks/network/access/qdecompresshelper/main.cpp3
-rw-r--r--tests/manual/android_content_uri/CMakeLists.txt2
-rw-r--r--tests/manual/dialogs/wizardpanel.cpp2
-rw-r--r--tests/manual/examples/corelib/permissions/android/AndroidManifest.xml3
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/example.html4
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/example.md4
-rw-r--r--tests/manual/examples/widgets/scroller/CMakeLists.txt2
-rw-r--r--tests/manual/examples/widgets/tools/plugandpaint/plugins/CMakeLists.txt2
-rw-r--r--tests/manual/highdpi/CMakeLists.txt2
-rw-r--r--tests/manual/highdpi/dprgadget/CMakeLists.txt2
-rw-r--r--tests/manual/highdpi/kitchensink/CMakeLists.txt2
-rw-r--r--tests/manual/highdpi/pixelgadget/CMakeLists.txt2
-rw-r--r--tests/manual/highdpi/screengadget/CMakeLists.txt2
-rw-r--r--tests/manual/inputdevices/CMakeLists.txt2
-rw-r--r--tests/manual/permissions/android/AndroidManifest.xml3
-rw-r--r--tests/manual/rhi/hdr/CMakeLists.txt2
-rw-r--r--tests/manual/rhi/imguirenderer/CMakeLists.txt2
-rw-r--r--tests/manual/wasm/a11y/CMakeLists.txt2
-rw-r--r--tests/manual/wasm/a11y/basic_widgets/CMakeLists.txt2
-rw-r--r--tests/manual/wasm/eventloop/eventloop_auto/CMakeLists.txt2
-rw-r--r--tests/manual/wasm/network/echo_client_mainthread/CMakeLists.txt2
-rw-r--r--tests/manual/wasm/network/echo_client_secondarythread/CMakeLists.txt2
-rw-r--r--tests/manual/wasm/network/echo_server/CMakeLists.txt2
-rw-r--r--tests/manual/wasm/network/sockify_sockets_auto/CMakeLists.txt2
-rw-r--r--tests/manual/wasm/qstdweb/CMakeLists.txt3
-rw-r--r--tests/manual/xembed/CMakeLists.txt2
-rw-r--r--tests/manual/xembed/gtk-container/CMakeLists.txt2
-rwxr-xr-xtests/testserver/echo/echo.sh2
-rwxr-xr-xutil/edid/qedidvendortable.py4
-rw-r--r--util/gradientgen/gradientgen.cpp4
-rw-r--r--util/locale_database/cldr.py53
-rwxr-xr-xutil/locale_database/cldr2qtimezone.py46
381 files changed, 6554 insertions, 2081 deletions
diff --git a/cmake/FindWrapBrotli.cmake b/cmake/FindWrapBrotli.cmake
index e2d7b564f6..d254f4292e 100644
--- a/cmake/FindWrapBrotli.cmake
+++ b/cmake/FindWrapBrotli.cmake
@@ -20,6 +20,13 @@ if (unofficial-brotli_FOUND)
set(WrapBrotli_FOUND ON)
else()
+ get_cmake_property(__packages_not_found PACKAGES_NOT_FOUND)
+ if(__packages_not_found)
+ list(REMOVE_ITEM __packages_not_found unofficial-brotli)
+ set_property(GLOBAL PROPERTY PACKAGES_NOT_FOUND "${__packages_not_found}")
+ endif()
+ unset(__packages_not_found)
+
find_package(PkgConfig QUIET)
if (PKG_CONFIG_FOUND)
pkg_check_modules(libbrotlidec QUIET IMPORTED_TARGET "libbrotlidec")
diff --git a/cmake/FindWrapSystemHarfbuzz.cmake b/cmake/FindWrapSystemHarfbuzz.cmake
index 07b3405bc0..d989c93e44 100644
--- a/cmake/FindWrapSystemHarfbuzz.cmake
+++ b/cmake/FindWrapSystemHarfbuzz.cmake
@@ -28,6 +28,13 @@ if(harfbuzz_FOUND AND TARGET "${__harfbuzz_target_name}")
if(harfbuzz_VERSION)
set(WrapSystemHarfbuzz_VERSION "${harfbuzz_VERSION}")
endif()
+else()
+ get_cmake_property(__packages_not_found PACKAGES_NOT_FOUND)
+ if(__packages_not_found)
+ list(REMOVE_ITEM __packages_not_found harfbuzz)
+ set_property(GLOBAL PROPERTY PACKAGES_NOT_FOUND "${__packages_not_found}")
+ endif()
+ unset(__packages_not_found)
endif()
if(__harfbuzz_broken_config_file OR NOT __harfbuzz_found)
diff --git a/cmake/FindWrapSystemPCRE2.cmake b/cmake/FindWrapSystemPCRE2.cmake
index 61e0d2fb5b..ce00252c8c 100644
--- a/cmake/FindWrapSystemPCRE2.cmake
+++ b/cmake/FindWrapSystemPCRE2.cmake
@@ -16,6 +16,13 @@ if(PCRE2_FOUND AND TARGET "${__pcre2_target_name}")
if(PCRE2_VERSION)
set(WrapSystemPCRE2_VERSION "${PCRE2_VERSION}")
endif()
+else()
+ get_cmake_property(__packages_not_found PACKAGES_NOT_FOUND)
+ if(__packages_not_found)
+ list(REMOVE_ITEM __packages_not_found PCRE2)
+ set_property(GLOBAL PROPERTY PACKAGES_NOT_FOUND "${__packages_not_found}")
+ endif()
+ unset(__packages_not_found)
endif()
if(NOT __pcre2_found)
diff --git a/cmake/FindWrapZSTD.cmake b/cmake/FindWrapZSTD.cmake
index fb424236b8..7e5adcf276 100644
--- a/cmake/FindWrapZSTD.cmake
+++ b/cmake/FindWrapZSTD.cmake
@@ -39,6 +39,13 @@ if(TARGET zstd::libzstd_static OR TARGET zstd::libzstd_shared)
INTERFACE_LINK_LIBRARIES "zstd::libzstd${zstdtargetsuffix}")
endif()
else()
+ get_cmake_property(__packages_not_found PACKAGES_NOT_FOUND)
+ if(__packages_not_found)
+ list(REMOVE_ITEM __packages_not_found zstd)
+ set_property(GLOBAL PROPERTY PACKAGES_NOT_FOUND "${__packages_not_found}")
+ endif()
+ unset(__packages_not_found)
+
find_package(PkgConfig QUIET)
pkg_check_modules(PC_ZSTD QUIET "libzstd")
diff --git a/cmake/QtAppHelpers.cmake b/cmake/QtAppHelpers.cmake
index c0ad53ab9e..f0dbd110ab 100644
--- a/cmake/QtAppHelpers.cmake
+++ b/cmake/QtAppHelpers.cmake
@@ -35,8 +35,6 @@ function(qt_internal_add_app target)
"a future Qt version. Use the LIBRARIES option instead.")
endif()
- qt_internal_library_deprecation_level(deprecation_define)
-
if(arg_NO_UNITY_BUILD)
set(arg_NO_UNITY_BUILD "NO_UNITY_BUILD")
else()
diff --git a/cmake/QtAutoDetectHelpers.cmake b/cmake/QtAutoDetectHelpers.cmake
index ad0764b804..5621888308 100644
--- a/cmake/QtAutoDetectHelpers.cmake
+++ b/cmake/QtAutoDetectHelpers.cmake
@@ -137,9 +137,9 @@ function(qt_auto_detect_android)
# ANDROID_NATIVE_API_LEVEL is an just an alias to ANDROID_PLATFORM, check for both
if(NOT DEFINED ANDROID_PLATFORM AND NOT DEFINED ANDROID_NATIVE_API_LEVEL)
message(STATUS "Neither ANDROID_PLATFORM nor ANDROID_NATIVE_API_LEVEL"
- " were specified, using API level 23 as default")
- set(ANDROID_PLATFORM "android-23" CACHE STRING "")
- set(ANDROID_NATIVE_API_LEVEL 23 CACHE STRING "")
+ " were specified, using API level 28 as default")
+ set(ANDROID_PLATFORM "android-28" CACHE STRING "")
+ set(ANDROID_NATIVE_API_LEVEL 28 CACHE STRING "")
endif()
if(NOT DEFINED ANDROID_STL)
set(ANDROID_STL "c++_shared" CACHE STRING "")
diff --git a/cmake/QtFlagHandlingHelpers.cmake b/cmake/QtFlagHandlingHelpers.cmake
index 6a62b85c03..251a356df0 100644
--- a/cmake/QtFlagHandlingHelpers.cmake
+++ b/cmake/QtFlagHandlingHelpers.cmake
@@ -258,29 +258,6 @@ function(qt_internal_apply_intel_cet target visibility)
endif()
endfunction()
-function(qt_internal_library_deprecation_level result)
- # QT_DISABLE_DEPRECATED_UP_TO controls which version we use as a cut-off
- # compiling in to the library. E.g. if it is set to QT_VERSION then no
- # code which was deprecated before QT_VERSION will be compiled in.
- if (NOT DEFINED QT_DISABLE_DEPRECATED_UP_TO)
- if(WIN32)
- # On Windows, due to the way DLLs work, we need to export all functions,
- # including the inlines
- list(APPEND deprecations "QT_DISABLE_DEPRECATED_UP_TO=0x040800")
- else()
- # On other platforms, Qt's own compilation does need to compile the Qt 5.0 API
- list(APPEND deprecations "QT_DISABLE_DEPRECATED_UP_TO=0x050000")
- endif()
- else()
- list(APPEND deprecations "QT_DISABLE_DEPRECATED_UP_TO=${QT_DISABLE_DEPRECATED_UP_TO}")
- endif()
- # QT_WARN_DEPRECATED_UP_TO controls the upper-bound of deprecation
- # warnings that are emitted. E.g. if it is set to 0x060500 then all use of
- # things deprecated in or before 6.5.0 will be warned against.
- list(APPEND deprecations "QT_WARN_DEPRECATED_UP_TO=0x070000")
- set("${result}" "${deprecations}" PARENT_SCOPE)
-endfunction()
-
# Sets the exceptions flags for the given target according to exceptions_on
function(qt_internal_set_exceptions_flags target exceptions_on)
set(_defs "")
diff --git a/cmake/QtFrameworkHelpers.cmake b/cmake/QtFrameworkHelpers.cmake
index 750caf2cb8..7d10a98108 100644
--- a/cmake/QtFrameworkHelpers.cmake
+++ b/cmake/QtFrameworkHelpers.cmake
@@ -185,6 +185,8 @@ endfunction()
# <out_var>_version framework version, e.g. 'A', 'B' etc.
# <out_var>_bundle_version framework bundle version, same as the PROJECT_VERSION, e.g. '6.0.0'.
# <out_var>_header_dir top-level header directory, e.g. 'QtCore.framework/Headers'.
+# <out_var>_versioned_binary_dir versioned directory that contains the framework binary,
+# e.g. 'QtCore.framework/Versions/A'
# <out_var>_versioned_header_dir header directory for specific framework version,
# e.g. 'QtCore.framework/Versions/A/Headers'
# <out_var>_private_header_dir header directory for the specific framework version and
@@ -208,11 +210,14 @@ function(qt_internal_get_framework_info out_var target)
set(${out_var}_name "${module}")
set(${out_var}_dir "${${out_var}_name}.framework")
set(${out_var}_header_dir "${${out_var}_dir}/Headers")
+
if(UIKIT)
- # iOS frameworks do not version their headers
+ # iOS frameworks do not have a Versions sub-directory
+ set(${out_var}_versioned_binary_dir "${${out_var}_dir}")
set(${out_var}_versioned_header_dir "${${out_var}_header_dir}")
else()
- set(${out_var}_versioned_header_dir "${${out_var}_dir}/Versions/${${out_var}_version}/Headers")
+ set(${out_var}_versioned_binary_dir "${${out_var}_dir}/Versions/${${out_var}_version}")
+ set(${out_var}_versioned_header_dir "${${out_var}_versioned_binary_dir}/Headers")
endif()
set(${out_var}_private_header_dir "${${out_var}_versioned_header_dir}/${${out_var}_bundle_version}")
set(${out_var}_private_module_header_dir "${${out_var}_private_header_dir}/${module}")
@@ -222,6 +227,7 @@ function(qt_internal_get_framework_info out_var target)
set(${out_var}_header_dir "${${out_var}_header_dir}" PARENT_SCOPE)
set(${out_var}_version "${${out_var}_version}" PARENT_SCOPE)
set(${out_var}_bundle_version "${${out_var}_bundle_version}" PARENT_SCOPE)
+ set(${out_var}_versioned_binary_dir "${${out_var}_versioned_binary_dir}" PARENT_SCOPE)
set(${out_var}_versioned_header_dir "${${out_var}_versioned_header_dir}" PARENT_SCOPE)
set(${out_var}_private_header_dir "${${out_var}_private_header_dir}" PARENT_SCOPE)
set(${out_var}_private_module_header_dir "${${out_var}_private_module_header_dir}" PARENT_SCOPE)
diff --git a/cmake/QtHeadersClean.cmake b/cmake/QtHeadersClean.cmake
index 938b6a7b41..a1ebfcef28 100644
--- a/cmake/QtHeadersClean.cmake
+++ b/cmake/QtHeadersClean.cmake
@@ -130,7 +130,8 @@ function(qt_internal_add_headersclean_target module_target module_headers)
endif()
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang|IntelLLVM")
- list(APPEND hcleanFLAGS -Wshorten-64-to-32)
+ list(APPEND hcleanFLAGS -Wshorten-64-to-32
+ -Wweak-vtables)
endif()
separate_arguments(cxx_flags NATIVE_COMMAND ${CMAKE_CXX_FLAGS})
diff --git a/cmake/QtModuleHelpers.cmake b/cmake/QtModuleHelpers.cmake
index ba03173073..cc111affad 100644
--- a/cmake/QtModuleHelpers.cmake
+++ b/cmake/QtModuleHelpers.cmake
@@ -497,8 +497,6 @@ function(qt_internal_add_module target)
endif()
endif()
- qt_internal_library_deprecation_level(deprecation_define)
-
if(NOT arg_HEADER_MODULE)
qt_autogen_tools_initial_setup(${target})
endif()
diff --git a/cmake/QtPluginHelpers.cmake b/cmake/QtPluginHelpers.cmake
index 787788c9a9..a4188b7289 100644
--- a/cmake/QtPluginHelpers.cmake
+++ b/cmake/QtPluginHelpers.cmake
@@ -170,8 +170,6 @@ function(qt_internal_add_plugin target)
qt_handle_multi_config_output_dirs("${target}")
- qt_internal_library_deprecation_level(deprecation_define)
-
qt_autogen_tools_initial_setup(${target})
unset(plugin_install_package_suffix)
diff --git a/cmake/QtPostProcessHelpers.cmake b/cmake/QtPostProcessHelpers.cmake
index 0a207f6634..53ff7e1358 100644
--- a/cmake/QtPostProcessHelpers.cmake
+++ b/cmake/QtPostProcessHelpers.cmake
@@ -653,13 +653,19 @@ set(__qt_internal_initial_qt_cmake_build_type \"${CMAKE_BUILD_TYPE}\")
endif()
# Save the default qpa platform.
- # Used by qtwayland/src/plugins/platforms/qwayland-generic/CMakeLists.txt. Otherwise
- # the DEFAULT_IF condition is evaluated incorrectly.
if(DEFINED QT_QPA_DEFAULT_PLATFORM)
string(APPEND QT_EXTRA_BUILD_INTERNALS_VARS
"set(QT_QPA_DEFAULT_PLATFORM \"${QT_QPA_DEFAULT_PLATFORM}\" CACHE STRING \"\")\n")
endif()
+ # Save the list of default qpa platforms.
+ # Used by qtwayland/src/plugins/platforms/qwayland-generic/CMakeLists.txt. Otherwise
+ # the DEFAULT_IF condition is evaluated incorrectly.
+ if(DEFINED QT_QPA_PLATFORMS)
+ string(APPEND QT_EXTRA_BUILD_INTERNALS_VARS
+ "set(QT_QPA_PLATFORMS \"${QT_QPA_PLATFORMS}\" CACHE STRING \"\")\n")
+ endif()
+
# Save minimum and policy-related CMake versions to ensure the same minimum is
# checked for when building other downstream repos (qtsvg, etc) and the policy settings
# will be consistent unless the downstream repos explicitly override them.
diff --git a/cmake/QtPriHelpers.cmake b/cmake/QtPriHelpers.cmake
index f410dc9b2a..f29b55b349 100644
--- a/cmake/QtPriHelpers.cmake
+++ b/cmake/QtPriHelpers.cmake
@@ -841,7 +841,7 @@ function(qt_generate_global_device_pri_file)
file(TO_CMAKE_PATH ${ANDROID_NDK} ANDROID_NDK)
string(APPEND content "DEFAULT_ANDROID_NDK_ROOT = ${ANDROID_NDK}\n")
- set(android_platform "android-23")
+ set(android_platform "android-28")
if(ANDROID_PLATFORM)
set(android_platform "${ANDROID_PLATFORM}")
elseif(ANDROID_NATIVE_API_LEVEL)
diff --git a/cmake/QtProcessConfigureArgs.cmake b/cmake/QtProcessConfigureArgs.cmake
index c64403b209..df0dfe48de 100644
--- a/cmake/QtProcessConfigureArgs.cmake
+++ b/cmake/QtProcessConfigureArgs.cmake
@@ -943,6 +943,7 @@ translate_string_input(platform QT_QMAKE_TARGET_MKSPEC)
translate_string_input(xplatform QT_QMAKE_TARGET_MKSPEC)
guess_compiler_from_mkspec()
translate_string_input(qpa_default_platform QT_QPA_DEFAULT_PLATFORM)
+translate_list_input(qpa_platforms QT_QPA_PLATFORMS)
translate_path_input(android-sdk ANDROID_SDK_ROOT)
translate_path_input(android-ndk ANDROID_NDK_ROOT)
diff --git a/cmake/QtPublicWasmToolchainHelpers.cmake b/cmake/QtPublicWasmToolchainHelpers.cmake
index 31f6b5aca5..a8994520e2 100644
--- a/cmake/QtPublicWasmToolchainHelpers.cmake
+++ b/cmake/QtPublicWasmToolchainHelpers.cmake
@@ -83,8 +83,6 @@ function(__qt_internal_get_qt_build_emsdk_version out_var)
file(READ "${WASM_BUILD_DIR}/src/corelib/global/qconfig.h" ver)
elseif(EXISTS "${WASM_BUILD_DIR}/include/QtCore/qconfig.h")
file(READ "${WASM_BUILD_DIR}/include/QtCore/qconfig.h" ver)
- else()
- message("qconfig.h not found, unable to determine Qt build Emscripten version")
endif()
if (ver)
string(REGEX MATCH "#define QT_EMCC_VERSION.\"[0-9]+\\.[0-9]+\\.[0-9]+\"" emOutput ${ver})
@@ -99,7 +97,7 @@ function(_qt_test_emscripten_version)
__qt_internal_query_emsdk_version("${emroot_path}" TRUE current_emsdk_ver)
__qt_internal_get_qt_build_emsdk_version(qt_build_emcc_version)
- if(NOT "${qt_build_emcc_version}" STREQUAL "${current_emsdk_ver}")
+ if(NOT "${qt_build_emcc_version}" STREQUAL "" AND NOT "${qt_build_emcc_version}" STREQUAL "${current_emsdk_ver}")
message("Qt Wasm built with Emscripten version: ${qt_build_emcc_version}")
message("You are using Emscripten version: ${current_emsdk_ver}")
message("The recommended version of Emscripten for this Qt is: ${_recommended_emver}")
diff --git a/cmake/QtTargetHelpers.cmake b/cmake/QtTargetHelpers.cmake
index 3740e85803..d361a8096d 100644
--- a/cmake/QtTargetHelpers.cmake
+++ b/cmake/QtTargetHelpers.cmake
@@ -479,6 +479,7 @@ function(qt_internal_setup_cmake_config_postfix)
# If postfix is set by user avoid changing it, but save postfix variable that has
# a non-default value for further warning.
if("${${postfix_var}}" STREQUAL "")
+ set(${postfix_var} "${${default_postfix_var}}")
set(${postfix_var} "${${default_postfix_var}}" PARENT_SCOPE)
elseif(NOT "${${postfix_var}}" STREQUAL "${${default_postfix_var}}")
list(APPEND custom_postfix_vars ${postfix_var})
diff --git a/cmake/QtTestHelpers.cmake b/cmake/QtTestHelpers.cmake
index 705de2f739..62ee91296f 100644
--- a/cmake/QtTestHelpers.cmake
+++ b/cmake/QtTestHelpers.cmake
@@ -38,8 +38,6 @@ function(qt_internal_add_benchmark target)
endif()
endif()
- qt_internal_library_deprecation_level(deprecation_define)
-
qt_internal_add_executable(${target}
NO_INSTALL # we don't install benchmarks
NO_UNITY_BUILD # excluded by default
@@ -251,7 +249,6 @@ function(qt_internal_add_test_to_batch batch_name name)
# Lazy-init the test batch
if(NOT TARGET ${target})
- qt_internal_library_deprecation_level(deprecation_define)
qt_internal_add_executable(${target}
${exceptions_text}
${gui_text}
@@ -513,7 +510,6 @@ function(qt_internal_add_test name)
list(APPEND private_includes ${arg_INCLUDE_DIRECTORIES})
qt_internal_prepare_test_target_flags(version_arg exceptions_text gui_text ${ARGN})
- qt_internal_library_deprecation_level(deprecation_define)
qt_internal_add_executable("${name}"
${exceptions_text}
@@ -566,12 +562,14 @@ function(qt_internal_add_test name)
LIBRARIES ${QT_CMAKE_EXPORT_NAMESPACE}::QuickTest
)
- qt_internal_extend_target("${name}" CONDITION arg_QMLTEST AND NOT ANDROID
+ qt_internal_extend_target("${name}"
+ CONDITION arg_QMLTEST AND NOT ANDROID AND NOT QT_FORCE_BUILTIN_TESTDATA
DEFINES
QUICK_TEST_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}"
)
- qt_internal_extend_target("${name}" CONDITION arg_QMLTEST AND ANDROID
+ qt_internal_extend_target("${name}"
+ CONDITION arg_QMLTEST AND (ANDROID OR QT_FORCE_BUILTIN_TESTDATA)
DEFINES
QUICK_TEST_SOURCE_DIR=":/"
)
@@ -774,7 +772,7 @@ function(qt_internal_add_test name)
endif()
endif()
- if(ANDROID OR IOS OR WASM OR INTEGRITY OR arg_BUILTIN_TESTDATA)
+ if(ANDROID OR IOS OR WASM OR INTEGRITY OR arg_BUILTIN_TESTDATA OR QT_FORCE_BUILTIN_TESTDATA)
set(builtin_testdata TRUE)
endif()
diff --git a/cmake/QtToolHelpers.cmake b/cmake/QtToolHelpers.cmake
index 7dd507c0ee..54ddefa760 100644
--- a/cmake/QtToolHelpers.cmake
+++ b/cmake/QtToolHelpers.cmake
@@ -100,8 +100,6 @@ function(qt_internal_add_tool target_name)
"removed in a future Qt version. Use the LIBRARIES option instead.")
endif()
- qt_internal_library_deprecation_level(deprecation_define)
-
if(arg_NO_UNITY_BUILD)
set(arg_NO_UNITY_BUILD "NO_UNITY_BUILD")
else()
diff --git a/cmake/README.md b/cmake/README.md
index 9d0743566d..0d8179a32c 100644
--- a/cmake/README.md
+++ b/cmake/README.md
@@ -190,7 +190,7 @@ If you don't supply the configuration argument ``-DANDROID_ABI=...``, it will de
* x86: ``-DANDROID_ABI=x86``
* x86_64: ``-DANDROID_ABI=x86_64``
-By default we set the android API level to 23. Should you need to change this supply the following
+By default we set the android API level to 28. Should you need to change this supply the following
configuration argument to the above CMake call: ``-DANDROID_PLATFORM=android-${API_LEVEL}``.
### Cross compiling for iOS
diff --git a/cmake/configure-cmake-mapping.md b/cmake/configure-cmake-mapping.md
index 78d9152a42..6a184f6119 100644
--- a/cmake/configure-cmake-mapping.md
+++ b/cmake/configure-cmake-mapping.md
@@ -89,7 +89,7 @@ The following table describes the mapping of configure options to CMake argument
| | | assumed. |
| -android-sdk <path> | -DANDROID_SDK_ROOT=<path> | |
| -android-ndk <path> | -DCMAKE_TOOLCHAIN_FILE=<toolchain file in NDK> | |
-| -android-ndk-platform android-23 | -DANDROID_PLATFORM=android-23 | |
+| -android-ndk-platform android-28 | -DANDROID_PLATFORM=android-28 | |
| -android-abis <abi_1>,...,<abi_n> | -DANDROID_ABI=<abi_1> | only one ABI can be specified |
| -android-style-assets | -DFEATURE_android_style_assets=ON | |
| -android-javac-source | -DQT_ANDROID_JAVAC_SOURCE=7 | Set the javac build source version. |
@@ -145,7 +145,8 @@ The following table describes the mapping of configure options to CMake argument
| -opengl <api> | -DINPUT_opengl=<api> | |
| -opengles3 | -DFEATURE_opengles3=ON | |
| -egl | -DFEATURE_egl=ON | |
-| -qpa <name> | -DQT_QPA_DEFAULT_PLATFORM=<name> | |
+| -qpa <name>;...;<name_n> | -DQT_QPA_PLATFORMS=<name>;...;<name_n> | |
+| -default-qpa <name> | -DQT_QPA_DEFAULT_PLATFORM=<name> | |
| -xcb-xlib | -DFEATURE_xcb_xlib=ON | |
| -direct2d | -DFEATURE_direct2d=ON | |
| -directfb | -DFEATURE_directfb=ON | |
diff --git a/cmake/visionos/Info.plist.app.in b/cmake/visionos/Info.plist.app.in
index 7aa4698649..984b7aa10b 100644
--- a/cmake/visionos/Info.plist.app.in
+++ b/cmake/visionos/Info.plist.app.in
@@ -38,5 +38,13 @@
<array>
<string>XROS</string>
</array>
+
+ <key>UIApplicationSceneManifest</key>
+ <dict>
+ <key>UIApplicationSupportsMultipleScenes</key>
+ <true/>
+ <key>UISceneConfigurations</key>
+ <dict/>
+ </dict>
</dict>
</plist>
diff --git a/coin/instructions/cmake_module_build_instructions.yaml b/coin/instructions/cmake_module_build_instructions.yaml
index a589941701..262fbfe540 100644
--- a/coin/instructions/cmake_module_build_instructions.yaml
+++ b/coin/instructions/cmake_module_build_instructions.yaml
@@ -84,6 +84,9 @@ instructions:
- condition: property
property: features
contains_value: Packaging
+ - condition: property
+ property: host.arch
+ equals_value: X86_64 # Sign only on X86 until Coin has support for arm signing
directory: "{{.InstallRoot}}/{{.AgentWorkingDir}}"
maxTimeInSeconds: 1200
maxTimeBetweenOutput: 1200
diff --git a/coin/instructions/cmake_qtbase_build_instructions.yaml b/coin/instructions/cmake_qtbase_build_instructions.yaml
index 01eb7f3264..05c05d0bfb 100644
--- a/coin/instructions/cmake_qtbase_build_instructions.yaml
+++ b/coin/instructions/cmake_qtbase_build_instructions.yaml
@@ -81,6 +81,9 @@ instructions:
- condition: property
property: features
contains_value: Packaging
+ - condition: property
+ property: host.arch
+ equals_value: X86_64 # Sign only on X86 until Coin has support for arm signing
directory: "{{.InstallRoot}}/{{.AgentWorkingDir}}"
maxTimeInSeconds: 1200
maxTimeBetweenOutput: 1200
diff --git a/config.tests/no_direct_extern_access/CMakeLists.txt b/config.tests/no_direct_extern_access/CMakeLists.txt
index b4b881f1dc..ec50ed178b 100644
--- a/config.tests/no_direct_extern_access/CMakeLists.txt
+++ b/config.tests/no_direct_extern_access/CMakeLists.txt
@@ -1,3 +1,5 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(direct_extern_access LANGUAGES CXX)
diff --git a/config_help.txt b/config_help.txt
index 13fc516da5..263195d7fd 100644
--- a/config_help.txt
+++ b/config_help.txt
@@ -290,8 +290,10 @@ Gui, printing, widget options:
-opengles3 ........... Enable OpenGL ES 3.x support instead of ES 2.x [auto]
-egl ................. Enable EGL support [auto]
- -qpa <name> .......... Select default QPA backend(s) (e.g., xcb, cocoa, windows)
- A prioritized list separated by semi-colons.
+ -qpa <qpa1>[;<qpa2>] . Select supported QPA backend(s) (e.g., xcb, cocoa,
+ windows). A list separated by semi-colons.
+ -default-qpa <name> .. Select the default QPA backend (e.g., xcb, cocoa,
+ windows).
-xcb-xlib............. Enable Xcb-Xlib support [auto]
Platform backends:
diff --git a/doc/global/externalsites/external-resources.qdoc b/doc/global/externalsites/external-resources.qdoc
index 272c73b3b0..0dcea08a53 100644
--- a/doc/global/externalsites/external-resources.qdoc
+++ b/doc/global/externalsites/external-resources.qdoc
@@ -33,6 +33,10 @@
\title Android: Tagged Pointers
*/
/*!
+ \externalpage https://developer.android.com/build/configure-app-module
+ \title Android: Configure the app module
+*/
+/*!
\externalpage https://developer.apple.com/documentation/uikit/uiapplication/1622952-canopenurl
\title iOS: canOpenURL:
*/
diff --git a/doc/global/macros.qdocconf b/doc/global/macros.qdocconf
index 450ded322a..0bb02323c1 100644
--- a/doc/global/macros.qdocconf
+++ b/doc/global/macros.qdocconf
@@ -85,19 +85,19 @@ macro.QtTAS = "Qt Tools for Android Studio"
# The following macros are used for various Android docs. The purpose is to keep
# it as simple as updating these instead of updating multiple lines in scattered locations.
-macro.AndroidAbis = "\\c{arm64-v8}, \\c{x86_64}, \\c{x86}, and \\c{armeabi-v7a}"
+macro.AndroidAbis = "\\c{arm64-v8a}, \\c{x86_64}, \\c{x86}, and \\c{armeabi-v7a}"
macro.NdkVer = "r26b"
macro.NdkFullVer = "26.1.10909125"
macro.NdkCompilerVer = "Clang 17.0.2"
macro.JdkVer = "17"
-macro.AndroidMinApiVer = "26"
+macro.AndroidMinApiVer = "28"
macro.AndroidMaxApiVer = "34"
-macro.AndroidMinVer = "8.0"
+macro.AndroidMinVer = "9"
macro.AndroidMaxVer = "14"
macro.AndroidPlatformVer = "34"
macro.AndroidBuildToolsVer = "34.0.0"
-macro.GradleVer = "8.3"
-macro.AGPVer = "7.4.1"
+macro.GradleVer = "8.7"
+macro.AGPVer = "8.4.0"
macro.AAOSVer = "10 to 13"
macro.beginfloatleft.HTML = "<div style=\"float: left; margin-right: 2em\">"
diff --git a/examples/corelib/platform/androidnotifier/android/AndroidManifest.xml b/examples/corelib/platform/androidnotifier/android/AndroidManifest.xml
index 778028a566..1d3cf1325b 100644
--- a/examples/corelib/platform/androidnotifier/android/AndroidManifest.xml
+++ b/examples/corelib/platform/androidnotifier/android/AndroidManifest.xml
@@ -26,7 +26,6 @@
<activity
android:name="org.qtproject.qt.android.bindings.QtActivity"
android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density"
- android:label="Qt Notifier"
android:launchMode="singleTop"
android:screenOrientation="unspecified"
android:exported="true">
@@ -38,10 +37,6 @@
<meta-data
android:name="android.app.lib_name"
android:value="-- %%INSERT_APP_LIB_NAME%% --"/>
-
- <meta-data
- android:name="android.app.background_running"
- android:value="false"/>
</activity>
</application>
</manifest>
diff --git a/examples/opengl/cube/fshader.glsl b/examples/opengl/cube/fshader.glsl
index 18068cf0e6..0c056b6165 100644
--- a/examples/opengl/cube/fshader.glsl
+++ b/examples/opengl/cube/fshader.glsl
@@ -1,3 +1,5 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifdef GL_ES
// Set default precision to medium
precision mediump int;
diff --git a/examples/opengl/cube/vshader.glsl b/examples/opengl/cube/vshader.glsl
index cfdc061852..ac57d96285 100644
--- a/examples/opengl/cube/vshader.glsl
+++ b/examples/opengl/cube/vshader.glsl
@@ -1,3 +1,5 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifdef GL_ES
// Set default precision to medium
precision mediump int;
diff --git a/examples/widgets/animation/CMakeLists.txt b/examples/widgets/animation/CMakeLists.txt
index d9a18bb866..ed8ee0558c 100644
--- a/examples/widgets/animation/CMakeLists.txt
+++ b/examples/widgets/animation/CMakeLists.txt
@@ -1 +1,3 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
qt_internal_add_example(easing)
diff --git a/examples/widgets/desktop/CMakeLists.txt b/examples/widgets/desktop/CMakeLists.txt
index 169fa9ffac..0f4eda12aa 100644
--- a/examples/widgets/desktop/CMakeLists.txt
+++ b/examples/widgets/desktop/CMakeLists.txt
@@ -1,2 +1,4 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
qt_internal_add_example(screenshot)
qt_internal_add_example(systray)
diff --git a/examples/widgets/doc/src/simpletreemodel.qdoc b/examples/widgets/doc/src/simpletreemodel.qdoc
index aa12a9585f..d8e5a6faa8 100644
--- a/examples/widgets/doc/src/simpletreemodel.qdoc
+++ b/examples/widgets/doc/src/simpletreemodel.qdoc
@@ -295,14 +295,14 @@
We begin with a text file in the following format:
\code
- Getting Started How to familiarize yourself with Qt Designer
- Launching Designer Running the Qt Designer application
- The User Interface How to interact with Qt Designer
+ Getting Started How to familiarize yourself with Qt Widgets Designer
+ Launching Designer Running the Qt Widgets Designer application
+ The User Interface How to interact with Qt Widgets Designer
\endcode
\dots
\code
Connection Editing Mode Connecting widgets together with signals and slots
- Connecting Objects Making connections in Qt Designer
+ Connecting Objects Making connections in Qt Widgets Designer
Editing Connections Changing existing connections
\endcode
diff --git a/examples/widgets/itemviews/editabletreemodel/default.txt b/examples/widgets/itemviews/editabletreemodel/default.txt
index 2b2fb579ae..c3ea35257c 100644
--- a/examples/widgets/itemviews/editabletreemodel/default.txt
+++ b/examples/widgets/itemviews/editabletreemodel/default.txt
@@ -1,6 +1,6 @@
-Getting Started How to familiarize yourself with Qt Designer
- Launching Designer Running the Qt Designer application
- The User Interface How to interact with Qt Designer
+Getting Started How to familiarize yourself with Qt Widgets Designer
+ Launching Designer Running the Qt Widgets Designer application
+ The User Interface How to interact with Qt Widgets Designer
Designing a Component Creating a GUI for your application
Creating a Dialog How to create a dialog
@@ -16,7 +16,7 @@ Using a Component in Your Application Generating code from forms
A Dialog Without Auto-Connect How to connect widgets without a naming scheme
A Dialog With Auto-Connect Using automatic connections
-Form Editing Mode How to edit a form in Qt Designer
+Form Editing Mode How to edit a form in Qt Widgets Designer
Managing Forms Loading and saving forms
Editing a Form Basic editing techniques
The Property Editor Changing widget properties
@@ -36,5 +36,5 @@ Using Containers How to group widgets together
Toolbox Widgets QToolBox
Connection Editing Mode Connecting widgets together with signals and slots
- Connecting Objects Making connections in Qt Designer
+ Connecting Objects Making connections in Qt Widgets Designer
Editing Connections Changing existing connections
diff --git a/examples/widgets/itemviews/simpletreemodel/default.txt b/examples/widgets/itemviews/simpletreemodel/default.txt
index 2b2fb579ae..c3ea35257c 100644
--- a/examples/widgets/itemviews/simpletreemodel/default.txt
+++ b/examples/widgets/itemviews/simpletreemodel/default.txt
@@ -1,6 +1,6 @@
-Getting Started How to familiarize yourself with Qt Designer
- Launching Designer Running the Qt Designer application
- The User Interface How to interact with Qt Designer
+Getting Started How to familiarize yourself with Qt Widgets Designer
+ Launching Designer Running the Qt Widgets Designer application
+ The User Interface How to interact with Qt Widgets Designer
Designing a Component Creating a GUI for your application
Creating a Dialog How to create a dialog
@@ -16,7 +16,7 @@ Using a Component in Your Application Generating code from forms
A Dialog Without Auto-Connect How to connect widgets without a naming scheme
A Dialog With Auto-Connect Using automatic connections
-Form Editing Mode How to edit a form in Qt Designer
+Form Editing Mode How to edit a form in Qt Widgets Designer
Managing Forms Loading and saving forms
Editing a Form Basic editing techniques
The Property Editor Changing widget properties
@@ -36,5 +36,5 @@ Using Containers How to group widgets together
Toolbox Widgets QToolBox
Connection Editing Mode Connecting widgets together with signals and slots
- Connecting Objects Making connections in Qt Designer
+ Connecting Objects Making connections in Qt Widgets Designer
Editing Connections Changing existing connections
diff --git a/examples/widgets/widgets/shortcuteditor/CMakeLists.txt b/examples/widgets/widgets/shortcuteditor/CMakeLists.txt
index 5d1c4a8dc1..d10248fbd7 100644
--- a/examples/widgets/widgets/shortcuteditor/CMakeLists.txt
+++ b/examples/widgets/widgets/shortcuteditor/CMakeLists.txt
@@ -1,3 +1,5 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(shortcuteditor LANGUAGES CXX)
diff --git a/qmake/CMakeLists.txt b/qmake/CMakeLists.txt
index 5a54570194..ee7a91eae6 100644
--- a/qmake/CMakeLists.txt
+++ b/qmake/CMakeLists.txt
@@ -35,8 +35,6 @@ if("${hostdatadir}" STREQUAL "")
set(hostdatadir ".")
endif()
-qt_internal_library_deprecation_level(deprecation_define)
-
target_compile_definitions(QtLibraryInfo PUBLIC
PROEVALUATOR_FULL
QT_BUILD_QMAKE
@@ -44,7 +42,6 @@ target_compile_definitions(QtLibraryInfo PUBLIC
QT_HOST_MKSPEC="${QT_QMAKE_HOST_MKSPEC}"
QT_TARGET_MKSPEC="${QT_QMAKE_TARGET_MKSPEC}"
QT_HOST_DATADIR="${hostdatadir}"
- ${deprecation_define}
)
qt_internal_set_exceptions_flags(QtLibraryInfo OFF)
diff --git a/src/3rdparty/gradle/gradle/wrapper/gradle-wrapper.properties b/src/3rdparty/gradle/gradle/wrapper/gradle-wrapper.properties
index ac72c34e8a..b82aa23a4f 100644
--- a/src/3rdparty/gradle/gradle/wrapper/gradle-wrapper.properties
+++ b/src/3rdparty/gradle/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
diff --git a/src/3rdparty/gradle/qt_attribution.json b/src/3rdparty/gradle/qt_attribution.json
index 8e759c8877..bbb069c2fb 100644
--- a/src/3rdparty/gradle/qt_attribution.json
+++ b/src/3rdparty/gradle/qt_attribution.json
@@ -4,11 +4,11 @@
"QDocModule": "qtcore",
"QtParts": ["tools"],
"Homepage": "https://gradle.org",
- "Version": "8.3",
- "DownloadLocation": "https://github.com/gradle/gradle/releases/tag/v8.3.0",
+ "Version": "8.7",
+ "DownloadLocation": "https://github.com/gradle/gradle/releases/tag/v8.7.0",
"QtUsage": "Needed to create Android packages",
"License": "Apache License 2.0",
"LicenseId": "Apache-2.0",
"LicenseFile": "LICENSE",
- "Copyright": "Copyright (C) 2023 Gradle Inc."
+ "Copyright": "Copyright (C) 2024 Gradle Inc."
}
diff --git a/src/3rdparty/libjpeg/LICENSE b/src/3rdparty/libjpeg/LICENSE
index bf8a7fda7f..2204864fa1 100644
--- a/src/3rdparty/libjpeg/LICENSE
+++ b/src/3rdparty/libjpeg/LICENSE
@@ -1,30 +1,33 @@
libjpeg-turbo Licenses
======================
-libjpeg-turbo is covered by three compatible BSD-style open source licenses:
+libjpeg-turbo is covered by two compatible BSD-style open source licenses:
- The IJG (Independent JPEG Group) License, which is listed in
[README.ijg](README.ijg)
- This license applies to the libjpeg API library and associated programs
- (any code inherited from libjpeg, and any modifications to that code.)
+ This license applies to the libjpeg API library and associated programs,
+ including any code inherited from libjpeg and any modifications to that
+ code. Note that the libjpeg-turbo SIMD source code bears the
+ [zlib License](https://opensource.org/licenses/Zlib), but in the context of
+ the overall libjpeg API library, the terms of the zlib License are subsumed
+ by the terms of the IJG License.
- The Modified (3-clause) BSD License, which is listed below
- This license covers the TurboJPEG API library and associated programs, as
- well as the build system.
-
-- The [zlib License](https://opensource.org/licenses/Zlib)
-
- This license is a subset of the other two, and it covers the libjpeg-turbo
- SIMD extensions.
+ This license applies to the TurboJPEG API library and associated programs, as
+ well as the build system. Note that the TurboJPEG API library wraps the
+ libjpeg API library, so in the context of the overall TurboJPEG API library,
+ both the terms of the IJG License and the terms of the Modified (3-clause)
+ BSD License apply.
Complying with the libjpeg-turbo Licenses
=========================================
This section provides a roll-up of the libjpeg-turbo licensing terms, to the
-best of our understanding.
+best of our understanding. This is not a license in and of itself. It is
+intended solely for clarification.
1. If you are distributing a modified version of the libjpeg-turbo source,
then:
@@ -38,7 +41,7 @@ best of our understanding.
- Clauses 1 and 3 of the zlib License
2. You must add your own copyright notice to the header of each source
- file you modified, so others can tell that you modified that file (if
+ file you modified, so others can tell that you modified that file. (If
there is not an existing copyright header in that file, then you can
simply add a notice stating that you modified the file.)
@@ -119,8 +122,8 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-Why Three Licenses?
-===================
+Why Two Licenses?
+=================
The zlib License could have been used instead of the Modified (3-clause) BSD
License, and since the IJG License effectively subsumes the distribution
diff --git a/src/3rdparty/libjpeg/import_from_libjpeg_tarball.sh b/src/3rdparty/libjpeg/import_from_libjpeg_tarball.sh
index fea6c5c9b4..0c984a8eed 100755
--- a/src/3rdparty/libjpeg/import_from_libjpeg_tarball.sh
+++ b/src/3rdparty/libjpeg/import_from_libjpeg_tarball.sh
@@ -145,7 +145,7 @@ sed -i -e "s/@COPYRIGHT_YEAR@/$cyear/" $TARGET_DIR/src/jversion.h
sed -n -e 's/^[ ]*"//
s/\(\\n\)*"[ ]*\\*$//
- /JCOPYRIGHT\ /,/^[ ]*$/ {
+ /JCOPYRIGHT.\ /,/^[ ]*$/ {
/Copyright/p
}
' $TARGET_DIR/src/jversion.h > $TARGET_DIR/COPYRIGHT.txt
diff --git a/src/3rdparty/libjpeg/qt_attribution.json b/src/3rdparty/libjpeg/qt_attribution.json
index 0b06d5c01e..ae2fa94e73 100644
--- a/src/3rdparty/libjpeg/qt_attribution.json
+++ b/src/3rdparty/libjpeg/qt_attribution.json
@@ -7,11 +7,11 @@
"Description": "The Independent JPEG Group's JPEG software",
"Homepage": "http://libjpeg-turbo.virtualgl.org/",
- "Version": "3.0.2",
- "DownloadLocation": "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/3.0.2/libjpeg-turbo-3.0.2.tar.gz",
+ "Version": "3.0.3",
+ "DownloadLocation": "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/3.0.3/libjpeg-turbo-3.0.3.tar.gz",
- "License": "Independent JPEG Group License and BSD 3-Clause \"New\" or \"Revised\" License and zlib License",
- "LicenseId": "IJG AND BSD-3-Clause AND Zlib",
- "LicenseFiles": [ "LICENSE", "ijg-license.txt", "zlib-license.txt"],
+ "License": "Independent JPEG Group License and BSD 3-Clause \"New\" or \"Revised\" License",
+ "LicenseId": "IJG AND BSD-3-Clause",
+ "LicenseFiles": [ "LICENSE", "ijg-license.txt" ],
"CopyrightFile": "COPYRIGHT.txt"
}
diff --git a/src/3rdparty/libjpeg/src/ChangeLog.md b/src/3rdparty/libjpeg/src/ChangeLog.md
index a929b62a8c..8039c5536d 100644
--- a/src/3rdparty/libjpeg/src/ChangeLog.md
+++ b/src/3rdparty/libjpeg/src/ChangeLog.md
@@ -1,3 +1,27 @@
+3.0.3
+=====
+
+### Significant changes relative to 3.0.2:
+
+1. Fixed an issue in the build system, introduced in 3.0.2, that caused all
+libjpeg-turbo components to depend on the Visual C++ run-time DLL when built
+with Visual C++ and CMake 3.15 or later, regardless of value of the
+`WITH_CRT_DLL` CMake variable.
+
+2. The x86-64 SIMD extensions now include support for Intel Control-flow
+Enforcement Technology (CET), which is enabled automatically if CET is enabled
+in the C compiler.
+
+3. Fixed a regression introduced by 3.0 beta2[6] that made it impossible for
+calling applications to supply custom Huffman tables when generating
+12-bit-per-component lossy JPEG images using the libjpeg API.
+
+4. Fixed a segfault that occurred when attempting to use the jpegtran `-drop`
+option with a specially-crafted malformed input image or drop image
+(specifically an image in which all of the scans contain fewer components than
+the number of components specified in the Start Of Frame segment.)
+
+
3.0.2
=====
diff --git a/src/3rdparty/libjpeg/src/jcmaster.c b/src/3rdparty/libjpeg/src/jcmaster.c
index 7e1408fcc9..161019763d 100644
--- a/src/3rdparty/libjpeg/src/jcmaster.c
+++ b/src/3rdparty/libjpeg/src/jcmaster.c
@@ -7,7 +7,7 @@
* Lossless JPEG Modifications:
* Copyright (C) 1999, Ken Murchison.
* libjpeg-turbo Modifications:
- * Copyright (C) 2010, 2016, 2018, 2022-2023, D. R. Commander.
+ * Copyright (C) 2010, 2016, 2018, 2022-2024, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
@@ -50,6 +50,113 @@ jpeg_calc_jpeg_dimensions(j_compress_ptr cinfo)
#endif
+LOCAL(boolean)
+using_std_huff_tables(j_compress_ptr cinfo)
+{
+ int i;
+
+ static const UINT8 bits_dc_luminance[17] = {
+ /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0
+ };
+ static const UINT8 val_dc_luminance[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
+ };
+
+ static const UINT8 bits_dc_chrominance[17] = {
+ /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0
+ };
+ static const UINT8 val_dc_chrominance[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
+ };
+
+ static const UINT8 bits_ac_luminance[17] = {
+ /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d
+ };
+ static const UINT8 val_ac_luminance[] = {
+ 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
+ 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
+ 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
+ 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
+ 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
+ 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
+ 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+ 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
+ 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+ 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
+ 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
+ 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
+ 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+ 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
+ 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
+ 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
+ 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
+ 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
+ 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+ 0xf9, 0xfa
+ };
+
+ static const UINT8 bits_ac_chrominance[17] = {
+ /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77
+ };
+ static const UINT8 val_ac_chrominance[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
+ 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
+ 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
+ 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
+ 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
+ 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
+ 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
+ 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+ 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+ 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
+ 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
+ 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
+ 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
+ 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
+ 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
+ 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
+ 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+ 0xf9, 0xfa
+ };
+
+ if (cinfo->dc_huff_tbl_ptrs[0] == NULL ||
+ cinfo->ac_huff_tbl_ptrs[0] == NULL ||
+ cinfo->dc_huff_tbl_ptrs[1] == NULL ||
+ cinfo->ac_huff_tbl_ptrs[1] == NULL)
+ return FALSE;
+
+ for (i = 2; i < NUM_HUFF_TBLS; i++) {
+ if (cinfo->dc_huff_tbl_ptrs[i] != NULL ||
+ cinfo->ac_huff_tbl_ptrs[i] != NULL)
+ return FALSE;
+ }
+
+ if (memcmp(cinfo->dc_huff_tbl_ptrs[0]->bits, bits_dc_luminance,
+ sizeof(bits_dc_luminance)) ||
+ memcmp(cinfo->dc_huff_tbl_ptrs[0]->huffval, val_dc_luminance,
+ sizeof(val_dc_luminance)) ||
+ memcmp(cinfo->ac_huff_tbl_ptrs[0]->bits, bits_ac_luminance,
+ sizeof(bits_ac_luminance)) ||
+ memcmp(cinfo->ac_huff_tbl_ptrs[0]->huffval, val_ac_luminance,
+ sizeof(val_ac_luminance)) ||
+ memcmp(cinfo->dc_huff_tbl_ptrs[1]->bits, bits_dc_chrominance,
+ sizeof(bits_dc_chrominance)) ||
+ memcmp(cinfo->dc_huff_tbl_ptrs[1]->huffval, val_dc_chrominance,
+ sizeof(val_dc_chrominance)) ||
+ memcmp(cinfo->ac_huff_tbl_ptrs[1]->bits, bits_ac_chrominance,
+ sizeof(bits_ac_chrominance)) ||
+ memcmp(cinfo->ac_huff_tbl_ptrs[1]->huffval, val_ac_chrominance,
+ sizeof(val_ac_chrominance)))
+ return FALSE;
+
+ return TRUE;
+}
+
+
LOCAL(void)
initial_setup(j_compress_ptr cinfo, boolean transcode_only)
/* Do computations that are needed before master selection phase */
@@ -605,6 +712,8 @@ GLOBAL(void)
jinit_c_master_control(j_compress_ptr cinfo, boolean transcode_only)
{
my_master_ptr master = (my_master_ptr)cinfo->master;
+ boolean empty_huff_tables = TRUE;
+ int i;
master->pub.prepare_for_pass = prepare_for_pass;
master->pub.pass_startup = pass_startup;
@@ -646,7 +755,16 @@ jinit_c_master_control(j_compress_ptr cinfo, boolean transcode_only)
(cinfo->progressive_mode && !cinfo->arith_code))
cinfo->optimize_coding = TRUE; /* assume default tables no good for
progressive mode or lossless mode */
- if (cinfo->data_precision == 12 && !cinfo->arith_code)
+ for (i = 0; i < NUM_HUFF_TBLS; i++) {
+ if (cinfo->dc_huff_tbl_ptrs[i] != NULL ||
+ cinfo->ac_huff_tbl_ptrs[i] != NULL) {
+ empty_huff_tables = FALSE;
+ break;
+ }
+ }
+ if (cinfo->data_precision == 12 && !cinfo->arith_code &&
+ !cinfo->optimize_coding &&
+ (empty_huff_tables || using_std_huff_tables(cinfo)))
cinfo->optimize_coding = TRUE; /* assume default tables no good for 12-bit
data precision */
diff --git a/src/3rdparty/libjpeg/src/jconfig.h b/src/3rdparty/libjpeg/src/jconfig.h
index 1e03e166e7..e81574b9a4 100644
--- a/src/3rdparty/libjpeg/src/jconfig.h
+++ b/src/3rdparty/libjpeg/src/jconfig.h
@@ -2,9 +2,9 @@
#define JPEG_LIB_VERSION 80
-#define LIBJPEG_TURBO_VERSION 3.0.2
+#define LIBJPEG_TURBO_VERSION 3.0.3
-#define LIBJPEG_TURBO_VERSION_NUMBER 3000002
+#define LIBJPEG_TURBO_VERSION_NUMBER 3000003
#define C_ARITH_CODING_SUPPORTED 1
diff --git a/src/3rdparty/libjpeg/src/jconfigint.h b/src/3rdparty/libjpeg/src/jconfigint.h
index afcb25d247..6e7dbd75a1 100644
--- a/src/3rdparty/libjpeg/src/jconfigint.h
+++ b/src/3rdparty/libjpeg/src/jconfigint.h
@@ -10,7 +10,7 @@
#define PACKAGE_NAME "libjpeg-turbo"
-#define VERSION "3.0.2"
+#define VERSION "3.0.3"
#if SIZE_MAX == 0xffffffff
#define SIZEOF_SIZE_T 4
diff --git a/src/3rdparty/libjpeg/src/jerror.c b/src/3rdparty/libjpeg/src/jerror.c
index d0ab5b88b0..3a75fec02c 100644
--- a/src/3rdparty/libjpeg/src/jerror.c
+++ b/src/3rdparty/libjpeg/src/jerror.c
@@ -4,7 +4,7 @@
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1991-1998, Thomas G. Lane.
* libjpeg-turbo Modifications:
- * Copyright (C) 2022, D. R. Commander.
+ * Copyright (C) 2022, 2024, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
@@ -46,7 +46,7 @@
#define JMESSAGE(code, string) string,
-const char * const jpeg_std_message_table[] = {
+static const char * const jpeg_std_message_table[] = {
#include "jerror.h"
NULL
};
@@ -229,23 +229,17 @@ reset_error_mgr(j_common_ptr cinfo)
GLOBAL(struct jpeg_error_mgr *)
jpeg_std_error(struct jpeg_error_mgr *err)
{
+ memset(err, 0, sizeof(struct jpeg_error_mgr));
+
err->error_exit = error_exit;
err->emit_message = emit_message;
err->output_message = output_message;
err->format_message = format_message;
err->reset_error_mgr = reset_error_mgr;
- err->trace_level = 0; /* default = no tracing */
- err->num_warnings = 0; /* no warnings emitted yet */
- err->msg_code = 0; /* may be useful as a flag for "no error" */
-
/* Initialize message table pointers */
err->jpeg_message_table = jpeg_std_message_table;
err->last_jpeg_message = (int)JMSG_LASTMSGCODE - 1;
- err->addon_message_table = NULL;
- err->first_addon_message = 0; /* for safety */
- err->last_addon_message = 0;
-
return err;
}
diff --git a/src/3rdparty/libjpeg/src/jversion.h b/src/3rdparty/libjpeg/src/jversion.h
index 5c127dc635..3b21737362 100644
--- a/src/3rdparty/libjpeg/src/jversion.h
+++ b/src/3rdparty/libjpeg/src/jversion.h
@@ -36,20 +36,21 @@
* their code
*/
-#define JCOPYRIGHT \
+#define JCOPYRIGHT1 \
"Copyright (C) 2009-2024 D. R. Commander\n" \
"Copyright (C) 2015, 2020 Google, Inc.\n" \
"Copyright (C) 2019-2020 Arm Limited\n" \
"Copyright (C) 2015-2016, 2018 Matthieu Darbois\n" \
"Copyright (C) 2011-2016 Siarhei Siamashka\n" \
- "Copyright (C) 2015 Intel Corporation\n" \
+ "Copyright (C) 2015 Intel Corporation\n"
+#define JCOPYRIGHT2 \
"Copyright (C) 2013-2014 Linaro Limited\n" \
"Copyright (C) 2013-2014 MIPS Technologies, Inc.\n" \
"Copyright (C) 2009, 2012 Pierre Ossman for Cendio AB\n" \
"Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies)\n" \
"Copyright (C) 1999-2006 MIYASAKA Masaru\n" \
"Copyright (C) 1999 Ken Murchison\n" \
- "Copyright (C) 1991-2020 Thomas G. Lane, Guido Vollbeding"
+ "Copyright (C) 1991-2020 Thomas G. Lane, Guido Vollbeding\n"
#define JCOPYRIGHT_SHORT \
"Copyright (C) 1991-2024 The libjpeg-turbo Project and many others"
diff --git a/src/3rdparty/libjpeg/zlib-license.txt b/src/3rdparty/libjpeg/zlib-license.txt
deleted file mode 100644
index 480c61edca..0000000000
--- a/src/3rdparty/libjpeg/zlib-license.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-This software is provided 'as-is', without any express or implied
-warranty. In no event will the authors be held liable for any damages
-arising from the use of this software.
-
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it
-freely, subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
diff --git a/src/android/CMakeLists.txt b/src/android/CMakeLists.txt
index 045076c8d3..007430598e 100644
--- a/src/android/CMakeLists.txt
+++ b/src/android/CMakeLists.txt
@@ -8,5 +8,6 @@ if (ANDROID)
add_subdirectory(jar)
add_subdirectory(java)
add_subdirectory(templates)
+ add_subdirectory(templates_aar)
endif()
diff --git a/src/android/jar/CMakeLists.txt b/src/android/jar/CMakeLists.txt
index c36bbdf75b..b786354a21 100644
--- a/src/android/jar/CMakeLists.txt
+++ b/src/android/jar/CMakeLists.txt
@@ -35,11 +35,17 @@ set(java_sources
src/org/qtproject/qt/android/QtWindow.java
src/org/qtproject/qt/android/QtActivityDelegateBase.java
src/org/qtproject/qt/android/QtEmbeddedDelegate.java
- src/org/qtproject/qt/android/QtEmbeddedDelegateFactory.java
+ src/org/qtproject/qt/android/QtEmbeddedViewInterfaceFactory.java
src/org/qtproject/qt/android/QtEmbeddedLoader.java
src/org/qtproject/qt/android/QtView.java
src/org/qtproject/qt/android/QtEmbeddedViewInterface.java
src/org/qtproject/qt/android/QtServiceEmbeddedDelegate.java
+ src/org/qtproject/qt/android/BackendRegister.java
+ src/org/qtproject/qt/android/QtWindowInterface.java
+ src/org/qtproject/qt/android/QtAccessibilityInterface.java
+ src/org/qtproject/qt/android/QtMenuInterface.java
+ src/org/qtproject/qt/android/QtLayoutInterface.java
+ src/org/qtproject/qt/android/QtInputInterface.java
)
qt_internal_add_jar(Qt${QtBase_VERSION_MAJOR}Android
diff --git a/src/android/jar/build.gradle b/src/android/jar/build.gradle
index 452d4ad780..6b5923f713 100644
--- a/src/android/jar/build.gradle
+++ b/src/android/jar/build.gradle
@@ -7,7 +7,7 @@ buildscript {
}
dependencies {
- classpath 'com.android.tools.build:gradle:8.0.2'
+ classpath 'com.android.tools.build:gradle:8.4.0'
}
}
@@ -27,7 +27,7 @@ android {
namespace "org.qtproject.qt.android"
defaultConfig {
- minSdkVersion 23
+ minSdkVersion 28
}
sourceSets {
diff --git a/src/android/jar/src/org/qtproject/qt/android/BackendRegister.java b/src/android/jar/src/org/qtproject/qt/android/BackendRegister.java
new file mode 100644
index 0000000000..b66a593ec6
--- /dev/null
+++ b/src/android/jar/src/org/qtproject/qt/android/BackendRegister.java
@@ -0,0 +1,9 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+package org.qtproject.qt.android;
+
+class BackendRegister
+{
+ static native void registerBackend(Class interfaceType, Object interfaceObject);
+ static native void unregisterBackend(Class interfaceType);
+}
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtAccessibilityDelegate.java b/src/android/jar/src/org/qtproject/qt/android/QtAccessibilityDelegate.java
index d23c87e792..8558e42c3b 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtAccessibilityDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtAccessibilityDelegate.java
@@ -61,6 +61,8 @@ class QtAccessibilityDelegate extends View.AccessibilityDelegate
}
// TODO do we want to have one QtAccessibilityDelegate for the whole app (QtRootLayout) or
// e.g. one per window?
+ // FIXME make QtAccessibilityDelegate window based or verify current way works
+ // also for child windows: QTBUG-120685
public QtAccessibilityDelegate(QtLayout layout)
{
m_layout = layout;
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtAccessibilityInterface.java b/src/android/jar/src/org/qtproject/qt/android/QtAccessibilityInterface.java
new file mode 100644
index 0000000000..41d0c4c612
--- /dev/null
+++ b/src/android/jar/src/org/qtproject/qt/android/QtAccessibilityInterface.java
@@ -0,0 +1,14 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+package org.qtproject.qt.android;
+
+@UsedFromNativeCode
+public interface QtAccessibilityInterface {
+ default void initializeAccessibility() { }
+ default void notifyLocationChange(int viewId) { }
+ default void notifyObjectHide(int viewId, int parentId) { }
+ default void notifyObjectFocus(int viewId) { }
+ default void notifyScrolledEvent(int viewId) { }
+ default void notifyValueChanged(int viewId, String value) { }
+ default void notifyObjectShow(int parentId) { }
+}
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtActivityBase.java b/src/android/jar/src/org/qtproject/qt/android/QtActivityBase.java
index 3cb6ba220e..c11130ebd7 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtActivityBase.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtActivityBase.java
@@ -19,7 +19,7 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
-public class QtActivityBase extends Activity
+public class QtActivityBase extends Activity implements QtNative.AppStateDetailsListener
{
private String m_applicationParams = "";
private boolean m_isCustomThemeSet = false;
@@ -96,6 +96,8 @@ public class QtActivityBase extends Activity
m_delegate = new QtActivityDelegate(this);
+ QtNative.registerAppStateListener(this);
+
handleActivityRestart();
addReferrer(getIntent());
@@ -108,6 +110,14 @@ public class QtActivityBase extends Activity
}
@Override
+ public void onAppStateDetailsChanged(QtNative.ApplicationStateDetails details) {
+ if (details.isStarted)
+ m_delegate.registerBackends();
+ else
+ m_delegate.unregisterBackends();
+ }
+
+ @Override
protected void onStart()
{
super.onStart();
@@ -153,6 +163,7 @@ public class QtActivityBase extends Activity
{
super.onDestroy();
if (!m_retainNonConfigurationInstance) {
+ QtNative.unregisterAppStateListener(this);
QtNative.terminateQt();
QtNative.setActivity(null);
QtNative.getQtThread().exit();
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java
index 1e1a36be3c..10e40c98df 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java
@@ -26,24 +26,24 @@ import android.view.Menu;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
-import android.view.Window;
-import android.view.WindowInsetsController;
import android.widget.ImageView;
import android.widget.PopupMenu;
import java.util.HashMap;
class QtActivityDelegate extends QtActivityDelegateBase
+ implements QtWindowInterface, QtAccessibilityInterface, QtMenuInterface, QtLayoutInterface
{
private static final String QtTAG = "QtActivityDelegate";
private QtRootLayout m_layout = null;
private ImageView m_splashScreen = null;
private boolean m_splashScreenSticky = false;
+ private boolean m_backendsRegistered = false;
private View m_dummyView = null;
private HashMap<Integer, View> m_nativeViews = new HashMap<Integer, View>();
-
+ private QtAccessibilityDelegate m_accessibilityDelegate = null;
QtActivityDelegate(Activity activity)
{
@@ -53,17 +53,43 @@ class QtActivityDelegate extends QtActivityDelegateBase
setActivityBackgroundDrawable();
}
+ void registerBackends()
+ {
+ if (!m_backendsRegistered) {
+ m_backendsRegistered = true;
+ BackendRegister.registerBackend(QtWindowInterface.class,
+ (QtWindowInterface)QtActivityDelegate.this);
+ BackendRegister.registerBackend(QtAccessibilityInterface.class,
+ (QtAccessibilityInterface)QtActivityDelegate.this);
+ BackendRegister.registerBackend(QtMenuInterface.class,
+ (QtMenuInterface)QtActivityDelegate.this);
+ BackendRegister.registerBackend(QtLayoutInterface.class,
+ (QtLayoutInterface)QtActivityDelegate.this);
+ BackendRegister.registerBackend(QtInputInterface.class,
+ (QtInputInterface)m_inputDelegate);
+ }
+ }
+
+ void unregisterBackends()
+ {
+ if (m_backendsRegistered) {
+ m_backendsRegistered = false;
+ BackendRegister.unregisterBackend(QtWindowInterface.class);
+ BackendRegister.unregisterBackend(QtAccessibilityInterface.class);
+ BackendRegister.unregisterBackend(QtMenuInterface.class);
+ BackendRegister.unregisterBackend(QtLayoutInterface.class);
+ BackendRegister.unregisterBackend(QtInputInterface.class);
+ }
+ }
- @UsedFromNativeCode
@Override
- QtLayout getQtLayout()
+ public QtLayout getQtLayout()
{
return m_layout;
}
- @UsedFromNativeCode
@Override
- void setSystemUiVisibility(int systemUiVisibility)
+ public void setSystemUiVisibility(int systemUiVisibility)
{
QtNative.runAction(() -> {
m_displayManager.setSystemUiVisibility(systemUiVisibility);
@@ -212,7 +238,55 @@ class QtActivityDelegate extends QtActivityDelegateBase
});
}
- @UsedFromNativeCode
+ @Override
+ public void notifyLocationChange(int viewId)
+ {
+ if (m_accessibilityDelegate == null)
+ return;
+ m_accessibilityDelegate.notifyLocationChange(viewId);
+ }
+
+ @Override
+ public void notifyObjectHide(int viewId, int parentId)
+ {
+ if (m_accessibilityDelegate == null)
+ return;
+ m_accessibilityDelegate.notifyObjectHide(viewId, parentId);
+ }
+
+ @Override
+ public void notifyObjectShow(int parentId)
+ {
+ if (m_accessibilityDelegate == null)
+ return;
+ m_accessibilityDelegate.notifyObjectShow(parentId);
+ }
+
+ @Override
+ public void notifyObjectFocus(int viewId)
+ {
+ if (m_accessibilityDelegate == null)
+ return;
+ m_accessibilityDelegate.notifyObjectFocus(viewId);
+ }
+
+ @Override
+ public void notifyValueChanged(int viewId, String value)
+ {
+ if (m_accessibilityDelegate == null)
+ return;
+ m_accessibilityDelegate.notifyValueChanged(viewId, value);
+ }
+
+ @Override
+ public void notifyScrolledEvent(int viewId)
+ {
+ if (m_accessibilityDelegate == null)
+ return;
+ m_accessibilityDelegate.notifyScrolledEvent(viewId);
+ }
+
+ @Override
public void initializeAccessibility()
{
QtNative.runAction(() -> {
@@ -224,27 +298,25 @@ class QtActivityDelegate extends QtActivityDelegateBase
});
}
- @UsedFromNativeCode
+ // QtMenuInterface implementation begin
+ @Override
public void resetOptionsMenu()
{
QtNative.runAction(() -> m_activity.invalidateOptionsMenu());
}
- @UsedFromNativeCode
+ @Override
public void openOptionsMenu()
{
QtNative.runAction(() -> m_activity.openOptionsMenu());
}
- private boolean m_contextMenuVisible = false;
-
- public void onCreatePopupMenu(Menu menu)
+ @Override
+ public void closeContextMenu()
{
- QtNative.fillContextMenu(menu);
- m_contextMenuVisible = true;
+ QtNative.runAction(() -> m_activity.closeContextMenu());
}
- @UsedFromNativeCode
@Override
public void openContextMenu(final int x, final int y, final int w, final int h)
{
@@ -264,11 +336,14 @@ class QtActivityDelegate extends QtActivityDelegateBase
popup.show();
}, 100);
}
+ // QtMenuInterface implementation end
- @UsedFromNativeCode
- public void closeContextMenu()
+ private boolean m_contextMenuVisible = false;
+
+ public void onCreatePopupMenu(Menu menu)
{
- QtNative.runAction(() -> m_activity.closeContextMenu());
+ QtNative.fillContextMenu(menu);
+ m_contextMenuVisible = true;
}
@Override
@@ -310,7 +385,7 @@ class QtActivityDelegate extends QtActivityDelegateBase
@UsedFromNativeCode
@Override
- void removeTopLevelWindow(final int id)
+ public void removeTopLevelWindow(final int id)
{
QtNative.runAction(()-> {
if (m_topLevelWindows.containsKey(id)) {
@@ -328,7 +403,7 @@ class QtActivityDelegate extends QtActivityDelegateBase
@UsedFromNativeCode
@Override
- void bringChildToFront(final int id)
+ public void bringChildToFront(final int id)
{
QtNative.runAction(() -> {
QtWindow window = m_topLevelWindows.get(id);
@@ -339,7 +414,7 @@ class QtActivityDelegate extends QtActivityDelegateBase
@UsedFromNativeCode
@Override
- void bringChildToBack(int id)
+ public void bringChildToBack(int id)
{
QtNative.runAction(() -> {
QtWindow window = m_topLevelWindows.get(id);
@@ -348,16 +423,6 @@ class QtActivityDelegate extends QtActivityDelegateBase
});
}
- @Override
- QtAccessibilityDelegate createAccessibilityDelegate()
- {
- if (m_layout != null)
- return new QtAccessibilityDelegate(m_layout);
-
- Log.w(QtTAG, "Null layout, failed to initialize accessibility delegate.");
- return null;
- }
-
private void setActivityBackgroundDrawable()
{
TypedValue attr = new TypedValue();
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegateBase.java b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegateBase.java
index 6fd539d8dd..4980a47d08 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegateBase.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegateBase.java
@@ -37,7 +37,6 @@ abstract class QtActivityDelegateBase
{
protected Activity m_activity;
protected HashMap<Integer, QtWindow> m_topLevelWindows;
- protected QtAccessibilityDelegate m_accessibilityDelegate = null;
protected QtDisplayManager m_displayManager = null;
protected QtInputDelegate m_inputDelegate = null;
@@ -46,20 +45,12 @@ abstract class QtActivityDelegateBase
// Subclass must implement these
abstract void startNativeApplicationImpl(String appParams, String mainLib);
- abstract QtAccessibilityDelegate createAccessibilityDelegate();
- abstract QtLayout getQtLayout();
// With these we are okay with default implementation doing nothing
void setUpLayout() {}
void setUpSplashScreen(int orientation) {}
void hideSplashScreen(final int duration) {}
- void openContextMenu(final int x, final int y, final int w, final int h) {}
void setActionBarVisibility(boolean visible) {}
- void addTopLevelWindow(final QtWindow window) {}
- void removeTopLevelWindow(final int id) {}
- void bringChildToFront(final int id) {}
- void bringChildToBack(int id) {}
- void setSystemUiVisibility(int systemUiVisibility) {}
QtActivityDelegateBase(Activity activity)
{
@@ -72,7 +63,6 @@ abstract class QtActivityDelegateBase
return m_displayManager;
}
- @UsedFromNativeCode
QtInputDelegate getInputDelegate() {
return m_inputDelegate;
}
@@ -158,62 +148,6 @@ abstract class QtActivityDelegateBase
hideSplashScreen(0);
}
- @UsedFromNativeCode
- public void notifyLocationChange(int viewId)
- {
- if (m_accessibilityDelegate == null)
- return;
- m_accessibilityDelegate.notifyLocationChange(viewId);
- }
-
- @UsedFromNativeCode
- public void notifyObjectHide(int viewId, int parentId)
- {
- if (m_accessibilityDelegate == null)
- return;
- m_accessibilityDelegate.notifyObjectHide(viewId, parentId);
- }
-
- @UsedFromNativeCode
- public void notifyObjectShow(int parentId)
- {
- if (m_accessibilityDelegate == null)
- return;
- m_accessibilityDelegate.notifyObjectShow(parentId);
- }
-
- @UsedFromNativeCode
- public void notifyObjectFocus(int viewId)
- {
- if (m_accessibilityDelegate == null)
- return;
- m_accessibilityDelegate.notifyObjectFocus(viewId);
- }
-
- @UsedFromNativeCode
- public void notifyValueChanged(int viewId, String value)
- {
- if (m_accessibilityDelegate == null)
- return;
- m_accessibilityDelegate.notifyValueChanged(viewId, value);
- }
-
- @UsedFromNativeCode
- public void notifyScrolledEvent(int viewId)
- {
- if (m_accessibilityDelegate == null)
- return;
- m_accessibilityDelegate.notifyScrolledEvent(viewId);
- }
-
- @UsedFromNativeCode
- public void initializeAccessibility()
- {
- QtNative.runAction(() -> {
- m_accessibilityDelegate = createAccessibilityDelegate();
- });
- }
-
void handleUiModeChange(int uiMode)
{
// QTBUG-108365
@@ -240,28 +174,4 @@ abstract class QtActivityDelegateBase
break;
}
}
-
- @UsedFromNativeCode
- public void resetOptionsMenu()
- {
- QtNative.runAction(() -> m_activity.invalidateOptionsMenu());
- }
-
- @UsedFromNativeCode
- public void openOptionsMenu()
- {
- QtNative.runAction(() -> m_activity.openOptionsMenu());
- }
-
- public void onCreatePopupMenu(Menu menu)
- {
- QtNative.fillContextMenu(menu);
- m_contextMenuVisible = true;
- }
-
- @UsedFromNativeCode
- public void closeContextMenu()
- {
- QtNative.runAction(() -> m_activity.closeContextMenu());
- }
}
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedDelegate.java b/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedDelegate.java
index ff694777d5..5298ac02bd 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedDelegate.java
@@ -15,19 +15,24 @@ import android.os.Handler;
import android.os.Looper;
import android.util.DisplayMetrics;
import android.util.Log;
+import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.PopupMenu;
import java.util.ArrayList;
import java.util.HashMap;
class QtEmbeddedDelegate extends QtActivityDelegateBase
- implements QtNative.AppStateDetailsListener, QtEmbeddedViewInterface
+ implements QtNative.AppStateDetailsListener, QtEmbeddedViewInterface, QtWindowInterface,
+ QtMenuInterface, QtLayoutInterface
{
+ private static final String QtTAG = "QtEmbeddedDelegate";
// TODO simplistic implementation with one QtView, expand to support multiple views QTBUG-117649
private QtView m_view;
private QtNative.ApplicationStateDetails m_stateDetails;
private boolean m_windowLoaded = false;
+ private boolean m_backendsRegistered = false;
public QtEmbeddedDelegate(Activity context) {
super(context);
@@ -76,7 +81,7 @@ class QtEmbeddedDelegate extends QtActivityDelegateBase
if (m_activity == activity && m_stateDetails.isStarted) {
m_activity.getApplication().unregisterActivityLifecycleCallbacks(this);
QtNative.unregisterAppStateListener(QtEmbeddedDelegate.this);
- QtEmbeddedDelegateFactory.remove(m_activity);
+ QtEmbeddedViewInterfaceFactory.remove(m_activity);
QtNative.terminateQt();
QtNative.setActivity(null);
QtNative.getQtThread().exit();
@@ -89,6 +94,17 @@ class QtEmbeddedDelegate extends QtActivityDelegateBase
public void onAppStateDetailsChanged(QtNative.ApplicationStateDetails details) {
synchronized (this) {
m_stateDetails = details;
+ if (details.isStarted && !m_backendsRegistered) {
+ m_backendsRegistered = true;
+ BackendRegister.registerBackend(QtWindowInterface.class, (QtWindowInterface)this);
+ BackendRegister.registerBackend(QtMenuInterface.class, (QtMenuInterface)this);
+ BackendRegister.registerBackend(QtLayoutInterface.class, (QtLayoutInterface)this);
+ } else if (!details.isStarted && m_backendsRegistered) {
+ m_backendsRegistered = false;
+ BackendRegister.unregisterBackend(QtWindowInterface.class);
+ BackendRegister.unregisterBackend(QtMenuInterface.class);
+ BackendRegister.unregisterBackend(QtLayoutInterface.class);
+ }
}
}
@@ -115,16 +131,7 @@ class QtEmbeddedDelegate extends QtActivityDelegateBase
}
@Override
- QtAccessibilityDelegate createAccessibilityDelegate()
- {
- // FIXME make QtAccessibilityDelegate window based or verify current way works
- // also for child windows: QTBUG-120685
- return null;
- }
-
- @UsedFromNativeCode
- @Override
- QtLayout getQtLayout()
+ public QtLayout getQtLayout()
{
// TODO verify if returning m_view here works, this is used by the androidjniinput
// when e.g. showing a keyboard, so depends on getting the keyboard focus working
@@ -175,4 +182,36 @@ class QtEmbeddedDelegate extends QtActivityDelegateBase
m_windowLoaded = true;
}
}
+
+ // QtMenuInterface implementation begin
+ @Override
+ public void resetOptionsMenu() { QtNative.runAction(() -> m_activity.invalidateOptionsMenu()); }
+
+ @Override
+ public void openOptionsMenu() { QtNative.runAction(() -> m_activity.openOptionsMenu()); }
+
+ @Override
+ public void closeContextMenu() { QtNative.runAction(() -> m_activity.closeContextMenu()); }
+
+ @Override
+ public void openContextMenu(final int x, final int y, final int w, final int h)
+ {
+ QtLayout layout = getQtLayout();
+ layout.postDelayed(() -> {
+ final QtEditText focusedEditText = m_inputDelegate.getCurrentQtEditText();
+ if (focusedEditText == null) {
+ Log.w(QtTAG, "No focused view when trying to open context menu");
+ return;
+ }
+ layout.setLayoutParams(focusedEditText, new QtLayout.LayoutParams(w, h, x, y), false);
+ PopupMenu popup = new PopupMenu(m_activity, focusedEditText);
+ QtNative.fillContextMenu(popup.getMenu());
+ popup.setOnMenuItemClickListener(menuItem ->
+ m_activity.onContextItemSelected(menuItem));
+ popup.setOnDismissListener(popupMenu ->
+ m_activity.onContextMenuClosed(popupMenu.getMenu()));
+ popup.show();
+ }, 100);
+ }
+ // QtMenuInterface implementation end
}
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedDelegateFactory.java b/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedDelegateFactory.java
deleted file mode 100644
index 8cf89e5bc3..0000000000
--- a/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedDelegateFactory.java
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (C) 2024 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
-
-package org.qtproject.qt.android;
-
-import android.app.Activity;
-import android.app.Application;
-import android.os.Bundle;
-
-import java.util.HashMap;
-
-class QtEmbeddedDelegateFactory {
- private static final HashMap<Activity, QtEmbeddedDelegate> m_delegates = new HashMap<>();
- private static final Object m_delegateLock = new Object();
-
- @UsedFromNativeCode
- public static QtActivityDelegateBase getActivityDelegate(Activity activity) {
- synchronized (m_delegateLock) {
- return m_delegates.get(activity);
- }
- }
-
- public static QtEmbeddedDelegate create(Activity activity) {
- synchronized (m_delegateLock) {
- if (!m_delegates.containsKey(activity))
- m_delegates.put(activity, new QtEmbeddedDelegate(activity));
-
- return m_delegates.get(activity);
- }
- }
-
- public static void remove(Activity activity) {
- synchronized (m_delegateLock) {
- m_delegates.remove(activity);
- }
- }
-}
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedLoader.java b/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedLoader.java
index 0c6c4b49f0..69ecced7ff 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedLoader.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedLoader.java
@@ -48,6 +48,6 @@ class QtEmbeddedLoader extends QtLoader {
protected void finish() {
// Called when loading fails - clear the delegate to make sure we don't hold reference
// to the embedding Context
- QtEmbeddedDelegateFactory.remove((Activity)m_context.getBaseContext());
+ QtEmbeddedViewInterfaceFactory.remove((Activity)m_context.getBaseContext());
}
}
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedViewInterfaceFactory.java b/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedViewInterfaceFactory.java
new file mode 100644
index 0000000000..8a5764e93f
--- /dev/null
+++ b/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedViewInterfaceFactory.java
@@ -0,0 +1,34 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+package org.qtproject.qt.android;
+
+import android.content.Context;
+import android.app.Activity;
+import android.app.Service;
+
+import java.util.HashMap;
+
+class QtEmbeddedViewInterfaceFactory {
+ private static final HashMap<Context, QtEmbeddedViewInterface> m_interfaces = new HashMap<>();
+ private static final Object m_interfaceLock = new Object();
+
+ public static QtEmbeddedViewInterface create(Context context) {
+ synchronized (m_interfaceLock) {
+ if (!m_interfaces.containsKey(context)) {
+ if (context instanceof Activity)
+ m_interfaces.put(context, new QtEmbeddedDelegate((Activity)context));
+ else if (context instanceof Service)
+ m_interfaces.put(context, new QtServiceEmbeddedDelegate((Service)context));
+ }
+
+ return m_interfaces.get(context);
+ }
+ }
+
+ public static void remove(Context context) {
+ synchronized (m_interfaceLock) {
+ m_interfaces.remove(context);
+ }
+ }
+}
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtInputConnection.java b/src/android/jar/src/org/qtproject/qt/android/QtInputConnection.java
index 1bfe05e7ac..b95f817d33 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtInputConnection.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtInputConnection.java
@@ -77,6 +77,10 @@ class QtInputConnection extends BaseInputConnection
Log.w(QtTAG, "HideKeyboardRunnable: The activity reference is null");
return;
}
+ if (m_qtInputConnectionListener == null) {
+ Log.w(QtTAG, "HideKeyboardRunnable: QtInputConnectionListener is null");
+ return;
+ }
Rect r = new Rect();
activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(r);
@@ -109,7 +113,7 @@ class QtInputConnection extends BaseInputConnection
{
if (closing)
m_view.postDelayed(new HideKeyboardRunnable(), 100);
- else
+ else if (m_qtInputConnectionListener != null)
m_qtInputConnectionListener.onSetClosing(false);
}
@@ -297,7 +301,8 @@ class QtInputConnection extends BaseInputConnection
restartImmInput();
break;
default:
- m_qtInputConnectionListener.onSendKeyEventDefaultCase();
+ if (m_qtInputConnectionListener != null)
+ m_qtInputConnectionListener.onSendKeyEventDefaultCase();
break;
}
}
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java b/src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java
index cfa273e410..bf5578285a 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java
@@ -21,7 +21,8 @@ import android.view.inputmethod.InputMethodManager;
import org.qtproject.qt.android.QtInputConnection.QtInputConnectionListener;
/** @noinspection FieldCanBeLocal*/
-class QtInputDelegate implements QtInputConnection.QtInputConnectionListener {
+class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, QtInputInterface
+{
// keyboard methods
public static native void keyDown(int key, int unicode, int modifier, boolean autoRepeat);
@@ -90,6 +91,140 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener {
m_imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
}
+ // QtInputInterface implementation begin
+ @Override
+ public void updateSelection(final int selStart, final int selEnd,
+ final int candidatesStart, final int candidatesEnd)
+ {
+ QtNative.runAction(() -> {
+ if (m_imm == null)
+ return;
+
+ m_imm.updateSelection(m_currentEditText, selStart, selEnd, candidatesStart, candidatesEnd);
+ });
+ }
+
+ @Override
+ public void showSoftwareKeyboard(Activity activity, QtLayout layout,
+ final int x, final int y, final int width, final int height,
+ final int inputHints, final int enterKeyType)
+ {
+ QtNative.runAction(() -> {
+ if (m_imm == null || m_currentEditText == null)
+ return;
+
+ if (updateSoftInputMode(activity, height))
+ return;
+
+ m_currentEditText.setEditTextOptions(enterKeyType, inputHints);
+
+ m_currentEditText.postDelayed(() -> {
+ m_imm.showSoftInput(m_currentEditText, 0, new ResultReceiver(new Handler()) {
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ switch (resultCode) {
+ case InputMethodManager.RESULT_SHOWN:
+ QtNativeInputConnection.updateCursorPosition();
+ //FALLTHROUGH
+ case InputMethodManager.RESULT_UNCHANGED_SHOWN:
+ setKeyboardVisibility(true, System.nanoTime());
+ if (m_softInputMode == 0) {
+ probeForKeyboardHeight(layout, activity,
+ x, y, width, height, inputHints, enterKeyType);
+ }
+ break;
+ case InputMethodManager.RESULT_HIDDEN:
+ case InputMethodManager.RESULT_UNCHANGED_HIDDEN:
+ setKeyboardVisibility(false, System.nanoTime());
+ break;
+ }
+ }
+ });
+ if (m_currentEditText.m_optionsChanged) {
+ m_imm.restartInput(m_currentEditText);
+ m_currentEditText.m_optionsChanged = false;
+ }
+ }, 15);
+ });
+ }
+
+ @Override
+ public int getSelectHandleWidth()
+ {
+ int width = 0;
+ if (m_leftSelectionHandle != null && m_rightSelectionHandle != null) {
+ width = Math.max(m_leftSelectionHandle.width(), m_rightSelectionHandle.width());
+ } else if (m_cursorHandle != null) {
+ width = m_cursorHandle.width();
+ }
+ return width;
+ }
+
+ /* called from the C++ code when the position of the cursor or selection handles needs to
+ be adjusted.
+ mode is one of QAndroidInputContext::CursorHandleShowMode
+ */
+ @Override
+ public void updateHandles(Activity activity, QtLayout layout, int mode,
+ int editX, int editY, int editButtons,
+ int x1, int y1, int x2, int y2, boolean rtl)
+ {
+ QtNative.runAction(() -> updateHandleImpl(activity, layout, mode, editX, editY, editButtons,
+ x1, y1, x2, y2, rtl));
+ }
+
+ @Override
+ public QtInputConnection.QtInputConnectionListener getInputConnectionListener()
+ {
+ return this;
+ }
+
+ @Override
+ public void resetSoftwareKeyboard()
+ {
+ if (m_imm == null || m_currentEditText == null)
+ return;
+ m_currentEditText.postDelayed(() -> {
+ m_imm.restartInput(m_currentEditText);
+ m_currentEditText.m_optionsChanged = false;
+ }, 5);
+ }
+
+ @Override
+ public void hideSoftwareKeyboard()
+ {
+ m_isKeyboardHidingAnimationOngoing = true;
+ QtNative.runAction(() -> {
+ if (m_imm == null || m_currentEditText == null)
+ return;
+
+ m_imm.hideSoftInputFromWindow(m_currentEditText.getWindowToken(), 0,
+ new ResultReceiver(new Handler()) {
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ switch (resultCode) {
+ case InputMethodManager.RESULT_SHOWN:
+ case InputMethodManager.RESULT_UNCHANGED_SHOWN:
+ setKeyboardVisibility(true, System.nanoTime());
+ break;
+ case InputMethodManager.RESULT_HIDDEN:
+ case InputMethodManager.RESULT_UNCHANGED_HIDDEN:
+ setKeyboardVisibility(false, System.nanoTime());
+ break;
+ }
+ }
+ });
+ });
+ }
+
+ // Is the keyboard fully visible i.e. visible and no ongoing animation
+ @Override
+ public boolean isSoftwareKeyboardVisible()
+ {
+ return isKeyboardVisible() && !m_isKeyboardHidingAnimationOngoing;
+ }
+ // QtInputInterface implementation end
+
// QtInputConnectionListener methods
@Override
public void onSetClosing(boolean closing) {
@@ -113,13 +248,6 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener {
return m_keyboardIsVisible;
}
- // Is the keyboard fully visible i.e. visible and no ongoing animation
- @UsedFromNativeCode
- public boolean isSoftwareKeyboardVisible()
- {
- return isKeyboardVisible() && !m_isKeyboardHidingAnimationOngoing;
- }
-
void setSoftInputMode(int inputMode)
{
m_softInputMode = inputMode;
@@ -158,65 +286,11 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener {
}
- @UsedFromNativeCode
- public void resetSoftwareKeyboard()
- {
- if (m_imm == null || m_currentEditText == null)
- return;
- m_currentEditText.postDelayed(() -> {
- m_imm.restartInput(m_currentEditText);
- m_currentEditText.m_optionsChanged = false;
- }, 5);
- }
-
void setFocusedView(QtEditText currentEditText)
{
m_currentEditText = currentEditText;
}
- public void showSoftwareKeyboard(Activity activity, QtLayout layout,
- final int x, final int y, final int width, final int height,
- final int inputHints, final int enterKeyType)
- {
- QtNative.runAction(() -> {
- if (m_imm == null || m_currentEditText == null)
- return;
-
- if (updateSoftInputMode(activity, height))
- return;
-
- m_currentEditText.setEditTextOptions(enterKeyType, inputHints);
-
- m_currentEditText.postDelayed(() -> {
- m_imm.showSoftInput(m_currentEditText, 0, new ResultReceiver(new Handler()) {
- @Override
- protected void onReceiveResult(int resultCode, Bundle resultData) {
- switch (resultCode) {
- case InputMethodManager.RESULT_SHOWN:
- QtNativeInputConnection.updateCursorPosition();
- //FALLTHROUGH
- case InputMethodManager.RESULT_UNCHANGED_SHOWN:
- setKeyboardVisibility(true, System.nanoTime());
- if (m_softInputMode == 0) {
- probeForKeyboardHeight(layout, activity,
- x, y, width, height, inputHints, enterKeyType);
- }
- break;
- case InputMethodManager.RESULT_HIDDEN:
- case InputMethodManager.RESULT_UNCHANGED_HIDDEN:
- setKeyboardVisibility(false, System.nanoTime());
- break;
- }
- }
- });
- if (m_currentEditText.m_optionsChanged) {
- m_imm.restartInput(m_currentEditText);
- m_currentEditText.m_optionsChanged = false;
- }
- }, 15);
- });
- }
-
private boolean updateSoftInputMode(Activity activity, int height)
{
DisplayMetrics metrics = new DisplayMetrics();
@@ -284,69 +358,6 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener {
}, m_probeKeyboardHeightDelayMs);
}
- public void hideSoftwareKeyboard()
- {
- m_isKeyboardHidingAnimationOngoing = true;
- QtNative.runAction(() -> {
- if (m_imm == null || m_currentEditText == null)
- return;
-
- m_imm.hideSoftInputFromWindow(m_currentEditText.getWindowToken(), 0,
- new ResultReceiver(new Handler()) {
- @Override
- protected void onReceiveResult(int resultCode, Bundle resultData) {
- switch (resultCode) {
- case InputMethodManager.RESULT_SHOWN:
- case InputMethodManager.RESULT_UNCHANGED_SHOWN:
- setKeyboardVisibility(true, System.nanoTime());
- break;
- case InputMethodManager.RESULT_HIDDEN:
- case InputMethodManager.RESULT_UNCHANGED_HIDDEN:
- setKeyboardVisibility(false, System.nanoTime());
- break;
- }
- }
- });
- });
- }
-
- @UsedFromNativeCode
- public void updateSelection(final int selStart, final int selEnd,
- final int candidatesStart, final int candidatesEnd)
- {
- QtNative.runAction(() -> {
- if (m_imm == null)
- return;
-
- m_imm.updateSelection(m_currentEditText, selStart, selEnd, candidatesStart, candidatesEnd);
- });
- }
-
- @UsedFromNativeCode
- public int getSelectHandleWidth()
- {
- int width = 0;
- if (m_leftSelectionHandle != null && m_rightSelectionHandle != null) {
- width = Math.max(m_leftSelectionHandle.width(), m_rightSelectionHandle.width());
- } else if (m_cursorHandle != null) {
- width = m_cursorHandle.width();
- }
- return width;
- }
-
- /* called from the C++ code when the position of the cursor or selection handles needs to
- be adjusted.
- mode is one of QAndroidInputContext::CursorHandleShowMode
- */
- @UsedFromNativeCode
- public void updateHandles(Activity activity, QtLayout layout, int mode,
- int editX, int editY, int editButtons,
- int x1, int y1, int x2, int y2, boolean rtl)
- {
- QtNative.runAction(() -> updateHandleImpl(activity, layout, mode, editX, editY, editButtons,
- x1, y1, x2, y2, rtl));
- }
-
private void updateHandleImpl(Activity activity, QtLayout layout, int mode,
int editX, int editY, int editButtons,
int x1, int y1, int x2, int y2, boolean rtl)
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtInputInterface.java b/src/android/jar/src/org/qtproject/qt/android/QtInputInterface.java
new file mode 100644
index 0000000000..1dc4d5fd7f
--- /dev/null
+++ b/src/android/jar/src/org/qtproject/qt/android/QtInputInterface.java
@@ -0,0 +1,21 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+package org.qtproject.qt.android;
+
+import android.app.Activity;
+
+@UsedFromNativeCode
+interface QtInputInterface {
+ void updateSelection(final int selStart, final int selEnd, final int candidatesStart,
+ final int candidatesEnd);
+ void showSoftwareKeyboard(Activity activity, QtLayout layout, final int x, final int y,
+ final int width, final int height, final int inputHints,
+ final int enterKeyType);
+ void resetSoftwareKeyboard();
+ void hideSoftwareKeyboard();
+ boolean isSoftwareKeyboardVisible();
+ int getSelectHandleWidth();
+ void updateHandles(Activity activity, QtLayout layout, int mode, int editX, int editY,
+ int editButtons, int x1, int y1, int x2, int y2, boolean rtl);
+ QtInputConnection.QtInputConnectionListener getInputConnectionListener();
+}
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtLayoutInterface.java b/src/android/jar/src/org/qtproject/qt/android/QtLayoutInterface.java
new file mode 100644
index 0000000000..8444266893
--- /dev/null
+++ b/src/android/jar/src/org/qtproject/qt/android/QtLayoutInterface.java
@@ -0,0 +1,8 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+package org.qtproject.qt.android;
+
+@UsedFromNativeCode
+interface QtLayoutInterface {
+ QtLayout getQtLayout();
+}
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtMenuInterface.java b/src/android/jar/src/org/qtproject/qt/android/QtMenuInterface.java
new file mode 100644
index 0000000000..556b9a57b9
--- /dev/null
+++ b/src/android/jar/src/org/qtproject/qt/android/QtMenuInterface.java
@@ -0,0 +1,11 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+package org.qtproject.qt.android;
+
+@UsedFromNativeCode
+interface QtMenuInterface {
+ void resetOptionsMenu();
+ void openOptionsMenu();
+ void closeContextMenu();
+ void openContextMenu(final int x, final int y, final int w, final int h);
+}
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtServiceEmbeddedDelegate.java b/src/android/jar/src/org/qtproject/qt/android/QtServiceEmbeddedDelegate.java
index 29f1d1790f..d8af626ca0 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtServiceEmbeddedDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtServiceEmbeddedDelegate.java
@@ -28,13 +28,8 @@ class QtServiceEmbeddedDelegate implements QtEmbeddedViewInterface, QtNative.App
m_service = service;
QtNative.registerAppStateListener(this);
QtNative.setService(service);
- }
-
- @UsedFromNativeCode
- QtInputDelegate getInputDelegate()
- {
- // TODO Implement text input (QTBUG-122552)
- return null;
+ // QTBUG-122920 TODO Implement accessibility for service UIs
+ // QTBUG-122552 TODO Implement text input
}
@Override
@@ -107,6 +102,7 @@ class QtServiceEmbeddedDelegate implements QtEmbeddedViewInterface, QtNative.App
{
QtNative.setApplicationState(ApplicationSuspended);
QtNative.unregisterAppStateListener(QtServiceEmbeddedDelegate.this);
+ QtEmbeddedViewInterfaceFactory.remove(m_service);
QtNative.terminateQt();
QtNative.setService(null);
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtView.java b/src/android/jar/src/org/qtproject/qt/android/QtView.java
index ddf70b3b5b..b4fa0382ed 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtView.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtView.java
@@ -44,24 +44,15 @@ abstract class QtView extends ViewGroup {
private static native void resizeWindow(long windowReference,
int x, int y, int width, int height);
- /**
- * Create QtView for embedding a QWindow. Instantiating a QtView will load the Qt libraries
- * if they have not already been loaded, including the app library specified by appName, and
- * starting the said Qt app.
- * @param context the hosting Context
- * @param appLibName the name of the Qt app library to load and start. This corresponds to the
- target name set in Qt app's CMakeLists.txt
- **/
- public QtView(Context context, String appLibName) throws InvalidParameterException {
+ /**
+ * Create a QtView for embedding a QWindow without loading the Qt libraries or starting
+ * the Qt app.
+ * @param context the hosting Context
+ **/
+ public QtView(Context context) {
super(context);
- if (appLibName == null || appLibName.isEmpty()) {
- throw new InvalidParameterException("QtView: argument 'appLibName' may not be empty "+
- "or null");
- }
- QtEmbeddedLoader loader = new QtEmbeddedLoader(context);
- m_viewInterface = QtEmbeddedDelegateFactory.create((Activity)context);
- loader.setMainLibraryName(appLibName);
+ m_viewInterface = QtEmbeddedViewInterfaceFactory.create(context);
addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom,
@@ -78,10 +69,22 @@ abstract class QtView extends ViewGroup {
}
}
});
- loader.loadQtLibraries();
- // Start Native Qt application
- m_viewInterface.startQtApplication(loader.getApplicationParameters(),
- loader.getMainLibraryPath());
+ }
+ /**
+ * Create a QtView for embedding a QWindow, and load the Qt libraries if they have not already
+ * been loaded, including the app library specified by appName, and starting the said Qt app.
+ * @param context the hosting Context
+ * @param appLibName the name of the Qt app library to load and start. This corresponds to the
+ target name set in Qt app's CMakeLists.txt
+ **/
+ public QtView(Context context, String appLibName) throws InvalidParameterException {
+ this(context);
+ if (appLibName == null || appLibName.isEmpty()) {
+ throw new InvalidParameterException("QtView: argument 'appLibName' may not be empty "+
+ "or null");
+ }
+
+ loadQtLibraries(appLibName);
}
@Override
@@ -139,6 +142,15 @@ abstract class QtView extends ViewGroup {
m_windowListener = listener;
}
+ void loadQtLibraries(String appLibName) {
+ QtEmbeddedLoader loader = new QtEmbeddedLoader(getContext());
+ loader.setMainLibraryName(appLibName);
+ loader.loadQtLibraries();
+ // Start Native Qt application
+ m_viewInterface.startQtApplication(loader.getApplicationParameters(),
+ loader.getMainLibraryPath());
+ }
+
void setWindowReference(long windowReference) {
m_windowReference = windowReference;
}
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtWindow.java b/src/android/jar/src/org/qtproject/qt/android/QtWindow.java
index d72e69d32a..e88309e47e 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtWindow.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtWindow.java
@@ -26,11 +26,12 @@ class QtWindow extends QtLayout implements QtSurfaceInterface {
private static native void setSurface(int windowId, Surface surface);
static native void windowFocusChanged(boolean hasFocus, int id);
- public QtWindow(Context context, QtWindow parentWindow, QtInputDelegate delegate)
+ public QtWindow(Context context, QtWindow parentWindow,
+ QtInputConnection.QtInputConnectionListener listener)
{
super(context);
setId(View.generateViewId());
- m_editText = new QtEditText(context, delegate);
+ m_editText = new QtEditText(context, listener);
setParent(parentWindow);
setFocusableInTouchMode(true);
addView(m_editText, new QtLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtWindowInterface.java b/src/android/jar/src/org/qtproject/qt/android/QtWindowInterface.java
new file mode 100644
index 0000000000..1fb312786f
--- /dev/null
+++ b/src/android/jar/src/org/qtproject/qt/android/QtWindowInterface.java
@@ -0,0 +1,11 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+package org.qtproject.qt.android;
+@UsedFromNativeCode
+interface QtWindowInterface {
+ default void addTopLevelWindow(final QtWindow window) { }
+ default void removeTopLevelWindow(final int id) { }
+ default void bringChildToFront(final int id) { }
+ default void bringChildToBack(int id) { }
+ default void setSystemUiVisibility(int systemUiVisibility) { }
+}
diff --git a/src/android/templates/build.gradle b/src/android/templates/build.gradle
index f94ffbde54..4a93923277 100644
--- a/src/android/templates/build.gradle
+++ b/src/android/templates/build.gradle
@@ -5,7 +5,7 @@ buildscript {
}
dependencies {
- classpath 'com.android.tools.build:gradle:7.4.1'
+ classpath 'com.android.tools.build:gradle:8.4.0'
}
}
@@ -14,11 +14,11 @@ repositories {
mavenCentral()
}
-apply plugin: 'com.android.application'
+apply plugin: qtGradlePluginType
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
- implementation 'androidx.core:core:1.10.1'
+ implementation 'androidx.core:core:1.13.1'
}
android {
@@ -29,12 +29,14 @@ android {
* - qtAndroidDir - holds the path to qt android files
* needed to build any Qt application
* on Android.
+ * - qtGradlePluginType - whether to build an app or a library
*
* are defined in gradle.properties file. This file is
* updated by QtCreator and androiddeployqt tools.
* Changing them manually might break the compilation!
*******************************************************/
+ namespace androidPackageName
compileSdkVersion androidCompileSdkVersion
buildToolsVersion androidBuildToolsVersion
ndkVersion androidNdkVersion
diff --git a/src/android/templates/doc/src/android-manifest-file-configuration.qdoc b/src/android/templates/doc/src/android-manifest-file-configuration.qdoc
index db0d3c7277..d32d16aa47 100644
--- a/src/android/templates/doc/src/android-manifest-file-configuration.qdoc
+++ b/src/android/templates/doc/src/android-manifest-file-configuration.qdoc
@@ -50,8 +50,10 @@ Qt sets the following manifest configuration by default:
\li {1, 5} \l {Android: App Manifest <manifest>}{<manifest>}
\li package
\li Sets the package name. The default value is \c {org.qtproject.example.app_name}.
+ \warning This field is deprecated and moved to \c build.gradle. It will be removed
+ in an upcoming release.
\row
- \li \c {android:installLocation}
+ \li android:installLocation
\li Sets the app's installation location, whether internal or external storage.
The default value is \c auto.
\row
@@ -63,7 +65,7 @@ Qt sets the following manifest configuration by default:
\li Sets the public version name. Populated from \c ANDROID_VERSION_NAME (qmake)
and \c QT_ANDROID_VERSION_NAME (CMake). The default value is \c {1.0}.
\row
- \li \c {<supports-screens>}
+ \li <supports-screens>
\li Sets the screen sizes that the app supports,
default values are \c anyDensity, \c largeScreens,
\c normalScreens, and \c smallScreens.
diff --git a/src/android/templates_aar/AndroidManifest.xml b/src/android/templates_aar/AndroidManifest.xml
new file mode 100644
index 0000000000..9c9e91e650
--- /dev/null
+++ b/src/android/templates_aar/AndroidManifest.xml
@@ -0,0 +1,9 @@
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ package="org.qtproject.example"
+ android:versionCode="-- %%INSERT_VERSION_CODE%% --"
+ android:versionName="-- %%INSERT_VERSION_NAME%% --">
+ <!-- %%INSERT_PERMISSIONS -->
+ <!-- %%INSERT_FEATURES -->
+</manifest>
diff --git a/src/android/templates_aar/CMakeLists.txt b/src/android/templates_aar/CMakeLists.txt
new file mode 100644
index 0000000000..07c421fbab
--- /dev/null
+++ b/src/android/templates_aar/CMakeLists.txt
@@ -0,0 +1,24 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+# Android aar specific template files
+
+set(templates_aar_files
+ "${CMAKE_CURRENT_SOURCE_DIR}/AndroidManifest.xml")
+
+add_custom_target(Qt${QtBase_VERSION_MAJOR}AndroidAarTemplates
+ SOURCES
+ ${templates_aar_files}
+)
+
+qt_path_join(destination ${QT_INSTALL_DIR} ${INSTALL_DATADIR} "src/android/templates_aar")
+
+qt_copy_or_install(FILES ${templates_aar_files}
+ DESTINATION "${destination}")
+
+if(NOT QT_WILL_INSTALL)
+ qt_internal_copy_at_build_time(TARGET Qt${QtBase_VERSION_MAJOR}AndroidAarTemplates
+ FILES ${templates_aar_files}
+ DESTINATION ${destination}
+ )
+endif()
diff --git a/src/assets/CMakeLists.txt b/src/assets/CMakeLists.txt
index 9357953132..2ab060b022 100644
--- a/src/assets/CMakeLists.txt
+++ b/src/assets/CMakeLists.txt
@@ -1 +1,3 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
add_subdirectory(icons)
diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt
index ce3def3cd6..1055cf4ab5 100644
--- a/src/corelib/CMakeLists.txt
+++ b/src/corelib/CMakeLists.txt
@@ -897,7 +897,7 @@ qt_internal_extend_target(Core CONDITION QT_FEATURE_timezone AND UNIX AND NOT AN
qt_internal_extend_target(Core
CONDITION
- QT_FEATURE_icu AND QT_FEATURE_timezone AND NOT ANDROID AND NOT APPLE
+ QT_FEATURE_icu AND QT_FEATURE_timezone AND NOT UNIX
SOURCES
time/qtimezoneprivate_icu.cpp
)
@@ -1484,3 +1484,39 @@ qt_internal_extend_target(Core
# QReadWriteLock::destroyRecursive(QReadWriteLockPrivate*)
"_ZN*14QReadWriteLock16destroyRecursiveEP*21QReadWriteLockPrivate*"
)
+
+function(qt_internal_library_deprecation_level)
+ # QT_DISABLE_DEPRECATED_UP_TO controls which version we use as a cut-off
+ # compiling in to the library. E.g. if it is set to QT_VERSION then no
+ # code which was deprecated before QT_VERSION will be compiled in.
+ if(NOT DEFINED QT_DISABLE_DEPRECATED_UP_TO)
+ if(WIN32)
+ # On Windows, due to the way DLLs work, we need to export all functions,
+ # including the inlines
+ set(QT_DISABLE_DEPRECATED_UP_TO "0x040800")
+ else()
+ # On other platforms, Qt's own compilation does need to compile the Qt 5.0 API
+ set(QT_DISABLE_DEPRECATED_UP_TO "0x050000")
+ endif()
+ elseif(NOT QT_DISABLE_DEPRECATED_UP_TO MATCHES "^0x[0-9][0-9][0-9][0-9][0-9][0-9]$")
+ message(FATAL_ERROR "Ivalid format of the QT_DISABLE_DEPRECATED_UP_TO macro:"
+ " ${QT_DISABLE_DEPRECATED_UP_TO}. The expected format is the hexadecimal number,"
+ " e.g. 0x060102")
+ endif()
+ # QT_WARN_DEPRECATED_UP_TO controls the upper-bound of deprecation
+ # warnings that are emitted. E.g. if it is set to 0x060500 then all use of
+ # things deprecated in or before 6.5.0 will be warned against.
+ set(QT_WARN_DEPRECATED_UP_TO 0x070000)
+
+ set(output_header "${CMAKE_CURRENT_BINARY_DIR}/global/qtdeprecationdefinitions.h")
+ configure_file(
+ "${CMAKE_CURRENT_SOURCE_DIR}/global/qtdeprecationdefinitions.h.in"
+ "${output_header}"
+ @ONLY
+ NEWLINE_STYLE UNIX
+ )
+
+ target_sources(Core PRIVATE "${output_header}")
+ set_source_files_properties("${output_header}" PROPERTIES GENERATED TRUE)
+endfunction()
+qt_internal_library_deprecation_level()
diff --git a/src/corelib/Qt6AndroidMacros.cmake b/src/corelib/Qt6AndroidMacros.cmake
index 6218df1947..3e96130b85 100644
--- a/src/corelib/Qt6AndroidMacros.cmake
+++ b/src/corelib/Qt6AndroidMacros.cmake
@@ -217,6 +217,10 @@ function(qt6_android_generate_deployment_settings target)
${target} "_qt_android_native_package_source_dir")
# version code
+ _qt_internal_add_android_deployment_property(file_contents "android-package-name"
+ ${target} "QT_ANDROID_PACKAGE_NAME")
+
+ # version code
_qt_internal_add_android_deployment_property(file_contents "android-version-code"
${target} "QT_ANDROID_VERSION_CODE")
@@ -381,6 +385,9 @@ function(qt6_android_add_apk_target target)
if(TARGET aab)
add_dependencies(aab ${target}_make_aab)
endif()
+ if(TARGET aar)
+ add_dependencies(aar ${target}_make_aar)
+ endif()
if(TARGET apk)
add_dependencies(apk ${target}_make_apk)
_qt_internal_create_global_apk_all_target_if_needed()
@@ -418,8 +425,10 @@ function(qt6_android_add_apk_target target)
endif()
set(apk_file_name "${target}.apk")
+ set(aar_file_name "${target}.aar")
set(dep_file_name "${target}.d")
set(apk_final_file_path "${apk_final_dir}/${apk_file_name}")
+ set(aar_final_file_path "${apk_final_dir}/${aar_file_name}")
set(dep_file_path "${apk_final_dir}/${dep_file_name}")
set(target_file_copy_relative_path
"libs/${CMAKE_ANDROID_ARCH_ABI}/$<TARGET_FILE_NAME:${target}>")
@@ -523,10 +532,33 @@ function(qt6_android_add_apk_target target)
VERBATIM
${uses_terminal}
)
+
+ # Add custom command that creates the aar and triggers rebuild if files listed in
+ # ${dep_file_path} are changed.
+ add_custom_command(OUTPUT "${aar_final_file_path}"
+ COMMAND ${CMAKE_COMMAND}
+ -E copy "$<TARGET_FILE:${target}>"
+ "${apk_final_dir}/${target_file_copy_relative_path}"
+ COMMAND "${deployment_tool}"
+ --input "${deployment_file}"
+ --output "${apk_final_dir}"
+ --apk "${aar_final_file_path}"
+ --depfile "${dep_file_path}"
+ --builddir "${relative_to_dir}"
+ --build-aar
+ ${extra_args}
+ COMMENT "Creating AAR for ${target}"
+ DEPENDS "${target}" "${deployment_file}" ${extra_deps}
+ DEPFILE "${dep_file_path}"
+ VERBATIM
+ ${uses_terminal}
+ )
cmake_policy(POP)
# Create a ${target}_make_apk target to trigger the apk build.
add_custom_target(${target}_make_apk DEPENDS "${apk_final_file_path}")
+ # Create a ${target}_make_aar target to trigger the aar build.
+ add_custom_target(${target}_make_aar DEPENDS "${aar_final_file_path}")
else()
add_custom_target(${target}_make_apk
DEPENDS ${target}_prepare_apk_dir
@@ -540,6 +572,19 @@ function(qt6_android_add_apk_target target)
VERBATIM
${uses_terminal}
)
+
+ add_custom_target(${target}_make_aar
+ DEPENDS ${target}_prepare_apk_dir
+ COMMAND ${deployment_tool}
+ --input ${deployment_file}
+ --output ${apk_final_dir}
+ --apk ${aar_final_file_path}
+ --build-aar
+ ${extra_args}
+ COMMENT "Creating AAR for ${target}"
+ VERBATIM
+ ${uses_terminal}
+ )
endif()
# Add target triggering AAB creation. Since the _make_aab target is not added to the ALL
@@ -638,6 +683,11 @@ function(_qt_internal_create_global_android_targets)
# It will trigger building all the apk build targets that are added as part of the project.
# Allow opting out.
_qt_internal_create_global_android_targets_impl(aab)
+
+ # Create a top-level "aar" target for convenience, so that users can call 'ninja aar'.
+ # It will trigger building all the aar build targets that are added as part of the project.
+ # Allow opting out.
+ _qt_internal_create_global_android_targets_impl(aar)
endfunction()
# The function collects all known non-imported shared libraries that are created in the build tree.
diff --git a/src/corelib/Qt6CoreConfigExtras.cmake.in b/src/corelib/Qt6CoreConfigExtras.cmake.in
index 7fd929e59b..b7ac0925af 100644
--- a/src/corelib/Qt6CoreConfigExtras.cmake.in
+++ b/src/corelib/Qt6CoreConfigExtras.cmake.in
@@ -1,3 +1,5 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
if(NOT DEFINED QT_DEFAULT_MAJOR_VERSION)
set(QT_DEFAULT_MAJOR_VERSION 6)
endif()
diff --git a/src/corelib/compat/removed_api.cpp b/src/corelib/compat/removed_api.cpp
index 05bcda0943..2210cae848 100644
--- a/src/corelib/compat/removed_api.cpp
+++ b/src/corelib/compat/removed_api.cpp
@@ -928,6 +928,28 @@ QUrl QUrl::fromEncoded(const QByteArray &input, ParsingMode mode)
#endif // QT_CORE_REMOVED_SINCE(6, 7)
#if QT_CORE_REMOVED_SINCE(6, 8)
+#include "qabstractitemmodel.h"
+
+bool QPersistentModelIndex::operator<(const QPersistentModelIndex &other) const noexcept
+{
+ return is_lt(compareThreeWay(*this, other));
+}
+
+bool QPersistentModelIndex::operator==(const QPersistentModelIndex &other) const noexcept
+{
+ return comparesEqual(*this, other);
+}
+
+bool QPersistentModelIndex::operator==(const QModelIndex &other) const noexcept
+{
+ return comparesEqual(*this, other);
+}
+
+bool QPersistentModelIndex::operator!=(const QModelIndex &other) const noexcept
+{
+ return !comparesEqual(*this, other);
+}
+
#include "qbitarray.h" // inlined API
#include "qbytearray.h" // inlined API
@@ -1085,6 +1107,20 @@ bool QRegularExpression::operator==(const QRegularExpression &other) const
}
#endif // QT_CONFIG(regularexpression)
+#if QT_CONFIG(future)
+#include "qresultstore.h"
+
+bool QtPrivate::ResultIteratorBase::operator==(const QtPrivate::ResultIteratorBase &other) const
+{
+ return comparesEqual(*this, other);
+}
+
+bool QtPrivate::ResultIteratorBase::operator!=(const QtPrivate::ResultIteratorBase &other) const
+{
+ return !comparesEqual(*this, other);
+}
+#endif // QT_CONFIG(future)
+
#include "qstring.h" // inlined API
#if QT_CONFIG(thread)
@@ -1115,6 +1151,18 @@ bool QUrlQuery::operator==(const QUrlQuery &other) const
return comparesEqual(*this, other);
}
+#include "quuid.h"
+
+bool QUuid::operator<(const QUuid &other) const noexcept
+{
+ return is_lt(compareThreeWay(*this, other));
+}
+
+bool QUuid::operator>(const QUuid &other) const noexcept
+{
+ return is_gt(compareThreeWay(*this, other));
+}
+
#include "qxmlstream.h" // inlined API
// #include "qotherheader.h"
diff --git a/src/corelib/configure.cmake b/src/corelib/configure.cmake
index 18c09d2241..83983dfa2e 100644
--- a/src/corelib/configure.cmake
+++ b/src/corelib/configure.cmake
@@ -860,7 +860,8 @@ qt_feature("timezone_locale" PRIVATE
SECTION "Utilities"
LABEL "QTimeZone"
PURPOSE "Provides support for localized time-zone display names."
- DISABLE ON # Implementation is currently incomplete, so leave turned off
+ CONDITION
+ QT_FEATURE_timezone AND ( ( UNIX AND NOT APPLE AND NOT ANDROID ) OR QT_FEATURE_icu )
)
qt_feature("datetimeparser" PRIVATE
SECTION "Utilities"
diff --git a/src/corelib/doc/src/cmake/cmake-properties.qdoc b/src/corelib/doc/src/cmake/cmake-properties.qdoc
index 8fe2b0e88f..4b602d5d07 100644
--- a/src/corelib/doc/src/cmake/cmake-properties.qdoc
+++ b/src/corelib/doc/src/cmake/cmake-properties.qdoc
@@ -245,6 +245,56 @@ CMake will attempt to use the latest installed version.
*/
/*!
+\page cmake-target-property-qt-android-package-name.html
+\ingroup cmake-properties-qtcore
+\ingroup cmake-target-properties-qtcore
+\ingroup cmake-android-build-properties
+
+\title QT_ANDROID_PACKAGE_NAME
+\target cmake-target-property-QT_ANDROID_PACKAGE_NAME
+
+\summary {The app's package name.}
+
+\cmakepropertysince 6.8
+\preliminarycmakeproperty
+\cmakepropertyandroidonly
+
+Specifies the app's package name. This is usually a unique dot separated
+name for the app, that will be used to identify the app on devices or in
+the Play Store. For example, "org.qtproject.example.gallery".
+
+The package name set by this property is passed to the \c build.gradle file
+as a \c namespace property, instead of \c AndroidManifest.xml, since the
+latter is deprecated since Android Gradle Plugin 7.4.
+
+The package name considers some words or characters as illegal and the build
+will clean such names if any is encountered. An underscore (\c _) either replaces
+illegal characters or is appended to illegal words.
+
+\list
+ \li Allowed characters: alphanumeric, an underscore or a dot [a-zA-Z0-9_.].
+ \li Illegal words: abstract, continue, for, new, switch, assert, default,
+ if, package, synchronized, boolean, do, goto, private, this, break,
+ double, implements, protected, throw, byte, else, import, public,
+ throws, case, enum, instanceof, return, transient, catch, extends,
+ int, short, try, char, final, interface, static, void, class, finally,
+ long, strictfp, volatile, const, float, native, super, while.
+\endlist
+
+The default package name for Qt for Android apps is \c org.qtproject.example.<target_name>.
+
+\note Setting the package name manually in \c build.gradle (via
+\c namespace property) takes precedence over \c AndroidManifest.xml
+(via \c package attribute), and the latter also takes precedence over
+this property.
+
+For more information, see Android's
+\l{Android: Configure the app module}{configure the app module}.
+
+\sa{qt6_android_generate_deployment_settings}{qt_android_generate_deployment_settings()}
+*/
+
+/*!
\page cmake-target-property-qt-android-version-code.html
\ingroup cmake-properties-qtcore
\ingroup cmake-target-properties-qtcore
diff --git a/src/corelib/doc/src/cmake/qt_android_generate_deployment_settings.qdoc b/src/corelib/doc/src/cmake/qt_android_generate_deployment_settings.qdoc
index 5a7bbdc33f..daa3680070 100644
--- a/src/corelib/doc/src/cmake/qt_android_generate_deployment_settings.qdoc
+++ b/src/corelib/doc/src/cmake/qt_android_generate_deployment_settings.qdoc
@@ -63,6 +63,7 @@ how to accomplish this.
\li \l{cmake-target-property-QT_ANDROID_MIN_SDK_VERSION}{QT_ANDROID_MIN_SDK_VERSION}
\li \l{cmake-target-property-QT_ANDROID_PACKAGE_SOURCE_DIR}{QT_ANDROID_PACKAGE_SOURCE_DIR}
\li \l{cmake-target-property-QT_ANDROID_TARGET_SDK_VERSION}{QT_ANDROID_TARGET_SDK_VERSION}
+\li \l{cmake-target-property-QT_ANDROID_PACKAGE_NAME}{QT_ANDROID_PACKAGE_NAME}
\li \l{cmake-target-property-QT_ANDROID_VERSION_NAME}{QT_ANDROID_VERSION_NAME}
\li \l{cmake-target-property-QT_ANDROID_VERSION_CODE}{QT_ANDROID_VERSION_CODE}
\li \l{cmake-target-property-QT_QML_IMPORT_PATH}{QT_QML_IMPORT_PATH}
diff --git a/src/corelib/global/qcompare.cpp b/src/corelib/global/qcompare.cpp
index ac220b8434..81abf01984 100644
--- a/src/corelib/global/qcompare.cpp
+++ b/src/corelib/global/qcompare.cpp
@@ -149,6 +149,7 @@ CHECK(strong, equivalent);
/*!
\class Qt::strong_ordering
\inmodule QtCore
+ \inheaderfile QtCompare
\brief Qt::strong_ordering represents a comparison where equivalent values are
indistinguishable.
\sa Qt::weak_ordering, Qt::partial_ordering, {Comparison types overview}
@@ -334,6 +335,7 @@ CHECK(strong, equivalent);
/*!
\class Qt::weak_ordering
\inmodule QtCore
+ \inheaderfile QtCompare
\brief Qt::weak_ordering represents a comparison where equivalent values are
still distinguishable.
\sa Qt::strong_ordering, Qt::partial_ordering, {Comparison types overview}
@@ -484,6 +486,7 @@ CHECK(strong, equivalent);
/*!
\class Qt::partial_ordering
\inmodule QtCore
+ \inheaderfile QtCompare
\brief Qt::partial_ordering represents the result of a comparison that allows
for unordered results.
\sa Qt::strong_ordering, Qt::weak_ordering, {Comparison types overview}
@@ -1354,4 +1357,57 @@ CHECK(strong, equivalent);
\sa Qt::partial_ordering, Qt::weak_ordering, Qt::strong_ordering
*/
+/*!
+ \class Qt::totally_ordered_wrapper
+ \inmodule QtCore
+ \inheaderfile QtCompare
+ \brief Qt::totally_ordered_wrapper is a wrapper type that provides strict
+ total order for the wrapped types.
+ \since 6.8
+
+ One of its primary usecases is to prevent \e {Undefined Behavior} (UB) when
+ comparing pointers.
+
+ Consider the following simple class:
+
+ \code
+ template <typename T>
+ struct PointerWrapperBad {
+ int val;
+ T *ptr;
+ };
+ \endcode
+
+ Lexicographical comparison of the two instances of the \c PointerWrapperBad
+ type would result in UB, because it will call \c {operator<()} or
+ \c {operator<=>()} on the \c {ptr} members.
+
+ To fix it, use the new wrapper type:
+
+ \code
+ template <typename T>
+ struct PointerWrapperGood {
+ int val;
+ Qt::totally_ordered_wrapper<T *> ptr;
+
+ friend bool
+ operator==(PointerWrapperGood lhs, PointerWrapperGood rhs) noexcept = default;
+ friend auto
+ operator<=>(PointerWrapperGood lhs, PointerWrapperGood rhs) noexecpt = default;
+ };
+ \endcode
+
+ The \c {operator<()} and (if available) \c {operator<=>()} operators for
+ the \c {Qt::totally_ordered_wrapper} type use the
+ \l {https://en.cppreference.com/w/cpp/utility/functional/less}{std::less}
+ and \l {https://en.cppreference.com/w/cpp/utility/compare/compare_three_way}
+ {std::compare_three_way} function objects respectively, providing
+ \l {https://en.cppreference.com/w/cpp/language/operator_comparison#Pointer_total_order}
+ {strict total order over pointers} when doing the comparison.
+
+ As a result, the relational operators for \c {PointerWrapperGood::ptr}
+ member will be well-defined, and we can even \c {=default} the relational
+ operators for the \c {PointerWrapperGood} class, like it's shown above.
+*/
+
QT_END_NAMESPACE
diff --git a/src/corelib/global/qcomparehelpers.h b/src/corelib/global/qcomparehelpers.h
index 97c972bfa7..18bc1b5e2e 100644
--- a/src/corelib/global/qcomparehelpers.h
+++ b/src/corelib/global/qcomparehelpers.h
@@ -559,9 +559,103 @@ constexpr Qt::strong_ordering compareThreeWay(Enum lhs, Enum rhs) noexcept
{
return compareThreeWay(qToUnderlying(lhs), qToUnderlying(rhs));
}
-
} // namespace Qt
+namespace QtOrderingPrivate {
+
+template <typename Head, typename...Tail, std::size_t...Is>
+constexpr std::tuple<Tail...> qt_tuple_pop_front_impl(const std::tuple<Head, Tail...> &t,
+ std::index_sequence<Is...>) noexcept
+{
+ return std::tuple<Tail...>(std::get<Is + 1>(t)...);
+}
+
+template <typename Head, typename...Tail>
+constexpr std::tuple<Tail...> qt_tuple_pop_front(const std::tuple<Head, Tail...> &t) noexcept
+{
+ return qt_tuple_pop_front_impl(t, std::index_sequence_for<Tail...>{});
+}
+
+template <typename LhsHead, typename...LhsTail, typename RhsHead, typename...RhsTail>
+constexpr auto compareThreeWayMulti(const std::tuple<LhsHead, LhsTail...> &lhs, // ie. not empty
+ const std::tuple<RhsHead, RhsTail...> &rhs) noexcept
+{
+ static_assert(sizeof...(LhsTail) == sizeof...(RhsTail),
+ // expanded together below, but provide a nicer error message:
+ "The tuple arguments have to have the same size.");
+
+ using Qt::compareThreeWay;
+ using R = std::common_type_t<
+ decltype(compareThreeWay(std::declval<LhsHead>(), std::declval<RhsHead>())),
+ decltype(compareThreeWay(std::declval<LhsTail>(), std::declval<RhsTail>()))...
+ >;
+
+ const auto &l = std::get<0>(lhs);
+ const auto &r = std::get<0>(rhs);
+ static_assert(noexcept(compareThreeWay(l, r)),
+ "This function requires all relational operators to be noexcept.");
+ const auto res = compareThreeWay(l, r);
+ if constexpr (sizeof...(LhsTail) > 0) {
+ if (is_eq(res))
+ return R{compareThreeWayMulti(qt_tuple_pop_front(lhs), qt_tuple_pop_front(rhs))};
+ }
+ return R{res};
+}
+
+} //QtOrderingPrivate
+
+namespace Qt {
+// A wrapper class that adapts the wrappee to use the strongly-ordered
+// <functional> function objects for implementing the relational operators.
+// Mostly useful to avoid UB on pointers (which it currently mandates P to be),
+// because all the comparison helpers (incl. std::compare_three_way on
+// std::tuple<T*>!) will use the language-level operators.
+//
+template <typename P>
+class totally_ordered_wrapper
+{
+ static_assert(std::is_pointer_v<P>);
+ using T = std::remove_pointer_t<P>;
+
+ P ptr;
+public:
+ explicit constexpr totally_ordered_wrapper(P p) : ptr(p) {}
+
+ constexpr P get() const noexcept { return ptr; }
+ constexpr P operator->() const noexcept { return get(); }
+ constexpr T& operator*() const noexcept { return *get(); }
+
+ explicit constexpr operator bool() const noexcept { return get(); }
+
+private:
+ friend constexpr auto compareThreeWay(const totally_ordered_wrapper &lhs, const totally_ordered_wrapper &rhs) noexcept
+ { return Qt::compareThreeWay(lhs.ptr, rhs.ptr); }
+#define MAKE_RELOP(Ret, op, Op) \
+ friend constexpr Ret operator op (const totally_ordered_wrapper &lhs, const totally_ordered_wrapper &rhs) noexcept \
+ { return std:: Op {}(lhs.ptr, rhs.ptr); } \
+ friend constexpr Ret operator op (const totally_ordered_wrapper &lhs, const P &rhs) noexcept \
+ { return std:: Op {}(lhs.ptr, rhs ); } \
+ friend constexpr Ret operator op (const P &lhs, const totally_ordered_wrapper &rhs) noexcept \
+ { return std:: Op {}(lhs, rhs.ptr); } \
+ friend constexpr Ret operator op (const totally_ordered_wrapper &lhs, std::nullptr_t) noexcept \
+ { return std:: Op {}(lhs.ptr, nullptr); } \
+ friend constexpr Ret operator op (std::nullptr_t, const totally_ordered_wrapper &rhs) noexcept \
+ { return std:: Op {}(nullptr, rhs.ptr); } \
+ /* end */
+ MAKE_RELOP(bool, ==, equal_to<P>)
+ MAKE_RELOP(bool, !=, not_equal_to<P>)
+ MAKE_RELOP(bool, < , less<P>)
+ MAKE_RELOP(bool, <=, less_equal<P>)
+ MAKE_RELOP(bool, > , greater<P>)
+ MAKE_RELOP(bool, >=, greater_equal<P>)
+#ifdef __cpp_lib_three_way_comparison
+ MAKE_RELOP(auto, <=>, compare_three_way)
+#endif
+#undef MAKE_RELOP
+};
+
+} //Qt
+
QT_END_NAMESPACE
#endif // QCOMPAREHELPERS_H
diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp
index 1b03733d2a..a71387287f 100644
--- a/src/corelib/global/qlibraryinfo.cpp
+++ b/src/corelib/global/qlibraryinfo.cpp
@@ -523,6 +523,56 @@ QString QLibraryInfo::path(LibraryPath p)
}
+static QString normalizePath(QString ret)
+{
+ qsizetype startIndex = 0;
+ /* We support placeholders of the form $(<ENV_VAR>) in qt.conf.
+ The loop below tries to find all such placeholders, and replaces
+ them with the actual value of the ENV_VAR environment variable
+ */
+ while (true) {
+ startIndex = ret.indexOf(u'$', startIndex);
+ if (startIndex < 0)
+ break;
+ if (ret.size() < startIndex + 3)
+ break;
+ if (ret.at(startIndex + 1) != u'(') {
+ startIndex++;
+ continue;
+ }
+ qsizetype endIndex = ret.indexOf(u')', startIndex + 2);
+ if (endIndex < 0)
+ break;
+ auto envVarName = QStringView{ret}.sliced(startIndex + 2, endIndex - startIndex - 2);
+ QString value = qEnvironmentVariable(envVarName.toLocal8Bit().constData());
+ ret.replace(startIndex, endIndex - startIndex + 1, value);
+ startIndex += value.size();
+ }
+ return QDir::fromNativeSeparators(ret);
+};
+
+#if QT_CONFIG(settings)
+static QVariant libraryPathToValue(QLibraryInfo::LibraryPath loc)
+{
+ QVariant value;
+ auto li = QLibraryInfoPrivate::locationInfo(loc);
+ if (li.key.isNull())
+ return value;
+ QSettings *config = QLibraryInfoPrivate::configuration();
+ Q_ASSERT(config != nullptr);
+ config->beginGroup("Paths"_L1);
+ auto cleanup = qScopeGuard([&]() { config->endGroup(); });
+ if (li.fallbackKey.isNull()) {
+ value = config->value(li.key, li.defaultValue);
+ } else {
+ value = config->value(li.key);
+ if (!value.isValid())
+ value = config->value(li.fallbackKey, li.defaultValue);
+ }
+ return value;
+}
+#endif // settings
+
/*
Returns the path specified by \a p.
@@ -538,48 +588,10 @@ QString QLibraryInfoPrivate::path(QLibraryInfo::LibraryPath p, UsageMode usageMo
if (havePaths()) {
fromConf = true;
- auto li = QLibraryInfoPrivate::locationInfo(loc);
- if (!li.key.isNull()) {
- QSettings *config = QLibraryInfoPrivate::configuration();
- Q_ASSERT(config != nullptr);
- config->beginGroup("Paths"_L1);
-
- if (li.fallbackKey.isNull()) {
- ret = config->value(li.key, li.defaultValue).toString();
- } else {
- QVariant v = config->value(li.key);
- if (!v.isValid())
- v = config->value(li.fallbackKey, li.defaultValue);
- ret = v.toString();
- }
-
- qsizetype startIndex = 0;
- /* We support placeholders of the form $(<ENV_VAR>) in qt.conf.
- The loop below tries to find all such placeholders, and replaces
- them with the actual value of the ENV_VAR environment variable
- */
- while (true) {
- startIndex = ret.indexOf(u'$', startIndex);
- if (startIndex < 0)
- break;
- if (ret.size() < startIndex + 3)
- break;
- if (ret.at(startIndex + 1) != u'(') {
- startIndex++;
- continue;
- }
- qsizetype endIndex = ret.indexOf(u')', startIndex + 2);
- if (endIndex < 0)
- break;
- auto envVarName = QStringView{ret}.mid(startIndex + 2, endIndex - startIndex - 2);
- QString value = QString::fromLocal8Bit(qgetenv(envVarName.toLocal8Bit().constData()));
- ret.replace(startIndex, endIndex - startIndex + 1, value);
- startIndex += value.size();
- }
-
- config->endGroup();
-
- ret = QDir::fromNativeSeparators(ret);
+ QVariant value = libraryPathToValue(loc);
+ if (value.isValid()) {
+ ret = std::move(value).toString();
+ ret = normalizePath(std::move(ret));
}
}
#endif // settings
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h
index 2398c0a1a4..1569577b12 100644
--- a/src/corelib/global/qnamespace.h
+++ b/src/corelib/global/qnamespace.h
@@ -1356,6 +1356,11 @@ namespace Qt {
PreventContextMenu
};
+ enum class ContextMenuTrigger {
+ Press,
+ Release,
+ };
+
enum InputMethodQuery {
ImEnabled = 0x1,
ImCursorRectangle = 0x2,
@@ -1731,6 +1736,7 @@ namespace Qt {
Q_ENUM_NS(ScrollBarPolicy)
Q_ENUM_NS(FocusPolicy)
Q_ENUM_NS(ContextMenuPolicy)
+ Q_ENUM_NS(ContextMenuTrigger)
Q_ENUM_NS(ArrowType)
Q_ENUM_NS(ToolButtonStyle)
Q_ENUM_NS(PenStyle)
diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc
index ddfade675a..b2ec64f435 100644
--- a/src/corelib/global/qnamespace.qdoc
+++ b/src/corelib/global/qnamespace.qdoc
@@ -2087,6 +2087,18 @@
*/
/*!
+ \enum Qt::ContextMenuTrigger
+ \since 6.8
+
+ This enum type defines the mouse event used to trigger a context menu event.
+
+ \value Press context menu on mouse press event, default on UNIX systems.
+ \value Release context menu on mouse release event, default on Windows.
+
+ \sa QStyleHints::contextMenuTrigger
+*/
+
+/*!
\enum Qt::FocusPolicy
This enum type defines the various policies a widget can have with
diff --git a/src/corelib/global/qtconfigmacros.h b/src/corelib/global/qtconfigmacros.h
index 03d52d885a..b643122d5c 100644
--- a/src/corelib/global/qtconfigmacros.h
+++ b/src/corelib/global/qtconfigmacros.h
@@ -9,6 +9,7 @@
#endif
#include <QtCore/qtconfiginclude.h>
+#include <QtCore/qtdeprecationdefinitions.h>
#include <QtCore/qtversionchecks.h>
#include <assert.h>
diff --git a/src/corelib/global/qtdeprecationdefinitions.h.in b/src/corelib/global/qtdeprecationdefinitions.h.in
new file mode 100644
index 0000000000..0570f63a5a
--- /dev/null
+++ b/src/corelib/global/qtdeprecationdefinitions.h.in
@@ -0,0 +1,28 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QTDEPRECATIONDEFINITIONS_H
+#define QTDEPRECATIONDEFINITIONS_H
+
+#ifndef QT_DISABLE_DEPRECATED_UP_TO
+# ifdef QT_DISABLE_DEPRECATED_BEFORE // If the deprecated macro is defined, use its value
+# define QT_DISABLE_DEPRECATED_UP_TO QT_DISABLE_DEPRECATED_BEFORE
+# else
+# define QT_DISABLE_DEPRECATED_UP_TO @QT_DISABLE_DEPRECATED_UP_TO@
+# endif
+#endif
+
+#if QT_DISABLE_DEPRECATED_UP_TO < @QT_DISABLE_DEPRECATED_UP_TO@
+# warning QT_DISABLE_DEPRECATED_UP_TO is set to the version that is lower than the version that \
+ Qt was built with. This may lead to linking issues.
+#endif
+
+#ifndef QT_WARN_DEPRECATED_UP_TO
+# ifdef QT_DEPRECATED_WARNINGS_SINCE // If the deprecated macro is defined, use its value
+# define QT_WARN_DEPRECATED_UP_TO QT_DEPRECATED_WARNINGS_SINCE
+# else
+# define QT_WARN_DEPRECATED_UP_TO @QT_WARN_DEPRECATED_UP_TO@
+# endif
+#endif
+
+#endif // QTDEPRECATIONDEFINITIONS_H
diff --git a/src/corelib/global/qtdeprecationmarkers.h b/src/corelib/global/qtdeprecationmarkers.h
index 6df5ebce6d..68f4fda186 100644
--- a/src/corelib/global/qtdeprecationmarkers.h
+++ b/src/corelib/global/qtdeprecationmarkers.h
@@ -5,6 +5,7 @@
#define QTDEPRECATIONMARKERS_H
#include <QtCore/qtconfigmacros.h>
+#include <QtCore/qtdeprecationdefinitions.h>
#include <QtCore/qtversionchecks.h>
#include <QtCore/qcompilerdetection.h> // for Q_DECL_DEPRECATED
@@ -44,28 +45,6 @@ QT_BEGIN_NAMESPACE
# define Q_DECL_ENUMERATOR_DEPRECATED_X(ignored)
#endif
-// If the deprecated macro is defined, use its value
-#if !defined(QT_DISABLE_DEPRECATED_UP_TO) && defined(QT_DISABLE_DEPRECATED_BEFORE)
-# define QT_DISABLE_DEPRECATED_UP_TO QT_DISABLE_DEPRECATED_BEFORE
-#endif
-
-// If the deprecated macro is defined, use its value
-#if !defined(QT_WARN_DEPRECATED_UP_TO) && defined(QT_DEPRECATED_WARNINGS_SINCE)
-# define QT_WARN_DEPRECATED_UP_TO QT_DEPRECATED_WARNINGS_SINCE
-#endif
-
-#ifndef QT_WARN_DEPRECATED_UP_TO
-# ifdef QT_DISABLE_DEPRECATED_UP_TO
-# define QT_WARN_DEPRECATED_UP_TO QT_DISABLE_DEPRECATED_UP_TO
-# else
-# define QT_WARN_DEPRECATED_UP_TO QT_VERSION
-# endif
-#endif
-
-#ifndef QT_DISABLE_DEPRECATED_UP_TO
-#define QT_DISABLE_DEPRECATED_UP_TO QT_VERSION_CHECK(5, 0, 0)
-#endif
-
/*
QT_DEPRECATED_SINCE(major, minor) evaluates as true if the Qt version is greater than
the deprecation point specified.
diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp
index 9291201d88..05947f3380 100644
--- a/src/corelib/io/qdir.cpp
+++ b/src/corelib/io/qdir.cpp
@@ -313,9 +313,10 @@ inline void QDirPrivate::sortFileList(QDir::SortFlags sort, const QFileInfoList
names->append(fi.fileName());
}
} else {
- QScopedArrayPointer<QDirSortItem> si(new QDirSortItem[n]);
+ QVarLengthArray<QDirSortItem, 64> si;
+ si.reserve(n);
for (qsizetype i = 0; i < n; ++i)
- si[i] = QDirSortItem{l.at(i), sort};
+ si.emplace_back(l.at(i), sort);
#ifndef QT_BOOTSTRAPPED
if (sort.testAnyFlag(QDir::LocaleAware)) {
diff --git a/src/corelib/io/qdirlisting.cpp b/src/corelib/io/qdirlisting.cpp
index 008003e856..45ece02a17 100644
--- a/src/corelib/io/qdirlisting.cpp
+++ b/src/corelib/io/qdirlisting.cpp
@@ -80,7 +80,6 @@
#include <QtCore/private/qduplicatetracker_p.h>
#include <memory>
-#include <stack>
#include <vector>
QT_BEGIN_NAMESPACE
@@ -92,6 +91,7 @@ class QDirListingPrivate
public:
void init(bool resolveEngine);
void advance();
+ void beginIterating();
bool entryMatches(QDirEntryInfo &info);
void pushDirectory(QDirEntryInfo &info);
@@ -113,10 +113,10 @@ public:
#endif
using FEngineIteratorPtr = std::unique_ptr<QAbstractFileEngineIterator>;
- std::stack<FEngineIteratorPtr, std::vector<FEngineIteratorPtr>> fileEngineIterators;
+ std::vector<FEngineIteratorPtr> fileEngineIterators;
#ifndef QT_NO_FILESYSTEMITERATOR
using FsIteratorPtr = std::unique_ptr<QFileSystemIterator>;
- std::stack<FsIteratorPtr, std::vector<FsIteratorPtr>> nativeIterators;
+ std::vector<FsIteratorPtr> nativeIterators;
#endif
// Loop protection
@@ -143,7 +143,21 @@ void QDirListingPrivate::init(bool resolveEngine = true)
engine = QFileSystemEngine::createLegacyEngine(initialEntryInfo.entry,
initialEntryInfo.metaData);
}
+}
+/*!
+ \internal
+
+ Resets the iteration state (if any), so that calling begin()/cbegin()
+ always starts iterating anew.
+*/
+void QDirListingPrivate::beginIterating()
+{
+#ifndef QT_NO_FILESYSTEMITERATOR
+ nativeIterators.clear();
+#endif
+ fileEngineIterators.clear();
+ visitedLinks.clear();
pushDirectory(initialEntryInfo);
}
@@ -167,7 +181,7 @@ void QDirListingPrivate::pushDirectory(QDirEntryInfo &entryInfo)
if (engine) {
engine->setFileName(path);
if (auto it = engine->beginEntryList(path, filters, nameFilters)) {
- fileEngineIterators.emplace(std::move(it));
+ fileEngineIterators.emplace_back(std::move(it));
} else {
// No iterator; no entry list.
}
@@ -178,7 +192,7 @@ void QDirListingPrivate::pushDirectory(QDirEntryInfo &entryInfo)
fentry = &entryInfo.fileInfoOpt->d_ptr->fileEntry;
else
fentry = &entryInfo.entry;
- nativeIterators.emplace(std::make_unique<QFileSystemIterator>(*fentry, filters));
+ nativeIterators.emplace_back(std::make_unique<QFileSystemIterator>(*fentry, filters));
#else
qWarning("Qt was built with -no-feature-filesystemiterator: no files/plugins will be found!");
#endif
@@ -196,19 +210,18 @@ bool QDirListingPrivate::entryMatches(QDirEntryInfo &entryInfo)
Advances the internal iterator, either a QAbstractFileEngineIterator (e.g.
QResourceFileEngineIterator) or a QFileSystemIterator (which uses low-level
- system methods, e.g. readdir() on Unix).
-
- An iterator stack is used for holding the iterators.
+ system methods, e.g. readdir() on Unix). The iterators are stored in a
+ vector.
A typical example of doing recursive iteration:
- while iterating directory A we find a sub-dir B
- - an iterator for B is added to the iterator stack
- - B's iterator is processed (the top() of the stack) first; then loop
+ - an iterator for B is added to the vector
+ - B's iterator is processed (vector.back()) first; then the loop
goes back to processing A's iterator
*/
void QDirListingPrivate::advance()
{
- // Use get() in both code paths below because the iterator returned by top()
+ // Use get() in both code paths below because the iterator returned by back()
// may be invalidated due to reallocation when appending new iterators in
// pushDirectory().
@@ -216,7 +229,7 @@ void QDirListingPrivate::advance()
while (!fileEngineIterators.empty()) {
// Find the next valid iterator that matches the filters.
QAbstractFileEngineIterator *it;
- while (it = fileEngineIterators.top().get(), it->advance()) {
+ while (it = fileEngineIterators.back().get(), it->advance()) {
QDirEntryInfo entryInfo;
entryInfo.fileInfoOpt = it->currentFileInfo();
if (entryMatches(entryInfo)) {
@@ -225,7 +238,7 @@ void QDirListingPrivate::advance()
}
}
- fileEngineIterators.pop();
+ fileEngineIterators.pop_back();
}
} else {
#ifndef QT_NO_FILESYSTEMITERATOR
@@ -233,7 +246,8 @@ void QDirListingPrivate::advance()
while (!nativeIterators.empty()) {
// Find the next valid iterator that matches the filters.
QFileSystemIterator *it;
- while (it = nativeIterators.top().get(), it->advance(entryInfo.entry, entryInfo.metaData)) {
+ while (it = nativeIterators.back().get(),
+ it->advance(entryInfo.entry, entryInfo.metaData)) {
if (entryMatches(entryInfo)) {
currentEntryInfo = std::move(entryInfo);
return;
@@ -241,7 +255,7 @@ void QDirListingPrivate::advance()
entryInfo = {};
}
- nativeIterators.pop();
+ nativeIterators.pop_back();
}
#endif
}
@@ -498,14 +512,15 @@ QString QDirListing::iteratorPath() const
Here's how to find and read all files filtered by name, recursively:
\snippet code/src_corelib_io_qdirlisting.cpp 1
- \note As this is a unidirectional (forward-only) iterator, calling
- begin()/cbegin() more than once on the same QDirListing object could
- result in unexpected behavior (for example, some entries being skipped).
+ \note This is a forward-only iterator, every time begin()/cbegin() is
+ called (on the same QDirListing object), the internal state is reset and
+ the iteration starts anew.
\sa fileInfo(), fileName(), filePath()
*/
QDirListing::const_iterator QDirListing::begin() const
{
+ d->beginIterating();
const_iterator it{d.get()};
return ++it;
}
diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp
index 52188dde51..ea594470ea 100644
--- a/src/corelib/io/qfile.cpp
+++ b/src/corelib/io/qfile.cpp
@@ -510,7 +510,7 @@ QFile::moveToTrash()
\since 5.15
\overload
- Moves the file specified by fileName() to the trash. Returns \c true if successful,
+ Moves the file specified by \a fileName to the trash. Returns \c true if successful,
and sets \a pathInTrash (if provided) to the path at which the file can be found within
the trash; otherwise returns \c false.
diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp
index 2f6c0ae184..fb48f22bc6 100644
--- a/src/corelib/io/qfilesystemengine_unix.cpp
+++ b/src/corelib/io/qfilesystemengine_unix.cpp
@@ -641,30 +641,17 @@ QFileSystemEntry QFileSystemEngine::getRawLinkPath(const QFileSystemEntry &link,
QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry, QFileSystemMetaData &data)
{
Q_CHECK_FILE_NAME(entry, entry);
+ char *resolved_name = nullptr;
-#if !defined(Q_OS_DARWIN) && !defined(Q_OS_QNX) && !defined(Q_OS_ANDROID) && !defined(Q_OS_HAIKU) && _POSIX_VERSION < 200809L && !defined(Q_OS_VXWORKS)
- // realpath(X,0) is not supported
- Q_UNUSED(data);
- return QFileSystemEntry(slowCanonicalized(absoluteName(entry).filePath()));
-#else
-# if defined(Q_OS_DARWIN) || defined(Q_OS_ANDROID) || _POSIX_VERSION < 200801L
- // used to store the result of realpath in case where realpath cannot allocate itself
+#ifdef PATH_MAX
+ // use the stack to avoid the overhead of memory allocation
char stack_result[PATH_MAX + 1];
#else
- // enables unconditionally passing stack_result below
+ // system with unlimited file paths -> must use heap
std::nullptr_t stack_result = nullptr;
-# endif
- auto resolved_path_deleter = [&](char *ptr) {
- // frees resolved_name if it was allocated by realpath
-# if defined(Q_OS_DARWIN) || defined(Q_OS_ANDROID) || _POSIX_VERSION < 200801L
- // ptr is either null, or points to stack_result
- Q_ASSERT(!ptr || ptr == stack_result);
- return;
-#else
- free(ptr);
-# endif
- };
- std::unique_ptr<char, decltype (resolved_path_deleter)> resolved_name {nullptr, resolved_path_deleter};
+ auto freer = qScopeGuard([&] { free(resolved_name); });
+#endif
+
# if defined(Q_OS_DARWIN) || defined(Q_OS_ANDROID)
// On some Android and macOS versions, realpath() will return a path even if
// it does not exist. To work around this, we check existence in advance.
@@ -674,14 +661,14 @@ QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry,
if (!data.exists())
errno = ENOENT;
else
- resolved_name.reset(realpath(entry.nativeFilePath().constData(), stack_result));
+ resolved_name = realpath(entry.nativeFilePath().constData(), stack_result);
# else
- resolved_name.reset(realpath(entry.nativeFilePath().constData(), stack_result));
+ resolved_name = realpath(entry.nativeFilePath().constData(), stack_result);
# endif
if (resolved_name) {
data.knownFlagsMask |= QFileSystemMetaData::ExistsAttribute;
data.entryFlags |= QFileSystemMetaData::ExistsAttribute;
- QString canonicalPath = QDir::cleanPath(QFile::decodeName(resolved_name.get()));
+ QString canonicalPath = QDir::cleanPath(QFile::decodeName(resolved_name));
return QFileSystemEntry(canonicalPath);
} else if (errno == ENOENT || errno == ENOTDIR) { // file doesn't exist
data.knownFlagsMask |= QFileSystemMetaData::ExistsAttribute;
@@ -689,7 +676,6 @@ QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry,
return QFileSystemEntry();
}
return entry;
-#endif
}
//static
diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp
index 4360b5b076..1e285bb36b 100644
--- a/src/corelib/io/qurl.cpp
+++ b/src/corelib/io/qurl.cpp
@@ -1014,8 +1014,9 @@ inline bool QUrlPrivate::setScheme(const QString &value, qsizetype len, bool doS
inline void QUrlPrivate::setAuthority(const QString &auth, qsizetype from, qsizetype end, QUrl::ParsingMode mode)
{
sectionIsPresent &= ~Authority;
- sectionIsPresent |= Host;
port = -1;
+ if (from == end && !auth.isNull())
+ sectionIsPresent |= Host; // empty but not null authority implies host
// we never actually _loop_
while (from != end) {
@@ -1155,8 +1156,11 @@ inline void QUrlPrivate::setQuery(const QString &value, qsizetype from, qsizetyp
inline void QUrlPrivate::appendHost(QString &appendTo, QUrl::FormattingOptions options) const
{
- if (host.isEmpty())
+ if (host.isEmpty()) {
+ if ((sectionIsPresent & Host) && appendTo.isNull())
+ appendTo.detach();
return;
+ }
if (host.at(0).unicode() == '[') {
// IPv6 addresses might contain a zone-id which needs to be recoded
if (options != 0)
@@ -1274,7 +1278,9 @@ QUrlPrivate::setHost(const QString &value, qsizetype from, qsizetype iend, QUrl:
const qsizetype len = end - begin;
host.clear();
- sectionIsPresent |= Host;
+ sectionIsPresent &= ~Host;
+ if (!value.isNull() || (sectionIsPresent & Authority))
+ sectionIsPresent |= Host;
if (len == 0)
return true;
@@ -2029,11 +2035,6 @@ void QUrl::setAuthority(const QString &authority, ParsingMode mode)
}
d->setAuthority(authority, 0, authority.size(), mode);
- if (authority.isNull()) {
- // QUrlPrivate::setAuthority cleared almost everything
- // but it leaves the Host bit set
- d->sectionIsPresent &= ~QUrlPrivate::Authority;
- }
}
/*!
@@ -2297,8 +2298,7 @@ void QUrl::setHost(const QString &host, ParsingMode mode)
}
if (d->setHost(data, 0, data.size(), mode)) {
- if (host.isNull())
- d->sectionIsPresent &= ~QUrlPrivate::Host;
+ return;
} else if (!data.startsWith(u'[')) {
// setHost failed, it might be IPv6 or IPvFuture in need of bracketing
Q_ASSERT(d->error);
@@ -2311,6 +2311,7 @@ void QUrl::setHost(const QString &host, ParsingMode mode)
// source data contains ':', so it's an IPv6 error
d->error->code = QUrlPrivate::InvalidIPv6AddressError;
}
+ d->sectionIsPresent &= ~QUrlPrivate::Host;
} else {
// succeeded
d->clearError();
diff --git a/src/corelib/itemmodels/qabstractitemmodel.cpp b/src/corelib/itemmodels/qabstractitemmodel.cpp
index cd29f2fcc2..216db3b42a 100644
--- a/src/corelib/itemmodels/qabstractitemmodel.cpp
+++ b/src/corelib/itemmodels/qabstractitemmodel.cpp
@@ -288,6 +288,9 @@ void QPersistentModelIndexData::destroy(QPersistentModelIndexData *data)
\brief The QPersistentModelIndex class is used to locate data in a data model.
\ingroup model-view
+ \compares strong
+ \compareswith strong QModelIndex
+ \endcompareswith
A QPersistentModelIndex is a model index that can be stored by an
application, and later used to access information in a model.
@@ -375,45 +378,53 @@ QPersistentModelIndex::~QPersistentModelIndex()
}
/*!
- Returns \c{true} if this persistent model index is equal to the \a other
- persistent model index; otherwise returns \c{false}.
+ \fn bool QPersistentModelIndex::operator==(const QPersistentModelIndex &lhs, const QPersistentModelIndex &rhs)
+ Returns \c{true} if \a lhs persistent model index is equal to the \a rhs
+ persistent model index; otherwise returns \c{false}.
- The internal data pointer, row, column, and model values in the persistent
- model index are used when comparing with another persistent model index.
+ The internal data pointer, row, column, and model values in the persistent
+ model index are used when comparing with another persistent model index.
*/
-bool QPersistentModelIndex::operator==(const QPersistentModelIndex &other) const noexcept
+/*!
+ \fn bool QPersistentModelIndex::operator!=(const QPersistentModelIndex &lhs, const QPersistentModelIndex &rhs)
+ \since 4.2
+
+ Returns \c{true} if \a lhs persistent model index is not equal to the \a rhs
+ persistent model index; otherwise returns \c{false}.
+*/
+bool comparesEqual(const QPersistentModelIndex &lhs, const QPersistentModelIndex &rhs) noexcept
{
- if (d && other.d)
- return d->index == other.d->index;
- return d == other.d;
+ if (lhs.d && rhs.d)
+ return lhs.d->index == rhs.d->index;
+ return lhs.d == rhs.d;
}
/*!
+ \fn bool QPersistentModelIndex::operator<(const QPersistentModelIndex &lhs, const QPersistentModelIndex &rhs)
\since 4.1
- Returns \c{true} if this persistent model index is smaller than the \a other
+ Returns \c{true} if \a lhs persistent model index is smaller than the \a rhs
persistent model index; otherwise returns \c{false}.
The internal data pointer, row, column, and model values in the persistent
model index are used when comparing with another persistent model index.
*/
-
-bool QPersistentModelIndex::operator<(const QPersistentModelIndex &other) const noexcept
+Qt::strong_ordering compareThreeWay(const QPersistentModelIndex &lhs,
+ const QPersistentModelIndex &rhs) noexcept
{
- if (d && other.d)
- return d->index < other.d->index;
+ if (lhs.d && rhs.d)
+ return compareThreeWay(lhs.d->index, rhs.d->index);
- return std::less<>{}(d, other.d);
+ using Qt::totally_ordered_wrapper;
+ return compareThreeWay(totally_ordered_wrapper{lhs.d}, totally_ordered_wrapper{rhs.d});
}
-/*!
- \fn bool QPersistentModelIndex::operator!=(const QPersistentModelIndex &other) const
- \since 4.2
-
- Returns \c{true} if this persistent model index is not equal to the \a
- other persistent model index; otherwise returns \c{false}.
-*/
+Qt::strong_ordering compareThreeWay(const QPersistentModelIndex &lhs,
+ const QModelIndex &rhs) noexcept
+{
+ return compareThreeWay(lhs.d ? lhs.d->index : QModelIndex{}, rhs);
+}
/*!
Sets the persistent model index to refer to the same item in a model
@@ -470,32 +481,26 @@ QPersistentModelIndex::operator QModelIndex() const
}
/*!
- Returns \c{true} if this persistent model index refers to the same location as
- the \a other model index; otherwise returns \c{false}.
+ \fn bool QPersistentModelIndex::operator==(const QPersistentModelIndex &lhs, const QModelIndex &rhs)
+ Returns \c{true} if \a lhs persistent model index refers to the same location as
+ the \a rhs model index; otherwise returns \c{false}.
The internal data pointer, row, column, and model values in the persistent
model index are used when comparing with another model index.
-*/
-
-bool QPersistentModelIndex::operator==(const QModelIndex &other) const noexcept
-{
- if (d)
- return d->index == other;
- return !other.isValid();
-}
+ */
/*!
- \fn bool QPersistentModelIndex::operator!=(const QModelIndex &other) const
+ \fn bool QPersistentModelIndex::operator!=(const QPersistentModelIndex &lhs, const QModelIndex &rhs)
- Returns \c{true} if this persistent model index does not refer to the same
- location as the \a other model index; otherwise returns \c{false}.
+ Returns \c{true} if \a lhs persistent model index does not refer to the same
+ location as the \a rhs model index; otherwise returns \c{false}.
*/
-bool QPersistentModelIndex::operator!=(const QModelIndex &other) const noexcept
+bool comparesEqual(const QPersistentModelIndex &lhs, const QModelIndex &rhs) noexcept
{
- if (d)
- return d->index != other;
- return other.isValid();
+ if (lhs.d)
+ return lhs.d->index == rhs;
+ return !rhs.isValid();
}
/*!
@@ -1158,6 +1163,7 @@ void QAbstractItemModel::resetInternalData()
\ingroup model-view
+ \compares strong
This class is used as an index into item models derived from
QAbstractItemModel. The index is used by item views, delegates, and
@@ -1328,24 +1334,22 @@ void QAbstractItemModel::resetInternalData()
*/
/*!
- \fn bool QModelIndex::operator==(const QModelIndex &other) const
+ \fn bool QModelIndex::operator==(const QModelIndex &lhs, const QModelIndex &rhs)
- Returns \c{true} if this model index refers to the same location as the
- \a other model index; otherwise returns \c{false}.
+ Returns \c{true} if \a lhs model index refers to the same location as the
+ \a rhs model index; otherwise returns \c{false}.
The internal data pointer, row, column, and model values are used when
comparing with another model index.
*/
-
/*!
- \fn bool QModelIndex::operator!=(const QModelIndex &other) const
+ \fn bool QModelIndex::operator!=(const QModelIndex &lhs, const QModelIndex &rhs)
- Returns \c{true} if this model index does not refer to the same location as
- the \a other model index; otherwise returns \c{false}.
+ Returns \c{true} if \a lhs model index does not refer to the same location as
+ the \a rhs model index; otherwise returns \c{false}.
*/
-
/*!
\fn QModelIndex QModelIndex::parent() const
@@ -4124,10 +4128,10 @@ bool QAbstractListModel::dropMimeData(const QMimeData *data, Qt::DropAction acti
*/
/*!
- \fn bool QModelIndex::operator<(const QModelIndex &other) const
+ \fn bool QModelIndex::operator<(const QModelIndex &lhs, const QModelIndex &rhs)
\since 4.1
- Returns \c{true} if this model index is smaller than the \a other
+ Returns \c{true} if \a lhs model index is smaller than the \a rhs
model index; otherwise returns \c{false}.
The less than calculation is not directly useful to developers - the way that indexes
diff --git a/src/corelib/itemmodels/qabstractitemmodel.h b/src/corelib/itemmodels/qabstractitemmodel.h
index 8f22f14989..418fc6b864 100644
--- a/src/corelib/itemmodels/qabstractitemmodel.h
+++ b/src/corelib/itemmodels/qabstractitemmodel.h
@@ -5,11 +5,14 @@
#ifndef QABSTRACTITEMMODEL_H
#define QABSTRACTITEMMODEL_H
+#include <QtCore/qcompare.h>
#include <QtCore/qhash.h>
#include <QtCore/qlist.h>
#include <QtCore/qobject.h>
#include <QtCore/qvariant.h>
+#include <tuple>
+
QT_REQUIRE_CONFIG(itemmodel);
QT_BEGIN_NAMESPACE
@@ -138,19 +141,16 @@ public:
inline QVariant data(int role = Qt::DisplayRole) const;
inline void multiData(QModelRoleDataSpan roleDataSpan) const;
inline Qt::ItemFlags flags() const;
- constexpr inline const QAbstractItemModel *model() const noexcept { return m; }
+ constexpr inline const QAbstractItemModel *model() const noexcept { return m.get(); }
constexpr inline bool isValid() const noexcept { return (r >= 0) && (c >= 0) && (m != nullptr); }
- constexpr inline bool operator==(const QModelIndex &other) const noexcept
- { return (other.r == r) && (other.i == i) && (other.c == c) && (other.m == m); }
- constexpr inline bool operator!=(const QModelIndex &other) const noexcept
- { return !(*this == other); }
- constexpr inline bool operator<(const QModelIndex &other) const noexcept
- {
- return r < other.r
- || (r == other.r && (c < other.c
- || (c == other.c && (i < other.i
- || (i == other.i && std::less<const QAbstractItemModel *>()(m, other.m))))));
- }
+
+private:
+ constexpr auto asTuple() const noexcept { return std::tie(r, c, i, m); }
+ friend constexpr bool comparesEqual(const QModelIndex &lhs, const QModelIndex &rhs) noexcept
+ { return lhs.asTuple() == rhs.asTuple(); }
+ friend constexpr Qt::strong_ordering compareThreeWay(const QModelIndex &lhs, const QModelIndex &rhs) noexcept
+ { return QtOrderingPrivate::compareThreeWayMulti(lhs.asTuple(), rhs.asTuple()); }
+ Q_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE(QModelIndex)
private:
inline QModelIndex(int arow, int acolumn, const void *ptr, const QAbstractItemModel *amodel) noexcept
: r(arow), c(acolumn), i(reinterpret_cast<quintptr>(ptr)), m(amodel) {}
@@ -158,7 +158,7 @@ private:
: r(arow), c(acolumn), i(id), m(amodel) {}
int r, c;
quintptr i;
- const QAbstractItemModel *m;
+ Qt::totally_ordered_wrapper<const QAbstractItemModel *> m;
};
Q_DECLARE_TYPEINFO(QModelIndex, Q_RELOCATABLE_TYPE);
@@ -178,17 +178,21 @@ public:
QPersistentModelIndex(const QModelIndex &index);
QPersistentModelIndex(const QPersistentModelIndex &other);
~QPersistentModelIndex();
+#if QT_CORE_REMOVED_SINCE(6, 8)
bool operator<(const QPersistentModelIndex &other) const noexcept;
bool operator==(const QPersistentModelIndex &other) const noexcept;
inline bool operator!=(const QPersistentModelIndex &other) const noexcept
{ return !operator==(other); }
+#endif
QPersistentModelIndex &operator=(const QPersistentModelIndex &other);
inline QPersistentModelIndex(QPersistentModelIndex &&other) noexcept
: d(std::exchange(other.d, nullptr)) {}
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QPersistentModelIndex)
void swap(QPersistentModelIndex &other) noexcept { qt_ptr_swap(d, other.d); }
+#if QT_CORE_REMOVED_SINCE(6, 8)
bool operator==(const QModelIndex &other) const noexcept;
bool operator!=(const QModelIndex &other) const noexcept;
+#endif
QPersistentModelIndex &operator=(const QModelIndex &other);
operator QModelIndex() const;
int row() const;
@@ -208,6 +212,18 @@ private:
friend size_t qHash(const QPersistentModelIndex &, size_t seed) noexcept;
friend bool qHashEquals(const QPersistentModelIndex &a, const QPersistentModelIndex &b) noexcept
{ return a.d == b.d; }
+ friend Q_CORE_EXPORT bool
+ comparesEqual(const QPersistentModelIndex &lhs, const QPersistentModelIndex &rhs) noexcept;
+ friend Q_CORE_EXPORT bool
+ comparesEqual(const QPersistentModelIndex &lhs, const QModelIndex &rhs) noexcept;
+ friend Q_CORE_EXPORT Qt::strong_ordering // ### Qt 7: partial_ordering?
+ compareThreeWay(const QPersistentModelIndex &lhs, const QPersistentModelIndex &rhs) noexcept;
+ friend Q_CORE_EXPORT Qt::strong_ordering // ### Qt 7: partial_ordering?
+ compareThreeWay(const QPersistentModelIndex &lhs, const QModelIndex &rhs) noexcept;
+#if !QT_CORE_REMOVED_SINCE(6, 8)
+ Q_DECLARE_STRONGLY_ORDERED(QPersistentModelIndex)
+ Q_DECLARE_STRONGLY_ORDERED(QPersistentModelIndex, QModelIndex)
+#endif
#ifndef QT_NO_DEBUG_STREAM
friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QPersistentModelIndex &);
#endif
diff --git a/src/corelib/itemmodels/qitemselectionmodel.h b/src/corelib/itemmodels/qitemselectionmodel.h
index c4b8dadc97..aaf32e68ef 100644
--- a/src/corelib/itemmodels/qitemselectionmodel.h
+++ b/src/corelib/itemmodels/qitemselectionmodel.h
@@ -77,7 +77,7 @@ private:
friend bool comparesEqual(const QItemSelectionRange &lhs,
const QItemSelectionRange &rhs) noexcept
{
- return (lhs.tl == rhs.tl && lhs.br == rhs.br);
+ return comparesEqual(lhs.tl, rhs.tl) && comparesEqual(lhs.br, rhs.br);
}
Q_DECLARE_EQUALITY_COMPARABLE(QItemSelectionRange)
QPersistentModelIndex tl, br;
diff --git a/src/corelib/kernel/qapplicationstatic.h b/src/corelib/kernel/qapplicationstatic.h
index bf5e79b8bf..345a880748 100644
--- a/src/corelib/kernel/qapplicationstatic.h
+++ b/src/corelib/kernel/qapplicationstatic.h
@@ -11,6 +11,10 @@
#include <new>
+#if 0
+#pragma qt_class(QApplicationStatic)
+#endif
+
QT_BEGIN_NAMESPACE
namespace QtGlobalStatic {
diff --git a/src/corelib/kernel/qcore_mac.mm b/src/corelib/kernel/qcore_mac.mm
index 54c4373aed..00b0d078d7 100644
--- a/src/corelib/kernel/qcore_mac.mm
+++ b/src/corelib/kernel/qcore_mac.mm
@@ -541,7 +541,7 @@ QMacRootLevelAutoReleasePool::QMacRootLevelAutoReleasePool()
if (qEnvironmentVariableIsSet(ROOT_LEVEL_POOL_DISABLE_SWITCH))
return;
- pool.reset(new QMacAutoReleasePool);
+ pool.emplace();
[[[ROOT_LEVEL_POOL_MARKER alloc] init] autorelease];
diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h
index e63c320805..5ecf8072f4 100644
--- a/src/corelib/kernel/qcore_mac_p.h
+++ b/src/corelib/kernel/qcore_mac_p.h
@@ -19,6 +19,8 @@
#include <QtCore/qoperatingsystemversion.h>
+#include <optional>
+
#ifdef Q_OS_MACOS
#include <mach/port.h>
struct mach_header;
@@ -48,7 +50,6 @@ kern_return_t IOObjectRelease(io_object_t object);
#endif
#include "qstring.h"
-#include "qscopedpointer.h"
#include "qpair.h"
#if defined( __OBJC__) && defined(QT_NAMESPACE)
@@ -129,7 +130,7 @@ public:
Q_NODISCARD_CTOR QMacRootLevelAutoReleasePool();
~QMacRootLevelAutoReleasePool();
private:
- QScopedPointer<QMacAutoReleasePool> pool;
+ std::optional<QMacAutoReleasePool> pool = std::nullopt;
};
#endif
diff --git a/src/corelib/kernel/qelapsedtimer.cpp b/src/corelib/kernel/qelapsedtimer.cpp
index 511b81a04e..c4308a0b8f 100644
--- a/src/corelib/kernel/qelapsedtimer.cpp
+++ b/src/corelib/kernel/qelapsedtimer.cpp
@@ -14,6 +14,8 @@ QT_BEGIN_NAMESPACE
\reentrant
\ingroup tools
+ \compares strong
+
The QElapsedTimer class is usually used to quickly calculate how much
time has elapsed between two events. Its API is similar to that of QTime,
so code that was using that can be ported quickly to the new class.
@@ -155,8 +157,7 @@ QT_BEGIN_NAMESPACE
Returns \c true if \a lhs and \a rhs contain different times, false otherwise.
*/
/*!
- \fn bool operator<(const QElapsedTimer &lhs, const QElapsedTimer &rhs) noexcept
- \relates QElapsedTimer
+ \fn bool QElapsedTimer::operator<(const QElapsedTimer &lhs, const QElapsedTimer &rhs) noexcept
Returns \c true if \a lhs was started before \a rhs, false otherwise.
diff --git a/src/corelib/kernel/qelapsedtimer.h b/src/corelib/kernel/qelapsedtimer.h
index 7d8b889f61..e71573456d 100644
--- a/src/corelib/kernel/qelapsedtimer.h
+++ b/src/corelib/kernel/qelapsedtimer.h
@@ -4,6 +4,7 @@
#ifndef QELAPSEDTIMER_H
#define QELAPSEDTIMER_H
+#include <QtCore/qcompare.h>
#include <QtCore/qglobal.h>
#include <chrono>
@@ -45,15 +46,41 @@ public:
Duration durationTo(const QElapsedTimer &other) const noexcept;
qint64 msecsTo(const QElapsedTimer &other) const noexcept;
qint64 secsTo(const QElapsedTimer &other) const noexcept;
-
- friend bool operator==(const QElapsedTimer &lhs, const QElapsedTimer &rhs) noexcept
- { return lhs.t1 == rhs.t1 && lhs.t2 == rhs.t2; }
- friend bool operator!=(const QElapsedTimer &lhs, const QElapsedTimer &rhs) noexcept
- { return !(lhs == rhs); }
-
friend bool Q_CORE_EXPORT operator<(const QElapsedTimer &lhs, const QElapsedTimer &rhs) noexcept;
private:
+ friend bool comparesEqual(const QElapsedTimer &lhs, const QElapsedTimer &rhs) noexcept
+ {
+ return lhs.t1 == rhs.t1 && lhs.t2 == rhs.t2;
+ }
+ Q_DECLARE_EQUALITY_COMPARABLE(QElapsedTimer)
+
+ friend Qt::strong_ordering compareThreeWay(const QElapsedTimer &lhs,
+ const QElapsedTimer &rhs) noexcept
+ {
+ return Qt::compareThreeWay(lhs.t1, rhs.t1);
+ }
+
+#if defined(__cpp_lib_three_way_comparison)
+ friend std::strong_ordering
+ operator<=>(const QElapsedTimer &lhs, const QElapsedTimer &rhs) noexcept
+ {
+ return compareThreeWay(lhs, rhs);
+ }
+#else
+ friend bool operator>(const QElapsedTimer &lhs, const QElapsedTimer &rhs) noexcept
+ {
+ return is_gt(compareThreeWay(lhs, rhs));
+ }
+ friend bool operator<=(const QElapsedTimer &lhs, const QElapsedTimer &rhs) noexcept
+ {
+ return is_lteq(compareThreeWay(lhs, rhs));
+ }
+ friend bool operator>=(const QElapsedTimer &lhs, const QElapsedTimer &rhs) noexcept
+ {
+ return is_gteq(compareThreeWay(lhs, rhs));
+ }
+#endif // defined(__cpp_lib_three_way_comparison)
qint64 t1 = Q_INT64_C(0x8000000000000000);
qint64 t2 = Q_INT64_C(0x8000000000000000);
};
diff --git a/src/corelib/kernel/qjniobject.cpp b/src/corelib/kernel/qjniobject.cpp
index 8244a4390f..892f02e7a4 100644
--- a/src/corelib/kernel/qjniobject.cpp
+++ b/src/corelib/kernel/qjniobject.cpp
@@ -105,9 +105,9 @@ using namespace Qt::StringLiterals;
// C++ code
QJniObject string1 = QJniObject::fromString("String1");
QJniObject string2 = QJniObject::fromString("String2");
- QJniObject stringArray = QJniObject::callStaticObjectMethod<jstringArray>(
+ QJniObject stringArray = QJniObject::callStaticObjectMethod<jobjectArray>(
"org/qtproject/qt/TestClass",
- "stringArray"
+ "stringArray",
string1.object<jstring>(),
string2.object<jstring>());
\endcode
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp
index 9a57f46cbf..1c2665e53c 100644
--- a/src/corelib/kernel/qmetatype.cpp
+++ b/src/corelib/kernel/qmetatype.cpp
@@ -2660,6 +2660,36 @@ bool QMetaType::hasRegisteredConverterFunction(QMetaType fromType, QMetaType toT
}
/*!
+ \internal
+ Non-template helper ("SCARY") for IsMetaTypePair::registerConverter().
+*/
+bool QtPrivate::hasRegisteredConverterFunctionToPairVariantInterface(QMetaType m)
+{
+ const QMetaType to = QMetaType::fromType<QtMetaTypePrivate::QPairVariantInterfaceImpl>();
+ return QMetaType::hasRegisteredConverterFunction(m, to);
+}
+
+/*!
+ \internal
+ Non-template helper ("SCARY") for SequentialValueTypeIsMetaType::registerConverter().
+*/
+bool QtPrivate::hasRegisteredConverterFunctionToIterableMetaSequence(QMetaType m)
+{
+ const QMetaType to = QMetaType::fromType<QIterable<QMetaSequence>>();
+ return QMetaType::hasRegisteredConverterFunction(m, to);
+}
+
+/*!
+ \internal
+ Non-template helper ("SCARY") for AssociativeKeyTypeIsMetaType::registerConverter().
+*/
+bool QtPrivate::hasRegisteredConverterFunctionToIterableMetaAssociation(QMetaType m)
+{
+ const QMetaType to = QMetaType::fromType<QIterable<QMetaAssociation>>();
+ return QMetaType::hasRegisteredConverterFunction(m, to);
+}
+
+/*!
\fn template<typename From, typename To> bool QMetaType::hasRegisteredMutableViewFunction()
Returns \c true, if the meta type system has a registered mutable view on type From of type To.
\since 6.0
@@ -2677,6 +2707,26 @@ bool QMetaType::hasRegisteredMutableViewFunction(QMetaType fromType, QMetaType t
}
/*!
+ \internal
+ Non-template helper ("SCARY") for SequentialValueTypeIsMetaType::registerMutableView().
+*/
+bool QtPrivate::hasRegisteredMutableViewFunctionToIterableMetaSequence(QMetaType m)
+{
+ const QMetaType to = QMetaType::fromType<QIterable<QMetaSequence>>();
+ return QMetaType::hasRegisteredMutableViewFunction(m, to);
+}
+
+/*!
+ \internal
+ Non-template helper ("SCARY") for AssociativeKeyTypeIsMetaType::registerMutableView().
+*/
+bool QtPrivate::hasRegisteredMutableViewFunctionToIterableMetaAssociation(QMetaType m)
+{
+ const QMetaType to = QMetaType::fromType<QIterable<QMetaAssociation>>();
+ return QMetaType::hasRegisteredMutableViewFunction(m, to);
+}
+
+/*!
\fn const char *QMetaType::typeName(int typeId)
\deprecated
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index 80d10f5c9a..12a67aef58 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -1750,11 +1750,19 @@ QT_FOR_EACH_STATIC_TYPE(Q_DECLARE_BUILTIN_METATYPE)
QT_BEGIN_NAMESPACE
+namespace QtPrivate {
+// out-of-line helpers to reduce template code bloat ("SCARY") and improve compile times:
+Q_CORE_EXPORT bool hasRegisteredConverterFunctionToPairVariantInterface(QMetaType m);
+Q_CORE_EXPORT bool hasRegisteredConverterFunctionToIterableMetaSequence(QMetaType m);
+Q_CORE_EXPORT bool hasRegisteredMutableViewFunctionToIterableMetaSequence(QMetaType m);
+Q_CORE_EXPORT bool hasRegisteredConverterFunctionToIterableMetaAssociation(QMetaType m);
+Q_CORE_EXPORT bool hasRegisteredMutableViewFunctionToIterableMetaAssociation(QMetaType m);
+}
+
template <typename T>
inline bool QtPrivate::IsMetaTypePair<T, true>::registerConverter()
{
- const QMetaType to = QMetaType::fromType<QtMetaTypePrivate::QPairVariantInterfaceImpl>();
- if (!QMetaType::hasRegisteredConverterFunction(QMetaType::fromType<T>(), to)) {
+ if (!QtPrivate::hasRegisteredConverterFunctionToPairVariantInterface(QMetaType::fromType<T>())) {
QtMetaTypePrivate::QPairVariantInterfaceConvertFunctor<T> o;
return QMetaType::registerConverter<T, QtMetaTypePrivate::QPairVariantInterfaceImpl>(o);
}
@@ -1786,8 +1794,7 @@ struct SequentialValueTypeIsMetaType<T, true>
{
static bool registerConverter()
{
- const QMetaType to = QMetaType::fromType<QIterable<QMetaSequence>>();
- if (!QMetaType::hasRegisteredConverterFunction(QMetaType::fromType<T>(), to)) {
+ if (!QtPrivate::hasRegisteredConverterFunctionToIterableMetaSequence(QMetaType::fromType<T>())) {
QSequentialIterableConvertFunctor<T> o;
return QMetaType::registerConverter<T, QIterable<QMetaSequence>>(o);
}
@@ -1796,8 +1803,7 @@ struct SequentialValueTypeIsMetaType<T, true>
static bool registerMutableView()
{
- const QMetaType to = QMetaType::fromType<QIterable<QMetaSequence>>();
- if (!QMetaType::hasRegisteredMutableViewFunction(QMetaType::fromType<T>(), to)) {
+ if (!QtPrivate::hasRegisteredMutableViewFunctionToIterableMetaSequence(QMetaType::fromType<T>())) {
QSequentialIterableMutableViewFunctor<T> o;
return QMetaType::registerMutableView<T, QIterable<QMetaSequence>>(o);
}
@@ -1830,8 +1836,7 @@ struct AssociativeKeyTypeIsMetaType<T, true> : AssociativeMappedTypeIsMetaType<T
{
static bool registerConverter()
{
- const QMetaType to = QMetaType::fromType<QIterable<QMetaAssociation>>();
- if (!QMetaType::hasRegisteredConverterFunction(QMetaType::fromType<T>(), to)) {
+ if (!QtPrivate::hasRegisteredConverterFunctionToIterableMetaAssociation(QMetaType::fromType<T>())) {
QAssociativeIterableConvertFunctor<T> o;
return QMetaType::registerConverter<T, QIterable<QMetaAssociation>>(o);
}
@@ -1840,8 +1845,7 @@ struct AssociativeKeyTypeIsMetaType<T, true> : AssociativeMappedTypeIsMetaType<T
static bool registerMutableView()
{
- const QMetaType to = QMetaType::fromType<QIterable<QMetaAssociation>>();
- if (!QMetaType::hasRegisteredMutableViewFunction(QMetaType::fromType<T>(), to)) {
+ if (!QtPrivate::hasRegisteredMutableViewFunctionToIterableMetaAssociation(QMetaType::fromType<T>())) {
QAssociativeIterableMutableViewFunctor<T> o;
return QMetaType::registerMutableView<T, QIterable<QMetaAssociation>>(o);
}
diff --git a/src/corelib/kernel/qproperty_p.h b/src/corelib/kernel/qproperty_p.h
index 8ae6664a2b..376482a6af 100644
--- a/src/corelib/kernel/qproperty_p.h
+++ b/src/corelib/kernel/qproperty_p.h
@@ -19,12 +19,13 @@
#include <qproperty.h>
#include <qmetaobject.h>
-#include <qscopedpointer.h>
#include <qscopedvaluerollback.h>
#include <qvariant.h>
#include <vector>
#include <QtCore/QVarLengthArray>
+#include <memory>
+
QT_BEGIN_NAMESPACE
namespace QtPrivate {
@@ -292,7 +293,7 @@ private:
ObserverArray inlineDependencyObservers; // for things we are observing
QPropertyObserverPointer firstObserver; // list of observers observing us
- QScopedPointer<std::vector<QPropertyObserver>> heapObservers; // for things we are observing
+ std::unique_ptr<std::vector<QPropertyObserver>> heapObservers; // for things we are observing
protected:
QUntypedPropertyData *propertyDataPtr = nullptr;
diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h
index d567bcbb7c..306e5b3a38 100644
--- a/src/corelib/kernel/qvariant.h
+++ b/src/corelib/kernel/qvariant.h
@@ -497,6 +497,7 @@ public:
// If possible we reuse the current QVariant private.
if (isDetached() && d.type() == metaType) {
*reinterpret_cast<VT *>(const_cast<void *>(constData())) = std::forward<T>(avalue);
+ d.is_null = false;
} else {
*this = QVariant::fromValue<VT>(std::forward<T>(avalue));
}
diff --git a/src/corelib/mimetypes/mime/packages/freedesktop.org.xml b/src/corelib/mimetypes/mime/packages/freedesktop.org.xml
index b7aa6a1995..e77349a12e 100644
--- a/src/corelib/mimetypes/mime/packages/freedesktop.org.xml
+++ b/src/corelib/mimetypes/mime/packages/freedesktop.org.xml
@@ -10699,39 +10699,39 @@ command to generate the output files.
<glob pattern="*.udeb"/>
</mime-type>
<mime-type type="application/x-designer">
- <comment>Qt Designer interface document</comment>
- <comment xml:lang="zh_TW">Qt Designer 介面文件</comment>
- <comment xml:lang="zh_CN">Qt Designer 界面文档</comment>
- <comment xml:lang="uk">документ інтерфейсу Qt Designer</comment>
- <comment xml:lang="tr">Qt Designer arayüz belgesi</comment>
- <comment xml:lang="sv">Qt Designer-gränssnittsdokument</comment>
- <comment xml:lang="sq">dokument ndërfaqesh Qt Designer</comment>
- <comment xml:lang="sl">Dokument vmesnika Qt Designer</comment>
- <comment xml:lang="si">Qt Designer අතුරුමුහුණත් ලේඛනය</comment>
- <comment xml:lang="ru">Документ интерфейса Qt Designer</comment>
- <comment xml:lang="pt_BR">Documento de interface do Qt Designer</comment>
- <comment xml:lang="pt">documento de interface Qt Designer</comment>
- <comment xml:lang="pl">Dokument interfejsu Qt Designer</comment>
- <comment xml:lang="nl">Qt Designer-interfacedocument</comment>
+ <comment>Qt Widgets Designer interface document</comment>
+ <comment xml:lang="zh_TW">Qt Widgets Designer 介面文件</comment>
+ <comment xml:lang="zh_CN">Qt Widgets Designer 界面文档</comment>
+ <comment xml:lang="uk">документ інтерфейсу Qt Widgets Designer</comment>
+ <comment xml:lang="tr">Qt Widgets Designer arayüz belgesi</comment>
+ <comment xml:lang="sv">Qt Widgets Designer-gränssnittsdokument</comment>
+ <comment xml:lang="sq">dokument ndërfaqesh Qt Widgets Designer</comment>
+ <comment xml:lang="sl">Dokument vmesnika Qt Widgets Designer</comment>
+ <comment xml:lang="si">Qt Widgets Designer අතුරුමුහුණත් ලේඛනය</comment>
+ <comment xml:lang="ru">Документ интерфейса Qt Widgets Designer</comment>
+ <comment xml:lang="pt_BR">Documento de interface do Qt Widgets Designer</comment>
+ <comment xml:lang="pt">documento de interface Qt Widgets Designer</comment>
+ <comment xml:lang="pl">Dokument interfejsu Qt Widgets Designer</comment>
+ <comment xml:lang="nl">Qt Widgets Designer-interfacedocument</comment>
<comment xml:lang="ko">Qt 디자이너 인터페이스 문서</comment>
- <comment xml:lang="kk">Qt Designer интерфейс құжаты</comment>
- <comment xml:lang="ja">Qt Designer インターフェイスドキュメント</comment>
- <comment xml:lang="it">Documento interfaccia Qt Designer</comment>
- <comment xml:lang="is">Qt Designer viðmótsskjal</comment>
- <comment xml:lang="id">Dokumen antarmuka Qt Designer</comment>
- <comment xml:lang="hu">Qt Designer felületleíró dokumentum</comment>
- <comment xml:lang="hr">Qt Designer dokument sučelja</comment>
- <comment xml:lang="he">מסמך מנשק של Qt Designer</comment>
- <comment xml:lang="fr">document d'interface Qt Designer</comment>
- <comment xml:lang="fi">Qt Designer -käyttöliittymän asiakirja</comment>
- <comment xml:lang="eu">Qt Designer interfaze dokumentua</comment>
- <comment xml:lang="es">documento de interfaz de Qt Designer</comment>
- <comment xml:lang="en_GB">Qt Designer interface document</comment>
+ <comment xml:lang="kk">Qt Widgets Designer интерфейс құжаты</comment>
+ <comment xml:lang="ja">Qt Widgets Designer インターフェイスドキュメント</comment>
+ <comment xml:lang="it">Documento interfaccia Qt Widgets Designer</comment>
+ <comment xml:lang="is">Qt Widgets Designer viðmótsskjal</comment>
+ <comment xml:lang="id">Dokumen antarmuka Qt Widgets Designer</comment>
+ <comment xml:lang="hu">Qt Widgets Designer felületleíró dokumentum</comment>
+ <comment xml:lang="hr">Qt Widgets Designer dokument sučelja</comment>
+ <comment xml:lang="he">מסמך מנשק של Qt Widgets Designer</comment>
+ <comment xml:lang="fr">document d'interface Qt Widgets Designer</comment>
+ <comment xml:lang="fi">Qt Widgets Designer -käyttöliittymän asiakirja</comment>
+ <comment xml:lang="eu">Qt Widgets Designer interfaze dokumentua</comment>
+ <comment xml:lang="es">documento de interfaz de Qt Widgets Designer</comment>
+ <comment xml:lang="en_GB">Qt Widgets Designer interface document</comment>
<comment xml:lang="de">Qt-Designer-Oberflächendokument</comment>
- <comment xml:lang="da">Qt Designer-brugerflade-dokument</comment>
- <comment xml:lang="ca">document d'interfície Qt Designer</comment>
- <comment xml:lang="bg">Документ — интерфейс, Qt Designer</comment>
- <comment xml:lang="be">дакумент інтэрфейсу Qt Designer</comment>
+ <comment xml:lang="da">Qt Widgets Designer-brugerflade-dokument</comment>
+ <comment xml:lang="ca">document d'interfície Qt Widgets Designer</comment>
+ <comment xml:lang="bg">Документ — интерфейс, Qt Widgets Designer</comment>
+ <comment xml:lang="be">дакумент інтэрфейсу Qt Widgets Designer</comment>
<comment xml:lang="ar">مستند واجهة مصمم كيوت</comment>
<generic-icon name="x-office-document"/>
<sub-class-of type="application/xml"/>
diff --git a/src/corelib/platform/android/qandroidnativeinterface.cpp b/src/corelib/platform/android/qandroidnativeinterface.cpp
index fc3a09c78b..351893eb81 100644
--- a/src/corelib/platform/android/qandroidnativeinterface.cpp
+++ b/src/corelib/platform/android/qandroidnativeinterface.cpp
@@ -49,7 +49,7 @@ QT_DEFINE_NATIVE_INTERFACE(QAndroidApplication);
\fn QJniObject QNativeInterface::QAndroidApplication::context()
Returns the Android context as a \c QJniObject. The context is an \c Activity
- if the main activity object is valid. Otherwise, the context is a \c Service.
+ if the most recently started activity object is valid. Otherwise, the context is a \c Service.
\since 6.2
*/
diff --git a/src/corelib/plugin/quuid.cpp b/src/corelib/plugin/quuid.cpp
index 9c7216c3c5..42f21eea88 100644
--- a/src/corelib/plugin/quuid.cpp
+++ b/src/corelib/plugin/quuid.cpp
@@ -142,6 +142,11 @@ static QUuid createFromName(const QUuid &ns, const QByteArray &baseData, QCrypto
\reentrant
+ \compares strong
+ \compareswith strong GUID
+ \note Comparison with GUID is Windows-only.
+ \endcompareswith
+
Using \e{U}niversally \e{U}nique \e{ID}entifiers (UUID) is a
standard way to uniquely identify entities in a distributed
computing environment. A UUID is a 16-byte (128-bit) number
@@ -600,16 +605,16 @@ QUuid QUuid::fromRfc4122(QByteArrayView bytes) noexcept
}
/*!
- \fn bool QUuid::operator==(const QUuid &other) const
+ \fn bool QUuid::operator==(const QUuid &lhs, const QUuid &rhs)
- Returns \c true if this QUuid and the \a other QUuid are identical;
+ Returns \c true if \a lhs QUuid and the \a rhs QUuid are identical;
otherwise returns \c false.
*/
/*!
- \fn bool QUuid::operator!=(const QUuid &other) const
+ \fn bool QUuid::operator!=(const QUuid &lhs, const QUuid &rhs)
- Returns \c true if this QUuid and the \a other QUuid are different;
+ Returns \c true if \a lhs QUuid and the \a rhs QUuid are different;
otherwise returns \c false.
*/
@@ -898,51 +903,31 @@ QUuid::Version QUuid::version() const noexcept
}
/*!
- \fn bool QUuid::operator<(const QUuid &other) const
+ \fn bool QUuid::operator<(const QUuid &lhs, const QUuid &rhs)
- Returns \c true if this QUuid has the same \l{Variant field}
- {variant field} as the \a other QUuid and is lexicographically
- \e{before} the \a other QUuid. If the \a other QUuid has a
+ Returns \c true if \a lhs QUuid has the same \l{Variant field}
+ {variant field} as the \a rhs QUuid and is lexicographically
+ \e{before} the \a rhs QUuid. If the \a rhs QUuid has a
different variant field, the return value is determined by
comparing the two \l{QUuid::Variant} {variants}.
\sa variant()
*/
-bool QUuid::operator<(const QUuid &other) const noexcept
-{
- if (variant() != other.variant())
- return variant() < other.variant();
-
-#define ISLESS(f1, f2) if (f1!=f2) return (f1<f2);
- ISLESS(data1, other.data1);
- ISLESS(data2, other.data2);
- ISLESS(data3, other.data3);
- for (int n = 0; n < 8; n++) {
- ISLESS(data4[n], other.data4[n]);
- }
-#undef ISLESS
- return false;
-}
/*!
- \fn bool QUuid::operator>(const QUuid &other) const
+ \fn bool QUuid::operator>(const QUuid &lhs, const QUuid &rhs)
- Returns \c true if this QUuid has the same \l{Variant field}
- {variant field} as the \a other QUuid and is lexicographically
- \e{after} the \a other QUuid. If the \a other QUuid has a
+ Returns \c true if \a lhs QUuid has the same \l{Variant field}
+ {variant field} as the \a rhs QUuid and is lexicographically
+ \e{after} the \a rhs QUuid. If the \a rhs QUuid has a
different variant field, the return value is determined by
comparing the two \l{QUuid::Variant} {variants}.
\sa variant()
*/
-bool QUuid::operator>(const QUuid &other) const noexcept
-{
- return other < *this;
-}
/*!
- \fn bool operator<=(const QUuid &lhs, const QUuid &rhs)
- \relates QUuid
+ \fn bool QUuid::operator<=(const QUuid &lhs, const QUuid &rhs)
\since 5.5
Returns \c true if \a lhs has the same \l{Variant field}
@@ -955,8 +940,7 @@ bool QUuid::operator>(const QUuid &other) const noexcept
*/
/*!
- \fn bool operator>=(const QUuid &lhs, const QUuid &rhs)
- \relates QUuid
+ \fn bool QUuid::operator>=(const QUuid &lhs, const QUuid &rhs)
\since 5.5
Returns \c true if \a lhs has the same \l{Variant field}
@@ -1009,17 +993,17 @@ QUuid QUuid::createUuid()
#endif // !Q_OS_WIN && !QT_BOOTSTRAPPED
/*!
- \fn bool QUuid::operator==(const GUID &guid) const
+ \fn bool QUuid::operator==(const QUuid &lhs, const GUID &rhs)
- Returns \c true if this UUID is equal to the Windows GUID \a guid;
+ Returns \c true if \a lhs UUID is equal to the Windows GUID \a rhs;
otherwise returns \c false.
*/
/*!
- \fn bool QUuid::operator!=(const GUID &guid) const
+ \fn bool QUuid::operator!=(const QUuid &lhs, const GUID &rhs)
- Returns \c true if this UUID is not equal to the Windows GUID \a
- guid; otherwise returns \c false.
+ Returns \c true if \a lhs UUID is not equal to the Windows GUID \a rhs;
+ otherwise returns \c false.
*/
#ifndef QT_NO_DEBUG_STREAM
diff --git a/src/corelib/plugin/quuid.h b/src/corelib/plugin/quuid.h
index 7125e8e2cc..14029f1abc 100644
--- a/src/corelib/plugin/quuid.h
+++ b/src/corelib/plugin/quuid.h
@@ -4,6 +4,7 @@
#ifndef QUUID_H
#define QUUID_H
+#include <QtCore/qcompare.h>
#include <QtCore/qendian.h>
#include <QtCore/qstring.h>
@@ -122,27 +123,60 @@ QT_WARNING_POP
constexpr quint128 toUInt128(QSysInfo::Endian order = QSysInfo::BigEndian) const noexcept;
#endif
- constexpr bool operator==(const QUuid &orig) const noexcept
+private:
+ friend constexpr bool comparesEqual(const QUuid &lhs, const QUuid &rhs) noexcept
{
- if (data1 != orig.data1 || data2 != orig.data2 ||
- data3 != orig.data3)
+ if (lhs.data1 != rhs.data1 || lhs.data2 != rhs.data2 || lhs.data3 != rhs.data3)
return false;
- for (uint i = 0; i < 8; i++)
- if (data4[i] != orig.data4[i])
+ for (uint i = 0; i < 8; i++) {
+ if (lhs.data4[i] != rhs.data4[i])
return false;
+ }
return true;
}
+ friend Qt::strong_ordering compareThreeWay(const QUuid &lhs, const QUuid &rhs) noexcept
+ {
+ if (lhs.variant() != rhs.variant())
+ return Qt::compareThreeWay(lhs.variant(), rhs.variant());
+ if (lhs.data1 != rhs.data1)
+ return Qt::compareThreeWay(lhs.data1, rhs.data1);
+ if (lhs.data2 != rhs.data2)
+ return Qt::compareThreeWay(lhs.data2, rhs.data2);
+ if (lhs.data3 != rhs.data3)
+ return Qt::compareThreeWay(lhs.data3, rhs.data3);
+
+ int c = std::memcmp(lhs.data4, rhs.data4, sizeof(lhs.data4));
+ return Qt::compareThreeWay(c, 0);
+ }
+
+public:
+/* To prevent a meta-type creation ambiguity on Windows, we put comparison
+ macros under NOT QT_CORE_REMOVED_SINCE(6, 8) part. */
+#if QT_CORE_REMOVED_SINCE(6, 8)
+ constexpr bool operator==(const QUuid &orig) const noexcept
+ {
+ return comparesEqual(*this, orig);
+ }
constexpr bool operator!=(const QUuid &orig) const noexcept
{
- return !(*this == orig);
+ return !operator==(orig);
}
bool operator<(const QUuid &other) const noexcept;
bool operator>(const QUuid &other) const noexcept;
-
+#else
+private:
+#if defined(__cpp_lib_three_way_comparison) && !defined(Q_QDOC)
+ QT_DECLARE_3WAY_HELPER_STRONG(QUuid, QUuid, /* non-constexpr */, /* no attributes */)
+#else
+ QT_DECLARE_ORDERING_HELPER_STRONG(QUuid, QUuid, /* non-constexpr */, /* no attributes */)
+#endif // defined(__cpp_lib_three_way_comparison) && !defined(Q_QDOC)
+ Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(QUuid)
+#endif // QT_CORE_REMOVED_SINCE(6, 8)
+public:
#if defined(Q_OS_WIN) || defined(Q_QDOC)
// On Windows we have a type GUID that is used by the platform API, so we
// provide convenience operators to cast from and to this type.
@@ -162,17 +196,29 @@ QT_WARNING_POP
GUID guid = { data1, data2, data3, { data4[0], data4[1], data4[2], data4[3], data4[4], data4[5], data4[6], data4[7] } };
return guid;
}
-
+private:
+ friend constexpr bool comparesEqual(const QUuid &lhs, const GUID &rhs) noexcept
+ {
+ return comparesEqual(lhs, QUuid(rhs));
+ }
+public:
+/* To prevent a meta-type creation ambiguity on Windows, we put comparison
+ macros under NOT QT_CORE_REMOVED_SINCE(6, 8) part. */
+#if QT_CORE_REMOVED_SINCE(6, 8)
constexpr bool operator==(const GUID &guid) const noexcept
{
- return *this == QUuid(guid);
+ return comparesEqual(*this, QUuid(guid));
}
constexpr bool operator!=(const GUID &guid) const noexcept
{
- return !(*this == guid);
+ return !operator==(guid);
}
+#else
+ Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(QUuid, GUID)
+#endif // !QT_CORE_REMOVED_SINCE(6, 8)
#endif
+public:
static QUuid createUuid();
#ifndef QT_BOOTSTRAPPED
static QUuid createUuidV3(const QUuid &ns, const QByteArray &baseData);
@@ -291,11 +337,6 @@ constexpr quint128 QUuid::toUInt128(QSysInfo::Endian order) const noexcept
}
#endif
-inline bool operator<=(const QUuid &lhs, const QUuid &rhs) noexcept
-{ return !(rhs < lhs); }
-inline bool operator>=(const QUuid &lhs, const QUuid &rhs) noexcept
-{ return !(lhs < rhs); }
-
#if defined(Q_QDOC)
// provide fake declarations of qXXXEndian() functions, so that qDoc could
// distinguish them from the general template
diff --git a/src/corelib/text/qbytearray.cpp b/src/corelib/text/qbytearray.cpp
index e6387e4bed..c140a6aec8 100644
--- a/src/corelib/text/qbytearray.cpp
+++ b/src/corelib/text/qbytearray.cpp
@@ -56,10 +56,6 @@ static constexpr inline uchar asciiLower(uchar c)
return c >= 'A' && c <= 'Z' ? c | 0x20 : c;
}
-qsizetype qFindByteArray(
- const char *haystack0, qsizetype haystackLen, qsizetype from,
- const char *needle0, qsizetype needleLen);
-
/*****************************************************************************
Safe and portable C string functions; extensions to standard string.h
*****************************************************************************/
@@ -2680,31 +2676,6 @@ QByteArray QByteArray::repeated(qsizetype times) const
return result;
}
-#define REHASH(a) \
- if (ol_minus_1 < sizeof(std::size_t) * CHAR_BIT) \
- hashHaystack -= std::size_t(a) << ol_minus_1; \
- hashHaystack <<= 1
-
-qsizetype QtPrivate::findByteArray(QByteArrayView haystack, qsizetype from, QByteArrayView needle) noexcept
-{
- const auto ol = needle.size();
- const auto l = haystack.size();
- if (ol == 0) {
- if (from < 0)
- return qMax(from + l, 0);
- else
- return from > l ? -1 : from;
- }
-
- if (ol == 1)
- return findByteArray(haystack, from, needle.front());
-
- if (from > l || ol + from > l)
- return -1;
-
- return qFindByteArray(haystack.data(), haystack.size(), from, needle.data(), ol);
-}
-
/*! \fn qsizetype QByteArray::indexOf(QByteArrayView bv, qsizetype from) const
\since 6.0
@@ -2745,10 +2716,10 @@ static qsizetype lastIndexOfHelper(const char *haystack, qsizetype l, const char
const char *end = haystack;
haystack += from;
- const auto ol_minus_1 = std::size_t(ol - 1);
+ const qregisteruint ol_minus_1 = ol - 1;
const char *n = needle + ol_minus_1;
const char *h = haystack + ol_minus_1;
- std::size_t hashNeedle = 0, hashHaystack = 0;
+ qregisteruint hashNeedle = 0, hashHaystack = 0;
qsizetype idx;
for (idx = 0; idx < ol; ++idx) {
hashNeedle = ((hashNeedle<<1) + *(n-idx));
@@ -2760,10 +2731,11 @@ static qsizetype lastIndexOfHelper(const char *haystack, qsizetype l, const char
if (hashHaystack == hashNeedle && memcmp(needle, haystack, ol) == 0)
return haystack - end;
--haystack;
- REHASH(*(haystack + ol));
+ if (ol_minus_1 < sizeof(ol_minus_1) * CHAR_BIT)
+ hashHaystack -= qregisteruint(*(haystack + ol)) << ol_minus_1;
+ hashHaystack <<= 1;
}
return -1;
-
}
static inline qsizetype lastIndexOfCharHelper(QByteArrayView haystack, qsizetype from, char needle) noexcept
@@ -4218,24 +4190,6 @@ QByteArray QByteArray::toBase64(Base64Options options) const
\sa toUShort()
*/
-static char *qulltoa2(char *p, qulonglong n, int base)
-{
-#if defined(QT_CHECK_RANGE)
- if (base < 2 || base > 36) {
- qWarning("QByteArray::setNum: Invalid base %d", base);
- base = 10;
- }
-#endif
- constexpr char b = 'a' - 10;
- do {
- const int c = n % base;
- n /= base;
- *--p = c + (c < 10 ? '0' : b);
- } while (n);
-
- return p;
-}
-
/*!
\overload
@@ -4255,9 +4209,7 @@ QByteArray &QByteArray::setNum(qlonglong n, int base)
p = qulltoa2(buff + buffsize, qulonglong(n), base);
}
- clear();
- append(p, buffsize - (p - buff));
- return *this;
+ return assign(QByteArrayView{p, buff + buffsize});
}
/*!
@@ -4272,9 +4224,7 @@ QByteArray &QByteArray::setNum(qulonglong n, int base)
char buff[buffsize];
char *p = qulltoa2(buff + buffsize, n, base);
- clear();
- append(p, buffsize - (p - buff));
- return *this;
+ return assign(QByteArrayView{p, buff + buffsize});
}
/*!
@@ -5206,5 +5156,3 @@ size_t qHash(const QByteArray::FromBase64Result &key, size_t seed) noexcept
*/
QT_END_NAMESPACE
-
-#undef REHASH
diff --git a/src/corelib/text/qbytearraymatcher.cpp b/src/corelib/text/qbytearraymatcher.cpp
index ae38fb584b..a332f035ef 100644
--- a/src/corelib/text/qbytearraymatcher.cpp
+++ b/src/corelib/text/qbytearraymatcher.cpp
@@ -212,26 +212,10 @@ qsizetype QByteArrayMatcher::indexIn(QByteArrayView data, qsizetype from) const
\sa setPattern()
*/
-
-static qsizetype findChar(const char *str, qsizetype len, char ch, qsizetype from)
-{
- const uchar *s = (const uchar *)str;
- uchar c = (uchar)ch;
- if (from < 0)
- from = qMax(from + len, qsizetype(0));
- if (from < len) {
- const uchar *n = s + from - 1;
- const uchar *e = s + len;
- while (++n != e)
- if (*n == c)
- return n - s;
- }
- return -1;
-}
-
/*!
\internal
*/
+Q_NEVER_INLINE
static qsizetype qFindByteArrayBoyerMoore(
const char *haystack, qsizetype haystackLen, qsizetype haystackOffset,
const char *needle, qsizetype needleLen)
@@ -244,20 +228,19 @@ static qsizetype qFindByteArrayBoyerMoore(
(const uchar *)needle, needleLen, skiptable);
}
-#define REHASH(a) \
- if (sl_minus_1 < sizeof(std::size_t) * CHAR_BIT) \
- hashHaystack -= std::size_t(a) << sl_minus_1; \
- hashHaystack <<= 1
-
/*!
\internal
*/
-qsizetype qFindByteArray(
- const char *haystack0, qsizetype haystackLen, qsizetype from,
- const char *needle, qsizetype needleLen)
+static qsizetype qFindByteArray(const char *haystack0, qsizetype l, qsizetype from,
+ const char *needle, qsizetype sl);
+qsizetype QtPrivate::findByteArray(QByteArrayView haystack, qsizetype from, QByteArrayView needle) noexcept
{
- const auto l = haystackLen;
- const auto sl = needleLen;
+ const auto haystack0 = haystack.data();
+ const auto l = haystack.size();
+ const auto sl = needle.size();
+ if (sl == 1)
+ return findByteArray(haystack, from, needle.front());
+
if (from < 0)
from += l;
if (std::size_t(sl + from) > std::size_t(l))
@@ -267,27 +250,28 @@ qsizetype qFindByteArray(
if (!l)
return -1;
- if (sl == 1)
- return findChar(haystack0, haystackLen, needle[0], from);
-
/*
We use the Boyer-Moore algorithm in cases where the overhead
for the skip table should pay off, otherwise we use a simple
hash function.
*/
if (l > 500 && sl > 5)
- return qFindByteArrayBoyerMoore(haystack0, haystackLen, from,
- needle, needleLen);
+ return qFindByteArrayBoyerMoore(haystack0, l, from, needle.data(), sl);
+ return qFindByteArray(haystack0, l, from, needle.data(), sl);
+}
+qsizetype qFindByteArray(const char *haystack0, qsizetype l, qsizetype from,
+ const char *needle, qsizetype sl)
+{
/*
We use some hashing for efficiency's sake. Instead of
comparing strings, we compare the hash value of str with that
- of a part of this QString. Only if that matches, we call memcmp().
+ of a part of this QByteArray. Only if that matches, we call memcmp().
*/
const char *haystack = haystack0 + from;
const char *end = haystack0 + (l - sl);
- const auto sl_minus_1 = std::size_t(sl - 1);
- std::size_t hashNeedle = 0, hashHaystack = 0;
+ const qregisteruint sl_minus_1 = sl - 1;
+ qregisteruint hashNeedle = 0, hashHaystack = 0;
qsizetype idx;
for (idx = 0; idx < sl; ++idx) {
hashNeedle = ((hashNeedle<<1) + needle[idx]);
@@ -301,7 +285,9 @@ qsizetype qFindByteArray(
&& memcmp(needle, haystack, sl) == 0)
return haystack - haystack0;
- REHASH(*haystack);
+ if (sl_minus_1 < sizeof(sl_minus_1) * CHAR_BIT)
+ hashHaystack -= qregisteruint(*haystack) << sl_minus_1;
+ hashHaystack <<= 1;
++haystack;
}
return -1;
@@ -409,7 +395,4 @@ qsizetype QStaticByteArrayMatcherBase::indexOfIn(const char *needle, size_t nlen
\snippet code/src_corelib_text_qbytearraymatcher.cpp 1
*/
-
QT_END_NAMESPACE
-
-#undef REHASH
diff --git a/src/corelib/text/qlocale.cpp b/src/corelib/text/qlocale.cpp
index ab95b300eb..86ab072b73 100644
--- a/src/corelib/text/qlocale.cpp
+++ b/src/corelib/text/qlocale.cpp
@@ -4760,6 +4760,11 @@ QStringList QLocale::uiLanguages(TagSeparator separator) const
const bool isSystem = d->m_data == &systemLocaleData;
if (isSystem) {
uiLanguages = systemLocale()->query(QSystemLocale::UILanguages).toStringList();
+ if (separator != TagSeparator::Dash) {
+ // Map from default separator, Dash, used by backends:
+ const QChar join = QLatin1Char(sep);
+ uiLanguages = uiLanguages.replaceInStrings(u"-", QStringView(&join, 1));
+ }
// ... but we need to include likely-adjusted forms of each of those, too.
// For now, collect up locale Ids representing the entries, for later processing:
for (const auto &entry : std::as_const(uiLanguages))
diff --git a/src/corelib/text/qlocale_tools.cpp b/src/corelib/text/qlocale_tools.cpp
index b6639bcb71..52124672ca 100644
--- a/src/corelib/text/qlocale_tools.cpp
+++ b/src/corelib/text/qlocale_tools.cpp
@@ -552,6 +552,18 @@ QString qulltoa(qulonglong number, int base, const QStringView zero)
return QString(reinterpret_cast<QChar *>(p), end - p);
}
+char *qulltoa2(char *p, qulonglong n, int base)
+{
+#if defined(QT_CHECK_RANGE)
+ if (base < 2 || base > 36) {
+ qWarning("QByteArray::setNum: Invalid base %d", base);
+ base = 10;
+ }
+#endif
+ qulltoString_helper(n, base, p);
+ return p;
+}
+
/*!
\internal
@@ -795,4 +807,78 @@ QByteArray qdtoAscii(double d, QLocaleData::DoubleForm form, int precision, bool
return dtoString<QByteArray>(d, form, precision, uppercase);
}
+#if defined(QT_SUPPORTS_INT128) || (defined(Q_CC_MSVC) && (_MSC_VER >= 1930))
+static inline quint64 toUInt64(qinternaluint128 v)
+{
+#ifdef Q_CC_MSVC
+ return quint64(v._Word[0]);
+#else
+ return quint64(v);
+#endif
+}
+QString quint128toBasicLatin(qinternaluint128 number, int base)
+{
+ // We divide our 128-bit number into parts that we can do text
+ // concatenation with. This list is the maximum power of the
+ // base that is less than 2^64.
+ static constexpr auto dividers = []() constexpr {
+ std::array<quint64, 35> bases {};
+ for (int base = 2; base <= 36; ++base) {
+ quint64 v = base;
+ while (v * base > v)
+ v *= base;
+ bases[base - 2] = v;
+ }
+ return bases;
+ }();
+ static constexpr auto digitCounts = []() constexpr {
+ std::array<quint8, 35> digits{};
+ for (int base = 2; base <= 36; ++base) {
+ quint64 v = base;
+ int i = 0;
+ for (i = 0; v * base > v; ++i)
+ v *= base;
+ digits[base - 2] = i;
+ }
+ return digits;
+ }();
+
+ QString result;
+
+ constexpr unsigned flags = QLocaleData::NoFlags;
+ const QLocaleData *dd = QLocaleData::c();
+
+ // special base cases:
+ constexpr int Width = -1;
+ if (base == 2 || base == 4 || base == 16) {
+ // 2^64 is a power of 2, 4 and 16
+ result = dd->unsLongLongToString(quint64(number), 64, base, Width, flags);
+ result.prepend(dd->unsLongLongToString(quint64(number >> 64), -1, base, Width, flags));
+ } else {
+ int digitCount = digitCounts[base - 2];
+ quint64 divider = dividers[base - 2];
+ quint64 lower = toUInt64(number % divider);
+ number /= divider;
+ while (number) {
+ result.prepend(dd->unsLongLongToString(lower, digitCount, base, Width, flags));
+ lower = toUInt64(number % divider);
+ number /= divider;
+ }
+ result.prepend(dd->unsLongLongToString(lower, -1, base, Width, flags));
+ }
+ return result;
+}
+
+QString qint128toBasicLatin(qinternalint128 number, int base)
+{
+ const bool negative = number < 0;
+ if (negative)
+ number *= -1;
+ QString result = quint128toBasicLatin(qinternaluint128(number), base);
+ if (negative)
+ result.prepend(u'-');
+ return result;
+}
+#endif // defined(QT_SUPPORTS_INT128) || (defined(Q_CC_MSVC) && (_MSC_VER >= 1930))
+
QT_END_NAMESPACE
diff --git a/src/corelib/text/qlocale_tools_p.h b/src/corelib/text/qlocale_tools_p.h
index 9b02403ea4..ef1e156f50 100644
--- a/src/corelib/text/qlocale_tools_p.h
+++ b/src/corelib/text/qlocale_tools_p.h
@@ -20,6 +20,15 @@
QT_BEGIN_NAMESPACE
+#if defined(QT_SUPPORTS_INT128)
+using qinternalint128 = qint128;
+using qinternaluint128 = quint128;
+#elif defined(Q_CC_MSVC) && (_MSC_VER >= 1930)
+#include <__msvc_int128.hpp>
+using qinternalint128 = std::_Signed128;
+using qinternaluint128 = std::_Unsigned128;
+#endif
+
enum StrayCharacterMode {
TrailingJunkProhibited,
TrailingJunkAllowed,
@@ -36,12 +45,20 @@ void qt_doubleToAscii(double d, QLocaleData::DoubleForm form, int precision,
[[nodiscard]] QString qulltoBasicLatin(qulonglong l, int base, bool negative);
[[nodiscard]] QString qulltoa(qulonglong l, int base, const QStringView zero);
+[[nodiscard]] char *qulltoa2(char *p, qulonglong n, int base);
[[nodiscard]] Q_CORE_EXPORT QString qdtoa(qreal d, int *decpt, int *sign);
[[nodiscard]] QString qdtoBasicLatin(double d, QLocaleData::DoubleForm form,
int precision, bool uppercase);
[[nodiscard]] QByteArray qdtoAscii(double d, QLocaleData::DoubleForm form,
int precision, bool uppercase);
+#if defined(QT_SUPPORTS_INT128) || (defined(Q_CC_MSVC) && (_MSC_VER >= 1930))
+[[nodiscard]] Q_CORE_EXPORT QString quint128toBasicLatin(qinternaluint128 number,
+ int base = 10);
+[[nodiscard]] Q_CORE_EXPORT QString qint128toBasicLatin(qinternalint128 number,
+ int base = 10);
+#endif
+
[[nodiscard]] constexpr inline bool isZero(double d)
{
return d == 0; // Amusingly, compilers do not grumble.
diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp
index f0bf0c50a3..4d9e60c995 100644
--- a/src/corelib/text/qstring.cpp
+++ b/src/corelib/text/qstring.cpp
@@ -63,8 +63,8 @@
#endif
#define REHASH(a) \
- if (sl_minus_1 < sizeof(std::size_t) * CHAR_BIT) \
- hashHaystack -= std::size_t(a) << sl_minus_1; \
+ if (sl_minus_1 < sizeof(sl_minus_1) * CHAR_BIT) \
+ hashHaystack -= decltype(hashHaystack)(a) << sl_minus_1; \
hashHaystack <<= 1
QT_BEGIN_NAMESPACE
@@ -183,10 +183,10 @@ static qsizetype qLastIndexOf(Haystack haystack0, qsizetype from,
const auto needle = needle0.data();
const auto *end = haystack;
haystack += from;
- const std::size_t sl_minus_1 = sl ? sl - 1 : 0;
+ const qregisteruint sl_minus_1 = sl ? sl - 1 : 0;
const auto *n = needle + sl_minus_1;
const auto *h = haystack + sl_minus_1;
- std::size_t hashNeedle = 0, hashHaystack = 0;
+ qregisteruint hashNeedle = 0, hashHaystack = 0;
if (cs == Qt::CaseSensitive) {
for (qsizetype idx = 0; idx < sl; ++idx) {
@@ -9241,9 +9241,6 @@ static qsizetype resolveStringRefsAndReturnTotalSize(ParseResult &parts, const A
} // unnamed namespace
-Q_ALWAYS_INLINE QString to_string(QLatin1StringView s) noexcept { return s; }
-Q_ALWAYS_INLINE QString to_string(QStringView s) noexcept { return s.toString(); }
-
template <typename StringView>
static QString argToQStringImpl(StringView pattern, size_t numArgs, const QtPrivate::ArgBase **args)
{
@@ -9257,7 +9254,7 @@ static QString argToQStringImpl(StringView pattern, size_t numArgs, const QtPriv
argIndexToPlaceholderMap.resize(qsizetype(numArgs));
else if (Q_UNLIKELY(static_cast<size_t>(argIndexToPlaceholderMap.size()) < numArgs)) // 3b
qWarning("QString::arg: %d argument(s) missing in %ls",
- int(numArgs - argIndexToPlaceholderMap.size()), qUtf16Printable(to_string(pattern)));
+ int(numArgs - argIndexToPlaceholderMap.size()), qUtf16Printable(pattern.toString()));
// 5
const qsizetype totalSize = resolveStringRefsAndReturnTotalSize(parts, argIndexToPlaceholderMap, args);
@@ -9905,8 +9902,8 @@ qsizetype QtPrivate::findString(QStringView haystack0, qsizetype from, QStringVi
const char16_t *needle = needle0.utf16();
const char16_t *haystack = haystack0.utf16() + from;
const char16_t *end = haystack0.utf16() + (l - sl);
- const std::size_t sl_minus_1 = sl - 1;
- std::size_t hashNeedle = 0, hashHaystack = 0;
+ const qregisteruint sl_minus_1 = sl - 1;
+ qregisteruint hashNeedle = 0, hashHaystack = 0;
qsizetype idx;
if (cs == Qt::CaseSensitive) {
diff --git a/src/corelib/thread/qfutureinterface.h b/src/corelib/thread/qfutureinterface.h
index 180a59a94e..ea7d40ad90 100644
--- a/src/corelib/thread/qfutureinterface.h
+++ b/src/corelib/thread/qfutureinterface.h
@@ -465,6 +465,9 @@ std::vector<T> QFutureInterface<T>::takeResults()
}
#endif
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_CLANG("-Wweak-vtables") // QTBUG-125115
+
template <>
class QFutureInterface<void> : public QFutureInterfaceBase
{
@@ -495,6 +498,8 @@ public:
}
};
+QT_WARNING_POP // Clang -Wweak-vtables
+
template<typename T>
inline void swap(QFutureInterface<T> &a, QFutureInterface<T> &b) noexcept
{
diff --git a/src/corelib/thread/qresultstore.cpp b/src/corelib/thread/qresultstore.cpp
index 14ed7c6b87..8b7601f5b0 100644
--- a/src/corelib/thread/qresultstore.cpp
+++ b/src/corelib/thread/qresultstore.cpp
@@ -88,16 +88,6 @@ void ResultIteratorBase::batchedAdvance()
m_vectorIndex = 0;
}
-bool ResultIteratorBase::operator==(const ResultIteratorBase &other) const
-{
- return (mapIterator == other.mapIterator && m_vectorIndex == other.m_vectorIndex);
-}
-
-bool ResultIteratorBase::operator!=(const ResultIteratorBase &other) const
-{
- return !operator==(other);
-}
-
bool ResultIteratorBase::isVector() const
{
return mapIterator.value().isVector();
diff --git a/src/corelib/thread/qresultstore.h b/src/corelib/thread/qresultstore.h
index 30ce1fe904..f21068206f 100644
--- a/src/corelib/thread/qresultstore.h
+++ b/src/corelib/thread/qresultstore.h
@@ -46,12 +46,21 @@ public:
ResultIteratorBase operator++();
int batchSize() const;
void batchedAdvance();
+#if QT_CORE_REMOVED_SINCE(6, 8)
bool operator==(const ResultIteratorBase &other) const;
bool operator!=(const ResultIteratorBase &other) const;
+#endif
bool isVector() const;
bool canIncrementVectorIndex() const;
bool isValid() const;
+private:
+ friend bool comparesEqual(const ResultIteratorBase &lhs,
+ const ResultIteratorBase &rhs) noexcept
+ {
+ return (lhs.mapIterator == rhs.mapIterator && lhs.m_vectorIndex == rhs.m_vectorIndex);
+ }
+ Q_DECLARE_EQUALITY_COMPARABLE(ResultIteratorBase)
protected:
QMap<int, ResultItem>::const_iterator mapIterator;
int m_vectorIndex;
diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp
index 556f05018f..44487a2cc2 100644
--- a/src/corelib/thread/qthread_unix.cpp
+++ b/src/corelib/thread/qthread_unix.cpp
@@ -282,9 +282,13 @@ void *QThreadPrivate::start(void *arg)
#ifdef PTHREAD_CANCEL_DISABLE
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, nullptr);
#endif
-#if !defined(Q_OS_QNX)
+#if !defined(Q_OS_QNX) && !defined(Q_OS_VXWORKS)
// On QNX, calling finish() from a thread_local destructor causes the C
// library to hang.
+ // On VxWorks, its pthread implementation fails on call to `pthead_setspecific` which is made
+ // by first QObject constructor during `finish()`. This causes call to QThread::current, since
+ // QObject doesn't have parent, and since the pthread is already removed, it tries to set
+ // QThreadData for current pthread key, which crashes.
static thread_local
#endif
auto cleanup = qScopeGuard([=] { finish(arg); });
diff --git a/src/corelib/time/qtimezone.cpp b/src/corelib/time/qtimezone.cpp
index 3a68277a6c..7dd5dbf423 100644
--- a/src/corelib/time/qtimezone.cpp
+++ b/src/corelib/time/qtimezone.cpp
@@ -455,10 +455,17 @@ QTimeZone::QTimeZone(const QByteArray &ianaId)
d = new QUtcTimeZonePrivate(ianaId);
// If not recognized, try creating it with the system backend.
if (!d->isValid()) {
- if (ianaId.isEmpty())
+ if (ianaId.isEmpty()) {
d = newBackendTimeZone();
- else // Constructor MUST produce invalid for unsupported ID.
+ } else { // Constructor MUST produce invalid for unsupported ID.
d = newBackendTimeZone(ianaId);
+ if (!d->isValid()) {
+ // We may have a legacy alias for a supported IANA ID:
+ const QByteArray name = QTimeZonePrivate::aliasToIana(ianaId);
+ if (!name.isEmpty() && name != ianaId)
+ d = newBackendTimeZone(name);
+ }
+ }
}
// Can also handle UTC with arbitrary (valid) offset, but only do so as
// fall-back, since either of the above may handle it more informatively.
diff --git a/src/corelib/time/qtimezonelocale.cpp b/src/corelib/time/qtimezonelocale.cpp
index 5757e55d28..cf3a84b317 100644
--- a/src/corelib/time/qtimezonelocale.cpp
+++ b/src/corelib/time/qtimezonelocale.cpp
@@ -4,7 +4,9 @@
#include <private/qtimezonelocale_p.h>
#include <private/qtimezoneprivate_p.h>
-#if !QT_CONFIG(icu) // Use data generated from CLDR:
+#if !QT_CONFIG(icu)
+# include <private/qdatetime_p.h>
+// Use data generated from CLDR:
# include <private/qtimezonelocale_data_p.h>
# include <private/qtimezoneprivate_data_p.h>
#endif
@@ -12,9 +14,90 @@
QT_BEGIN_NAMESPACE
#if QT_CONFIG(icu) // Get data from ICU:
+namespace {
+
+// Convert TimeType and NameType into ICU UCalendarDisplayNameType
+constexpr UCalendarDisplayNameType ucalDisplayNameType(QTimeZone::TimeType timeType,
+ QTimeZone::NameType nameType)
+{
+ // TODO ICU C UCalendarDisplayNameType does not support full set of C++ TimeZone::EDisplayType
+ // For now, treat Generic as Standard
+ switch (nameType) {
+ case QTimeZone::OffsetName:
+ Q_UNREACHABLE(); // Callers of ucalTimeZoneDisplayName() should take care of OffsetName.
+ case QTimeZone::ShortName:
+ return timeType == QTimeZone::DaylightTime ? UCAL_SHORT_DST : UCAL_SHORT_STANDARD;
+ case QTimeZone::DefaultName:
+ case QTimeZone::LongName:
+ return timeType == QTimeZone::DaylightTime ? UCAL_DST : UCAL_STANDARD;
+ }
+ Q_UNREACHABLE_RETURN(UCAL_STANDARD);
+}
+
+} // nameless namespace
+
namespace QtTimeZoneLocale {
+// Qt wrapper around ucal_getTimeZoneDisplayName()
+// Used directly by ICU backend; indirectly by TZ (see below).
+QString ucalTimeZoneDisplayName(UCalendar *ucal,
+ QTimeZone::TimeType timeType,
+ QTimeZone::NameType nameType,
+ const QByteArray &localeCode)
+{
+ constexpr int32_t BigNameLength = 50;
+ int32_t size = BigNameLength;
+ QString result(size, Qt::Uninitialized);
+ auto dst = [&result]() { return reinterpret_cast<UChar *>(result.data()); };
+ UErrorCode status = U_ZERO_ERROR;
+ const UCalendarDisplayNameType utype = ucalDisplayNameType(timeType, nameType);
+
+ // size = ucal_getTimeZoneDisplayName(cal, type, locale, result, resultLength, status)
+ size = ucal_getTimeZoneDisplayName(ucal, utype, localeCode.constData(),
+ dst(), size, &status);
+
+ // If overflow, then resize and retry
+ if (size > BigNameLength || status == U_BUFFER_OVERFLOW_ERROR) {
+ result.resize(size);
+ status = U_ZERO_ERROR;
+ size = ucal_getTimeZoneDisplayName(ucal, utype, localeCode.constData(),
+ dst(), size, &status);
+ }
+
+ if (!U_SUCCESS(status))
+ return QString();
+
+ // Resize and return:
+ result.resize(size);
+ return result;
+}
+
} // QtTimeZoneLocale
+
+// Used by TZ backends when ICU is available:
+QString QTimeZonePrivate::localeName(qint64 atMSecsSinceEpoch, int offsetFromUtc,
+ QTimeZone::TimeType timeType,
+ QTimeZone::NameType nameType,
+ const QLocale &locale) const
+{
+ Q_UNUSED(atMSecsSinceEpoch);
+ // TODO: use CLDR data for the offset name.
+ // No ICU API for offset formats, so fall back to our ISO one, even if
+ // locale isn't C:
+ if (nameType == QTimeZone::OffsetName)
+ return isoOffsetFormat(offsetFromUtc);
+
+ const QString id = QString::fromUtf8(m_id);
+ const QByteArray loc = locale.name().toUtf8();
+ UErrorCode status = U_ZERO_ERROR;
+ UCalendar *ucal = ucal_open(reinterpret_cast<const UChar *>(id.data()), id.size(),
+ loc.constData(), UCAL_DEFAULT, &status);
+ if (ucal && U_SUCCESS(status)) {
+ auto tidier = qScopeGuard([ucal]() { ucal_close(ucal); });
+ return QtTimeZoneLocale::ucalTimeZoneDisplayName(ucal, timeType, nameType, loc);
+ }
+ return QString();
+}
#else // No ICU, use QTZ[LP}_data_p.h data for feature timezone_locale.
namespace {
using namespace QtTimeZoneLocale; // QTZL_data_p.h
@@ -24,6 +107,20 @@ using namespace QtTimeZoneCldr; // QTZP_data_p.h
// Accessors for the QTZP_data_p.h
} // nameless namespace
+
+QString QTimeZonePrivate::localeName(qint64 atMSecsSinceEpoch, int offsetFromUtc,
+ QTimeZone::TimeType timeType,
+ QTimeZone::NameType nameType,
+ const QLocale &locale) const
+{
+ Q_ASSERT(nameType != QTimeZone::OffsetName || locale.language() != QLocale::C);
+ // Get data from QTZ[LP]_data_p.h
+
+ Q_UNUSED(atMSecsSinceEpoch);
+ Q_UNUSED(offsetFromUtc);
+ Q_UNUSED(timeType);
+ return QString();
+}
#endif // ICU
QT_END_NAMESPACE
diff --git a/src/corelib/time/qtimezonelocale_p.h b/src/corelib/time/qtimezonelocale_p.h
index adc8e83b35..6e6c6b51fd 100644
--- a/src/corelib/time/qtimezonelocale_p.h
+++ b/src/corelib/time/qtimezonelocale_p.h
@@ -14,18 +14,31 @@
//
// We mean it.
//
+#include <private/qglobal_p.h>
+#include <QtCore/qstring.h>
#include <QtCore/qtimezone.h>
+#if QT_CONFIG(icu)
+#include <unicode/ucal.h>
+#endif
+
QT_REQUIRE_CONFIG(timezone);
QT_REQUIRE_CONFIG(timezone_locale);
+QT_BEGIN_NAMESPACE
+
namespace QtTimeZoneLocale {
#if QT_CONFIG(icu)
+QString ucalTimeZoneDisplayName(UCalendar *ucal, QTimeZone::TimeType timeType,
+ QTimeZone::NameType nameType,
+ const QString &localeCode);
#else
// Define data types for QTZL_data_p.h
#endif
}
+QT_END_NAMESPACE
+
#endif // QTIMEZONELOCALE_P_H
diff --git a/src/corelib/time/qtimezoneprivate.cpp b/src/corelib/time/qtimezoneprivate.cpp
index 2ad0d874b6..4c01d095c4 100644
--- a/src/corelib/time/qtimezoneprivate.cpp
+++ b/src/corelib/time/qtimezoneprivate.cpp
@@ -5,6 +5,9 @@
#include "qtimezone.h"
#include "qtimezoneprivate_p.h"
+#if QT_CONFIG(timezone_locale)
+# include "qtimezonelocale_p.h"
+#endif
#include "qtimezoneprivate_data_p.h"
#include <qdatastream.h>
@@ -51,6 +54,11 @@ constexpr bool atLowerWindowsKey(const WindowsData &entry, qint16 winIdKey) noex
return entry.windowsIdKey < winIdKey;
}
+static bool earlierAliasId(const AliasData &entry, QByteArrayView aliasId) noexcept
+{
+ return entry.aliasId().compare(aliasId, Qt::CaseInsensitive) < 0;
+}
+
static bool earlierWindowsId(const WindowsData &entry, QByteArrayView winId) noexcept
{
return entry.windowsId().compare(winId, Qt::CaseInsensitive) < 0;
@@ -172,22 +180,37 @@ QString QTimeZonePrivate::displayName(qint64 atMSecsSinceEpoch,
QTimeZone::NameType nameType,
const QLocale &locale) const
{
- if (nameType == QTimeZone::OffsetName)
- return isoOffsetFormat(offsetFromUtc(atMSecsSinceEpoch));
-
- if (isDaylightTime(atMSecsSinceEpoch))
- return displayName(QTimeZone::DaylightTime, nameType, locale);
- else
- return displayName(QTimeZone::StandardTime, nameType, locale);
+ const Data tran = data(atMSecsSinceEpoch);
+ if (tran.atMSecsSinceEpoch != invalidMSecs()) {
+ if (nameType == QTimeZone::OffsetName && locale.language() == QLocale::C)
+ return isoOffsetFormat(tran.offsetFromUtc);
+ if (nameType == QTimeZone::ShortName && isDataLocale(locale))
+ return tran.abbreviation;
+
+ QTimeZone::TimeType timeType
+ = tran.daylightTimeOffset != 0 ? QTimeZone::DaylightTime : QTimeZone::StandardTime;
+#if QT_CONFIG(timezone_locale)
+ return localeName(atMSecsSinceEpoch, tran.offsetFromUtc, timeType, nameType, locale);
+#else
+ return displayName(timeType, nameType, locale);
+#endif
+ }
+ return QString();
}
QString QTimeZonePrivate::displayName(QTimeZone::TimeType timeType,
QTimeZone::NameType nameType,
const QLocale &locale) const
{
- Q_UNUSED(timeType);
- Q_UNUSED(nameType);
- Q_UNUSED(locale);
+ const Data tran = data(timeType);
+ if (tran.atMSecsSinceEpoch != invalidMSecs()) {
+ if (nameType == QTimeZone::OffsetName && isDataLocale(locale))
+ return isoOffsetFormat(tran.offsetFromUtc);
+
+#if QT_CONFIG(timezone_locale)
+ return localeName(tran.atMSecsSinceEpoch, tran.offsetFromUtc, timeType, nameType, locale);
+#endif
+ }
return QString();
}
@@ -227,6 +250,56 @@ bool QTimeZonePrivate::isDaylightTime(qint64 atMSecsSinceEpoch) const
return false;
}
+QTimeZonePrivate::Data QTimeZonePrivate::data(QTimeZone::TimeType timeType) const
+{
+ // True if tran is valid and has the DST-ness to match timeType:
+ const auto validMatch = [timeType](const QTimeZonePrivate::Data &tran) {
+ return tran.atMSecsSinceEpoch != invalidMSecs()
+ && ((timeType == QTimeZone::DaylightTime) != (tran.daylightTimeOffset == 0));
+ };
+
+ // Get current tran, use if suitable:
+ const qint64 currentMSecs = QDateTime::currentMSecsSinceEpoch();
+ QTimeZonePrivate::Data tran = data(currentMSecs);
+ if (validMatch(tran))
+ return tran;
+
+ if (hasTransitions()) {
+ // Otherwise, next tran probably flips DST-ness:
+ tran = nextTransition(currentMSecs);
+ if (validMatch(tran))
+ return tran;
+
+ // Failing that, prev (or present, if current MSecs is exactly a
+ // transition moment) tran defines what data() got us and the one before
+ // that probably flips DST-ness; failing that, keep marching backwards
+ // in search of a DST interval:
+ tran = previousTransition(currentMSecs + 1);
+ while (tran.atMSecsSinceEpoch != invalidMSecs()) {
+ tran = previousTransition(tran.atMSecsSinceEpoch);
+ if (validMatch(tran))
+ return tran;
+ }
+ }
+ return {};
+}
+
+/*!
+ \internal
+
+ Returns true if the abbreviation given in data()'s returns is appropriate
+ for use in the given \a locale.
+
+ Base implementation assumes data() corresponds to the system locale; derived
+ classes should override if their data() is something else (such as
+ C/English).
+*/
+bool QTimeZonePrivate::isDataLocale(const QLocale &locale) const
+{
+ // Guess data is for the system locale unless backend overrides that.
+ return locale == QLocale::system();
+}
+
QTimeZonePrivate::Data QTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const
{
Q_UNUSED(forMSecsSinceEpoch);
@@ -701,6 +774,15 @@ QString QTimeZonePrivate::isoOffsetFormat(int offsetFromUtc, QTimeZone::NameType
return result;
}
+QByteArray QTimeZonePrivate::aliasToIana(QByteArrayView alias)
+{
+ const auto data = std::lower_bound(std::begin(aliasMappingTable), std::end(aliasMappingTable),
+ alias, earlierAliasId);
+ if (data != std::end(aliasMappingTable) && data->aliasId() == alias)
+ return data->ianaId().toByteArray();
+ return {};
+}
+
QByteArray QTimeZonePrivate::ianaIdToWindowsId(const QByteArray &id)
{
const auto idUtf8 = QUtf8StringView(id);
@@ -906,6 +988,19 @@ QTimeZonePrivate::Data QUtcTimeZonePrivate::data(qint64 forMSecsSinceEpoch) cons
return d;
}
+// Override to shortcut past base's complications:
+QTimeZonePrivate::Data QUtcTimeZonePrivate::data(QTimeZone::TimeType timeType) const
+{
+ Q_UNUSED(timeType);
+ return data(QDateTime::currentMSecsSinceEpoch());
+}
+
+bool QUtcTimeZonePrivate::isDataLocale(const QLocale &locale) const
+{
+ // Officially only supports C locale names; these are surely also viable for English.
+ return locale.language() == QLocale::C || locale.language() == QLocale::English;
+}
+
void QUtcTimeZonePrivate::init(const QByteArray &zoneId)
{
m_id = zoneId;
@@ -933,6 +1028,15 @@ QString QUtcTimeZonePrivate::comment() const
return m_comment;
}
+// Override to bypass complications in base-class:
+QString QUtcTimeZonePrivate::displayName(qint64 atMSecsSinceEpoch,
+ QTimeZone::NameType nameType,
+ const QLocale &locale) const
+{
+ Q_UNUSED(atMSecsSinceEpoch);
+ return displayName(QTimeZone::StandardTime, nameType, locale);
+}
+
QString QUtcTimeZonePrivate::displayName(QTimeZone::TimeType timeType,
QTimeZone::NameType nameType,
const QLocale &locale) const
diff --git a/src/corelib/time/qtimezoneprivate_data_p.h b/src/corelib/time/qtimezoneprivate_data_p.h
index 5174f06a0d..794dd36b40 100644
--- a/src/corelib/time/qtimezoneprivate_data_p.h
+++ b/src/corelib/time/qtimezoneprivate_data_p.h
@@ -25,7 +25,7 @@ QT_BEGIN_NAMESPACE
namespace QtTimeZoneCldr {
/*
- Recognized UTC-offset zones and CLDR-derived data on Windows IDs.
+ Recognized UTC-offset zones and CLDR-derived data on timezone IDs.
The UTC-offset zone table is provided for generic UTC±HH:mm format time
zones. The UTC backend can support arbitrary offsets in seconds, but only
@@ -44,6 +44,17 @@ namespace QtTimeZoneCldr {
of its last update and how to update it.
*/
+struct AliasData
+{
+ // Table is sorted on aliasId(), then on ianaId().
+ // Indices in alias table, not IANA (group) table
+ quint16 aliasIdIndex;
+ quint16 ianaIdIndex;
+ // Values for the actual IDs:
+ constexpr QByteArrayView aliasId() const;
+ constexpr QByteArrayView ianaId() const;
+};
+
struct ZoneData
{
// Keys (table is sorted in Windows ID, then on territory enum value):
@@ -77,8 +88,8 @@ struct UtcData
// GENERATED PART STARTS HERE
/*
- This part of the file was generated on 2024-01-29 from the
- Common Locale Data Repository v43 file supplemental/windowsZones.xml
+ This part of the file was generated on 2024-02-06 from the
+ Common Locale Data Repository v43
http://www.unicode.org/cldr/
@@ -86,6 +97,144 @@ struct UtcData
edited) CLDR data; see qtbase/util/locale_database/.
*/
+// Alias ID Index, IANA ID Index
+static constexpr AliasData aliasMappingTable[] = {
+ { 0, 14 }, // Africa/Asmara -> Africa/Asmera
+ { 28, 44 }, // Africa/Timbuktu -> Africa/Bamako
+ { 58, 89 }, // America/Argentina/Buenos_Aires -> America/Buenos_Aires
+ { 110, 138 }, // America/Argentina/Catamarca -> America/Catamarca
+ { 156, 138 }, // America/Argentina/ComodRivadavia -> America/Catamarca
+ { 189, 215 }, // America/Argentina/Cordoba -> America/Cordoba
+ { 231, 255 }, // America/Argentina/Jujuy -> America/Jujuy
+ { 269, 295 }, // America/Argentina/Mendoza -> America/Mendoza
+ { 311, 328 }, // America/Atikokan -> America/Coral_Harbour
+ { 350, 363 }, // America/Atka -> America/Adak
+ { 376, 393 }, // America/Ensenada -> America/Tijuana
+ { 409, 428 }, // America/Fort_Wayne -> America/Indianapolis
+ { 449, 428 }, // America/Indiana/Indianapolis -> America/Indianapolis
+ { 478, 506 }, // America/Kentucky/Louisville -> America/Louisville
+ { 525, 541 }, // America/Knox_IN -> America/Indiana/Knox
+ { 562, 579 }, // America/Montreal -> America/Toronto
+ { 595, 608 }, // America/Nuuk -> America/Godthab
+ { 624, 643 }, // America/Porto_Acre -> America/Rio_Branco
+ { 662, 215 }, // America/Rosario -> America/Cordoba
+ { 678, 695 }, // America/Shiprock -> America/Denver
+ { 710, 725 }, // America/Virgin -> America/St_Thomas
+ { 743, 765 }, // Antarctica/South_Pole -> Pacific/Auckland
+ { 782, 797 }, // Asia/Ashkhabad -> Asia/Ashgabat
+ { 811, 826 }, // Asia/Chongqing -> Asia/Shanghai
+ { 840, 826 }, // Asia/Chungking -> Asia/Shanghai
+ { 855, 866 }, // Asia/Dacca -> Asia/Dhaka
+ { 877, 826 }, // Asia/Harbin -> Asia/Shanghai
+ { 889, 906 }, // Asia/Ho_Chi_Minh -> Asia/Saigon
+ { 918, 932 }, // Asia/Istanbul -> Europe/Istanbul
+ { 948, 961 }, // Asia/Kashgar -> Asia/Urumqi
+ { 973, 988 }, // Asia/Kathmandu -> Asia/Katmandu
+ { 1002, 1015 }, // Asia/Kolkata -> Asia/Calcutta
+ { 1029, 1040 }, // Asia/Macao -> Asia/Macau
+ { 1051, 1065 }, // Asia/Tel_Aviv -> Asia/Jerusalem
+ { 1080, 1092 }, // Asia/Thimbu -> Asia/Thimphu
+ { 1105, 1124 }, // Asia/Ujung_Pandang -> Asia/Makassar
+ { 1138, 1154 }, // Asia/Ulan_Bator -> Asia/Ulaanbaatar
+ { 1171, 1183 }, // Asia/Yangon -> Asia/Rangoon
+ { 1196, 1211 }, // Atlantic/Faroe -> Atlantic/Faeroe
+ { 1227, 1246 }, // Atlantic/Jan_Mayen -> Arctic/Longyearbyen
+ { 1266, 1280 }, // Australia/ACT -> Australia/Sydney
+ { 1297, 1280 }, // Australia/Canberra -> Australia/Sydney
+ { 1316, 1330 }, // Australia/LHI -> Australia/Lord_Howe
+ { 1350, 1280 }, // Australia/NSW -> Australia/Sydney
+ { 1364, 1380 }, // Australia/North -> Australia/Darwin
+ { 1397, 1418 }, // Australia/Queensland -> Australia/Brisbane
+ { 1437, 1453 }, // Australia/South -> Australia/Adelaide
+ { 1472, 1491 }, // Australia/Tasmania -> Australia/Hobart
+ { 1508, 1527 }, // Australia/Victoria -> Australia/Melbourne
+ { 1547, 1562 }, // Australia/West -> Australia/Perth
+ { 1578, 1599 }, // Australia/Yancowinna -> Australia/Broken_Hill
+ { 1621, 643 }, // Brazil/Acre -> America/Rio_Branco
+ { 1633, 1650 }, // Brazil/DeNoronha -> America/Noronha
+ { 1666, 1678 }, // Brazil/East -> America/Sao_Paulo
+ { 1696, 1708 }, // Brazil/West -> America/Manaus
+ { 1723, 1739 }, // Canada/Atlantic -> America/Halifax
+ { 1755, 1770 }, // Canada/Central -> America/Winnipeg
+ { 1787, 1812 }, // Canada/East-Saskatchewan -> America/Regina
+ { 1827, 579 }, // Canada/Eastern -> America/Toronto
+ { 1842, 1858 }, // Canada/Mountain -> America/Edmonton
+ { 1875, 1895 }, // Canada/Newfoundland -> America/St_Johns
+ { 1912, 1927 }, // Canada/Pacific -> America/Vancouver
+ { 1945, 1812 }, // Canada/Saskatchewan -> America/Regina
+ { 1965, 1978 }, // Canada/Yukon -> America/Whitehorse
+ { 1997, 2015 }, // Chile/Continental -> America/Santiago
+ { 2032, 2051 }, // Chile/EasterIsland -> Pacific/Easter
+ { 2066, 2071 }, // Cuba -> America/Havana
+ { 2086, 2090 }, // EST -> Etc/GMT+5
+ { 2100, 2106 }, // Egypt -> Africa/Cairo
+ { 2119, 2124 }, // Eire -> Europe/Dublin
+ { 2138, 2148 }, // Etc/GMT+0 -> Etc/GMT
+ { 2156, 2148 }, // Etc/GMT-0 -> Etc/GMT
+ { 2166, 2148 }, // Etc/GMT0 -> Etc/GMT
+ { 2175, 2148 }, // Etc/Greenwich -> Etc/GMT
+ { 2189, 2197 }, // Etc/UCT -> Etc/UTC
+ { 2205, 2197 }, // Etc/Universal -> Etc/UTC
+ { 2219, 2197 }, // Etc/Zulu -> Etc/UTC
+ { 2228, 2243 }, // Europe/Belfast -> Europe/London
+ { 2257, 2269 }, // Europe/Kyiv -> Europe/Kiev
+ { 2281, 2296 }, // Europe/Nicosia -> Asia/Nicosia
+ { 2309, 2325 }, // Europe/Tiraspol -> Europe/Chisinau
+ { 2341, 2243 }, // GB -> Europe/London
+ { 2344, 2243 }, // GB-Eire -> Europe/London
+ { 2352, 2148 }, // GMT -> Etc/GMT
+ { 2356, 2148 }, // GMT+0 -> Etc/GMT
+ { 2362, 2148 }, // GMT-0 -> Etc/GMT
+ { 2368, 2148 }, // GMT0 -> Etc/GMT
+ { 2373, 2148 }, // Greenwich -> Etc/GMT
+ { 2383, 2387 }, // HST -> Etc/GMT+10
+ { 2398, 2407 }, // Hongkong -> Asia/Hong_Kong
+ { 2422, 2430 }, // Iceland -> Atlantic/Reykjavik
+ { 2449, 2454 }, // Iran -> Asia/Tehran
+ { 2466, 1065 }, // Israel -> Asia/Jerusalem
+ { 2473, 2481 }, // Jamaica -> America/Jamaica
+ { 2497, 2503 }, // Japan -> Asia/Tokyo
+ { 2514, 2524 }, // Kwajalein -> Pacific/Kwajalein
+ { 2542, 2548 }, // Libya -> Africa/Tripoli
+ { 2563, 2567 }, // MST -> Etc/GMT+7
+ { 2577, 393 }, // Mexico/BajaNorte -> America/Tijuana
+ { 2594, 2609 }, // Mexico/BajaSur -> America/Mazatlan
+ { 2626, 2641 }, // Mexico/General -> America/Mexico_City
+ { 2661, 765 }, // NZ -> Pacific/Auckland
+ { 2664, 2672 }, // NZ-CHAT -> Pacific/Chatham
+ { 2688, 695 }, // Navajo -> America/Denver
+ { 2695, 826 }, // PRC -> Asia/Shanghai
+ { 2699, 2713 }, // Pacific/Chuuk -> Pacific/Truk
+ { 2726, 2741 }, // Pacific/Kanton -> Pacific/Enderbury
+ { 2759, 2775 }, // Pacific/Pohnpei -> Pacific/Ponape
+ { 2790, 2804 }, // Pacific/Samoa -> Pacific/Pago_Pago
+ { 2822, 2713 }, // Pacific/Yap -> Pacific/Truk
+ { 2834, 2841 }, // Poland -> Europe/Warsaw
+ { 2855, 2864 }, // Portugal -> Europe/Lisbon
+ { 2878, 2882 }, // ROC -> Asia/Taipei
+ { 2894, 2898 }, // ROK -> Asia/Seoul
+ { 2909, 2919 }, // Singapore -> Asia/Singapore
+ { 2934, 932 }, // Turkey -> Europe/Istanbul
+ { 2941, 2197 }, // UCT -> Etc/UTC
+ { 2945, 2955 }, // US/Alaska -> America/Anchorage
+ { 2973, 363 }, // US/Aleutian -> America/Adak
+ { 2985, 2996 }, // US/Arizona -> America/Phoenix
+ { 3012, 3023 }, // US/Central -> America/Chicago
+ { 3039, 428 }, // US/East-Indiana -> America/Indianapolis
+ { 3055, 3066 }, // US/Eastern -> America/New_York
+ { 3083, 3093 }, // US/Hawaii -> Pacific/Honolulu
+ { 3110, 541 }, // US/Indiana-Starke -> America/Indiana/Knox
+ { 3128, 3140 }, // US/Michigan -> America/Detroit
+ { 3156, 695 }, // US/Mountain -> America/Denver
+ { 3168, 3179 }, // US/Pacific -> America/Los_Angeles
+ { 3199, 3179 }, // US/Pacific-New -> America/Los_Angeles
+ { 3214, 2804 }, // US/Samoa -> Pacific/Pago_Pago
+ { 3223, 2197 }, // UTC -> Etc/UTC
+ { 3227, 2197 }, // Universal -> Etc/UTC
+ { 3237, 3242 }, // W-SU -> Europe/Moscow
+ { 3256, 2197 }, // Zulu -> Etc/UTC
+};
+
// Windows ID Key, Territory Enum, IANA ID Index
static constexpr ZoneData zoneDataTable[] = {
{ 1, 1, 0 }, // Afghanistan Standard Time / Afghanistan
@@ -1361,8 +1510,217 @@ static constexpr char ianaIdData[] = {
0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x33, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b,
0x31, 0x34, 0x3a, 0x30, 0x30, 0x0
};
+
+static constexpr char aliasIdData[] = {
+0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x73, 0x6d, 0x61, 0x72, 0x61, 0x0, 0x41, 0x66,
+0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x73, 0x6d, 0x65, 0x72, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69,
+0x63, 0x61, 0x2f, 0x54, 0x69, 0x6d, 0x62, 0x75, 0x6b, 0x74, 0x75, 0x0, 0x41, 0x66, 0x72, 0x69,
+0x63, 0x61, 0x2f, 0x42, 0x61, 0x6d, 0x61, 0x6b, 0x6f, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
+0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x42, 0x75, 0x65, 0x6e,
+0x6f, 0x73, 0x5f, 0x41, 0x69, 0x72, 0x65, 0x73, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
+0x2f, 0x42, 0x75, 0x65, 0x6e, 0x6f, 0x73, 0x5f, 0x41, 0x69, 0x72, 0x65, 0x73, 0x0, 0x41, 0x6d,
+0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f,
+0x43, 0x61, 0x74, 0x61, 0x6d, 0x61, 0x72, 0x63, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
+0x61, 0x2f, 0x43, 0x61, 0x74, 0x61, 0x6d, 0x61, 0x72, 0x63, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72,
+0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x43, 0x6f,
+0x6d, 0x6f, 0x64, 0x52, 0x69, 0x76, 0x61, 0x64, 0x61, 0x76, 0x69, 0x61, 0x0, 0x41, 0x6d, 0x65,
+0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x43,
+0x6f, 0x72, 0x64, 0x6f, 0x62, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43,
+0x6f, 0x72, 0x64, 0x6f, 0x62, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41,
+0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x4a, 0x75, 0x6a, 0x75, 0x79, 0x0, 0x41,
+0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x75, 0x6a, 0x75, 0x79, 0x0, 0x41, 0x6d, 0x65,
+0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x4d,
+0x65, 0x6e, 0x64, 0x6f, 0x7a, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d,
+0x65, 0x6e, 0x64, 0x6f, 0x7a, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41,
+0x74, 0x69, 0x6b, 0x6f, 0x6b, 0x61, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
+0x43, 0x6f, 0x72, 0x61, 0x6c, 0x5f, 0x48, 0x61, 0x72, 0x62, 0x6f, 0x75, 0x72, 0x0, 0x41, 0x6d,
+0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x74, 0x6b, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69,
+0x63, 0x61, 0x2f, 0x41, 0x64, 0x61, 0x6b, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
+0x45, 0x6e, 0x73, 0x65, 0x6e, 0x61, 0x64, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
+0x2f, 0x54, 0x69, 0x6a, 0x75, 0x61, 0x6e, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
+0x2f, 0x46, 0x6f, 0x72, 0x74, 0x5f, 0x57, 0x61, 0x79, 0x6e, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72,
+0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x70, 0x6f, 0x6c, 0x69, 0x73,
+0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61,
+0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x70, 0x6f, 0x6c, 0x69, 0x73, 0x0, 0x41, 0x6d,
+0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x65, 0x6e, 0x74, 0x75, 0x63, 0x6b, 0x79, 0x2f, 0x4c,
+0x6f, 0x75, 0x69, 0x73, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
+0x61, 0x2f, 0x4c, 0x6f, 0x75, 0x69, 0x73, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0, 0x41, 0x6d, 0x65,
+0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x6e, 0x6f, 0x78, 0x5f, 0x49, 0x4e, 0x0, 0x41, 0x6d, 0x65,
+0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x4b, 0x6e, 0x6f,
+0x78, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x72, 0x65,
+0x61, 0x6c, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x6f, 0x72, 0x6f, 0x6e,
+0x74, 0x6f, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x75, 0x75, 0x6b, 0x0,
+0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x6f, 0x64, 0x74, 0x68, 0x61, 0x62, 0x0,
+0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x6f, 0x5f, 0x41, 0x63,
+0x72, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x69, 0x6f, 0x5f, 0x42,
+0x72, 0x61, 0x6e, 0x63, 0x6f, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x6f,
+0x73, 0x61, 0x72, 0x69, 0x6f, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x68,
+0x69, 0x70, 0x72, 0x6f, 0x63, 0x6b, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44,
+0x65, 0x6e, 0x76, 0x65, 0x72, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x56, 0x69,
+0x72, 0x67, 0x69, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f,
+0x54, 0x68, 0x6f, 0x6d, 0x61, 0x73, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63,
+0x61, 0x2f, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x5f, 0x50, 0x6f, 0x6c, 0x65, 0x0, 0x50, 0x61, 0x63,
+0x69, 0x66, 0x69, 0x63, 0x2f, 0x41, 0x75, 0x63, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x0, 0x41, 0x73,
+0x69, 0x61, 0x2f, 0x41, 0x73, 0x68, 0x6b, 0x68, 0x61, 0x62, 0x61, 0x64, 0x0, 0x41, 0x73, 0x69,
+0x61, 0x2f, 0x41, 0x73, 0x68, 0x67, 0x61, 0x62, 0x61, 0x74, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f,
+0x43, 0x68, 0x6f, 0x6e, 0x67, 0x71, 0x69, 0x6e, 0x67, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53,
+0x68, 0x61, 0x6e, 0x67, 0x68, 0x61, 0x69, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x43, 0x68, 0x75,
+0x6e, 0x67, 0x6b, 0x69, 0x6e, 0x67, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x61, 0x63, 0x63,
+0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x68, 0x61, 0x6b, 0x61, 0x0, 0x41, 0x73, 0x69,
+0x61, 0x2f, 0x48, 0x61, 0x72, 0x62, 0x69, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x48, 0x6f,
+0x5f, 0x43, 0x68, 0x69, 0x5f, 0x4d, 0x69, 0x6e, 0x68, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53,
+0x61, 0x69, 0x67, 0x6f, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x49, 0x73, 0x74, 0x61, 0x6e,
+0x62, 0x75, 0x6c, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x49, 0x73, 0x74, 0x61, 0x6e,
+0x62, 0x75, 0x6c, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x73, 0x68, 0x67, 0x61, 0x72,
+0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x72, 0x75, 0x6d, 0x71, 0x69, 0x0, 0x41, 0x73, 0x69,
+0x61, 0x2f, 0x4b, 0x61, 0x74, 0x68, 0x6d, 0x61, 0x6e, 0x64, 0x75, 0x0, 0x41, 0x73, 0x69, 0x61,
+0x2f, 0x4b, 0x61, 0x74, 0x6d, 0x61, 0x6e, 0x64, 0x75, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b,
+0x6f, 0x6c, 0x6b, 0x61, 0x74, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x43, 0x61, 0x6c, 0x63,
+0x75, 0x74, 0x74, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x61, 0x6f, 0x0,
+0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x61, 0x75, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f,
+0x54, 0x65, 0x6c, 0x5f, 0x41, 0x76, 0x69, 0x76, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4a, 0x65,
+0x72, 0x75, 0x73, 0x61, 0x6c, 0x65, 0x6d, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x68, 0x69,
+0x6d, 0x62, 0x75, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x68, 0x69, 0x6d, 0x70, 0x68, 0x75,
+0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x6a, 0x75, 0x6e, 0x67, 0x5f, 0x50, 0x61, 0x6e, 0x64,
+0x61, 0x6e, 0x67, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x61, 0x6b, 0x61, 0x73, 0x73, 0x61,
+0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x6c, 0x61, 0x6e, 0x5f, 0x42, 0x61, 0x74, 0x6f,
+0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x6c, 0x61, 0x61, 0x6e, 0x62, 0x61, 0x61, 0x74,
+0x61, 0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x59, 0x61, 0x6e, 0x67, 0x6f, 0x6e, 0x0, 0x41,
+0x73, 0x69, 0x61, 0x2f, 0x52, 0x61, 0x6e, 0x67, 0x6f, 0x6f, 0x6e, 0x0, 0x41, 0x74, 0x6c, 0x61,
+0x6e, 0x74, 0x69, 0x63, 0x2f, 0x46, 0x61, 0x72, 0x6f, 0x65, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e,
+0x74, 0x69, 0x63, 0x2f, 0x46, 0x61, 0x65, 0x72, 0x6f, 0x65, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e,
+0x74, 0x69, 0x63, 0x2f, 0x4a, 0x61, 0x6e, 0x5f, 0x4d, 0x61, 0x79, 0x65, 0x6e, 0x0, 0x41, 0x72,
+0x63, 0x74, 0x69, 0x63, 0x2f, 0x4c, 0x6f, 0x6e, 0x67, 0x79, 0x65, 0x61, 0x72, 0x62, 0x79, 0x65,
+0x6e, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x41, 0x43, 0x54, 0x0,
+0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x53, 0x79, 0x64, 0x6e, 0x65, 0x79,
+0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x43, 0x61, 0x6e, 0x62, 0x65,
+0x72, 0x72, 0x61, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4c, 0x48,
+0x49, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4c, 0x6f, 0x72, 0x64,
+0x5f, 0x48, 0x6f, 0x77, 0x65, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f,
+0x4e, 0x53, 0x57, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4e, 0x6f,
+0x72, 0x74, 0x68, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x44, 0x61,
+0x72, 0x77, 0x69, 0x6e, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x51,
+0x75, 0x65, 0x65, 0x6e, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61,
+0x6c, 0x69, 0x61, 0x2f, 0x42, 0x72, 0x69, 0x73, 0x62, 0x61, 0x6e, 0x65, 0x0, 0x41, 0x75, 0x73,
+0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x0, 0x41, 0x75, 0x73,
+0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x41, 0x64, 0x65, 0x6c, 0x61, 0x69, 0x64, 0x65, 0x0,
+0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x73, 0x6d, 0x61, 0x6e,
+0x69, 0x61, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x48, 0x6f, 0x62,
+0x61, 0x72, 0x74, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x56, 0x69,
+0x63, 0x74, 0x6f, 0x72, 0x69, 0x61, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61,
+0x2f, 0x4d, 0x65, 0x6c, 0x62, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72,
+0x61, 0x6c, 0x69, 0x61, 0x2f, 0x57, 0x65, 0x73, 0x74, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61,
+0x6c, 0x69, 0x61, 0x2f, 0x50, 0x65, 0x72, 0x74, 0x68, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61,
+0x6c, 0x69, 0x61, 0x2f, 0x59, 0x61, 0x6e, 0x63, 0x6f, 0x77, 0x69, 0x6e, 0x6e, 0x61, 0x0, 0x41,
+0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x42, 0x72, 0x6f, 0x6b, 0x65, 0x6e, 0x5f,
+0x48, 0x69, 0x6c, 0x6c, 0x0, 0x42, 0x72, 0x61, 0x7a, 0x69, 0x6c, 0x2f, 0x41, 0x63, 0x72, 0x65,
+0x0, 0x42, 0x72, 0x61, 0x7a, 0x69, 0x6c, 0x2f, 0x44, 0x65, 0x4e, 0x6f, 0x72, 0x6f, 0x6e, 0x68,
+0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x6f, 0x6e, 0x68,
+0x61, 0x0, 0x42, 0x72, 0x61, 0x7a, 0x69, 0x6c, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x0, 0x41, 0x6d,
+0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6f, 0x5f, 0x50, 0x61, 0x75, 0x6c, 0x6f, 0x0,
+0x42, 0x72, 0x61, 0x7a, 0x69, 0x6c, 0x2f, 0x57, 0x65, 0x73, 0x74, 0x0, 0x41, 0x6d, 0x65, 0x72,
+0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x6e, 0x61, 0x75, 0x73, 0x0, 0x43, 0x61, 0x6e, 0x61, 0x64,
+0x61, 0x2f, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69,
+0x63, 0x61, 0x2f, 0x48, 0x61, 0x6c, 0x69, 0x66, 0x61, 0x78, 0x0, 0x43, 0x61, 0x6e, 0x61, 0x64,
+0x61, 0x2f, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
+0x61, 0x2f, 0x57, 0x69, 0x6e, 0x6e, 0x69, 0x70, 0x65, 0x67, 0x0, 0x43, 0x61, 0x6e, 0x61, 0x64,
+0x61, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x2d, 0x53, 0x61, 0x73, 0x6b, 0x61, 0x74, 0x63, 0x68, 0x65,
+0x77, 0x61, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65, 0x67, 0x69,
+0x6e, 0x61, 0x0, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72,
+0x6e, 0x0, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69,
+0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x64, 0x6d, 0x6f, 0x6e, 0x74,
+0x6f, 0x6e, 0x0, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x4e, 0x65, 0x77, 0x66, 0x6f, 0x75,
+0x6e, 0x64, 0x6c, 0x61, 0x6e, 0x64, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53,
+0x74, 0x5f, 0x4a, 0x6f, 0x68, 0x6e, 0x73, 0x0, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x50,
+0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x56,
+0x61, 0x6e, 0x63, 0x6f, 0x75, 0x76, 0x65, 0x72, 0x0, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f,
+0x53, 0x61, 0x73, 0x6b, 0x61, 0x74, 0x63, 0x68, 0x65, 0x77, 0x61, 0x6e, 0x0, 0x43, 0x61, 0x6e,
+0x61, 0x64, 0x61, 0x2f, 0x59, 0x75, 0x6b, 0x6f, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
+0x61, 0x2f, 0x57, 0x68, 0x69, 0x74, 0x65, 0x68, 0x6f, 0x72, 0x73, 0x65, 0x0, 0x43, 0x68, 0x69,
+0x6c, 0x65, 0x2f, 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x0, 0x41,
+0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x69, 0x61, 0x67, 0x6f, 0x0,
+0x43, 0x68, 0x69, 0x6c, 0x65, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x49, 0x73, 0x6c, 0x61,
+0x6e, 0x64, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x65,
+0x72, 0x0, 0x43, 0x75, 0x62, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48,
+0x61, 0x76, 0x61, 0x6e, 0x61, 0x0, 0x45, 0x53, 0x54, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d,
+0x54, 0x2b, 0x35, 0x0, 0x45, 0x67, 0x79, 0x70, 0x74, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
+0x2f, 0x43, 0x61, 0x69, 0x72, 0x6f, 0x0, 0x45, 0x69, 0x72, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f,
+0x70, 0x65, 0x2f, 0x44, 0x75, 0x62, 0x6c, 0x69, 0x6e, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d,
+0x54, 0x2b, 0x30, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x0, 0x45, 0x74, 0x63, 0x2f,
+0x47, 0x4d, 0x54, 0x2d, 0x30, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x30, 0x0, 0x45,
+0x74, 0x63, 0x2f, 0x47, 0x72, 0x65, 0x65, 0x6e, 0x77, 0x69, 0x63, 0x68, 0x0, 0x45, 0x74, 0x63,
+0x2f, 0x55, 0x43, 0x54, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x55, 0x54, 0x43, 0x0, 0x45, 0x74, 0x63,
+0x2f, 0x55, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x5a,
+0x75, 0x6c, 0x75, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x65, 0x6c, 0x66, 0x61,
+0x73, 0x74, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x6f, 0x6e, 0x64, 0x6f, 0x6e,
+0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x79, 0x69, 0x76, 0x0, 0x45, 0x75, 0x72,
+0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x69, 0x65, 0x76, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
+0x4e, 0x69, 0x63, 0x6f, 0x73, 0x69, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x69, 0x63,
+0x6f, 0x73, 0x69, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x54, 0x69, 0x72, 0x61,
+0x73, 0x70, 0x6f, 0x6c, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x43, 0x68, 0x69, 0x73,
+0x69, 0x6e, 0x61, 0x75, 0x0, 0x47, 0x42, 0x0, 0x47, 0x42, 0x2d, 0x45, 0x69, 0x72, 0x65, 0x0,
+0x47, 0x4d, 0x54, 0x0, 0x47, 0x4d, 0x54, 0x2b, 0x30, 0x0, 0x47, 0x4d, 0x54, 0x2d, 0x30, 0x0,
+0x47, 0x4d, 0x54, 0x30, 0x0, 0x47, 0x72, 0x65, 0x65, 0x6e, 0x77, 0x69, 0x63, 0x68, 0x0, 0x48,
+0x53, 0x54, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x30, 0x0, 0x48, 0x6f,
+0x6e, 0x67, 0x6b, 0x6f, 0x6e, 0x67, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x48, 0x6f, 0x6e, 0x67,
+0x5f, 0x4b, 0x6f, 0x6e, 0x67, 0x0, 0x49, 0x63, 0x65, 0x6c, 0x61, 0x6e, 0x64, 0x0, 0x41, 0x74,
+0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x52, 0x65, 0x79, 0x6b, 0x6a, 0x61, 0x76, 0x69, 0x6b,
+0x0, 0x49, 0x72, 0x61, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x65, 0x68, 0x72, 0x61,
+0x6e, 0x0, 0x49, 0x73, 0x72, 0x61, 0x65, 0x6c, 0x0, 0x4a, 0x61, 0x6d, 0x61, 0x69, 0x63, 0x61,
+0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x61, 0x6d, 0x61, 0x69, 0x63, 0x61,
+0x0, 0x4a, 0x61, 0x70, 0x61, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x6f, 0x6b, 0x79,
+0x6f, 0x0, 0x4b, 0x77, 0x61, 0x6a, 0x61, 0x6c, 0x65, 0x69, 0x6e, 0x0, 0x50, 0x61, 0x63, 0x69,
+0x66, 0x69, 0x63, 0x2f, 0x4b, 0x77, 0x61, 0x6a, 0x61, 0x6c, 0x65, 0x69, 0x6e, 0x0, 0x4c, 0x69,
+0x62, 0x79, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x72, 0x69, 0x70, 0x6f,
+0x6c, 0x69, 0x0, 0x4d, 0x53, 0x54, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x37,
+0x0, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x2f, 0x42, 0x61, 0x6a, 0x61, 0x4e, 0x6f, 0x72, 0x74,
+0x65, 0x0, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x2f, 0x42, 0x61, 0x6a, 0x61, 0x53, 0x75, 0x72,
+0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x7a, 0x61, 0x74, 0x6c, 0x61,
+0x6e, 0x0, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x2f, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c,
+0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x5f,
+0x43, 0x69, 0x74, 0x79, 0x0, 0x4e, 0x5a, 0x0, 0x4e, 0x5a, 0x2d, 0x43, 0x48, 0x41, 0x54, 0x0,
+0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x43, 0x68, 0x61, 0x74, 0x68, 0x61, 0x6d, 0x0,
+0x4e, 0x61, 0x76, 0x61, 0x6a, 0x6f, 0x0, 0x50, 0x52, 0x43, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66,
+0x69, 0x63, 0x2f, 0x43, 0x68, 0x75, 0x75, 0x6b, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
+0x2f, 0x54, 0x72, 0x75, 0x6b, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4b, 0x61,
+0x6e, 0x74, 0x6f, 0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45, 0x6e, 0x64,
+0x65, 0x72, 0x62, 0x75, 0x72, 0x79, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50,
+0x6f, 0x68, 0x6e, 0x70, 0x65, 0x69, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50,
+0x6f, 0x6e, 0x61, 0x70, 0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x53, 0x61,
+0x6d, 0x6f, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x61, 0x67, 0x6f,
+0x5f, 0x50, 0x61, 0x67, 0x6f, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x59, 0x61,
+0x70, 0x0, 0x50, 0x6f, 0x6c, 0x61, 0x6e, 0x64, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
+0x57, 0x61, 0x72, 0x73, 0x61, 0x77, 0x0, 0x50, 0x6f, 0x72, 0x74, 0x75, 0x67, 0x61, 0x6c, 0x0,
+0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x69, 0x73, 0x62, 0x6f, 0x6e, 0x0, 0x52, 0x4f,
+0x43, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x69, 0x70, 0x65, 0x69, 0x0, 0x52, 0x4f,
+0x4b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x65, 0x6f, 0x75, 0x6c, 0x0, 0x53, 0x69, 0x6e,
+0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x69, 0x6e, 0x67,
+0x61, 0x70, 0x6f, 0x72, 0x65, 0x0, 0x54, 0x75, 0x72, 0x6b, 0x65, 0x79, 0x0, 0x55, 0x43, 0x54,
+0x0, 0x55, 0x53, 0x2f, 0x41, 0x6c, 0x61, 0x73, 0x6b, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69,
+0x63, 0x61, 0x2f, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x0, 0x55, 0x53, 0x2f,
+0x41, 0x6c, 0x65, 0x75, 0x74, 0x69, 0x61, 0x6e, 0x0, 0x55, 0x53, 0x2f, 0x41, 0x72, 0x69, 0x7a,
+0x6f, 0x6e, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x68, 0x6f, 0x65,
+0x6e, 0x69, 0x78, 0x0, 0x55, 0x53, 0x2f, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x0, 0x41,
+0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x63, 0x61, 0x67, 0x6f, 0x0, 0x55,
+0x53, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x2d, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x0, 0x55,
+0x53, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
+0x61, 0x2f, 0x4e, 0x65, 0x77, 0x5f, 0x59, 0x6f, 0x72, 0x6b, 0x0, 0x55, 0x53, 0x2f, 0x48, 0x61,
+0x77, 0x61, 0x69, 0x69, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x48, 0x6f, 0x6e,
+0x6f, 0x6c, 0x75, 0x6c, 0x75, 0x0, 0x55, 0x53, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61,
+0x2d, 0x53, 0x74, 0x61, 0x72, 0x6b, 0x65, 0x0, 0x55, 0x53, 0x2f, 0x4d, 0x69, 0x63, 0x68, 0x69,
+0x67, 0x61, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x65, 0x74, 0x72,
+0x6f, 0x69, 0x74, 0x0, 0x55, 0x53, 0x2f, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x0,
+0x55, 0x53, 0x2f, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69,
+0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x73, 0x5f, 0x41, 0x6e, 0x67, 0x65, 0x6c, 0x65, 0x73, 0x0, 0x55,
+0x53, 0x2f, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2d, 0x4e, 0x65, 0x77, 0x0, 0x55, 0x53,
+0x2f, 0x53, 0x61, 0x6d, 0x6f, 0x61, 0x0, 0x55, 0x54, 0x43, 0x0, 0x55, 0x6e, 0x69, 0x76, 0x65,
+0x72, 0x73, 0x61, 0x6c, 0x0, 0x57, 0x2d, 0x53, 0x55, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
+0x2f, 0x4d, 0x6f, 0x73, 0x63, 0x6f, 0x77, 0x0, 0x5a, 0x75, 0x6c, 0x75, 0x0
+};
// GENERATED PART ENDS HERE
+constexpr QByteArrayView AliasData::aliasId() const { return aliasIdData + aliasIdIndex; }
+constexpr QByteArrayView AliasData::ianaId() const { return aliasIdData + ianaIdIndex; }
constexpr QByteArrayView WindowsData::windowsId() const { return windowsIdData + windowsIdIndex; }
// Each of the following returns a space-joined sequence of IANA IDs:
constexpr QByteArrayView WindowsData::ianaId() const { return ianaIdData + ianaIdIndex; }
diff --git a/src/corelib/time/qtimezoneprivate_icu.cpp b/src/corelib/time/qtimezoneprivate_icu.cpp
index 1a3baa70d0..a9fe68b83c 100644
--- a/src/corelib/time/qtimezoneprivate_icu.cpp
+++ b/src/corelib/time/qtimezoneprivate_icu.cpp
@@ -4,6 +4,7 @@
#include "qtimezone.h"
#include "qtimezoneprivate_p.h"
+#include "qtimezonelocale_p.h"
#include <unicode/ucal.h>
@@ -22,27 +23,6 @@ QT_BEGIN_NAMESPACE
// ICU utilities
-// Convert TimeType and NameType into ICU UCalendarDisplayNameType
-static UCalendarDisplayNameType ucalDisplayNameType(QTimeZone::TimeType timeType, QTimeZone::NameType nameType)
-{
- // TODO ICU C UCalendarDisplayNameType does not support full set of C++ TimeZone::EDisplayType
- switch (nameType) {
- case QTimeZone::ShortName :
- case QTimeZone::OffsetName :
- if (timeType == QTimeZone::DaylightTime)
- return UCAL_SHORT_DST;
- // Includes GenericTime
- return UCAL_SHORT_STANDARD;
- case QTimeZone::DefaultName :
- case QTimeZone::LongName :
- if (timeType == QTimeZone::DaylightTime)
- return UCAL_DST;
- // Includes GenericTime
- return UCAL_STANDARD;
- }
- return UCAL_STANDARD;
-}
-
// Qt wrapper around ucal_getDefaultTimeZone()
static QByteArray ucalDefaultTimeZoneId()
{
@@ -69,44 +49,6 @@ static QByteArray ucalDefaultTimeZoneId()
return QByteArray();
}
-// Qt wrapper around ucal_getTimeZoneDisplayName()
-static QString ucalTimeZoneDisplayName(UCalendar *ucal, QTimeZone::TimeType timeType,
- QTimeZone::NameType nameType,
- const QString &localeCode)
-{
- int32_t size = 50;
- QString result(size, Qt::Uninitialized);
- UErrorCode status = U_ZERO_ERROR;
-
- // size = ucal_getTimeZoneDisplayName(cal, type, locale, result, resultLength, status)
- size = ucal_getTimeZoneDisplayName(ucal,
- ucalDisplayNameType(timeType, nameType),
- localeCode.toUtf8(),
- reinterpret_cast<UChar *>(result.data()),
- size,
- &status);
-
- // If overflow, then resize and retry
- if (status == U_BUFFER_OVERFLOW_ERROR) {
- result.resize(size);
- status = U_ZERO_ERROR;
- size = ucal_getTimeZoneDisplayName(ucal,
- ucalDisplayNameType(timeType, nameType),
- localeCode.toUtf8(),
- reinterpret_cast<UChar *>(result.data()),
- size,
- &status);
- }
-
- // If successful on first or second go, resize and return
- if (U_SUCCESS(status)) {
- result.resize(size);
- return result;
- }
-
- return QString();
-}
-
// Qt wrapper around ucal_get() for offsets
static bool ucalOffsetsAtTime(UCalendar *m_ucal, qint64 atMSecsSinceEpoch,
int *utcOffset, int *dstOffset)
@@ -203,13 +145,11 @@ static QTimeZonePrivate::Data ucalTimeZoneTransition(UCalendar *m_ucal,
tran.offsetFromUtc = utc + dst;
tran.standardTimeOffset = utc;
tran.daylightTimeOffset = dst;
- // TODO No ICU API, use short name instead
- if (dst == 0)
- tran.abbreviation = ucalTimeZoneDisplayName(m_ucal, QTimeZone::StandardTime,
- QTimeZone::ShortName, QLocale().name());
- else
- tran.abbreviation = ucalTimeZoneDisplayName(m_ucal, QTimeZone::DaylightTime,
- QTimeZone::ShortName, QLocale().name());
+ // TODO No ICU API, use short name as abbreviation.
+ QTimeZone::TimeType timeType = dst == 0 ? QTimeZone::StandardTime : QTimeZone::DaylightTime;
+ using namespace QtTimeZoneLocale;
+ tran.abbreviation = ucalTimeZoneDisplayName(m_ucal, timeType,
+ QTimeZone::ShortName, QLocale().name());
return tran;
}
#endif // U_ICU_VERSION_SHORT
@@ -317,6 +257,7 @@ QString QIcuTimeZonePrivate::displayName(QTimeZone::TimeType timeType,
}
// Technically this may be suspect, if locale isn't QLocale(), since that's
// what we used when constructing m_ucal; does ICU cope with inconsistency ?
+ using namespace QtTimeZoneLocale;
return ucalTimeZoneDisplayName(m_ucal, timeType, nameType, locale.name());
}
diff --git a/src/corelib/time/qtimezoneprivate_p.h b/src/corelib/time/qtimezoneprivate_p.h
index 506acaa1f7..7034a7285c 100644
--- a/src/corelib/time/qtimezoneprivate_p.h
+++ b/src/corelib/time/qtimezoneprivate_p.h
@@ -99,6 +99,8 @@ public:
virtual bool isDaylightTime(qint64 atMSecsSinceEpoch) const;
virtual Data data(qint64 forMSecsSinceEpoch) const;
+ virtual Data data(QTimeZone::TimeType timeType) const;
+ virtual bool isDataLocale(const QLocale &locale) const;
QDateTimePrivate::ZoneState stateAtZoneTime(qint64 forLocalMSecs,
QDateTimePrivate::TransitionOptions resolve) const;
@@ -131,6 +133,7 @@ public:
static QString isoOffsetFormat(int offsetFromUtc,
QTimeZone::NameType mode = QTimeZone::OffsetName);
+ static QByteArray aliasToIana(QByteArrayView alias);
static QByteArray ianaIdToWindowsId(const QByteArray &ianaId);
static QByteArray windowsIdToDefaultIanaId(const QByteArray &windowsId);
static QByteArray windowsIdToDefaultIanaId(const QByteArray &windowsId,
@@ -150,6 +153,15 @@ public:
return QByteArrayLiteral("UTC");
}
+#if QT_CONFIG(timezone_locale)
+private:
+ // Defined in qtimezonelocale.cpp
+ QString localeName(qint64 atMSecsSinceEpoch, int offsetFromUtc,
+ QTimeZone::TimeType timeType,
+ QTimeZone::NameType nameType,
+ const QLocale &locale) const;
+#endif // L10n helpers.
+
protected:
QByteArray m_id;
};
@@ -179,11 +191,15 @@ public:
QUtcTimeZonePrivate *clone() const override;
Data data(qint64 forMSecsSinceEpoch) const override;
+ Data data(QTimeZone::TimeType timeType) const override;
+ bool isDataLocale(const QLocale &locale) const override;
QLocale::Territory territory() const override;
QString comment() const override;
- using QTimeZonePrivate::displayName;
+ QString displayName(qint64 atMSecsSinceEpoch,
+ QTimeZone::NameType nameType,
+ const QLocale &locale) const override;
QString displayName(QTimeZone::TimeType timeType,
QTimeZone::NameType nameType,
const QLocale &locale) const override;
@@ -217,7 +233,7 @@ private:
// TODO: shuffle (almost reverse) order of and rework #if-ery here to use #elif
// and match the #if-ery in each of QTZ's newBackendTimeZone() cascades for
// backend selection.
-#if QT_CONFIG(icu)
+#if QT_CONFIG(icu) && !defined(Q_OS_UNIX)
class Q_AUTOTEST_EXPORT QIcuTimeZonePrivate final : public QTimeZonePrivate
{
public:
@@ -241,6 +257,7 @@ public:
bool hasDaylightTime() const override;
bool isDaylightTime(qint64 atMSecsSinceEpoch) const override;
+ using QTimeZonePrivate::data;
Data data(qint64 forMSecsSinceEpoch) const override;
bool hasTransitions() const override;
@@ -259,7 +276,7 @@ private:
UCalendar *m_ucal;
};
-#endif // ICU
+#endif // ICU not on Unix.
#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN) && !defined(Q_OS_ANDROID)
struct QTzTransitionTime
@@ -321,6 +338,8 @@ public:
bool isDaylightTime(qint64 atMSecsSinceEpoch) const override;
Data data(qint64 forMSecsSinceEpoch) const override;
+ Data data(QTimeZone::TimeType timeType) const override;
+ bool isDataLocale(const QLocale &locale) const override;
bool hasTransitions() const override;
Data nextTransition(qint64 afterMSecsSinceEpoch) const override;
@@ -338,14 +357,6 @@ private:
Data dataForTzTransition(QTzTransitionTime tran) const;
Data dataFromRule(QTzTransitionRule rule, qint64 msecsSinceEpoch) const;
-#if QT_CONFIG(icu)
-# ifdef __cpp_lib_is_final
- static_assert(std::is_final<QIcuTimeZonePrivate>::value,
- "if QIcuTimeZonePrivate isn't final, we may need to specialize "
- "QExplicitlySharedDataPointer::clone() to call QTimeZonePrivate::clone()");
-# endif
- mutable QExplicitlySharedDataPointer<const QIcuTimeZonePrivate> m_icu;
-#endif
QTzTimeZoneCacheEntry cached_data;
const QList<QTzTransitionTime> &tranCache() const { return cached_data.m_tranTimes; }
};
@@ -378,6 +389,7 @@ public:
bool hasDaylightTime() const override;
bool isDaylightTime(qint64 atMSecsSinceEpoch) const override;
+ using QTimeZonePrivate::data;
Data data(qint64 forMSecsSinceEpoch) const override;
bool hasTransitions() const override;
@@ -432,6 +444,7 @@ public:
bool hasDaylightTime() const override;
bool isDaylightTime(qint64 atMSecsSinceEpoch) const override;
+ using QTimeZonePrivate::data;
Data data(qint64 forMSecsSinceEpoch) const override;
bool hasTransitions() const override;
@@ -481,6 +494,7 @@ public:
bool hasDaylightTime() const override;
bool isDaylightTime(qint64 atMSecsSinceEpoch) const override;
+ using QTimeZonePrivate::data;
Data data(qint64 forMSecsSinceEpoch) const override;
QByteArray systemTimeZoneId() const override;
diff --git a/src/corelib/time/qtimezoneprivate_tz.cpp b/src/corelib/time/qtimezoneprivate_tz.cpp
index f6156fe93e..8d14e75193 100644
--- a/src/corelib/time/qtimezoneprivate_tz.cpp
+++ b/src/corelib/time/qtimezoneprivate_tz.cpp
@@ -33,10 +33,6 @@ QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals;
-#if QT_CONFIG(icu)
-Q_CONSTINIT static QBasicMutex s_icu_mutex;
-#endif
-
/*
Private
@@ -771,9 +767,6 @@ QTzTimeZonePrivate::~QTzTimeZonePrivate()
QTzTimeZonePrivate *QTzTimeZonePrivate::clone() const
{
-#if QT_CONFIG(icu)
- const auto lock = qt_scoped_lock(s_icu_mutex);
-#endif
return new QTzTimeZonePrivate(*this);
}
@@ -1007,15 +1000,7 @@ QTzTimeZonePrivate::QTzTimeZonePrivate(const QByteArray &ianaId)
if (m_id.isEmpty()) {
// This can only happen for the system zone, when we've read the
// contents of /etc/localtime because it wasn't a symlink.
-#if QT_CONFIG(icu)
- // Use ICU's system zone, if only to avoid using the abbreviation as ID
- // (ICU might mis-recognize it) in displayName().
- m_icu = new QIcuTimeZonePrivate();
- // Use its ID, as an alternate source of data:
- m_id = m_icu->id();
- if (!m_id.isEmpty())
- return;
-#endif
+ // TODO: use CLDR generic abbreviation for the zone.
m_id = abbreviation(QDateTime::currentMSecsSinceEpoch()).toUtf8();
}
}
@@ -1034,70 +1019,19 @@ QString QTzTimeZonePrivate::displayName(QTimeZone::TimeType timeType,
QTimeZone::NameType nameType,
const QLocale &locale) const
{
- // TZ DB lacks localized names (it only has IANA IDs), so delegate to ICU
- // for those, when available.
-#if QT_CONFIG(icu)
- {
- auto lock = qt_scoped_lock(s_icu_mutex);
- // TODO Some valid TZ names are not valid ICU names, use translation table?
- if (!m_icu)
- m_icu = new QIcuTimeZonePrivate(m_id);
- if (m_icu->isValid())
- return m_icu->displayName(timeType, nameType, locale);
- }
-#else
- Q_UNUSED(timeType);
- Q_UNUSED(nameType);
- Q_UNUSED(locale);
-#endif
- // If ICU is unavailable, fall back to abbreviations.
- // Abbreviations don't have GenericTime
- if (timeType == QTimeZone::GenericTime)
- timeType = QTimeZone::StandardTime;
-
- // Get current tran, if valid and is what we want, then use it
- const qint64 currentMSecs = QDateTime::currentMSecsSinceEpoch();
- QTimeZonePrivate::Data tran = data(currentMSecs);
- if (tran.atMSecsSinceEpoch != invalidMSecs()
- && ((timeType == QTimeZone::DaylightTime && tran.daylightTimeOffset != 0)
- || (timeType == QTimeZone::StandardTime && tran.daylightTimeOffset == 0))) {
- return tran.abbreviation;
- }
-
- // Otherwise get next tran and if valid and is what we want, then use it
- tran = nextTransition(currentMSecs);
- if (tran.atMSecsSinceEpoch != invalidMSecs()
- && ((timeType == QTimeZone::DaylightTime && tran.daylightTimeOffset != 0)
- || (timeType == QTimeZone::StandardTime && tran.daylightTimeOffset == 0))) {
- return tran.abbreviation;
- }
-
- // Otherwise get prev tran and if valid and is what we want, then use it
- tran = previousTransition(currentMSecs);
- if (tran.atMSecsSinceEpoch != invalidMSecs())
- tran = previousTransition(tran.atMSecsSinceEpoch);
- if (tran.atMSecsSinceEpoch != invalidMSecs()
- && ((timeType == QTimeZone::DaylightTime && tran.daylightTimeOffset != 0)
- || (timeType == QTimeZone::StandardTime && tran.daylightTimeOffset == 0))) {
- return tran.abbreviation;
- }
-
- // Otherwise is strange sequence, so work backwards through trans looking for first match, if any
- auto it = std::partition_point(tranCache().cbegin(), tranCache().cend(),
- [currentMSecs](const QTzTransitionTime &at) {
- return at.atMSecsSinceEpoch <= currentMSecs;
- });
-
- while (it != tranCache().cbegin()) {
- --it;
- tran = dataForTzTransition(*it);
- int offset = tran.daylightTimeOffset;
- if ((timeType == QTimeZone::DaylightTime) != (offset == 0))
- return tran.abbreviation;
+ // TZ only provides C-locale abbreviations and offset:
+ if (nameType != QTimeZone::LongName && isDataLocale(locale)) {
+ QTimeZonePrivate::Data tran = data(timeType);
+ if (tran.atMSecsSinceEpoch != invalidMSecs()) {
+ if (nameType == QTimeZone::ShortName)
+ return tran.abbreviation;
+ // Save base class repeating the data(timeType) query:
+ if (locale.language() == QLocale::C)
+ return isoOffsetFormat(tran.offsetFromUtc);
+ }
}
-
- // Otherwise if no match use current data
- return data(currentMSecs).abbreviation;
+ // Otherwise, fall back to base class (and qtimezonelocale.cpp):
+ return QTimeZonePrivate::displayName(timeType, nameType, locale);
}
QString QTzTimeZonePrivate::abbreviation(qint64 atMSecsSinceEpoch) const
@@ -1184,6 +1118,64 @@ QTimeZonePrivate::Data QTzTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const
return dataFromRule(cached_data.m_tranRules.at(last->ruleIndex), forMSecsSinceEpoch);
}
+// Overridden because the final iteration over transitions only needs to look
+// forward and backwards one transition within the POSIX rule (when there is
+// one, as is common) to settle the whole period it covers, so we can then skip
+// all other transitions of the POSIX rule and iterate tranCache() backwards
+// from its most recent transition.
+QTimeZonePrivate::Data QTzTimeZonePrivate::data(QTimeZone::TimeType timeType) const
+{
+ // True if tran is valid and has the DST-ness to match timeType:
+ const auto validMatch = [timeType](const QTimeZonePrivate::Data &tran) {
+ return tran.atMSecsSinceEpoch != invalidMSecs()
+ && ((timeType == QTimeZone::DaylightTime) != (tran.daylightTimeOffset == 0));
+ };
+
+ // Get current tran, use if suitable:
+ const qint64 currentMSecs = QDateTime::currentMSecsSinceEpoch();
+ QTimeZonePrivate::Data tran = data(currentMSecs);
+ if (validMatch(tran))
+ return tran;
+
+ // Otherwise, next tran probably flips DST-ness:
+ tran = nextTransition(currentMSecs);
+ if (validMatch(tran))
+ return tran;
+
+ // Failing that, prev (or present, if current MSecs is eactly a transition
+ // moment) tran defines what data() got us and the one before that probably
+ // flips DST-ness:
+ tran = previousTransition(currentMSecs + 1);
+ if (tran.atMSecsSinceEpoch != invalidMSecs())
+ tran = previousTransition(tran.atMSecsSinceEpoch);
+ if (validMatch(tran))
+ return tran;
+
+ // Otherwise, we can look backwards through transitions for a match; if we
+ // have a POSIX rule, it clearly doesn't do DST (or we'd have hit it by
+ // now), so we only need to look in the tranCache() up to now.
+ const auto untilNow = [currentMSecs](const QTzTransitionTime &at) {
+ return at.atMSecsSinceEpoch <= currentMSecs;
+ };
+ auto it = std::partition_point(tranCache().cbegin(), tranCache().cend(), untilNow);
+ // That's the end or first future transition; we don't want to look at it,
+ // but at all those before it.
+ while (it != tranCache().cbegin()) {
+ --it;
+ tran = dataForTzTransition(*it);
+ if ((timeType == QTimeZone::DaylightTime) != (tran.daylightTimeOffset == 0))
+ return tran;
+ }
+
+ return {};
+}
+
+bool QTzTimeZonePrivate::isDataLocale(const QLocale &locale) const
+{
+ // TZ data uses English / C locale names:
+ return locale.language() == QLocale::C || locale.language() == QLocale::English;
+}
+
bool QTzTimeZonePrivate::hasTransitions() const
{
return true;
diff --git a/src/corelib/tools/qcryptographichash.cpp b/src/corelib/tools/qcryptographichash.cpp
index 2e82a394ee..8baec8ecc8 100644
--- a/src/corelib/tools/qcryptographichash.cpp
+++ b/src/corelib/tools/qcryptographichash.cpp
@@ -1338,7 +1338,7 @@ static HashBlock xored(const HashBlock &block, quint8 val) noexcept
class QMessageAuthenticationCodePrivate
{
public:
- QMessageAuthenticationCodePrivate(QCryptographicHash::Algorithm m)
+ explicit QMessageAuthenticationCodePrivate(QCryptographicHash::Algorithm m) noexcept
: messageHash(m)
{
}
diff --git a/src/corelib/tools/qsize.cpp b/src/corelib/tools/qsize.cpp
index d5e8e4c71b..27ff1d164d 100644
--- a/src/corelib/tools/qsize.cpp
+++ b/src/corelib/tools/qsize.cpp
@@ -266,15 +266,15 @@ QSize QSize::scaled(const QSize &s, Qt::AspectRatioMode mode) const noexcept
*/
/*!
- \fn bool QSize::operator==(const QSize &s1, const QSize &s2)
+ \fn bool QSize::operator==(const QSize &lhs, const QSize &rhs)
- Returns \c true if \a s1 and \a s2 are equal; otherwise returns \c false.
+ Returns \c true if \a lhs and \a rhs are equal; otherwise returns \c false.
*/
/*!
- \fn bool QSize::operator!=(const QSize &s1, const QSize &s2)
+ \fn bool QSize::operator!=(const QSize &lhs, const QSize &rhs)
- Returns \c true if \a s1 and \a s2 are different; otherwise returns \c false.
+ Returns \c true if \a lhs and \a rhs are different; otherwise returns \c false.
*/
/*!
@@ -714,9 +714,9 @@ QSizeF QSizeF::scaled(const QSizeF &s, Qt::AspectRatioMode mode) const noexcept
*/
/*!
- \fn bool QSizeF::operator==(const QSizeF &s1, const QSizeF &s2)
+ \fn bool QSizeF::operator==(const QSizeF &lhs, const QSizeF &rhs)
- Returns \c true if \a s1 and \a s2 are approximately equal; otherwise
+ Returns \c true if \a lhs and \a rhs are approximately equal; otherwise
returns false.
\warning This function does not check for strict equality; instead,
@@ -726,9 +726,9 @@ QSizeF QSizeF::scaled(const QSizeF &s, Qt::AspectRatioMode mode) const noexcept
*/
/*!
- \fn bool QSizeF::operator!=(const QSizeF &s1, const QSizeF &s2)
+ \fn bool QSizeF::operator!=(const QSizeF &lhs, const QSizeF &rhs)
- Returns \c true if \a s1 and \a s2 are sufficiently different; otherwise
+ Returns \c true if \a lhs and \a rhs are sufficiently different; otherwise
returns \c false.
\warning This function does not check for strict inequality; instead,
@@ -808,7 +808,24 @@ QSizeF QSizeF::scaled(const QSizeF &s, Qt::AspectRatioMode mode) const noexcept
\sa expandedTo(), scale()
*/
+/*!
+ \fn bool QSizeF::qFuzzyCompare(const QSizeF &lhs, const QSizeF &rhs)
+ \since 6.8
+
+ Returns \c true if the size \a lhs is approximately equal to the
+ size \a rhs; otherwise returns \c false.
+
+ The sizes are considered approximately equal if their width and
+ height are approximately equal.
+*/
+/*!
+ \fn bool QSizeF::qFuzzyIsNull(const QSizeF &size)
+ \since 6.8
+
+ Returns \c true if both width and height of the size \a size
+ are approximately equal to zero.
+*/
/*****************************************************************************
QSizeF stream functions
diff --git a/src/corelib/tools/qsize.h b/src/corelib/tools/qsize.h
index a5eaf34afe..67f7146201 100644
--- a/src/corelib/tools/qsize.h
+++ b/src/corelib/tools/qsize.h
@@ -59,10 +59,10 @@ public:
constexpr inline QSize &operator*=(qreal c) noexcept;
inline QSize &operator/=(qreal c);
- friend inline constexpr bool operator==(const QSize &s1, const QSize &s2) noexcept
+private:
+ friend constexpr bool comparesEqual(const QSize &s1, const QSize &s2) noexcept
{ return s1.wd == s2.wd && s1.ht == s2.ht; }
- friend inline constexpr bool operator!=(const QSize &s1, const QSize &s2) noexcept
- { return s1.wd != s2.wd || s1.ht != s2.ht; }
+ Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(QSize)
friend inline constexpr QSize operator+(const QSize &s1, const QSize &s2) noexcept
{ return QSize(s1.wd + s2.wd, s1.ht + s2.ht); }
friend inline constexpr QSize operator-(const QSize &s1, const QSize &s2) noexcept
@@ -75,6 +75,7 @@ public:
{ Q_ASSERT(!qFuzzyIsNull(c)); return QSize(qRound(s.wd / c), qRound(s.ht / c)); }
friend inline constexpr size_t qHash(const QSize &, size_t) noexcept;
+public:
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
[[nodiscard]] CGSize toCGSize() const noexcept;
#endif
@@ -242,16 +243,25 @@ public:
constexpr inline QSizeF &operator*=(qreal c) noexcept;
inline QSizeF &operator/=(qreal c);
+private:
QT_WARNING_PUSH
QT_WARNING_DISABLE_FLOAT_COMPARE
- friend constexpr inline bool operator==(const QSizeF &s1, const QSizeF &s2)
+ friend constexpr bool qFuzzyCompare(const QSizeF &s1, const QSizeF &s2) noexcept
{
+ // Cannot use qFuzzyCompare(), because it will give incorrect results
+ // if one of the arguments is 0.0.
return ((!s1.wd || !s2.wd) ? qFuzzyIsNull(s1.wd - s2.wd) : qFuzzyCompare(s1.wd, s2.wd))
&& ((!s1.ht || !s2.ht) ? qFuzzyIsNull(s1.ht - s2.ht) : qFuzzyCompare(s1.ht, s2.ht));
}
QT_WARNING_POP
- friend constexpr inline bool operator!=(const QSizeF &s1, const QSizeF &s2)
- { return !(s1 == s2); }
+ friend constexpr bool qFuzzyIsNull(const QSizeF &size) noexcept
+ { return qFuzzyIsNull(size.wd) && qFuzzyIsNull(size.ht); }
+ friend constexpr bool comparesEqual(const QSizeF &lhs, const QSizeF &rhs) noexcept
+ { return qFuzzyCompare(lhs, rhs); }
+ Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(QSizeF)
+ friend constexpr bool comparesEqual(const QSizeF &lhs, const QSize &rhs) noexcept
+ { return comparesEqual(lhs, rhs.toSizeF()); }
+ Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(QSizeF, QSize)
friend constexpr inline QSizeF operator+(const QSizeF &s1, const QSizeF &s2) noexcept
{ return QSizeF(s1.wd + s2.wd, s1.ht + s2.ht); }
friend constexpr inline QSizeF operator-(const QSizeF &s1, const QSizeF &s2) noexcept
@@ -263,6 +273,7 @@ public:
friend inline QSizeF operator/(const QSizeF &s, qreal c)
{ Q_ASSERT(!qFuzzyIsNull(c)); return QSizeF(s.wd / c, s.ht / c); }
+public:
constexpr inline QSize toSize() const noexcept;
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
diff --git a/src/corelib/tools/qspan.h b/src/corelib/tools/qspan.h
index d6ae2570ae..2671ba374f 100644
--- a/src/corelib/tools/qspan.h
+++ b/src/corelib/tools/qspan.h
@@ -433,6 +433,29 @@ public:
[[nodiscard]] constexpr QSpan<T> sliced(size_type pos) const { return subspan(pos); }
[[nodiscard]] constexpr QSpan<T> sliced(size_type pos, size_type n) const { return subspan(pos, n); }
+private:
+ // [span.objectrep]
+ [[nodiscard]] friend
+ QSpan<const std::byte, E == q20::dynamic_extent ? q20::dynamic_extent : E * sizeof(T)>
+ as_bytes(QSpan s) noexcept
+ {
+ using R = QSpan<const std::byte, E == q20::dynamic_extent ? q20::dynamic_extent : E * sizeof(T)>;
+ return R{reinterpret_cast<const std::byte *>(s.data()), s.size_bytes()};
+ }
+
+ template <typename U>
+ using if_mutable = std::enable_if_t<!std::is_const_v<U>, bool>;
+
+#ifndef Q_QDOC
+ template <typename T2 = T, if_mutable<T2> = true>
+#endif
+ [[nodiscard]] friend
+ QSpan<std::byte, E == q20::dynamic_extent ? q20::dynamic_extent : E * sizeof(T)>
+ as_writable_bytes(QSpan s) noexcept
+ {
+ using R = QSpan<std::byte, E == q20::dynamic_extent ? q20::dynamic_extent : E * sizeof(T)>;
+ return R{reinterpret_cast<std::byte *>(s.data()), s.size_bytes()};
+ }
}; // class QSpan
// [span.deduct]
diff --git a/src/corelib/tools/qspan.qdoc b/src/corelib/tools/qspan.qdoc
index 472f122877..9b55b09bf7 100644
--- a/src/corelib/tools/qspan.qdoc
+++ b/src/corelib/tools/qspan.qdoc
@@ -556,7 +556,6 @@
\sa subspan(QSpan<T,E>::size_type), subspan(), first(), last()
*/
-#if 0 // needs fix for QTBUG-118080 integrated into qt5.git
/*!
\fn template <typename T, size_t E> template <std::size_t Offset, std::size_t Count> auto QSpan<T, E>::subspan() const
\keyword subspan-t2
@@ -573,7 +572,6 @@
\sa subspan(QSpan<T,E>::size_type, QSpan<T,E>::size_type), subspan(), first(), last()
*/
-#endif
//
// runtime subspans:
@@ -649,3 +647,37 @@
\sa subspan(), first(QSpan<T,E>::size_type), last(QSpan<T,E>::size_type)
*/
+/*!
+ \fn template <typename T, size_t E> auto QSpan<T, E>::as_bytes(QSpan s)
+ \since 6.8
+
+ Returns \a s as a \c{QSpan<const std::byte, E'>} whose size() is equal to
+ \c{s.size_bytes()}.
+
+ If \c{E} is \c{std::dynamic_extent} then so is \c{E'}.
+ Otherwise, \c{E' = E * sizeof(T)}.
+
+ \note \c{q20::dynamic_extent} is a C++17 backport of C++20's
+ \l{https://en.cppreference.com/w/cpp/container/span/dynamic_extent}{\c{std::dynamic_extent}}.
+
+ \sa as_writable_bytes(), size_bytes()
+*/
+
+/*!
+ \fn template <typename T, size_t E> auto QSpan<T, E>::as_writable_bytes(QSpan s)
+ \since 6.8
+
+ Returns \a s as a \c{QSpan<std::byte, E'>} whose size() is equal to
+ \c{s.size_bytes()}.
+
+ If \c{E} is \c{std::dynamic_extent} then so is \c{E'}.
+ Otherwise, \c{E' = E * sizeof(T)}.
+
+ \note This function participates in overload resolution only if
+ \c{!std::is_const_v<T>}.
+
+ \note \c{q20::dynamic_extent} is a C++17 backport of C++20's
+ \l{https://en.cppreference.com/w/cpp/container/span/dynamic_extent}{\c{std::dynamic_extent}}.
+
+ \sa as_bytes(), size_bytes()
+*/
diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt
index cef71318d8..aed66563a7 100644
--- a/src/gui/CMakeLists.txt
+++ b/src/gui/CMakeLists.txt
@@ -7,7 +7,9 @@ qt_find_package(WrapPNG PROVIDED_TARGETS WrapPNG::WrapPNG)
qt_find_package(WrapFreetype PROVIDED_TARGETS WrapFreetype::WrapFreetype)
if (QT_FEATURE_gui)
- if(WIN32)
+ if(QT_QPA_PLATFORMS)
+ list(GET QT_QPA_PLATFORMS 0 _default_platform)
+ elseif(WIN32)
set(_default_platform "windows")
elseif(ANDROID)
set(_default_platform "android")
@@ -30,6 +32,11 @@ if (QT_FEATURE_gui)
endif()
set(QT_QPA_DEFAULT_PLATFORM "${_default_platform}" CACHE STRING "QPA default platform")
+ if(NOT "${QT_QPA_DEFAULT_PLATFORM}" IN_LIST QT_QPA_PLATFORMS)
+ list(APPEND QT_QPA_PLATFORMS "${QT_QPA_DEFAULT_PLATFORM}")
+ set(QT_QPA_PLATFORMS "${QT_QPA_PLATFORMS}" CACHE STRING
+ "QPA platforms deployed by default" FORCE)
+ endif()
endif()
# Silence warnings in 3rdparty code
@@ -376,6 +383,11 @@ qt_internal_extend_target(Gui CONDITION MACOS
${FWAppKit}
)
+qt_internal_extend_target(Gui CONDITION UIKIT
+ SOURCES
+ platform/ios/qiosnativeinterface.cpp
+)
+
qt_internal_extend_target(Gui CONDITION WASM
SOURCES
platform/wasm/qwasmnativeinterface.cpp
@@ -402,6 +414,12 @@ qt_internal_extend_target(Gui CONDITION APPLE
${FWImageIO}
)
+qt_internal_extend_target(Gui CONDITION QNX
+ SOURCES
+ painting/qrasterbackingstore.cpp painting/qrasterbackingstore_p.h
+ painting/qrhibackingstore.cpp painting/qrhibackingstore_p.h
+)
+
qt_internal_extend_target(Gui CONDITION QT_FEATURE_animation
SOURCES
animation/qguivariantanimation.cpp
diff --git a/src/gui/accessible/linux/atspiadaptor.cpp b/src/gui/accessible/linux/atspiadaptor.cpp
index b3269a2a95..a83dec4e64 100644
--- a/src/gui/accessible/linux/atspiadaptor.cpp
+++ b/src/gui/accessible/linux/atspiadaptor.cpp
@@ -35,6 +35,13 @@
#define ATSPI_COORD_TYPE_PARENT 2
#endif
+// ATSPI_*_VERSION defines were added in libatspi 2.50,
+// as was the AtspiLive enum; define values here for older versions
+#if !defined(ATSPI_MAJOR_VERSION) || !defined(ATSPI_MINOR_VERSION) || ATSPI_MAJOR_VERSION < 2 || ATSPI_MINOR_VERSION < 50
+#define ATSPI_LIVE_POLITE 1
+#define ATSPI_LIVE_ASSERTIVE 2
+#endif
+
QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals;
@@ -47,6 +54,7 @@ AtSpiAdaptor::AtSpiAdaptor(DBusConnection *connection, QObject *parent)
, sendFocus(0)
, sendObject(0)
, sendObject_active_descendant_changed(0)
+ , sendObject_announcement(0)
, sendObject_attributes_changed(0)
, sendObject_bounds_changed(0)
, sendObject_children_changed(0)
@@ -127,6 +135,7 @@ QString AtSpiAdaptor::introspect(const QString &path) const
" <interface name=\"org.a11y.atspi.Accessible\">\n"
" <property access=\"read\" type=\"s\" name=\"Name\"/>\n"
" <property access=\"read\" type=\"s\" name=\"Description\"/>\n"
+ " <property access=\"read\" type=\"s\" name=\"HelpText\"/>\n"
" <property access=\"read\" type=\"(so)\" name=\"Parent\">\n"
" <annotation value=\"QSpiObjectReference\" name=\"org.qtproject.QtDBus.QtTypeName\"/>\n"
" </property>\n"
@@ -678,6 +687,8 @@ void AtSpiAdaptor::setBitFlag(const QString &flag)
if (false) {
} else if (right.startsWith("ActiveDescendantChanged"_L1)) {
sendObject_active_descendant_changed = 1;
+ } else if (right.startsWith("Announcement"_L1)) {
+ sendObject_announcement = 1;
} else if (right.startsWith("AttributesChanged"_L1)) {
sendObject_attributes_changed = 1;
} else if (right.startsWith("BoundsChanged"_L1)) {
@@ -929,6 +940,26 @@ void AtSpiAdaptor::notifyStateChange(QAccessibleInterface *interface, const QStr
sendDBusSignal(path, ATSPI_DBUS_INTERFACE_EVENT_OBJECT ""_L1, "StateChanged"_L1, stateArgs);
}
+void AtSpiAdaptor::sendAnnouncement(QAccessibleAnnouncementEvent *event)
+{
+ QAccessibleInterface *iface = event->accessibleInterface();
+ if (!iface) {
+ qCWarning(lcAccessibilityAtspi, "Announcement event has no accessible set.");
+ return;
+ }
+ if (!iface->isValid()) {
+ qCWarning(lcAccessibilityAtspi) << "Announcement event with invalid accessible: " << iface;
+ return;
+ }
+
+ const QString path = pathForInterface(iface);
+ const QString message = event->message();
+ const QAccessible::AnnouncementPriority prio = event->priority();
+ const int politeness = (prio == QAccessible::AnnouncementPriority::Assertive) ? ATSPI_LIVE_ASSERTIVE : ATSPI_LIVE_POLITE;
+
+ const QVariantList args = packDBusSignalArguments(QString(), politeness, 0, QVariant::fromValue(QDBusVariant(message)));
+ sendDBusSignal(path, ATSPI_DBUS_INTERFACE_EVENT_OBJECT ""_L1, "Announcement"_L1, args);
+}
/*!
This function gets called when Qt notifies about accessibility updates.
@@ -1003,6 +1034,14 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event)
sendFocusChanged(event->accessibleInterface());
break;
}
+
+ case QAccessible::Announcement: {
+ if (sendObject || sendObject_announcement) {
+ QAccessibleAnnouncementEvent *announcementEvent = static_cast<QAccessibleAnnouncementEvent*>(event);
+ sendAnnouncement(announcementEvent);
+ }
+ break;
+ }
case QAccessible::TextInserted:
case QAccessible::TextRemoved:
case QAccessible::TextUpdated: {
@@ -1586,6 +1625,8 @@ bool AtSpiAdaptor::accessibleInterface(QAccessibleInterface *interface, const QS
sendReply(connection, message, accessibleInterfaces(interface));
} else if (function == "GetDescription"_L1) {
sendReply(connection, message, QVariant::fromValue(QDBusVariant(interface->text(QAccessible::Description))));
+ } else if (function == "GetHelpText"_L1) {
+ sendReply(connection, message, QVariant::fromValue(QDBusVariant(interface->text(QAccessible::Help))));
} else if (function == "GetState"_L1) {
quint64 spiState = spiStatesFromQState(interface->state());
if (interface->tableInterface()) {
@@ -1606,7 +1647,7 @@ bool AtSpiAdaptor::accessibleInterface(QAccessibleInterface *interface, const QS
sendReply(connection, message,
QVariant::fromValue(spiStateSetFromSpiStates(spiState)));
} else if (function == "GetAttributes"_L1) {
- sendReply(connection, message, QVariant::fromValue(QSpiAttributeSet()));
+ sendReply(connection, message, QVariant::fromValue(getAttributes(interface)));
} else if (function == "GetRelationSet"_L1) {
sendReply(connection, message, QVariant::fromValue(relationSet(interface, connection)));
} else if (function == "GetApplication"_L1) {
@@ -2264,6 +2305,38 @@ namespace
}
}
+QSpiAttributeSet AtSpiAdaptor::getAttributes(QAccessibleInterface *interface) const
+{
+ QSpiAttributeSet set;
+ QAccessibleAttributesInterface *attributesIface = interface->attributesInterface();
+ if (!attributesIface)
+ return set;
+
+ const QList<QAccessible::Attribute> attrKeys = attributesIface->attributeKeys();
+ for (QAccessible::Attribute key : attrKeys) {
+ const QVariant value = attributesIface->attributeValue(key);
+ // see "Core Accessibility API Mappings" spec: https://www.w3.org/TR/core-aam-1.2/
+ switch (key) {
+ case QAccessible::Attribute::Custom:
+ {
+ // forward custom attributes to AT-SPI as-is
+ Q_ASSERT((value.canConvert<QHash<QString, QString>>()));
+ const QHash<QString, QString> attrMap = value.value<QHash<QString, QString>>();
+ for (auto [name, val] : attrMap.asKeyValueRange())
+ set.insert(name, val);
+ break;
+ }
+ case QAccessible::Attribute::Level:
+ Q_ASSERT(value.canConvert<int>());
+ set.insert(QStringLiteral("level"), QString::number(value.toInt()));
+ break;
+ default:
+ break;
+ }
+ }
+ return set;
+}
+
// FIXME all attribute methods below should share code
QVariantList AtSpiAdaptor::getAttributes(QAccessibleInterface *interface, int offset, bool includeDefaults) const
{
diff --git a/src/gui/accessible/linux/atspiadaptor_p.h b/src/gui/accessible/linux/atspiadaptor_p.h
index 3a890f3d7d..68a455e7cb 100644
--- a/src/gui/accessible/linux/atspiadaptor_p.h
+++ b/src/gui/accessible/linux/atspiadaptor_p.h
@@ -16,7 +16,7 @@
// We mean it.
//
-#include <atspi/atspi-constants.h>
+#include <atspi/atspi.h>
#include <QtGui/private/qtguiglobal_p.h>
#include <QtDBus/qdbusvirtualobject.h>
@@ -85,8 +85,11 @@ private:
void notifyStateChange(QAccessibleInterface *interface, const QString& state, int value);
+ void sendAnnouncement(QAccessibleAnnouncementEvent *event);
+
// accessible helper functions
AtspiRole getRole(QAccessibleInterface *interface) const;
+ QSpiAttributeSet getAttributes(QAccessibleInterface *) const;
QSpiRelationArray relationSet(QAccessibleInterface *interface, const QDBusConnection &connection) const;
QStringList accessibleInterfaces(QAccessibleInterface *interface) const;
@@ -130,6 +133,7 @@ private:
// all of object
uint sendObject : 1;
uint sendObject_active_descendant_changed : 1;
+ uint sendObject_announcement : 1;
uint sendObject_attributes_changed : 1;
uint sendObject_bounds_changed : 1;
uint sendObject_children_changed : 1;
diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp
index 46bca16dad..eec779efb1 100644
--- a/src/gui/accessible/qaccessible.cpp
+++ b/src/gui/accessible/qaccessible.cpp
@@ -173,6 +173,7 @@ Q_LOGGING_CATEGORY(lcAccessibilityCore, "qt.accessibility.core");
\value ActionChanged An action has been changed.
\value ActiveDescendantChanged
\value Alert A system alert (e.g., a message from a QMessageBox)
+ \value [since 6.8] Announcement The announcement of a message is requested.
\value AttributeChanged
\value ContextHelpEnd Context help (QWhatsThis) for an object is finished.
\value ContextHelpStart Context help (QWhatsThis) for an object is initiated.
@@ -449,6 +450,30 @@ Q_LOGGING_CATEGORY(lcAccessibilityCore, "qt.accessibility.core");
\sa QAccessibleAttributesInterface
*/
+/*! \enum QAccessible::AnnouncementPriority
+ This enum describes the priority for announcements used by the
+ \l QAccessibleAnnouncementEvent.
+ \since 6.8
+
+ With \a QAccessible::AnouncementPriority::Polite, assistive technologies
+ should announce the message at the next graceful opportunity such as at the
+ end of speaking the current sentence or when the user pauses typing.
+
+ When specifying \a QAccessible::AnouncementPriority::Assertive, assistive
+ technologies should notify the user immediately.
+
+ Because an interruption might disorient users or cause them to not complete
+ their current task, \a QAccessible::AnouncementPriority::Assertive should
+ not be used unless the interruption is imperative.
+
+ \value Polite The announcement has normal priority.
+ \value Assertive The announcement has high priority and should notify
+ the user immediately, even if that means interrupting the user's
+ current task.
+
+ \sa QAccessibleAnnouncementEvent
+*/
+
/*!
\enum QAccessible::InterfaceType
@@ -1778,9 +1803,58 @@ QAccessibleTextSelectionEvent::~QAccessibleTextSelectionEvent()
{
}
+/*!
+ \since 6.8
+ \class QAccessibleAnnouncementEvent
+ \ingroup accessibility
+ \inmodule QtGui
+
+ \brief The QAccessibleAnnouncementEvent is used to request the announcement
+ of a given message by assistive technologies.
+
+ This class is used with \l QAccessible::updateAccessibility().
+*/
+
+/*! \fn QAccessibleAnnouncementEvent::QAccessibleAnnouncementEvent(QObject *object, const QString &message)
+
+ Constructs a new QAccessibleAnnouncementEvent event for \a object
+ to request the announcement of \a message with priority \l QAccessible::AnnouncementPriority::Polite.
+
+ \l QAccessibleAnnouncementEvent::setPriority can be used to adjust the priority.
+*/
+
+/*! \fn QAccessibleAnnouncementEvent::QAccessibleAnnouncementEvent(QAccessibleInterface *iface, const QString &message)
+
+ Constructs a new QAccessibleAnnouncementEvent event for \a iface
+ to request the announcement of \a message with priority \l QAccessible::AnnouncementPriority::Polite.
+
+ \l QAccessibleAnnouncementEvent::setPriority can be used to adjust the priority.
+*/
+
+/*! \fn QString QAccessibleAnnouncementEvent::message() const
+
+ Returns the message.
+*/
+
+/*! \fn QAccessible::AnnouncementPriority QAccessibleAnnouncementEvent::priority() const
+
+ Returns the priority.
+*/
+
+/*! \fn void QAccessibleAnnouncementEvent::setPriority(QAccessible::AnnouncementPriority priority)
+
+ Sets the priority with which the announcement will be requested to \a priority.
+*/
/*!
+ \internal
+*/
+QAccessibleAnnouncementEvent::~QAccessibleAnnouncementEvent()
+{
+}
+
+/*!
Returns the QAccessibleInterface associated with the event.
*/
QAccessibleInterface *QAccessibleEvent::accessibleInterface() const
@@ -3118,7 +3192,7 @@ bool QAccessibleSelectionInterface::isSelected(QAccessibleInterface *childItem)
Attributes are key-value pairs. Values are stored in \l QVariant.
- The \a QAccessible::Attributes enumeration describes the available keys and
+ The \l QAccessible::Attribute enumeration describes the available keys and
documents which type to use for the value of each key.
While the text-specific attributes handled by \l QAccessibleTextInterface::attributes
@@ -3151,8 +3225,11 @@ QAccessibleAttributesInterface::~QAccessibleAttributesInterface()
Returns the value of the attribute \a key of this object.
- If the specificed attribute is not set for this object, an invalid
- \l QVariant is returned.
+ If the attribute is set for this object, a value of the type documented for the
+ given key in the documentation of the \l QAccessible::Attribute enumeration is
+ returned in the \l QVariant.
+
+ Otherwise, an invalid \l QVariant is returned.
*/
/*! \internal */
diff --git a/src/gui/accessible/qaccessible.h b/src/gui/accessible/qaccessible.h
index 0a92e76c73..3d8daa4b3c 100644
--- a/src/gui/accessible/qaccessible.h
+++ b/src/gui/accessible/qaccessible.h
@@ -316,6 +316,7 @@ public:
Q_ASSERT(m_type != QAccessible::TextRemoved);
Q_ASSERT(m_type != QAccessible::TextUpdated);
Q_ASSERT(m_type != QAccessible::TableModelChanged);
+ Q_ASSERT(m_type != QAccessible::Announcement);
}
inline QAccessibleEvent(QAccessibleInterface *iface, QAccessible::Event typ)
@@ -330,6 +331,7 @@ public:
Q_ASSERT(m_type != QAccessible::TextRemoved);
Q_ASSERT(m_type != QAccessible::TextUpdated);
Q_ASSERT(m_type != QAccessible::TableModelChanged);
+ Q_ASSERT(m_type != QAccessible::Announcement);
m_uniqueId = QAccessible::uniqueId(iface);
m_object = iface->object();
}
@@ -605,6 +607,36 @@ protected:
int m_lastColumn;
};
+class Q_GUI_EXPORT QAccessibleAnnouncementEvent : public QAccessibleEvent
+{
+public:
+ inline QAccessibleAnnouncementEvent(QObject *object, const QString &message)
+ : QAccessibleEvent(object, QAccessible::InvalidEvent)
+ , m_message(message)
+ , m_priority(QAccessible::AnnouncementPriority::Polite)
+ {
+ m_type = QAccessible::Announcement;
+ }
+
+ inline QAccessibleAnnouncementEvent(QAccessibleInterface *iface, const QString &message)
+ : QAccessibleEvent(iface, QAccessible::InvalidEvent)
+ , m_message(message)
+ , m_priority(QAccessible::AnnouncementPriority::Polite)
+ {
+ m_type = QAccessible::Announcement;
+ }
+
+ ~QAccessibleAnnouncementEvent();
+
+ QString message() const { return m_message; }
+ QAccessible::AnnouncementPriority priority() const { return m_priority; }
+ void setPriority(QAccessible::AnnouncementPriority priority) { m_priority = priority; };
+
+protected:
+ QString m_message;
+ QAccessible::AnnouncementPriority m_priority;
+};
+
#ifndef Q_QDOC
#define QAccessibleInterface_iid "org.qt-project.Qt.QAccessibleInterface"
Q_DECLARE_INTERFACE(QAccessibleInterface, QAccessibleInterface_iid)
diff --git a/src/gui/accessible/qaccessible_base.h b/src/gui/accessible/qaccessible_base.h
index 2d2b1de316..1ca3dadc36 100644
--- a/src/gui/accessible/qaccessible_base.h
+++ b/src/gui/accessible/qaccessible_base.h
@@ -101,6 +101,7 @@ public:
HelpChanged = 0x80A0,
DefaultActionChanged = 0x80B0,
AcceleratorChanged = 0x80C0,
+ Announcement = 0x80D0,
InvalidEvent
};
@@ -367,6 +368,12 @@ public:
Level,
};
+ enum class AnnouncementPriority {
+ Polite,
+ Assertive
+ };
+ Q_ENUM(AnnouncementPriority)
+
typedef QAccessibleInterface*(*InterfaceFactory)(const QString &key, QObject*);
typedef void(*UpdateHandler)(QAccessibleEvent *event);
typedef void(*RootObjectHandler)(QObject*);
diff --git a/src/gui/accessible/qaccessiblebridge.cpp b/src/gui/accessible/qaccessiblebridge.cpp
index a8b54b0c68..0651c516ea 100644
--- a/src/gui/accessible/qaccessiblebridge.cpp
+++ b/src/gui/accessible/qaccessiblebridge.cpp
@@ -33,6 +33,8 @@ QT_BEGIN_NAMESPACE
Destroys the accessibility bridge object.
*/
+QAccessibleBridge::~QAccessibleBridge()
+ = default;
/*!
\fn void QAccessibleBridge::setRootObject(QAccessibleInterface *object)
diff --git a/src/gui/accessible/qaccessiblebridge.h b/src/gui/accessible/qaccessiblebridge.h
index 4d817c8e58..753f59597a 100644
--- a/src/gui/accessible/qaccessiblebridge.h
+++ b/src/gui/accessible/qaccessiblebridge.h
@@ -16,10 +16,10 @@ QT_BEGIN_NAMESPACE
class QAccessibleInterface;
class QAccessibleEvent;
-class QAccessibleBridge
+class Q_GUI_EXPORT QAccessibleBridge
{
public:
- virtual ~QAccessibleBridge() {}
+ virtual ~QAccessibleBridge();
virtual void setRootObject(QAccessibleInterface *) = 0;
virtual void notifyAccessibilityUpdate(QAccessibleEvent *event) = 0;
};
diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp
index 086ac37a07..82e78409f2 100644
--- a/src/gui/image/qicon.cpp
+++ b/src/gui/image/qicon.cpp
@@ -160,15 +160,16 @@ static inline int area(const QSize &s) { return s.width() * s.height(); }
// the 2x pixmaps then.)
static QPixmapIconEngineEntry *bestSizeScaleMatch(const QSize &size, qreal scale, QPixmapIconEngineEntry *pa, QPixmapIconEngineEntry *pb)
{
-
+ const auto scaleA = pa->pixmap.devicePixelRatio();
+ const auto scaleB = pb->pixmap.devicePixelRatio();
// scale: we can only differentiate on scale if the scale differs
- if (pa->scale != pb->scale) {
+ if (scaleA != scaleB) {
// Score the pixmaps: 0 is an exact scale match, positive
// scores have more detail than requested, negative scores
// have less detail than requested.
- qreal ascore = pa->scale - scale;
- qreal bscore = pb->scale - scale;
+ qreal ascore = scaleA - scale;
+ qreal bscore = scaleB - scale;
// always prefer positive scores to prevent upscaling
if ((ascore < 0) != (bscore < 0))
@@ -201,13 +202,14 @@ static QPixmapIconEngineEntry *bestSizeScaleMatch(const QSize &size, qreal scale
QPixmapIconEngineEntry *QPixmapIconEngine::tryMatch(const QSize &size, qreal scale, QIcon::Mode mode, QIcon::State state)
{
QPixmapIconEngineEntry *pe = nullptr;
- for (int i = 0; i < pixmaps.size(); ++i)
- if (pixmaps.at(i).mode == mode && pixmaps.at(i).state == state) {
+ for (auto &entry : pixmaps) {
+ if (entry.mode == mode && entry.state == state) {
if (pe)
- pe = bestSizeScaleMatch(size, scale, &pixmaps[i], pe);
+ pe = bestSizeScaleMatch(size, scale, &entry, pe);
else
- pe = &pixmaps[i];
+ pe = &entry;
}
+ }
return pe;
}
@@ -278,7 +280,7 @@ QPixmap QPixmapIconEngine::scaledPixmap(const QSize &size, QIcon::Mode mode, QIc
pm = pe->pixmap;
if (pm.isNull()) {
- int idx = pixmaps.size();
+ auto idx = pixmaps.size();
while (--idx >= 0) {
if (pe == &pixmaps.at(idx)) {
pixmaps.remove(idx);
@@ -369,7 +371,7 @@ void QPixmapIconEngine::addPixmap(const QPixmap &pixmap, QIcon::Mode mode, QIcon
{
if (!pixmap.isNull()) {
QPixmapIconEngineEntry *pe = tryMatch(pixmap.size(), pixmap.devicePixelRatio(), mode, state);
- if (pe && pe->size == pixmap.size() && pe->scale == pixmap.devicePixelRatio()) {
+ if (pe && pe->size == pixmap.size() && pe->pixmap.devicePixelRatio() == pixmap.devicePixelRatio()) {
pe->pixmap = pixmap;
pe->fileName.clear();
} else {
@@ -387,7 +389,7 @@ static inline int origIcoDepth(const QImage &image)
static inline int findBySize(const QList<QImage> &images, const QSize &size)
{
- for (int i = 0; i < images.size(); ++i) {
+ for (qsizetype i = 0; i < images.size(); ++i) {
if (images.at(i).size() == size)
return i;
}
@@ -862,7 +864,9 @@ QPixmap QIcon::pixmap(const QSize &size, Mode mode, State state) const
\since 6.0
Returns a pixmap with the requested \a size, \a devicePixelRatio, \a mode, and \a
- state, generating one if necessary.
+ state, generating one with the given \a mode and \a state if necessary. The pixmap
+ might be smaller than requested, but never larger, unless the device-pixel ratio
+ of the returned pixmap is larger than 1.
\sa actualSize(), paint()
*/
diff --git a/src/gui/image/qicon_p.h b/src/gui/image/qicon_p.h
index c5bf120620..dfce2d5b53 100644
--- a/src/gui/image/qicon_p.h
+++ b/src/gui/image/qicon_p.h
@@ -49,24 +49,22 @@ public:
struct QPixmapIconEngineEntry
{
- QPixmapIconEngineEntry():scale(1), mode(QIcon::Normal), state(QIcon::Off){}
- QPixmapIconEngineEntry(const QPixmap &pm, QIcon::Mode m = QIcon::Normal, QIcon::State s = QIcon::Off)
- :pixmap(pm), size(pm.size()), scale(pm.devicePixelRatio()), mode(m), state(s){}
- QPixmapIconEngineEntry(const QString &file, const QSize &sz = QSize(), QIcon::Mode m = QIcon::Normal, QIcon::State s = QIcon::Off)
- :fileName(file), size(sz), scale(1), mode(m), state(s){}
- QPixmapIconEngineEntry(const QString &file, const QImage &image, QIcon::Mode m = QIcon::Normal, QIcon::State s = QIcon::Off);
+ QPixmapIconEngineEntry() = default;
+ QPixmapIconEngineEntry(const QPixmap &pm, QIcon::Mode m, QIcon::State s)
+ : pixmap(pm), size(pm.size()), mode(m), state(s) {}
+ QPixmapIconEngineEntry(const QString &file, const QSize &sz, QIcon::Mode m, QIcon::State s)
+ : fileName(file), size(sz), mode(m), state(s) {}
+ QPixmapIconEngineEntry(const QString &file, const QImage &image, QIcon::Mode m, QIcon::State s);
QPixmap pixmap;
QString fileName;
QSize size;
- qreal scale;
- QIcon::Mode mode;
- QIcon::State state;
- bool isNull() const {return (fileName.isEmpty() && pixmap.isNull()); }
+ QIcon::Mode mode = QIcon::Normal;
+ QIcon::State state = QIcon::Off;
};
Q_DECLARE_TYPEINFO(QPixmapIconEngineEntry, Q_RELOCATABLE_TYPE);
inline QPixmapIconEngineEntry::QPixmapIconEngineEntry(const QString &file, const QImage &image, QIcon::Mode m, QIcon::State s)
- : fileName(file), size(image.size()), scale(image.devicePixelRatio()), mode(m), state(s)
+ : fileName(file), size(image.size()), mode(m), state(s)
{
pixmap.convertFromImage(image);
}
diff --git a/src/gui/image/qiconengine.h b/src/gui/image/qiconengine.h
index 61411b0660..f5c5184608 100644
--- a/src/gui/image/qiconengine.h
+++ b/src/gui/image/qiconengine.h
@@ -18,6 +18,7 @@ public:
virtual ~QIconEngine();
virtual void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) = 0;
virtual QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state);
+ // ### Qt7: add qreal scale argument and remove scaledPixmap
virtual QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state);
virtual void addPixmap(const QPixmap &pixmap, QIcon::Mode mode, QIcon::State state);
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index c97374e975..5228ac9477 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -3447,6 +3447,15 @@ void QGuiApplicationPrivate::updatePalette()
}
}
+QEvent::Type QGuiApplicationPrivate::contextMenuEventType()
+{
+ switch (QGuiApplication::styleHints()->contextMenuTrigger()) {
+ case Qt::ContextMenuTrigger::Press: return QEvent::MouseButtonPress;
+ case Qt::ContextMenuTrigger::Release: return QEvent::MouseButtonRelease;
+ }
+ return QEvent::None;
+}
+
void QGuiApplicationPrivate::clearPalette()
{
delete app_pal;
@@ -4392,6 +4401,9 @@ void *QGuiApplication::resolveInterface(const char *name, int revision) const
#if QT_CONFIG(wayland)
QT_NATIVE_INTERFACE_RETURN_IF(QWaylandApplication, platformNativeInterface());
#endif
+#if defined(Q_OS_VISIONOS)
+ QT_NATIVE_INTERFACE_RETURN_IF(QVisionOSApplication, platformIntegration);
+#endif
return QCoreApplication::resolveInterface(name, revision);
}
diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h
index cca79534fc..39c490c581 100644
--- a/src/gui/kernel/qguiapplication_p.h
+++ b/src/gui/kernel/qguiapplication_p.h
@@ -323,6 +323,8 @@ public:
static void updatePalette();
+ static QEvent::Type contextMenuEventType();
+
protected:
virtual void handleThemeChanged();
diff --git a/src/gui/kernel/qguiapplication_platform.h b/src/gui/kernel/qguiapplication_platform.h
index 545bf75c84..d9ff01bf14 100644
--- a/src/gui/kernel/qguiapplication_platform.h
+++ b/src/gui/kernel/qguiapplication_platform.h
@@ -32,6 +32,22 @@ struct wl_pointer;
struct wl_touch;
#endif
+#if defined(Q_OS_VISIONOS) || defined(Q_QDOC)
+# ifdef __OBJC__
+Q_FORWARD_DECLARE_OBJC_CLASS(CP_OBJECT_cp_layer_renderer_capabilities);
+typedef CP_OBJECT_cp_layer_renderer_capabilities *cp_layer_renderer_capabilities_t;
+Q_FORWARD_DECLARE_OBJC_CLASS(CP_OBJECT_cp_layer_renderer_configuration);
+typedef CP_OBJECT_cp_layer_renderer_configuration *cp_layer_renderer_configuration_t;
+Q_FORWARD_DECLARE_OBJC_CLASS(CP_OBJECT_cp_layer_renderer);
+typedef CP_OBJECT_cp_layer_renderer *cp_layer_renderer_t;
+# else
+typedef struct cp_layer_renderer_capabilities_s *cp_layer_renderer_capabilities_t;
+typedef struct cp_layer_renderer_configuration_s *cp_layer_renderer_configuration_t;
+typedef struct cp_layer_renderer_s *cp_layer_renderer_t;
+# endif
+#endif
+
+
QT_BEGIN_NAMESPACE
namespace QNativeInterface
@@ -61,6 +77,20 @@ struct Q_GUI_EXPORT QWaylandApplication
};
#endif
+#if defined(Q_OS_VISIONOS) || defined(Q_QDOC)
+struct Q_GUI_EXPORT QVisionOSApplication
+{
+ QT_DECLARE_NATIVE_INTERFACE(QVisionOSApplication, 1, QGuiApplication)
+ struct ImmersiveSpaceCompositorLayer {
+ virtual void configure(cp_layer_renderer_capabilities_t, cp_layer_renderer_configuration_t) const {}
+ virtual void render(cp_layer_renderer_t) = 0;
+ };
+ virtual void setImmersiveSpaceCompositorLayer(ImmersiveSpaceCompositorLayer *layer) = 0;
+ virtual void openImmersiveSpace() = 0;
+ virtual void dismissImmersiveSpace() = 0;
+};
+#endif
+
} // QNativeInterface
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qhighdpiscaling_p.h b/src/gui/kernel/qhighdpiscaling_p.h
index 189f31fd0a..d6deb8a72a 100644
--- a/src/gui/kernel/qhighdpiscaling_p.h
+++ b/src/gui/kernel/qhighdpiscaling_p.h
@@ -172,7 +172,7 @@ inline QMargins scale(const QMargins &margins, qreal scaleFactor, QPoint origin
template<typename T>
QList<T> scale(const QList<T> &list, qreal scaleFactor, QPoint origin = QPoint(0, 0))
{
- if (!QHighDpiScaling::isActive())
+ if (qFuzzyCompare(scaleFactor, qreal(1)))
return list;
QList<T> scaled;
@@ -184,7 +184,7 @@ QList<T> scale(const QList<T> &list, qreal scaleFactor, QPoint origin = QPoint(0
inline QRegion scale(const QRegion &region, qreal scaleFactor, QPoint origin = QPoint(0, 0))
{
- if (!QHighDpiScaling::isActive())
+ if (qFuzzyCompare(scaleFactor, qreal(1)))
return region;
QRegion scaled = region.translated(-origin);
diff --git a/src/gui/kernel/qpalette.cpp b/src/gui/kernel/qpalette.cpp
index 256ea52f01..e308b796ab 100644
--- a/src/gui/kernel/qpalette.cpp
+++ b/src/gui/kernel/qpalette.cpp
@@ -958,7 +958,10 @@ static constexpr QPalette::ResolveMask allResolveMask()
/*!
Returns a new QPalette that is a union of this instance and \a other.
- Color roles set in this instance take precedence.
+ Color roles set in this instance take precedence. Roles that are not
+ set in this instance will be taken from \a other.
+
+ \sa isBrushSet
*/
QPalette QPalette::resolve(const QPalette &other) const
{
diff --git a/src/gui/kernel/qstylehints.cpp b/src/gui/kernel/qstylehints.cpp
index 0d15d114ec..73c6199733 100644
--- a/src/gui/kernel/qstylehints.cpp
+++ b/src/gui/kernel/qstylehints.cpp
@@ -443,6 +443,40 @@ void QStyleHints::setShowShortcutsInContextMenus(bool s)
}
/*!
+ \property QStyleHints::contextMenuTrigger
+ \since 6.8
+ \brief mouse event used to trigger a context menu event.
+
+ The default on UNIX systems is to show context menu on mouse button press event, while on
+ Windows it is the mouse button release event. This property can be used to override the default
+ platform behavior.
+
+ \note Developers must use this property with great care, as it changes the default interaction
+ mode that their users will expect on the platform that they are running on.
+
+ \sa Qt::ContextMenuTrigger
+*/
+Qt::ContextMenuTrigger QStyleHints::contextMenuTrigger() const
+{
+ Q_D(const QStyleHints);
+ if (d->m_contextMenuTrigger == -1) {
+ return themeableHint(QPlatformTheme::ContextMenuOnMouseRelease).toBool()
+ ? Qt::ContextMenuTrigger::Release
+ : Qt::ContextMenuTrigger::Press;
+ }
+ return Qt::ContextMenuTrigger(d->m_contextMenuTrigger);
+}
+
+void QStyleHints::setContextMenuTrigger(Qt::ContextMenuTrigger contextMenuTrigger)
+{
+ Q_D(QStyleHints);
+ const Qt::ContextMenuTrigger currentTrigger = this->contextMenuTrigger();
+ d->m_contextMenuTrigger = int(contextMenuTrigger);
+ if (currentTrigger != contextMenuTrigger)
+ emit contextMenuTriggerChanged(contextMenuTrigger);
+}
+
+/*!
\property QStyleHints::passwordMaskDelay
\brief the time, in milliseconds, a typed letter is displayed unshrouded
in a text input field in password mode.
diff --git a/src/gui/kernel/qstylehints.h b/src/gui/kernel/qstylehints.h
index 8981383060..97ef59f3cf 100644
--- a/src/gui/kernel/qstylehints.h
+++ b/src/gui/kernel/qstylehints.h
@@ -36,6 +36,8 @@ class Q_GUI_EXPORT QStyleHints : public QObject
Q_PROPERTY(bool showIsMaximized READ showIsMaximized STORED false CONSTANT FINAL)
Q_PROPERTY(bool showShortcutsInContextMenus READ showShortcutsInContextMenus
WRITE setShowShortcutsInContextMenus NOTIFY showShortcutsInContextMenusChanged FINAL)
+ Q_PROPERTY(Qt::ContextMenuTrigger contextMenuTrigger READ contextMenuTrigger WRITE
+ setContextMenuTrigger NOTIFY contextMenuTriggerChanged FINAL)
Q_PROPERTY(int startDragDistance READ startDragDistance NOTIFY startDragDistanceChanged FINAL)
Q_PROPERTY(int startDragTime READ startDragTime NOTIFY startDragTimeChanged FINAL)
Q_PROPERTY(int startDragVelocity READ startDragVelocity STORED false CONSTANT FINAL)
@@ -80,6 +82,8 @@ public:
bool showIsMaximized() const;
bool showShortcutsInContextMenus() const;
void setShowShortcutsInContextMenus(bool showShortcutsInContextMenus);
+ Qt::ContextMenuTrigger contextMenuTrigger() const;
+ void setContextMenuTrigger(Qt::ContextMenuTrigger contextMenuTrigger);
int passwordMaskDelay() const;
QChar passwordMaskCharacter() const;
qreal fontSmoothingGamma() const;
@@ -108,6 +112,7 @@ Q_SIGNALS:
void tabFocusBehaviorChanged(Qt::TabFocusBehavior tabFocusBehavior);
void useHoverEffectsChanged(bool useHoverEffects);
void showShortcutsInContextMenusChanged(bool);
+ void contextMenuTriggerChanged(Qt::ContextMenuTrigger contextMenuTrigger);
void wheelScrollLinesChanged(int scrollLines);
void mouseQuickSelectionThresholdChanged(int threshold);
void colorSchemeChanged(Qt::ColorScheme colorScheme);
diff --git a/src/gui/kernel/qstylehints_p.h b/src/gui/kernel/qstylehints_p.h
index 2b3979512a..497bf95cbf 100644
--- a/src/gui/kernel/qstylehints_p.h
+++ b/src/gui/kernel/qstylehints_p.h
@@ -35,6 +35,7 @@ public:
int m_tabFocusBehavior = -1;
int m_uiEffects = -1;
int m_showShortcutsInContextMenus = -1;
+ int m_contextMenuTrigger = -1;
int m_wheelScrollLines = -1;
int m_mouseQuickSelectionThreshold = -1;
int m_mouseDoubleClickDistance = -1;
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index b40fd7e8e8..7c885032c7 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -2654,16 +2654,14 @@ bool QWindow::event(QEvent *ev)
This logic could be simplified by always synthesizing events in
QGuiApplicationPrivate, or perhaps even in each QPA plugin. See QTBUG-93486.
*/
- static const QEvent::Type contextMenuTrigger =
- QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::ContextMenuOnMouseRelease).toBool() ?
- QEvent::MouseButtonRelease : QEvent::MouseButtonPress;
auto asMouseEvent = [](QEvent *ev) {
const auto t = ev->type();
return t == QEvent::MouseButtonPress || t == QEvent::MouseButtonRelease
? static_cast<QMouseEvent *>(ev) : nullptr ;
};
- if (QMouseEvent *me = asMouseEvent(ev); me &&
- ev->type() == contextMenuTrigger && me->button() == Qt::RightButton) {
+ if (QMouseEvent *me = asMouseEvent(ev);
+ me && ev->type() == QGuiApplicationPrivate::contextMenuEventType()
+ && me->button() == Qt::RightButton) {
QContextMenuEvent e(QContextMenuEvent::Mouse, me->position().toPoint(),
me->globalPosition().toPoint(), me->modifiers());
QGuiApplication::sendEvent(this, &e);
diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp
index 2304ee2256..3b709ec77b 100644
--- a/src/gui/painting/qbackingstore.cpp
+++ b/src/gui/painting/qbackingstore.cpp
@@ -50,6 +50,7 @@ public:
QScopedPointer<QImage> highDpiBackingstore;
QRegion staticContents;
QSize size;
+ QSize nativeSize;
bool downscale = qEnvironmentVariableIntValue("QT_WIDGETS_HIGHDPI_DOWNSCALE") > 0;
};
@@ -115,14 +116,13 @@ QWindow* QBackingStore::window() const
void QBackingStore::beginPaint(const QRegion &region)
{
- const qreal dpr = d_ptr->backingStoreDevicePixelRatio();
+ const qreal toNativeFactor = d_ptr->deviceIndependentToNativeFactor();
- if (d_ptr->highDpiBackingstore &&
- d_ptr->highDpiBackingstore->devicePixelRatio() != dpr)
+ if (d_ptr->nativeSize != QHighDpi::scale(size(), toNativeFactor))
resize(size());
QPlatformBackingStore *platformBackingStore = handle();
- platformBackingStore->beginPaint(QHighDpi::scale(region, d_ptr->deviceIndependentToNativeFactor()));
+ platformBackingStore->beginPaint(QHighDpi::scale(region, toNativeFactor));
// When QtGui is applying a high-dpi scale factor the backing store
// creates a "large" backing store image. This image needs to be
@@ -131,18 +131,20 @@ void QBackingStore::beginPaint(const QRegion &region)
// the image data to avoid having the new devicePixelRatio be propagated
// back to the platform plugin.
QPaintDevice *device = platformBackingStore->paintDevice();
- if (QHighDpiScaling::isActive() && device->devType() == QInternal::Image) {
+ if (!qFuzzyCompare(toNativeFactor, qreal(1)) && device->devType() == QInternal::Image) {
QImage *source = static_cast<QImage *>(device);
const bool needsNewImage = d_ptr->highDpiBackingstore.isNull()
- || source->data_ptr() != d_ptr->highDpiBackingstore->data_ptr()
+ || source->constBits() != d_ptr->highDpiBackingstore->constBits()
|| source->size() != d_ptr->highDpiBackingstore->size()
- || source->devicePixelRatio() != d_ptr->highDpiBackingstore->devicePixelRatio();
- if (needsNewImage) {
+ || source->bytesPerLine() != d_ptr->highDpiBackingstore->bytesPerLine()
+ || source->format() != d_ptr->highDpiBackingstore->format();
+ if (needsNewImage)
d_ptr->highDpiBackingstore.reset(
new QImage(source->bits(), source->width(), source->height(), source->bytesPerLine(), source->format()));
- d_ptr->highDpiBackingstore->setDevicePixelRatio(dpr);
- }
+ d_ptr->highDpiBackingstore->setDevicePixelRatio(d_ptr->backingStoreDevicePixelRatio());
+ } else {
+ d_ptr->highDpiBackingstore.reset();
}
}
@@ -156,7 +158,7 @@ QPaintDevice *QBackingStore::paintDevice()
{
QPaintDevice *device = handle()->paintDevice();
- if (QHighDpiScaling::isActive() && device->devType() == QInternal::Image)
+ if (!qFuzzyCompare(d_ptr->deviceIndependentToNativeFactor(), qreal(1)) && device->devType() == QInternal::Image)
return d_ptr->highDpiBackingstore.data();
return device;
@@ -229,9 +231,10 @@ void QBackingStore::flush(const QRegion &region, QWindow *window, const QPoint &
*/
void QBackingStore::resize(const QSize &size)
{
- d_ptr->size = size;
const qreal factor = d_ptr->deviceIndependentToNativeFactor();
- handle()->resize(QHighDpi::scale(size, factor), QHighDpi::scale(d_ptr->staticContents, factor));
+ d_ptr->size = size;
+ d_ptr->nativeSize = QHighDpi::scale(size, factor);
+ handle()->resize(d_ptr->nativeSize, QHighDpi::scale(d_ptr->staticContents, factor));
}
/*!
diff --git a/src/gui/painting/qbackingstorerhisupport.cpp b/src/gui/painting/qbackingstorerhisupport.cpp
index fe5589dc2d..37c52155eb 100644
--- a/src/gui/painting/qbackingstorerhisupport.cpp
+++ b/src/gui/painting/qbackingstorerhisupport.cpp
@@ -114,8 +114,8 @@ bool QBackingStoreRhiSupport::create()
if (QRhi::probe(QRhi::Metal, &params)) {
rhi = QRhi::create(QRhi::Metal, &params, flags);
} else {
- qCDebug(lcQpaBackingStore, "Metal does not seem to be supported. Falling back to OpenGL.");
- rhi = QRhi::create(QRhi::OpenGLES2, &params, flags);
+ qCDebug(lcQpaBackingStore, "Metal does not seem to be supported");
+ return false;
}
}
#endif
diff --git a/src/gui/painting/qcolorspace.cpp b/src/gui/painting/qcolorspace.cpp
index 7a1d34a408..f21e6ec738 100644
--- a/src/gui/painting/qcolorspace.cpp
+++ b/src/gui/painting/qcolorspace.cpp
@@ -448,11 +448,15 @@ QColorTransform QColorSpacePrivate::transformationToXYZ() const
transform.d = ptr;
ptr->colorSpaceIn = this;
ptr->colorSpaceOut = this;
- // Convert to XYZ relative to our white point, not the regular D50 white point.
if (isThreeComponentMatrix())
- ptr->colorMatrix = QColorMatrix::chromaticAdaptation(whitePoint).inverted() * toXyz;
+ ptr->colorMatrix = toXyz;
else
ptr->colorMatrix = QColorMatrix::identity();
+ // Convert to XYZ relative to our white point, not the regular D50 white point.
+ if (!chad.isNull())
+ ptr->colorMatrix = chad.inverted() * ptr->colorMatrix;
+ else if (!whitePoint.isNull())
+ ptr->colorMatrix = QColorMatrix::chromaticAdaptation(whitePoint).inverted() * ptr->colorMatrix;
return transform;
}
diff --git a/src/gui/painting/qcolortransform.cpp b/src/gui/painting/qcolortransform.cpp
index aac07bdc09..33b1dcdeb0 100644
--- a/src/gui/painting/qcolortransform.cpp
+++ b/src/gui/painting/qcolortransform.cpp
@@ -1640,7 +1640,7 @@ void QColorTransformPrivate::applyConvertIn(const S *src, QColorVector *buffer,
loadUnpremultiplied(buffer, src, len, this);
if (!colorSpaceOut->isThreeComponentMatrix())
- applyMatrix<DoClamp>(buffer, len, colorMatrix); // colorMatrix should have the first half only.
+ applyMatrix<DoClamp>(buffer, len, colorSpaceIn->toXyz);
return;
}
}
@@ -1666,7 +1666,7 @@ void QColorTransformPrivate::applyConvertOut(D *dst, const S *src, QColorVector
// Avoid compiling this part for D=QCmyk32:
if constexpr (!std::is_same_v<D, QCmyk32>) {
if (colorSpaceOut->isThreeComponentMatrix()) {
- applyMatrix<doClamp>(buffer, len, colorMatrix); // colorMatrix should have the latter half only.
+ applyMatrix<doClamp>(buffer, len, colorMatrix);
if constexpr (std::is_same_v<S, QCmyk32>) {
storeOpaque(dst, buffer, len, this);
@@ -1695,14 +1695,34 @@ void QColorTransformPrivate::applyConvertOut(D *dst, const S *src, QColorVector
storeUnpremultipliedLUT(dst, src, buffer, len);
}
-template<typename D, typename S>
-void QColorTransformPrivate::applyElementListTransform(D *dst, const S *src, qsizetype count, TransformFlags flags) const
+/*!
+ \internal
+ Adapt Profile Connecting Color spaces.
+*/
+void QColorTransformPrivate::pcsAdapt(QColorVector *buffer, qsizetype count) const
{
- Q_ASSERT(!colorSpaceIn->isThreeComponentMatrix() || !colorSpaceOut->isThreeComponentMatrix());
+ // Match Profile Connection Spaces (PCS):
+ if (colorSpaceOut->isPcsLab && !colorSpaceIn->isPcsLab) {
+ for (qsizetype j = 0; j < count; ++j)
+ buffer[j] = buffer[j].xyzToLab();
+ } else if (colorSpaceIn->isPcsLab && !colorSpaceOut->isPcsLab) {
+ for (qsizetype j = 0; j < count; ++j)
+ buffer[j] = buffer[j].labToXyz();
+ }
+}
- if (!colorMatrix.isValid())
- return;
+/*!
+ \internal
+ Applies the color transformation on \a count S pixels starting from
+ \a src and stores the result in \a dst as D pixels .
+ Assumes unpremultiplied data by default. Set \a flags to change defaults.
+
+ \sa prepare()
+*/
+template<typename D, typename S>
+void QColorTransformPrivate::apply(D *dst, const S *src, qsizetype count, TransformFlags flags) const
+{
if (colorSpaceIn->isThreeComponentMatrix())
updateLutsIn();
if (colorSpaceOut->isThreeComponentMatrix())
@@ -1715,14 +1735,7 @@ void QColorTransformPrivate::applyElementListTransform(D *dst, const S *src, qsi
applyConvertIn(src + i, buffer, len, flags);
- // Match Profile Connection Spaces (PCS):
- if (colorSpaceOut->isPcsLab && !colorSpaceIn->isPcsLab) {
- for (qsizetype j = 0; j < len; ++j)
- buffer[j] = buffer[j].xyzToLab();
- } else if (colorSpaceIn->isPcsLab && !colorSpaceOut->isPcsLab) {
- for (qsizetype j = 0; j < len; ++j)
- buffer[j] = buffer[j].labToXyz();
- }
+ pcsAdapt(buffer, len);
applyConvertOut(dst + i, src + i, buffer, len, flags);
@@ -1730,64 +1743,6 @@ void QColorTransformPrivate::applyElementListTransform(D *dst, const S *src, qsi
}
}
-template<typename D, typename S>
-void QColorTransformPrivate::applyThreeComponentMatrix(D *dst, const S *src, qsizetype count, TransformFlags flags) const
-{
- Q_ASSERT(colorSpaceIn->isThreeComponentMatrix() && colorSpaceOut->isThreeComponentMatrix());
-
- if (!colorMatrix.isValid())
- return;
-
- updateLutsIn();
- updateLutsOut();
-
- bool doApplyMatrix = !colorMatrix.isIdentity();
- constexpr ApplyMatrixForm doClamp = (std::is_same_v<D, QRgbaFloat16> || std::is_same_v<D, QRgbaFloat32>) ? DoNotClamp : DoClamp;
-
- QUninitialized<QColorVector, WorkBlockSize> buffer;
- qsizetype i = 0;
- while (i < count) {
- const qsizetype len = qMin(count - i, WorkBlockSize);
- if (flags & InputPremultiplied)
- loadPremultiplied(buffer, src + i, len, this);
- else
- loadUnpremultiplied(buffer, src + i, len, this);
-
- if (doApplyMatrix)
- applyMatrix<doClamp>(buffer, len, colorMatrix);
- else
- clampIfNeeded<doClamp>(buffer, len);
-
- if (flags & InputOpaque)
- storeOpaque(dst + i, buffer, len, this);
- else if (flags & OutputPremultiplied)
- storePremultiplied(dst + i, src + i, buffer, len, this);
- else
- storeUnpremultiplied(dst + i, src + i, buffer, len, this);
-
- i += len;
- }
-}
-
-/*!
- \internal
- Applies the color transformation on \a count S pixels starting from
- \a src and stores the result in \a dst as D pixels .
-
- Assumes unpremultiplied data by default. Set \a flags to change defaults.
-
- \sa prepare()
-*/
-template<typename D, typename S>
-void QColorTransformPrivate::apply(D *dst, const S *src, qsizetype count, TransformFlags flags) const
-{
- if constexpr (!std::is_same_v<D, QCmyk32> && !std::is_same_v<S, QCmyk32>) {
- if (isThreeComponentMatrix())
- return applyThreeComponentMatrix<D, S>(dst, src, count, flags);
- }
- applyElementListTransform<D, S>(dst, src, count, flags);
-}
-
/*!
\internal
Is to be called on a color-transform to XYZ, returns only luminance values.
@@ -1970,15 +1925,6 @@ template void QColorTransformPrivate::apply<QRgbaFloat32, QCmyk32>(QRgbaFloat32
template void QColorTransformPrivate::apply<QRgbaFloat32, QRgba64>(QRgbaFloat32 *dst, const QRgba64 *src, qsizetype count, TransformFlags flags) const;
template void QColorTransformPrivate::apply<QRgbaFloat32, QRgbaFloat32>(QRgbaFloat32 *dst, const QRgbaFloat32 *src, qsizetype count, TransformFlags flags) const;
-bool QColorTransformPrivate::isThreeComponentMatrix() const
-{
- if (colorSpaceIn && !colorSpaceIn->isThreeComponentMatrix())
- return false;
- if (colorSpaceOut && !colorSpaceOut->isThreeComponentMatrix())
- return false;
- return true;
-}
-
/*!
\internal
*/
@@ -1991,7 +1937,7 @@ bool QColorTransformPrivate::isIdentity() const
if (colorSpaceIn && colorSpaceOut) {
if (colorSpaceIn->equals(colorSpaceOut.constData()))
return true;
- if (!isThreeComponentMatrix())
+ if (!colorSpaceIn->isThreeComponentMatrix() || !colorSpaceOut->isThreeComponentMatrix())
return false;
if (colorSpaceIn->transferFunction != colorSpaceOut->transferFunction)
return false;
@@ -2001,7 +1947,9 @@ bool QColorTransformPrivate::isIdentity() const
&& colorSpaceIn->trc[2] == colorSpaceOut->trc[2];
}
} else {
- if (!isThreeComponentMatrix())
+ if (colorSpaceIn && !colorSpaceIn->isThreeComponentMatrix())
+ return false;
+ if (colorSpaceOut && !colorSpaceOut->isThreeComponentMatrix())
return false;
if (colorSpaceIn && colorSpaceIn->transferFunction != QColorSpace::TransferFunction::Linear)
return false;
diff --git a/src/gui/painting/qcolortransform_p.h b/src/gui/painting/qcolortransform_p.h
index 59ea6a2405..c74fe100eb 100644
--- a/src/gui/painting/qcolortransform_p.h
+++ b/src/gui/painting/qcolortransform_p.h
@@ -37,7 +37,6 @@ public:
void updateLutsIn() const;
void updateLutsOut() const;
bool isIdentity() const;
- bool isThreeComponentMatrix() const;
Q_GUI_EXPORT void prepare();
enum TransformFlag {
@@ -60,14 +59,11 @@ public:
void applyReturnGray(D *dst, const S *src, qsizetype count, TransformFlags flags) const;
private:
+ void pcsAdapt(QColorVector *buffer, qsizetype len) const;
template<typename S>
void applyConvertIn(const S *src, QColorVector *buffer, qsizetype len, TransformFlags flags) const;
template<typename D, typename S>
void applyConvertOut(D *dst, const S *src, QColorVector *buffer, qsizetype len, TransformFlags flags) const;
- template<typename D, typename S>
- void applyElementListTransform(D *dst, const S *src, qsizetype count, TransformFlags flags) const;
- template<typename D, typename S>
- void applyThreeComponentMatrix(D *dst, const S *src, qsizetype count, TransformFlags flags) const;
};
QT_END_NAMESPACE
diff --git a/src/gui/painting/qicc.cpp b/src/gui/painting/qicc.cpp
index c01fa433ea..a2786fbb8b 100644
--- a/src/gui/painting/qicc.cpp
+++ b/src/gui/painting/qicc.cpp
@@ -559,6 +559,8 @@ static bool parseXyzData(const QByteArray &data, const TagEntry &tagEntry, QColo
static quint32 parseTRC(const QByteArrayView &tagData, QColorTrc &gamma, QColorTransferTable::Type type = QColorTransferTable::TwoWay)
{
+ if (tagData.size() < 12)
+ return 0;
const GenericTagData trcData = qFromUnaligned<GenericTagData>(tagData.constData());
if (trcData.type == quint32(Tag::curv)) {
Q_STATIC_ASSERT(sizeof(CurvTagData) == 12);
@@ -1067,6 +1069,8 @@ static bool parseDesc(const QByteArray &data, const TagEntry &tagEntry, QString
// Either 'desc' (ICCv2) or 'mluc' (ICCv4)
if (tag.type == quint32(Tag::desc)) {
+ if (tagEntry.size < sizeof(DescTagData))
+ return false;
Q_STATIC_ASSERT(sizeof(DescTagData) == 12);
const DescTagData desc = qFromUnaligned<DescTagData>(data.constData() + tagEntry.offset);
const quint32 len = desc.asciiDescriptionLength;
@@ -1287,7 +1291,7 @@ bool fromIccProfile(const QByteArray &data, QColorSpace *colorSpace)
qCWarning(lcIcc) << "fromIccProfile: failed tag offset sanity 2";
return false;
}
- if (tagTable.size < 12) {
+ if (tagTable.size < 8) {
qCWarning(lcIcc) << "fromIccProfile: failed minimal tag size sanity";
return false;
}
diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp
index 38f2a9b803..ccb8148d72 100644
--- a/src/gui/painting/qpdf.cpp
+++ b/src/gui/painting/qpdf.cpp
@@ -1035,6 +1035,7 @@ void QPdfEngine::drawTextItem(const QPointF &p, const QTextItem &textItem)
*d->currentPage << "Q\n";
}
+// Used by QtWebKit
void QPdfEngine::drawHyperlink(const QRectF &r, const QUrl &url)
{
Q_D(QPdfEngine);
diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp
index 8b712ee46d..f9089d7bba 100644
--- a/src/gui/painting/qregion.cpp
+++ b/src/gui/painting/qregion.cpp
@@ -876,9 +876,15 @@ QRegion QRegion::intersect(const QRect &r) const
/*!
\fn void QRegion::setRects(const QRect *rects, int number)
+ \overload
+ \obsolete Use the QSpan overload instead.
+*/
+
+/*!
+ \fn void QRegion::setRects(QSpan<const QRect> rects)
+ \since 6.8
- Sets the region using the array of rectangles specified by \a rects and
- \a number.
+ Sets the region using the array of rectangles specified by \a rects.
The rectangles \e must be optimally Y-X sorted and follow these restrictions:
\list
@@ -892,6 +898,11 @@ QRegion QRegion::intersect(const QRect &r) const
\omit
Only some platforms have these restrictions (Qt for Embedded Linux, X11 and \macos).
\endomit
+
+ \note For historical reasons, \c{rects.size()} must be less than \c{INT_MAX}
+ (see rectCount()).
+
+ \sa rects()
*/
namespace {
@@ -4214,18 +4225,39 @@ QRegion::const_iterator QRegion::end() const noexcept
return d->qt_rgn ? d->qt_rgn->end() : nullptr;
}
-void QRegion::setRects(const QRect *rects, int num)
+static Q_DECL_COLD_FUNCTION
+void set_rects_warn(const char *what)
+{
+ qWarning("QRegion::setRects(): %s", what);
+}
+
+void QRegion::setRects(const QRect *r, int n)
{
+ if (!r && n) { // old setRects() allowed this, but QSpan doesn't
+ set_rects_warn("passing num != 0 when rects == nullptr is deprecated.");
+ n = 0;
+ }
+ setRects(QSpan<const QRect>(r, n));
+}
+
+void QRegion::setRects(QSpan<const QRect> rects)
+{
+ const auto num = int(rects.size());
+ if (num != rects.size()) {
+ set_rects_warn("span size exceeds INT_MAX, ignoring");
+ return;
+ }
+
*this = QRegion();
- if (!rects || num == 0 || (num == 1 && rects->isEmpty()))
+ if (!rects.data() || num == 0 || (num == 1 && rects.front().isEmpty()))
return;
detach();
d->qt_rgn->numRects = num;
if (num == 1) {
- d->qt_rgn->extents = *rects;
- d->qt_rgn->innerRect = *rects;
+ d->qt_rgn->extents = rects.front();
+ d->qt_rgn->innerRect = rects.front();
} else {
d->qt_rgn->rects.resize(num);
@@ -4246,12 +4278,30 @@ void QRegion::setRects(const QRect *rects, int num)
}
}
+/*!
+ \since 6.8
+
+ Returns a span of non-overlapping rectangles that make up the region. The
+ span remains valid until the next call of a mutating (non-const) method on
+ this region.
+
+ The union of all the rectangles is equal to the original region.
+
+ \note This functions existed in Qt 5, too, but returned QVector<QRect>
+ instead.
+
+ \sa setRects()
+*/
+QSpan<const QRect> QRegion::rects() const noexcept
+{
+ return {begin(), end()};
+};
+
int QRegion::rectCount() const noexcept
{
return (d->qt_rgn ? d->qt_rgn->numRects : 0);
}
-
bool QRegion::operator==(const QRegion &r) const
{
if (!d->qt_rgn)
diff --git a/src/gui/painting/qregion.h b/src/gui/painting/qregion.h
index b0051b6067..4b852815f3 100644
--- a/src/gui/painting/qregion.h
+++ b/src/gui/painting/qregion.h
@@ -8,11 +8,11 @@
#include <QtCore/qatomic.h>
#include <QtCore/qrect.h>
#include <QtGui/qwindowdefs.h>
-#include <QtCore/qcontainerfwd.h>
#ifndef QT_NO_DATASTREAM
#include <QtCore/qdatastream.h>
#endif
+#include <QtCore/qspan.h>
QT_BEGIN_NAMESPACE
@@ -75,6 +75,8 @@ public:
QRect boundingRect() const noexcept;
void setRects(const QRect *rect, int num);
+ void setRects(QSpan<const QRect> r);
+ QSpan<const QRect> rects() const noexcept;
int rectCount() const noexcept;
QRegion operator|(const QRegion &r) const;
diff --git a/src/gui/platform/ios/qiosnativeinterface.cpp b/src/gui/platform/ios/qiosnativeinterface.cpp
new file mode 100644
index 0000000000..c942709e33
--- /dev/null
+++ b/src/gui/platform/ios/qiosnativeinterface.cpp
@@ -0,0 +1,26 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include <QtGui/private/qguiapplication_p.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QNativeInterface::Private;
+
+#if defined(Q_OS_VISIONOS)
+
+/*!
+ \class QNativeInterface::QVisionOSApplication
+ \since 6.8
+ \internal
+ \preliminary
+ \brief Native interface to QGuiApplication, to be retrieved from QPlatformIntegration.
+ \inmodule QtGui
+ \ingroup native-interfaces
+*/
+
+QT_DEFINE_NATIVE_INTERFACE(QVisionOSApplication);
+
+#endif // Q_OS_VISIONOS
+
+QT_END_NAMESPACE
diff --git a/src/gui/platform/unix/qgenericunixthemes.cpp b/src/gui/platform/unix/qgenericunixthemes.cpp
index fc4b2296d2..67de34923f 100644
--- a/src/gui/platform/unix/qgenericunixthemes.cpp
+++ b/src/gui/platform/unix/qgenericunixthemes.cpp
@@ -541,6 +541,48 @@ class QKdeThemePrivate : public QPlatformThemePrivate
{
public:
+ enum class KdeSettingType {
+ Root,
+ KDE,
+ Icons,
+ ToolBarIcons,
+ ToolBarStyle,
+ Fonts,
+ Colors,
+ };
+
+ enum class KdeSetting {
+ WidgetStyle,
+ ColorScheme,
+ SingleClick,
+ ShowIconsOnPushButtons,
+ IconTheme,
+ ToolBarIconSize,
+ ToolButtonStyle,
+ WheelScrollLines,
+ DoubleClickInterval,
+ StartDragDistance,
+ StartDragTime,
+ CursorBlinkRate,
+ Font,
+ Fixed,
+ MenuFont,
+ ToolBarFont,
+ ButtonBackground,
+ WindowBackground,
+ ViewForeground,
+ WindowForeground,
+ ViewBackground,
+ SelectionBackground,
+ SelectionForeground,
+ ViewBackgroundAlternate,
+ ButtonForeground,
+ ViewForegroundLink,
+ ViewForegroundVisited,
+ TooltipBackground,
+ TooltipForeground,
+ };
+
QKdeThemePrivate(const QStringList &kdeDirs, int kdeVersion);
static QString kdeGlobals(const QString &kdeDir, int kdeVersion)
@@ -551,7 +593,9 @@ public:
}
void refresh();
- static QVariant readKdeSetting(const QString &key, const QStringList &kdeDirs, int kdeVersion, QHash<QString, QSettings*> &kdeSettings);
+ static QVariant readKdeSetting(KdeSetting s, const QStringList &kdeDirs, int kdeVersion, QHash<QString, QSettings*> &settings);
+ QVariant readKdeSetting(KdeSetting s) const;
+ void clearKdeSettings() const;
static void readKdeSystemPalette(const QStringList &kdeDirs, int kdeVersion, QHash<QString, QSettings*> &kdeSettings, QPalette *pal);
static QFont *kdeFont(const QVariant &fontValue);
static QStringList kdeIconThemeSearchPaths(const QStringList &kdeDirs);
@@ -575,8 +619,9 @@ public:
Qt::ColorScheme m_colorScheme = Qt::ColorScheme::Unknown;
void updateColorScheme(const QString &themeName);
-#ifndef QT_NO_DBUS
private:
+ mutable QHash<QString, QSettings *> kdeSettings;
+#ifndef QT_NO_DBUS
std::unique_ptr<QGenericUnixThemeDBusListener> dbus;
bool initDbus();
void settingChangedHandler(QGenericUnixThemeDBusListener::Provider provider,
@@ -632,9 +677,136 @@ QKdeThemePrivate::QKdeThemePrivate(const QStringList &kdeDirs, int kdeVersion)
#endif // QT_NO_DBUS
}
+static constexpr QLatin1StringView settingsPrefix(QKdeThemePrivate::KdeSettingType type)
+{
+ switch (type) {
+ case QKdeThemePrivate::KdeSettingType::Root:
+ return QLatin1StringView();
+ case QKdeThemePrivate::KdeSettingType::KDE:
+ return QLatin1StringView("KDE/");
+ case QKdeThemePrivate::KdeSettingType::Fonts:
+ return QLatin1StringView();
+ case QKdeThemePrivate::KdeSettingType::Colors:
+ return QLatin1StringView("Colors:");
+ case QKdeThemePrivate::KdeSettingType::Icons:
+ return QLatin1StringView("Icons/");
+ case QKdeThemePrivate::KdeSettingType::ToolBarIcons:
+ return QLatin1StringView("ToolbarIcons/");
+ case QKdeThemePrivate::KdeSettingType::ToolBarStyle:
+ return QLatin1StringView("Toolbar style/");
+ }
+ Q_UNREACHABLE_RETURN(QLatin1StringView());
+}
+
+static constexpr QKdeThemePrivate::KdeSettingType settingsType(QKdeThemePrivate::KdeSetting setting)
+{
+#define CASE(s, type) case QKdeThemePrivate::KdeSetting::s:\
+ return QKdeThemePrivate::KdeSettingType::type
+
+ switch (setting) {
+ CASE(WidgetStyle, Root);
+ CASE(ColorScheme, Root);
+ CASE(SingleClick, KDE);
+ CASE(ShowIconsOnPushButtons, KDE);
+ CASE(IconTheme, Icons);
+ CASE(ToolBarIconSize, ToolBarIcons);
+ CASE(ToolButtonStyle, ToolBarStyle);
+ CASE(WheelScrollLines, KDE);
+ CASE(DoubleClickInterval, KDE);
+ CASE(StartDragDistance, KDE);
+ CASE(StartDragTime, KDE);
+ CASE(CursorBlinkRate, KDE);
+ CASE(Font, Root);
+ CASE(Fixed, Root);
+ CASE(MenuFont, Root);
+ CASE(ToolBarFont, Root);
+ CASE(ButtonBackground, Colors);
+ CASE(WindowBackground, Colors);
+ CASE(ViewForeground, Colors);
+ CASE(WindowForeground, Colors);
+ CASE(ViewBackground, Colors);
+ CASE(SelectionBackground, Colors);
+ CASE(SelectionForeground, Colors);
+ CASE(ViewBackgroundAlternate, Colors);
+ CASE(ButtonForeground, Colors);
+ CASE(ViewForegroundLink, Colors);
+ CASE(ViewForegroundVisited, Colors);
+ CASE(TooltipBackground, Colors);
+ CASE(TooltipForeground, Colors);
+ };
+ Q_UNREACHABLE_RETURN(QKdeThemePrivate::KdeSettingType::Root);
+}
+#undef CASE
+
+static constexpr QLatin1StringView settingsKey(QKdeThemePrivate::KdeSetting setting)
+{
+ switch (setting) {
+ case QKdeThemePrivate::KdeSetting::WidgetStyle:
+ return QLatin1StringView("widgetStyle");
+ case QKdeThemePrivate::KdeSetting::ColorScheme:
+ return QLatin1StringView("ColorScheme");
+ case QKdeThemePrivate::KdeSetting::SingleClick:
+ return QLatin1StringView("SingleClick");
+ case QKdeThemePrivate::KdeSetting::ShowIconsOnPushButtons:
+ return QLatin1StringView("ShowIconsOnPushButtons");
+ case QKdeThemePrivate::KdeSetting::IconTheme:
+ return QLatin1StringView("Theme");
+ case QKdeThemePrivate::KdeSetting::ToolBarIconSize:
+ return QLatin1StringView("Size");
+ case QKdeThemePrivate::KdeSetting::ToolButtonStyle:
+ return QLatin1StringView("ToolButtonStyle");
+ case QKdeThemePrivate::KdeSetting::WheelScrollLines:
+ return QLatin1StringView("WheelScrollLines");
+ case QKdeThemePrivate::KdeSetting::DoubleClickInterval:
+ return QLatin1StringView("DoubleClickInterval");
+ case QKdeThemePrivate::KdeSetting::StartDragDistance:
+ return QLatin1StringView("StartDragDist");
+ case QKdeThemePrivate::KdeSetting::StartDragTime:
+ return QLatin1StringView("StartDragTime");
+ case QKdeThemePrivate::KdeSetting::CursorBlinkRate:
+ return QLatin1StringView("CursorBlinkRate");
+ case QKdeThemePrivate::KdeSetting::Font:
+ return QLatin1StringView("font");
+ case QKdeThemePrivate::KdeSetting::Fixed:
+ return QLatin1StringView("fixed");
+ case QKdeThemePrivate::KdeSetting::MenuFont:
+ return QLatin1StringView("menuFont");
+ case QKdeThemePrivate::KdeSetting::ToolBarFont:
+ return QLatin1StringView("toolBarFont");
+ case QKdeThemePrivate::KdeSetting::ButtonBackground:
+ return QLatin1StringView("Button/BackgroundNormal");
+ case QKdeThemePrivate::KdeSetting::WindowBackground:
+ return QLatin1StringView("Window/BackgroundNormal");
+ case QKdeThemePrivate::KdeSetting::ViewForeground:
+ return QLatin1StringView("View/ForegroundNormal");
+ case QKdeThemePrivate::KdeSetting::WindowForeground:
+ return QLatin1StringView("Window/ForegroundNormal");
+ case QKdeThemePrivate::KdeSetting::ViewBackground:
+ return QLatin1StringView("View/BackgroundNormal");
+ case QKdeThemePrivate::KdeSetting::SelectionBackground:
+ return QLatin1StringView("Selection/BackgroundNormal");
+ case QKdeThemePrivate::KdeSetting::SelectionForeground:
+ return QLatin1StringView("Selection/ForegroundNormal");
+ case QKdeThemePrivate::KdeSetting::ViewBackgroundAlternate:
+ return QLatin1StringView("View/BackgroundAlternate");
+ case QKdeThemePrivate::KdeSetting::ButtonForeground:
+ return QLatin1StringView("Button/ForegroundNormal");
+ case QKdeThemePrivate::KdeSetting::ViewForegroundLink:
+ return QLatin1StringView("View/ForegroundLink");
+ case QKdeThemePrivate::KdeSetting::ViewForegroundVisited:
+ return QLatin1StringView("View/ForegroundVisited");
+ case QKdeThemePrivate::KdeSetting::TooltipBackground:
+ return QLatin1StringView("Tooltip/BackgroundNormal");
+ case QKdeThemePrivate::KdeSetting::TooltipForeground:
+ return QLatin1StringView("Tooltip/ForegroundNormal");
+ };
+ Q_UNREACHABLE_RETURN(QLatin1StringView());
+}
+
void QKdeThemePrivate::refresh()
{
resources.clear();
+ clearKdeSettings();
toolButtonStyle = Qt::ToolButtonTextBesideIcon;
toolBarIconSize = 0;
@@ -647,45 +819,39 @@ void QKdeThemePrivate::refresh()
else
iconFallbackThemeName = iconThemeName = QStringLiteral("oxygen");
- QHash<QString, QSettings*> kdeSettings;
-
QPalette systemPalette = QPalette();
readKdeSystemPalette(kdeDirs, kdeVersion, kdeSettings, &systemPalette);
resources.palettes[QPlatformTheme::SystemPalette] = new QPalette(systemPalette);
//## TODO tooltip color
- const QVariant styleValue = readKdeSetting(QStringLiteral("widgetStyle"), kdeDirs, kdeVersion, kdeSettings);
+ const QVariant styleValue = readKdeSetting(KdeSetting::WidgetStyle);
if (styleValue.isValid()) {
const QString style = styleValue.toString();
if (style != styleNames.front())
styleNames.push_front(style);
}
- const QVariant colorScheme = readKdeSetting(QStringLiteral("ColorScheme"), kdeDirs,
- kdeVersion, kdeSettings);
+ const QVariant colorScheme = readKdeSetting(KdeSetting::ColorScheme);
- if (colorScheme.isValid())
- updateColorScheme(colorScheme.toString());
- else
- m_colorScheme = Qt::ColorScheme::Unknown;
+ updateColorScheme(colorScheme.toString());
- const QVariant singleClickValue = readKdeSetting(QStringLiteral("KDE/SingleClick"), kdeDirs, kdeVersion, kdeSettings);
+ const QVariant singleClickValue = readKdeSetting(KdeSetting::SingleClick);
if (singleClickValue.isValid())
singleClick = singleClickValue.toBool();
- const QVariant showIconsOnPushButtonsValue = readKdeSetting(QStringLiteral("KDE/ShowIconsOnPushButtons"), kdeDirs, kdeVersion, kdeSettings);
+ const QVariant showIconsOnPushButtonsValue = readKdeSetting(KdeSetting::ShowIconsOnPushButtons);
if (showIconsOnPushButtonsValue.isValid())
showIconsOnPushButtons = showIconsOnPushButtonsValue.toBool();
- const QVariant themeValue = readKdeSetting(QStringLiteral("Icons/Theme"), kdeDirs, kdeVersion, kdeSettings);
+ const QVariant themeValue = readKdeSetting(KdeSetting::IconTheme);
if (themeValue.isValid())
iconThemeName = themeValue.toString();
- const QVariant toolBarIconSizeValue = readKdeSetting(QStringLiteral("ToolbarIcons/Size"), kdeDirs, kdeVersion, kdeSettings);
+ const QVariant toolBarIconSizeValue = readKdeSetting(KdeSetting::ToolBarIconSize);
if (toolBarIconSizeValue.isValid())
toolBarIconSize = toolBarIconSizeValue.toInt();
- const QVariant toolbarStyleValue = readKdeSetting(QStringLiteral("Toolbar style/ToolButtonStyle"), kdeDirs, kdeVersion, kdeSettings);
+ const QVariant toolbarStyleValue = readKdeSetting(KdeSetting::ToolButtonStyle);
if (toolbarStyleValue.isValid()) {
const QString toolBarStyle = toolbarStyleValue.toString();
if (toolBarStyle == "TextBesideIcon"_L1)
@@ -696,35 +862,35 @@ void QKdeThemePrivate::refresh()
toolButtonStyle = Qt::ToolButtonTextUnderIcon;
}
- const QVariant wheelScrollLinesValue = readKdeSetting(QStringLiteral("KDE/WheelScrollLines"), kdeDirs, kdeVersion, kdeSettings);
+ const QVariant wheelScrollLinesValue = readKdeSetting(KdeSetting::WheelScrollLines);
if (wheelScrollLinesValue.isValid())
wheelScrollLines = wheelScrollLinesValue.toInt();
- const QVariant doubleClickIntervalValue = readKdeSetting(QStringLiteral("KDE/DoubleClickInterval"), kdeDirs, kdeVersion, kdeSettings);
+ const QVariant doubleClickIntervalValue = readKdeSetting(KdeSetting::DoubleClickInterval);
if (doubleClickIntervalValue.isValid())
doubleClickInterval = doubleClickIntervalValue.toInt();
- const QVariant startDragDistValue = readKdeSetting(QStringLiteral("KDE/StartDragDist"), kdeDirs, kdeVersion, kdeSettings);
+ const QVariant startDragDistValue = readKdeSetting(KdeSetting::StartDragDistance);
if (startDragDistValue.isValid())
startDragDist = startDragDistValue.toInt();
- const QVariant startDragTimeValue = readKdeSetting(QStringLiteral("KDE/StartDragTime"), kdeDirs, kdeVersion, kdeSettings);
+ const QVariant startDragTimeValue = readKdeSetting(KdeSetting::StartDragTime);
if (startDragTimeValue.isValid())
startDragTime = startDragTimeValue.toInt();
- const QVariant cursorBlinkRateValue = readKdeSetting(QStringLiteral("KDE/CursorBlinkRate"), kdeDirs, kdeVersion, kdeSettings);
+ const QVariant cursorBlinkRateValue = readKdeSetting(KdeSetting::CursorBlinkRate);
if (cursorBlinkRateValue.isValid()) {
cursorBlinkRate = cursorBlinkRateValue.toInt();
cursorBlinkRate = cursorBlinkRate > 0 ? qBound(200, cursorBlinkRate, 2000) : 0;
}
// Read system font, ignore 'smallestReadableFont'
- if (QFont *systemFont = kdeFont(readKdeSetting(QStringLiteral("font"), kdeDirs, kdeVersion, kdeSettings)))
+ if (QFont *systemFont = kdeFont(readKdeSetting(KdeSetting::Font)))
resources.fonts[QPlatformTheme::SystemFont] = systemFont;
else
resources.fonts[QPlatformTheme::SystemFont] = new QFont(QLatin1StringView(defaultSystemFontNameC), defaultSystemFontSize);
- if (QFont *fixedFont = kdeFont(readKdeSetting(QStringLiteral("fixed"), kdeDirs, kdeVersion, kdeSettings))) {
+ if (QFont *fixedFont = kdeFont(readKdeSetting(KdeSetting::Fixed))) {
resources.fonts[QPlatformTheme::FixedFont] = fixedFont;
} else {
fixedFont = new QFont(QLatin1StringView(defaultFixedFontNameC), defaultSystemFontSize);
@@ -732,12 +898,12 @@ void QKdeThemePrivate::refresh()
resources.fonts[QPlatformTheme::FixedFont] = fixedFont;
}
- if (QFont *menuFont = kdeFont(readKdeSetting(QStringLiteral("menuFont"), kdeDirs, kdeVersion, kdeSettings))) {
+ if (QFont *menuFont = kdeFont(readKdeSetting(KdeSetting::MenuFont))) {
resources.fonts[QPlatformTheme::MenuFont] = menuFont;
resources.fonts[QPlatformTheme::MenuBarFont] = new QFont(*menuFont);
}
- if (QFont *toolBarFont = kdeFont(readKdeSetting(QStringLiteral("toolBarFont"), kdeDirs, kdeVersion, kdeSettings)))
+ if (QFont *toolBarFont = kdeFont(readKdeSetting(KdeSetting::ToolBarFont)))
resources.fonts[QPlatformTheme::ToolButtonFont] = toolBarFont;
QWindowSystemInterface::handleThemeChange();
@@ -747,7 +913,7 @@ void QKdeThemePrivate::refresh()
qDeleteAll(kdeSettings);
}
-QVariant QKdeThemePrivate::readKdeSetting(const QString &key, const QStringList &kdeDirs, int kdeVersion, QHash<QString, QSettings*> &kdeSettings)
+QVariant QKdeThemePrivate::readKdeSetting(KdeSetting s, const QStringList &kdeDirs, int kdeVersion, QHash<QString, QSettings*> &kdeSettings)
{
for (const QString &kdeDir : kdeDirs) {
QSettings *settings = kdeSettings.value(kdeDir);
@@ -759,6 +925,7 @@ QVariant QKdeThemePrivate::readKdeSetting(const QString &key, const QStringList
}
}
if (settings) {
+ const QString key = settingsPrefix(settingsType(s)) + settingsKey(s);
const QVariant value = settings->value(key);
if (value.isValid())
return value;
@@ -767,6 +934,16 @@ QVariant QKdeThemePrivate::readKdeSetting(const QString &key, const QStringList
return QVariant();
}
+QVariant QKdeThemePrivate::readKdeSetting(KdeSetting s) const
+{
+ return readKdeSetting(s, kdeDirs, kdeVersion, kdeSettings);
+}
+
+void QKdeThemePrivate::clearKdeSettings() const
+{
+ kdeSettings.clear();
+}
+
// Reads the color from the KDE configuration, and store it in the
// palette with the given color role if found.
static inline bool kdeColor(QPalette *pal, QPalette::ColorRole role, const QVariant &value)
@@ -782,7 +959,7 @@ static inline bool kdeColor(QPalette *pal, QPalette::ColorRole role, const QVari
void QKdeThemePrivate::readKdeSystemPalette(const QStringList &kdeDirs, int kdeVersion, QHash<QString, QSettings*> &kdeSettings, QPalette *pal)
{
- if (!kdeColor(pal, QPalette::Button, readKdeSetting(QStringLiteral("Colors:Button/BackgroundNormal"), kdeDirs, kdeVersion, kdeSettings))) {
+ if (!kdeColor(pal, QPalette::Button, readKdeSetting(KdeSetting::ButtonBackground, kdeDirs, kdeVersion, kdeSettings))) {
// kcolorscheme.cpp: SetDefaultColors
const QColor defaultWindowBackground(214, 210, 208);
const QColor defaultButtonBackground(223, 220, 217);
@@ -790,18 +967,18 @@ void QKdeThemePrivate::readKdeSystemPalette(const QStringList &kdeDirs, int kdeV
return;
}
- kdeColor(pal, QPalette::Window, readKdeSetting(QStringLiteral("Colors:Window/BackgroundNormal"), kdeDirs, kdeVersion, kdeSettings));
- kdeColor(pal, QPalette::Text, readKdeSetting(QStringLiteral("Colors:View/ForegroundNormal"), kdeDirs, kdeVersion, kdeSettings));
- kdeColor(pal, QPalette::WindowText, readKdeSetting(QStringLiteral("Colors:Window/ForegroundNormal"), kdeDirs, kdeVersion, kdeSettings));
- kdeColor(pal, QPalette::Base, readKdeSetting(QStringLiteral("Colors:View/BackgroundNormal"), kdeDirs, kdeVersion, kdeSettings));
- kdeColor(pal, QPalette::Highlight, readKdeSetting(QStringLiteral("Colors:Selection/BackgroundNormal"), kdeDirs, kdeVersion, kdeSettings));
- kdeColor(pal, QPalette::HighlightedText, readKdeSetting(QStringLiteral("Colors:Selection/ForegroundNormal"), kdeDirs, kdeVersion, kdeSettings));
- kdeColor(pal, QPalette::AlternateBase, readKdeSetting(QStringLiteral("Colors:View/BackgroundAlternate"), kdeDirs, kdeVersion, kdeSettings));
- kdeColor(pal, QPalette::ButtonText, readKdeSetting(QStringLiteral("Colors:Button/ForegroundNormal"), kdeDirs, kdeVersion, kdeSettings));
- kdeColor(pal, QPalette::Link, readKdeSetting(QStringLiteral("Colors:View/ForegroundLink"), kdeDirs, kdeVersion, kdeSettings));
- kdeColor(pal, QPalette::LinkVisited, readKdeSetting(QStringLiteral("Colors:View/ForegroundVisited"), kdeDirs, kdeVersion, kdeSettings));
- kdeColor(pal, QPalette::ToolTipBase, readKdeSetting(QStringLiteral("Colors:Tooltip/BackgroundNormal"), kdeDirs, kdeVersion, kdeSettings));
- kdeColor(pal, QPalette::ToolTipText, readKdeSetting(QStringLiteral("Colors:Tooltip/ForegroundNormal"), kdeDirs, kdeVersion, kdeSettings));
+ kdeColor(pal, QPalette::Window, readKdeSetting(KdeSetting::WindowBackground, kdeDirs, kdeVersion, kdeSettings));
+ kdeColor(pal, QPalette::Text, readKdeSetting(KdeSetting::ViewForeground, kdeDirs, kdeVersion, kdeSettings));
+ kdeColor(pal, QPalette::WindowText, readKdeSetting(KdeSetting::WindowForeground, kdeDirs, kdeVersion, kdeSettings));
+ kdeColor(pal, QPalette::Base, readKdeSetting(KdeSetting::ViewBackground, kdeDirs, kdeVersion, kdeSettings));
+ kdeColor(pal, QPalette::Highlight, readKdeSetting(KdeSetting::SelectionBackground, kdeDirs, kdeVersion, kdeSettings));
+ kdeColor(pal, QPalette::HighlightedText, readKdeSetting(KdeSetting::SelectionForeground, kdeDirs, kdeVersion, kdeSettings));
+ kdeColor(pal, QPalette::AlternateBase, readKdeSetting(KdeSetting::ViewBackgroundAlternate, kdeDirs, kdeVersion, kdeSettings));
+ kdeColor(pal, QPalette::ButtonText, readKdeSetting(KdeSetting::ButtonForeground, kdeDirs, kdeVersion, kdeSettings));
+ kdeColor(pal, QPalette::Link, readKdeSetting(KdeSetting::ViewForegroundLink, kdeDirs, kdeVersion, kdeSettings));
+ kdeColor(pal, QPalette::LinkVisited, readKdeSetting(KdeSetting::ViewForegroundVisited, kdeDirs, kdeVersion, kdeSettings));
+ kdeColor(pal, QPalette::ToolTipBase, readKdeSetting(KdeSetting::TooltipBackground, kdeDirs, kdeVersion, kdeSettings));
+ kdeColor(pal, QPalette::ToolTipText, readKdeSetting(KdeSetting::TooltipForeground, kdeDirs, kdeVersion, kdeSettings));
// The above code sets _all_ color roles to "normal" colors. In KDE, the disabled
// color roles are calculated by applying various effects described in kdeglobals.
@@ -957,13 +1134,13 @@ Qt::ColorScheme QKdeTheme::colorScheme() const
/*!
\internal
- \brief QKdeTheme::updateColorScheme - guess and set appearance for unix themes.
- KDE themes do not have an appearance property.
- The key words "dark" or "light" should be part of the theme name.
+ \brief QKdeTheme::updateColorScheme - guess and set a color scheme for unix themes.
+ KDE themes do not have a color scheme property.
+ The key words "dark" or "light" are usually part of the theme name.
This is, however, not a mandatory convention.
- If \param themeName contains a key word, the respective appearance is set.
- If it doesn't, the appearance is heuristically determined by comparing text and base color
+ If \param themeName contains a valid key word, the respective color scheme is set.
+ If it doesn't, the color scheme is heuristically determined by comparing text and base color
of the system palette.
*/
void QKdeThemePrivate::updateColorScheme(const QString &themeName)
@@ -991,7 +1168,6 @@ void QKdeThemePrivate::updateColorScheme(const QString &themeName)
m_colorScheme = Qt::ColorScheme::Unknown;
}
-
const QPalette *QKdeTheme::palette(Palette type) const
{
Q_D(const QKdeTheme);
diff --git a/src/gui/qt_cmdline.cmake b/src/gui/qt_cmdline.cmake
index 379cc417e7..446618ebc4 100644
--- a/src/gui/qt_cmdline.cmake
+++ b/src/gui/qt_cmdline.cmake
@@ -27,7 +27,8 @@ qt_commandline_option(opengl TYPE optionalString VALUES no yes desktop es2 dynam
qt_commandline_option(opengl-es-2 TYPE void NAME opengl VALUE es2)
qt_commandline_option(opengles3 TYPE boolean)
qt_commandline_option(openvg TYPE boolean)
-qt_commandline_option(qpa TYPE string NAME qpa_default_platform)
+qt_commandline_option(qpa TYPE string NAME qpa_platforms)
+qt_commandline_option(default-qpa TYPE string NAME qpa_default_platform)
qt_commandline_option(sm TYPE boolean NAME sessionmanager)
qt_commandline_option(tslib TYPE boolean)
qt_commandline_option(vulkan TYPE boolean)
diff --git a/src/gui/text/qcssparser.cpp b/src/gui/text/qcssparser.cpp
index 916e96ea63..7886d9ba91 100644
--- a/src/gui/text/qcssparser.cpp
+++ b/src/gui/text/qcssparser.cpp
@@ -36,6 +36,7 @@ struct QCssKnownValue
quint64 id;
};
+// This array is sorted alphabetically.
static const QCssKnownValue properties[NumProperties - 1] = {
{ "-qt-background-role", QtBackgroundRole },
{ "-qt-block-indent", QtBlockIndent },
@@ -47,6 +48,11 @@ static const QCssKnownValue properties[NumProperties - 1] = {
{ "-qt-list-number-suffix", QtListNumberSuffix },
{ "-qt-paragraph-type", QtParagraphType },
{ "-qt-stroke-color", QtStrokeColor },
+ { "-qt-stroke-dasharray", QtStrokeDashArray },
+ { "-qt-stroke-dashoffset", QtStrokeDashOffset },
+ { "-qt-stroke-linecap", QtStrokeLineCap },
+ { "-qt-stroke-linejoin", QtStrokeLineJoin },
+ { "-qt-stroke-miterlimit", QtStrokeMiterLimit },
{ "-qt-stroke-width", QtStrokeWidth },
{ "-qt-style-features", QtStyleFeatures },
{ "-qt-table-type", QtTableType },
@@ -160,6 +166,7 @@ static const QCssKnownValue values[NumKnownValues - 1] = {
{ "always", Value_Always },
{ "auto", Value_Auto },
{ "base", Value_Base },
+ { "beveljoin", Value_BevelJoin},
{ "bold", Value_Bold },
{ "bottom", Value_Bottom },
{ "bright-text", Value_BrightText },
@@ -176,6 +183,7 @@ static const QCssKnownValue values[NumKnownValues - 1] = {
{ "dot-dot-dash", Value_DotDotDash },
{ "dotted", Value_Dotted },
{ "double", Value_Double },
+ { "flatcap", Value_FlatCap},
{ "groove", Value_Groove },
{ "highlight", Value_Highlight },
{ "highlighted-text", Value_HighlightedText },
@@ -194,6 +202,7 @@ static const QCssKnownValue values[NumKnownValues - 1] = {
{ "mid", Value_Mid },
{ "middle", Value_Middle },
{ "midlight", Value_Midlight },
+ { "miterjoin", Value_MiterJoin},
{ "native", Value_Native },
{ "none", Value_None },
{ "normal", Value_Normal },
@@ -208,14 +217,18 @@ static const QCssKnownValue values[NumKnownValues - 1] = {
{ "pre-wrap", Value_PreWrap },
{ "ridge", Value_Ridge },
{ "right", Value_Right },
+ { "roundcap", Value_RoundCap},
+ { "roundjoin", Value_RoundJoin},
{ "selected", Value_Selected },
{ "shadow", Value_Shadow },
{ "small" , Value_Small },
{ "small-caps", Value_SmallCaps },
{ "solid", Value_Solid },
{ "square", Value_Square },
+ { "squarecap", Value_SquareCap},
{ "sub", Value_Sub },
{ "super", Value_Super },
+ { "svgmiterjoin", Value_SvgMiterJoin},
{ "text", Value_Text },
{ "top", Value_Top },
{ "transparent", Value_Transparent },
@@ -231,10 +244,10 @@ static const QCssKnownValue values[NumKnownValues - 1] = {
};
//Map id to strings as they appears in the 'values' array above
-static const short indexOfId[NumKnownValues] = { 0, 41, 48, 42, 49, 50, 55, 35, 26, 71, 72, 25, 43, 5, 64, 48,
- 29, 59, 60, 27, 52, 62, 6, 10, 39, 56, 19, 13, 17, 18, 20, 21, 51, 24, 46, 68, 37, 3, 2, 40, 63, 16,
- 11, 58, 14, 32, 65, 33, 66, 56, 67, 34, 70, 8, 28, 38, 12, 36, 61, 7, 9, 4, 69, 54, 22, 23, 30, 31,
- 1, 15, 0, 53, 45, 44 };
+static const short indexOfId[NumKnownValues] = { 0, 44, 51, 45, 52, 53, 60, 37, 28, 78, 79, 27, 46, 6, 71, 50,
+ 31, 65, 66, 29, 55, 69, 7, 11, 42, 62, 20, 14, 18, 19, 21, 23, 54, 26, 49, 75, 39, 3, 2, 43, 70, 17, 12,
+ 63, 15, 34, 72, 35, 73, 61, 74, 36, 64, 22, 56, 41, 5, 57, 67, 77, 9, 30, 40, 13, 38, 68, 8, 10, 4, 76,
+ 59, 24, 25, 32, 33, 1, 16, 0, 58, 48, 47 };
QString Value::toString() const
{
@@ -1835,6 +1848,35 @@ bool Declaration::borderCollapseValue() const
return d->values.at(0).toString() == "collapse"_L1;
}
+QList<qreal> Declaration::dashArray() const
+{
+ if (d->propertyId != Property::QtStrokeDashArray || d->values.empty())
+ return QList<qreal>();
+
+ bool isValid = true;
+ QList<qreal> dashes;
+ for (int i = 0; i < d->values.size(); i++) {
+ Value v = d->values[i];
+ // Separators must be at odd indices and Numbers at even indices.
+ bool isValidSeparator = (i & 1) && v.type == Value::TermOperatorComma;
+ bool isValidNumber = !(i & 1) && v.type == Value::Number;
+ if (!isValidNumber && !isValidSeparator) {
+ isValid = false;
+ break;
+ } else if (isValidNumber) {
+ bool ok;
+ dashes.append(v.variant.toReal(&ok));
+ if (!ok) {
+ isValid = false;
+ break;
+ }
+ }
+ }
+
+ isValid &= !(dashes.size() & 1);
+ return isValid ? dashes : QList<qreal>();
+}
+
QIcon Declaration::iconValue() const
{
if (d->parsed.isValid())
diff --git a/src/gui/text/qcssparser_p.h b/src/gui/text/qcssparser_p.h
index 7742271e41..ba4a611df3 100644
--- a/src/gui/text/qcssparser_p.h
+++ b/src/gui/text/qcssparser_p.h
@@ -169,6 +169,11 @@ enum Property {
QtAccent,
QtStrokeWidth,
QtStrokeColor,
+ QtStrokeLineCap,
+ QtStrokeLineJoin,
+ QtStrokeMiterLimit,
+ QtStrokeDashArray,
+ QtStrokeDashOffset,
QtForeground,
NumProperties
};
@@ -226,6 +231,13 @@ enum KnownValue {
Value_SmallCaps,
Value_Uppercase,
Value_Lowercase,
+ Value_SquareCap,
+ Value_FlatCap,
+ Value_RoundCap,
+ Value_MiterJoin,
+ Value_BevelJoin,
+ Value_RoundJoin,
+ Value_SvgMiterJoin,
/* keep these in same order as QPalette::ColorRole */
Value_FirstColorRole,
@@ -451,6 +463,8 @@ struct Q_GUI_EXPORT Declaration
void borderImageValue(QString *image, int *cuts, TileMode *h, TileMode *v) const;
bool borderCollapseValue() const;
+
+ QList<qreal> dashArray() const;
};
QT_CSS_DECLARE_TYPEINFO(Declaration, Q_RELOCATABLE_TYPE)
diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp
index d3a13d801b..3d6d3b7886 100644
--- a/src/gui/text/qfontdatabase.cpp
+++ b/src/gui/text/qfontdatabase.cpp
@@ -670,7 +670,7 @@ static QStringList fallbacksForFamily(const QString &family, QFont::Style style,
return *fallbacks;
// make sure that the db has all fallback families
- QStringList userFallbacks = db->applicationFallbackFontFamilies.value(script == QChar::Script_Common ? QChar::Script_Latin : script);
+ QStringList userFallbacks = db->applicationFallbackFontFamilies.value(script == QChar::Script_Latin ? QChar::Script_Common : script);
QStringList retList = userFallbacks + QGuiApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(family,style,styleHint,script);
QStringList::iterator i;
@@ -2187,6 +2187,8 @@ int QFontDatabasePrivate::addAppFont(const QByteArray &fontData, const QString &
// loaded, so it has to be flushed.
QFontCache::instance()->clear();
+ fallbacksCache.clear();
+
emit qApp->fontDatabaseChanged();
return i;
@@ -2386,23 +2388,32 @@ bool QFontDatabase::removeAllApplicationFonts()
be prioritized in reverse order, so that the last family added will be checked first and so
on.
+ \note Qt's font matching algorithm considers \c{QChar::Script_Common} (undetermined script)
+ and \c{QChar::Script_Latin} the same. Adding a fallback for either of these will also apply
+ to the other.
+
\sa setApplicationFallbackFontFamilies(), removeApplicationFallbackFontFamily(), applicationFallbackFontFamilies()
*/
void QFontDatabase::addApplicationFallbackFontFamily(QChar::Script script, const QString &familyName)
{
QMutexLocker locker(fontDatabaseMutex());
- if (script < QChar::Script_Latin) {
+ if (script < QChar::Script_Common) {
qCWarning(lcFontDb) << "Invalid script passed to addApplicationFallbackFontFamily:" << script;
return;
}
+ if (script == QChar::Script_Latin)
+ script = QChar::Script_Common;
+
auto *db = QFontDatabasePrivate::instance();
auto it = db->applicationFallbackFontFamilies.find(script);
if (it == db->applicationFallbackFontFamilies.end())
it = db->applicationFallbackFontFamilies.insert(script, QStringList{});
it->prepend(familyName);
+
+ QFontCache::instance()->clear();
db->fallbacksCache.clear();
}
@@ -2420,6 +2431,14 @@ bool QFontDatabase::removeApplicationFallbackFontFamily(QChar::Script script, co
{
QMutexLocker locker(fontDatabaseMutex());
+ if (script < QChar::Script_Common) {
+ qCWarning(lcFontDb) << "Invalid script passed to removeApplicationFallbackFontFamily:" << script;
+ return false;
+ }
+
+ if (script == QChar::Script_Latin)
+ script = QChar::Script_Common;
+
auto *db = QFontDatabasePrivate::instance();
auto it = db->applicationFallbackFontFamilies.find(script);
if (it != db->applicationFallbackFontFamilies.end()) {
@@ -2452,11 +2471,14 @@ void QFontDatabase::setApplicationFallbackFontFamilies(QChar::Script script, con
{
QMutexLocker locker(fontDatabaseMutex());
- if (script < QChar::Script_Latin) {
+ if (script < QChar::Script_Common) {
qCWarning(lcFontDb) << "Invalid script passed to setApplicationFallbackFontFamilies:" << script;
return;
}
+ if (script == QChar::Script_Latin)
+ script = QChar::Script_Common;
+
auto *db = QFontDatabasePrivate::instance();
db->applicationFallbackFontFamilies[script] = familyNames;
@@ -2476,6 +2498,9 @@ QStringList QFontDatabase::applicationFallbackFontFamilies(QChar::Script script)
{
QMutexLocker locker(fontDatabaseMutex());
+ if (script == QChar::Script_Latin)
+ script = QChar::Script_Common;
+
auto *db = QFontDatabasePrivate::instance();
return db->applicationFallbackFontFamilies.value(script);
}
diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp
index ab788a5f9b..c39d3514c5 100644
--- a/src/gui/text/qtextdocument.cpp
+++ b/src/gui/text/qtextdocument.cpp
@@ -53,6 +53,9 @@ namespace {
QTextDocument::ResourceProvider qt_defaultResourceProvider;
};
+QAbstractUndoItem::~QAbstractUndoItem()
+ = default;
+
/*!
\fn bool Qt::mightBeRichText(QAnyStringView text)
@@ -2757,6 +2760,51 @@ bool QTextHtmlExporter::emitCharFormatStyle(const QTextCharFormat &format)
html += " -qt-stroke-width:"_L1;
html += QString::number(outlinePen.widthF());
html += "px;"_L1;
+
+ html += " -qt-stroke-linecap:"_L1;
+ if (outlinePen.capStyle() == Qt::SquareCap)
+ html += "squarecap;"_L1;
+ else if (outlinePen.capStyle() == Qt::FlatCap)
+ html += "flatcap;"_L1;
+ else if (outlinePen.capStyle() == Qt::RoundCap)
+ html += "roundcap;"_L1;
+
+ html += " -qt-stroke-linejoin:"_L1;
+ if (outlinePen.joinStyle() == Qt::MiterJoin)
+ html += "miterjoin;"_L1;
+ else if (outlinePen.joinStyle() == Qt::SvgMiterJoin)
+ html += "svgmiterjoin;"_L1;
+ else if (outlinePen.joinStyle() == Qt::BevelJoin)
+ html += "beveljoin;"_L1;
+ else if (outlinePen.joinStyle() == Qt::RoundJoin)
+ html += "roundjoin;"_L1;
+
+ if (outlinePen.joinStyle() == Qt::MiterJoin ||
+ outlinePen.joinStyle() == Qt::SvgMiterJoin) {
+ html += " -qt-stroke-miterlimit:"_L1;
+ html += QString::number(outlinePen.miterLimit());
+ html += u';';
+ }
+
+ if (outlinePen.style() == Qt::CustomDashLine && !outlinePen.dashPattern().empty()) {
+ html += " -qt-stroke-dasharray:"_L1;
+ QString dashArrayString;
+ QList<qreal> dashes = outlinePen.dashPattern();
+
+ for (int i = 0; i < dashes.length() - 1; i++) {
+ qreal dash = dashes[i];
+ dashArrayString += QString::number(dash) + u',';
+ }
+
+ dashArrayString += QString::number(dashes.last());
+ html += dashArrayString;
+ html += u';';
+
+ html += " -qt-stroke-dashoffset:"_L1;
+ html += QString::number(outlinePen.dashOffset());
+ html += u';';
+ }
+
attributesEmitted = true;
}
diff --git a/src/gui/text/qtextdocument.h b/src/gui/text/qtextdocument.h
index b6253bfa46..11a8abcb50 100644
--- a/src/gui/text/qtextdocument.h
+++ b/src/gui/text/qtextdocument.h
@@ -45,15 +45,11 @@ namespace Qt
class Q_GUI_EXPORT QAbstractUndoItem
{
public:
- virtual ~QAbstractUndoItem() = 0;
+ virtual ~QAbstractUndoItem();
virtual void undo() = 0;
virtual void redo() = 0;
};
-inline QAbstractUndoItem::~QAbstractUndoItem()
-{
-}
-
class QTextDocumentPrivate;
class Q_GUI_EXPORT QTextDocument : public QObject
diff --git a/src/gui/text/qtexthtmlparser.cpp b/src/gui/text/qtexthtmlparser.cpp
index bc2200697d..54c291b82e 100644
--- a/src/gui/text/qtexthtmlparser.cpp
+++ b/src/gui/text/qtexthtmlparser.cpp
@@ -1422,6 +1422,61 @@ void QTextHtmlParserNode::applyCssDeclarations(const QList<QCss::Declaration> &d
}
break;
}
+ case QCss::QtStrokeLineCap:
+ {
+ QPen pen = charFormat.textOutline();
+ switch (identifier) {
+ case QCss::Value_SquareCap: pen.setCapStyle(Qt::SquareCap); break;
+ case QCss::Value_FlatCap: pen.setCapStyle(Qt::FlatCap); break;
+ case QCss::Value_RoundCap: pen.setCapStyle(Qt::RoundCap); break;
+ default: break;
+ }
+ charFormat.setTextOutline(pen);
+ break;
+ }
+ case QCss::QtStrokeLineJoin:
+ {
+ QPen pen = charFormat.textOutline();
+ switch (identifier) {
+ case QCss::Value_MiterJoin: pen.setJoinStyle(Qt::MiterJoin); break;
+ case QCss::Value_BevelJoin: pen.setJoinStyle(Qt::BevelJoin); break;
+ case QCss::Value_RoundJoin: pen.setJoinStyle(Qt::RoundJoin); break;
+ case QCss::Value_SvgMiterJoin: pen.setJoinStyle(Qt::SvgMiterJoin); break;
+ default: break;
+ }
+ charFormat.setTextOutline(pen);
+ break;
+ }
+ case QCss::QtStrokeMiterLimit:
+ {
+ qreal miterLimit;
+ if (decl.realValue(&miterLimit)) {
+ QPen pen = charFormat.textOutline();
+ pen.setMiterLimit(miterLimit);
+ charFormat.setTextOutline(pen);
+ }
+ break;
+ }
+ case QCss::QtStrokeDashArray:
+ {
+ QList<qreal> dashes = decl.dashArray();
+ if (!dashes.empty()) {
+ QPen pen = charFormat.textOutline();
+ pen.setDashPattern(dashes);
+ charFormat.setTextOutline(pen);
+ }
+ break;
+ }
+ case QCss::QtStrokeDashOffset:
+ {
+ qreal dashOffset;
+ if (decl.realValue(&dashOffset)) {
+ QPen pen = charFormat.textOutline();
+ pen.setDashOffset(dashOffset);
+ charFormat.setTextOutline(pen);
+ }
+ break;
+ }
case QCss::QtForeground:
{
QBrush brush = decl.brushValue();
diff --git a/src/gui/util/qdesktopservices.cpp b/src/gui/util/qdesktopservices.cpp
index 379d18dd60..4d98faf398 100644
--- a/src/gui/util/qdesktopservices.cpp
+++ b/src/gui/util/qdesktopservices.cpp
@@ -18,8 +18,6 @@
#include <qpa/qplatformintegration.h>
#include <qdir.h>
-#include <QtCore/private/qlocking_p.h>
-
QT_BEGIN_NAMESPACE
class QOpenUrlHandlerRegistry
@@ -36,36 +34,10 @@ public:
};
typedef QHash<QString, Handler> HandlerHash;
HandlerHash handlers;
-
-#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0)
- QObject context;
-
- void handlerDestroyed(QObject *handler);
-#endif
-
};
Q_GLOBAL_STATIC(QOpenUrlHandlerRegistry, handlerRegistry)
-#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0)
-void QOpenUrlHandlerRegistry::handlerDestroyed(QObject *handler)
-{
- const auto lock = qt_scoped_lock(mutex);
- HandlerHash::Iterator it = handlers.begin();
- while (it != handlers.end()) {
- if (it->receiver == handler) {
- it = handlers.erase(it);
- qWarning("Please call QDesktopServices::unsetUrlHandler() before destroying a "
- "registered URL handler object.\n"
- "Support for destroying a registered URL handler object is deprecated, "
- "and will be removed in Qt 6.6.");
- } else {
- ++it;
- }
- }
-}
-#endif
-
/*!
\class QDesktopServices
\brief The QDesktopServices class provides methods for accessing common desktop services.
@@ -307,11 +279,6 @@ void QDesktopServices::setUrlHandler(const QString &scheme, QObject *receiver, c
h.receiver = receiver;
h.name = method;
registry->handlers.insert(scheme.toLower(), h);
-#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0)
- QObject::connect(receiver, &QObject::destroyed, &registry->context,
- [registry](QObject *obj) { registry->handlerDestroyed(obj); },
- Qt::DirectConnection);
-#endif
}
/*!
diff --git a/src/network/access/http2/http2protocol_p.h b/src/network/access/http2/http2protocol_p.h
index fb5ff199c5..f0f18d1dd5 100644
--- a/src/network/access/http2/http2protocol_p.h
+++ b/src/network/access/http2/http2protocol_p.h
@@ -117,7 +117,7 @@ const qint32 maxSessionReceiveWindowSize((quint32(1) << 31) - 1);
// Presumably, we never use up to 100 streams so let it be 10 simultaneous:
const qint32 qtDefaultStreamReceiveWindowSize = maxSessionReceiveWindowSize / 10;
-struct Frame configurationToSettingsFrame(const QHttp2Configuration &configuration);
+struct Frame Q_AUTOTEST_EXPORT configurationToSettingsFrame(const QHttp2Configuration &configuration);
QByteArray settingsFrameToBase64(const Frame &settingsFrame);
void appendProtocolUpgradeHeaders(const QHttp2Configuration &configuration, QHttpNetworkRequest *request);
std::vector<uchar> assemble_hpack_block(const std::vector<Frame> &frames);
diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp
index 419491a711..3ef07c6993 100644
--- a/src/network/access/qhttpnetworkconnection.cpp
+++ b/src/network/access/qhttpnetworkconnection.cpp
@@ -52,10 +52,11 @@ static int getPreferredActiveChannelCount(QHttpNetworkConnection::ConnectionType
QHttpNetworkConnectionPrivate::QHttpNetworkConnectionPrivate(
quint16 connectionCount, const QString &hostName, quint16 port, bool encrypt,
- QHttpNetworkConnection::ConnectionType type)
+ bool isLocalSocket, QHttpNetworkConnection::ConnectionType type)
: hostName(hostName),
port(port),
encrypt(encrypt),
+ isLocalSocket(isLocalSocket),
activeChannelCount(getPreferredActiveChannelCount(type, connectionCount)),
channelCount(connectionCount),
channels(new QHttpNetworkConnectionChannel[channelCount]),
@@ -64,6 +65,8 @@ QHttpNetworkConnectionPrivate::QHttpNetworkConnectionPrivate(
#endif
connectionType(type)
{
+ if (isLocalSocket) // Don't try to do host lookup for local sockets
+ networkLayerState = IPv4;
// We allocate all 6 channels even if it's an HTTP/2-enabled
// connection: in case the protocol negotiation via NPN/ALPN fails,
// we will have normally working HTTP/1.1.
@@ -102,13 +105,18 @@ void QHttpNetworkConnectionPrivate::pauseConnection()
// Disable all socket notifiers
for (int i = 0; i < activeChannelCount; i++) {
- if (channels[i].socket) {
+ if (auto *absSocket = qobject_cast<QAbstractSocket *>(channels[i].socket)) {
#ifndef QT_NO_SSL
if (encrypt)
- QSslSocketPrivate::pauseSocketNotifiers(static_cast<QSslSocket*>(channels[i].socket));
+ QSslSocketPrivate::pauseSocketNotifiers(static_cast<QSslSocket*>(absSocket));
else
#endif
- QAbstractSocketPrivate::pauseSocketNotifiers(channels[i].socket);
+ QAbstractSocketPrivate::pauseSocketNotifiers(absSocket);
+ } else if (qobject_cast<QLocalSocket *>(channels[i].socket)) {
+ // @todo how would we do this?
+#if 0 // @todo Enable this when there is a debug category for this
+ qDebug() << "Should pause socket but there is no way to do it for local sockets";
+#endif
}
}
}
@@ -118,17 +126,21 @@ void QHttpNetworkConnectionPrivate::resumeConnection()
state = RunningState;
// Enable all socket notifiers
for (int i = 0; i < activeChannelCount; i++) {
- if (channels[i].socket) {
+ if (auto *absSocket = qobject_cast<QAbstractSocket *>(channels[i].socket)) {
#ifndef QT_NO_SSL
if (encrypt)
- QSslSocketPrivate::resumeSocketNotifiers(static_cast<QSslSocket*>(channels[i].socket));
+ QSslSocketPrivate::resumeSocketNotifiers(static_cast<QSslSocket*>(absSocket));
else
#endif
- QAbstractSocketPrivate::resumeSocketNotifiers(channels[i].socket);
+ QAbstractSocketPrivate::resumeSocketNotifiers(absSocket);
// Resume pending upload if needed
if (channels[i].state == QHttpNetworkConnectionChannel::WritingState)
QMetaObject::invokeMethod(&channels[i], "_q_uploadDataReadyRead", Qt::QueuedConnection);
+ } else if (qobject_cast<QLocalSocket *>(channels[i].socket)) {
+#if 0 // @todo Enable this when there is a debug category for this
+ qDebug() << "Should resume socket but there is no way to do it for local sockets";
+#endif
}
}
@@ -292,7 +304,12 @@ void QHttpNetworkConnectionPrivate::prepareRequest(HttpMessagePair &messagePair)
request.setHeaderField("User-Agent", "Mozilla/5.0");
// set the host
value = request.headerField("host");
- if (value.isEmpty()) {
+ if (isLocalSocket && value.isEmpty()) {
+ // The local socket connections might have a full file path, and that
+ // may not be suitable for the Host header. But we can use whatever the
+ // user has set in the URL.
+ request.prependHeaderField("Host", request.url().host().toLocal8Bit());
+ } else if (value.isEmpty()) {
QHostAddress add;
QByteArray host;
if (add.setAddress(hostName)) {
@@ -524,7 +541,9 @@ QHttpNetworkConnectionPrivate::parseRedirectResponse(QHttpNetworkReply *reply)
// Check redirect url protocol
const QUrl priorUrl(reply->request().url());
- if (redirectUrl.scheme() == "http"_L1 || redirectUrl.scheme() == "https"_L1) {
+ const QString targetUrlScheme = redirectUrl.scheme();
+ if (targetUrlScheme == "http"_L1 || targetUrlScheme == "https"_L1
+ || targetUrlScheme.startsWith("unix"_L1)) {
switch (reply->request().redirectPolicy()) {
case QNetworkRequest::NoLessSafeRedirectPolicy:
// Here we could handle https->http redirects as InsecureProtocolError.
@@ -535,7 +554,7 @@ QHttpNetworkConnectionPrivate::parseRedirectResponse(QHttpNetworkReply *reply)
break;
case QNetworkRequest::SameOriginRedirectPolicy:
if (priorUrl.host() != redirectUrl.host()
- || priorUrl.scheme() != redirectUrl.scheme()
+ || priorUrl.scheme() != targetUrlScheme
|| priorUrl.port() != redirectUrl.port()) {
return {{}, QNetworkReply::InsecureRedirectError};
}
@@ -1024,7 +1043,7 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest()
for (int i = 0; i < activeChannelCount; ++i) {
if (channels[i].resendCurrent && (channels[i].state != QHttpNetworkConnectionChannel::ClosingState)) {
if (!channels[i].socket
- || channels[i].socket->state() == QAbstractSocket::UnconnectedState) {
+ || QSocketAbstraction::socketState(channels[i].socket) == QAbstractSocket::UnconnectedState) {
if (!channels[i].ensureConnection())
continue;
}
@@ -1048,7 +1067,9 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest()
// try to get a free AND connected socket
for (int i = 0; i < activeChannelCount; ++i) {
if (channels[i].socket) {
- if (!channels[i].reply && !channels[i].isSocketBusy() && channels[i].socket->state() == QAbstractSocket::ConnectedState) {
+ if (!channels[i].reply && !channels[i].isSocketBusy()
+ && QSocketAbstraction::socketState(channels[i].socket)
+ == QAbstractSocket::ConnectedState) {
if (dequeueRequest(channels[i].socket))
channels[i].sendRequest();
}
@@ -1068,7 +1089,8 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest()
else if (networkLayerState == IPv6)
channels[0].networkLayerPreference = QAbstractSocket::IPv6Protocol;
channels[0].ensureConnection();
- if (channels[0].socket && channels[0].socket->state() == QAbstractSocket::ConnectedState
+ if (auto *s = channels[0].socket; s
+ && QSocketAbstraction::socketState(s) == QAbstractSocket::ConnectedState
&& !channels[0].pendingEncrypt) {
if (channels[0].h2RequestsToSend.size()) {
channels[0].sendRequest();
@@ -1095,9 +1117,13 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest()
// return fast if there is nothing to pipeline
if (highPriorityQueue.isEmpty() && lowPriorityQueue.isEmpty())
return;
- for (int i = 0; i < activeChannelCount; i++)
- if (channels[i].socket && channels[i].socket->state() == QAbstractSocket::ConnectedState)
+ for (int i = 0; i < activeChannelCount; i++) {
+ if (channels[i].socket
+ && QSocketAbstraction::socketState(channels[i].socket)
+ == QAbstractSocket::ConnectedState) {
fillPipeline(channels[i].socket);
+ }
+ }
// If there is not already any connected channels we need to connect a new one.
// We do not pair the channel with the request until we know if it is
@@ -1122,15 +1148,16 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest()
if (!channels[i].socket)
continue;
- if ((channels[i].socket->state() == QAbstractSocket::ConnectingState)
- || (channels[i].socket->state() == QAbstractSocket::HostLookupState)
+ using State = QAbstractSocket::SocketState;
+ if ((QSocketAbstraction::socketState(channels[i].socket) == State::ConnectingState)
+ || (QSocketAbstraction::socketState(channels[i].socket) == State::HostLookupState)
|| channels[i].pendingEncrypt) { // pendingEncrypt == "EncryptingState"
neededOpenChannels--;
continue;
}
if (!channels[i].reply && !channels[i].isSocketBusy()
- && (channels[i].socket->state() == QAbstractSocket::UnconnectedState)) {
+ && (QSocketAbstraction::socketState(channels[i].socket) == State::UnconnectedState)) {
channelsToConnect.push_back(i);
neededOpenChannels--;
}
@@ -1329,9 +1356,9 @@ void QHttpNetworkConnectionPrivate::_q_connectDelayedChannel()
}
QHttpNetworkConnection::QHttpNetworkConnection(quint16 connectionCount, const QString &hostName,
- quint16 port, bool encrypt, QObject *parent,
+ quint16 port, bool encrypt, bool isLocalSocket, QObject *parent,
QHttpNetworkConnection::ConnectionType connectionType)
- : QObject(*(new QHttpNetworkConnectionPrivate(connectionCount, hostName, port, encrypt,
+ : QObject(*(new QHttpNetworkConnectionPrivate(connectionCount, hostName, port, encrypt, isLocalSocket,
connectionType)), parent)
{
Q_D(QHttpNetworkConnection);
diff --git a/src/network/access/qhttpnetworkconnection_p.h b/src/network/access/qhttpnetworkconnection_p.h
index c2d062fb16..5e4bce5eb0 100644
--- a/src/network/access/qhttpnetworkconnection_p.h
+++ b/src/network/access/qhttpnetworkconnection_p.h
@@ -64,7 +64,8 @@ public:
};
QHttpNetworkConnection(quint16 channelCount, const QString &hostName, quint16 port = 80,
- bool encrypt = false, QObject *parent = nullptr,
+ bool encrypt = false, bool isLocalSocket = false,
+ QObject *parent = nullptr,
ConnectionType connectionType = ConnectionTypeHTTP);
~QHttpNetworkConnection();
@@ -155,7 +156,8 @@ public:
};
QHttpNetworkConnectionPrivate(quint16 connectionCount, const QString &hostName, quint16 port,
- bool encrypt, QHttpNetworkConnection::ConnectionType type);
+ bool encrypt, bool isLocalSocket,
+ QHttpNetworkConnection::ConnectionType type);
~QHttpNetworkConnectionPrivate();
void init();
@@ -205,6 +207,7 @@ public:
QString hostName;
quint16 port;
bool encrypt;
+ bool isLocalSocket;
bool delayIpv4 = true;
// Number of channels we are trying to use at the moment:
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
index e178d65356..8688e4b8d7 100644
--- a/src/network/access/qhttpnetworkconnectionchannel.cpp
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
@@ -12,6 +12,7 @@
#include <private/qhttp2protocolhandler_p.h>
#include <private/qhttpprotocolhandler_p.h>
#include <private/http2protocol_p.h>
+#include <private/qsocketabstraction_p.h>
#ifndef QT_NO_SSL
# include <private/qsslsocket_p.h>
@@ -78,6 +79,8 @@ void QHttpNetworkConnectionChannel::init()
#ifndef QT_NO_SSL
if (connection->d_func()->encrypt)
socket = new QSslSocket;
+ else if (connection->d_func()->isLocalSocket)
+ socket = new QLocalSocket;
else
socket = new QTcpSocket;
#else
@@ -85,7 +88,8 @@ void QHttpNetworkConnectionChannel::init()
#endif
#ifndef QT_NO_NETWORKPROXY
// Set by QNAM anyway, but let's be safe here
- socket->setProxy(QNetworkProxy::NoProxy);
+ if (auto s = qobject_cast<QAbstractSocket *>(socket))
+ s->setProxy(QNetworkProxy::NoProxy);
#endif
// After some back and forth in all the last years, this is now a DirectConnection because otherwise
@@ -94,32 +98,48 @@ void QHttpNetworkConnectionChannel::init()
QObject::connect(socket, &QIODevice::bytesWritten,
this, &QHttpNetworkConnectionChannel::_q_bytesWritten,
Qt::DirectConnection);
- QObject::connect(socket, &QAbstractSocket::connected,
- this, &QHttpNetworkConnectionChannel::_q_connected,
- Qt::DirectConnection);
QObject::connect(socket, &QIODevice::readyRead,
this, &QHttpNetworkConnectionChannel::_q_readyRead,
Qt::DirectConnection);
- // The disconnected() and error() signals may already come
- // while calling connectToHost().
- // In case of a cached hostname or an IP this
- // will then emit a signal to the user of QNetworkReply
- // but cannot be caught because the user did not have a chance yet
- // to connect to QNetworkReply's signals.
- qRegisterMetaType<QAbstractSocket::SocketError>();
- QObject::connect(socket, &QAbstractSocket::disconnected,
- this, &QHttpNetworkConnectionChannel::_q_disconnected,
- Qt::DirectConnection);
- QObject::connect(socket, &QAbstractSocket::errorOccurred,
- this, &QHttpNetworkConnectionChannel::_q_error,
- Qt::DirectConnection);
+
+ QSocketAbstraction::visit([this](auto *socket){
+ using SocketType = std::remove_pointer_t<decltype(socket)>;
+ QObject::connect(socket, &SocketType::connected,
+ this, &QHttpNetworkConnectionChannel::_q_connected,
+ Qt::DirectConnection);
+
+ // The disconnected() and error() signals may already come
+ // while calling connectToHost().
+ // In case of a cached hostname or an IP this
+ // will then emit a signal to the user of QNetworkReply
+ // but cannot be caught because the user did not have a chance yet
+ // to connect to QNetworkReply's signals.
+ QObject::connect(socket, &SocketType::disconnected,
+ this, &QHttpNetworkConnectionChannel::_q_disconnected,
+ Qt::DirectConnection);
+ if constexpr (std::is_same_v<SocketType, QAbstractSocket>) {
+ QObject::connect(socket, &QAbstractSocket::errorOccurred,
+ this, &QHttpNetworkConnectionChannel::_q_error,
+ Qt::DirectConnection);
+ } else if constexpr (std::is_same_v<SocketType, QLocalSocket>) {
+ auto convertAndForward = [this](QLocalSocket::LocalSocketError error) {
+ _q_error(static_cast<QAbstractSocket::SocketError>(error));
+ };
+ QObject::connect(socket, &SocketType::errorOccurred,
+ this, std::move(convertAndForward),
+ Qt::DirectConnection);
+ }
+ }, socket);
+
#ifndef QT_NO_NETWORKPROXY
- QObject::connect(socket, &QAbstractSocket::proxyAuthenticationRequired,
- this, &QHttpNetworkConnectionChannel::_q_proxyAuthenticationRequired,
- Qt::DirectConnection);
+ if (auto *s = qobject_cast<QAbstractSocket *>(socket)) {
+ QObject::connect(s, &QAbstractSocket::proxyAuthenticationRequired,
+ this, &QHttpNetworkConnectionChannel::_q_proxyAuthenticationRequired,
+ Qt::DirectConnection);
+ }
#endif
#ifndef QT_NO_SSL
@@ -156,8 +176,10 @@ void QHttpNetworkConnectionChannel::init()
#endif
#ifndef QT_NO_NETWORKPROXY
- if (proxy.type() != QNetworkProxy::NoProxy)
- socket->setProxy(proxy);
+ if (auto *s = qobject_cast<QAbstractSocket *>(socket);
+ s && proxy.type() != QNetworkProxy::NoProxy) {
+ s->setProxy(proxy);
+ }
#endif
isInitialized = true;
}
@@ -170,7 +192,7 @@ void QHttpNetworkConnectionChannel::close()
if (!socket)
state = QHttpNetworkConnectionChannel::IdleState;
- else if (socket->state() == QAbstractSocket::UnconnectedState)
+ else if (QSocketAbstraction::socketState(socket) == QAbstractSocket::UnconnectedState)
state = QHttpNetworkConnectionChannel::IdleState;
else
state = QHttpNetworkConnectionChannel::ClosingState;
@@ -190,7 +212,7 @@ void QHttpNetworkConnectionChannel::abort()
{
if (!socket)
state = QHttpNetworkConnectionChannel::IdleState;
- else if (socket->state() == QAbstractSocket::UnconnectedState)
+ else if (QSocketAbstraction::socketState(socket) == QAbstractSocket::UnconnectedState)
state = QHttpNetworkConnectionChannel::IdleState;
else
state = QHttpNetworkConnectionChannel::ClosingState;
@@ -201,7 +223,10 @@ void QHttpNetworkConnectionChannel::abort()
if (socket) {
// socket can be 0 since the host lookup is done from qhttpnetworkconnection.cpp while
// there is no socket yet.
- socket->abort();
+ auto callAbort = [](auto *s) {
+ s->abort();
+ };
+ QSocketAbstraction::visit(callAbort, socket);
}
}
@@ -268,7 +293,7 @@ bool QHttpNetworkConnectionChannel::ensureConnection()
if (!isInitialized)
init();
- QAbstractSocket::SocketState socketState = socket->state();
+ QAbstractSocket::SocketState socketState = QSocketAbstraction::socketState(socket);
// resend this request after we receive the disconnected signal
// If !socket->isOpen() then we have already called close() on the socket, but there was still a
@@ -335,7 +360,8 @@ bool QHttpNetworkConnectionChannel::ensureConnection()
connectHost = connection->d_func()->networkProxy.hostName();
connectPort = connection->d_func()->networkProxy.port();
}
- if (socket->proxy().type() == QNetworkProxy::HttpProxy) {
+ if (auto *abSocket = qobject_cast<QAbstractSocket *>(socket);
+ abSocket && abSocket->proxy().type() == QNetworkProxy::HttpProxy) {
// Make user-agent field available to HTTP proxy socket engine (QTBUG-17223)
QByteArray value;
// ensureConnection is called before any request has been assigned, but can also be
@@ -353,11 +379,11 @@ bool QHttpNetworkConnectionChannel::ensureConnection()
value = request.headerField("user-agent");
}
if (!value.isEmpty()) {
- QNetworkProxy proxy(socket->proxy());
+ QNetworkProxy proxy(abSocket->proxy());
auto h = proxy.headers();
h.replaceOrAppend(QHttpHeaders::WellKnownHeader::UserAgent, value);
proxy.setHeaders(std::move(h));
- socket->setProxy(proxy);
+ abSocket->setProxy(proxy);
}
}
#endif
@@ -380,7 +406,7 @@ bool QHttpNetworkConnectionChannel::ensureConnection()
// limit the socket read buffer size. we will read everything into
// the QHttpNetworkReply anyway, so let's grow only that and not
// here and there.
- socket->setReadBufferSize(64*1024);
+ sslSocket->setReadBufferSize(64*1024);
#else
// Need to dequeue the request so that we can emit the error.
if (!reply)
@@ -394,17 +420,24 @@ bool QHttpNetworkConnectionChannel::ensureConnection()
&& connection->cacheProxy().type() == QNetworkProxy::NoProxy
&& connection->transparentProxy().type() == QNetworkProxy::NoProxy) {
#endif
- socket->connectToHost(connectHost, connectPort, QIODevice::ReadWrite | QIODevice::Unbuffered, networkLayerPreference);
- // For an Unbuffered QTcpSocket, the read buffer size has a special meaning.
- socket->setReadBufferSize(1*1024);
+ if (auto *s = qobject_cast<QAbstractSocket *>(socket)) {
+ s->connectToHost(connectHost, connectPort,
+ QIODevice::ReadWrite | QIODevice::Unbuffered,
+ networkLayerPreference);
+ // For an Unbuffered QTcpSocket, the read buffer size has a special meaning.
+ s->setReadBufferSize(1 * 1024);
+ } else if (auto *s = qobject_cast<QLocalSocket *>(socket)) {
+ s->connectToServer(connectHost);
+ }
#ifndef QT_NO_NETWORKPROXY
} else {
- socket->connectToHost(connectHost, connectPort, QIODevice::ReadWrite, networkLayerPreference);
-
+ auto *s = qobject_cast<QAbstractSocket *>(socket);
+ Q_ASSERT(s);
// limit the socket read buffer size. we will read everything into
// the QHttpNetworkReply anyway, so let's grow only that and not
// here and there.
- socket->setReadBufferSize(64*1024);
+ s->connectToHost(connectHost, connectPort, QIODevice::ReadWrite, networkLayerPreference);
+ s->setReadBufferSize(64 * 1024);
}
#endif
}
@@ -507,7 +540,7 @@ void QHttpNetworkConnectionChannel::allDone()
// move next from pipeline to current request
if (!alreadyPipelinedRequests.isEmpty()) {
- if (resendCurrent || connectionCloseEnabled || socket->state() != QAbstractSocket::ConnectedState) {
+ if (resendCurrent || connectionCloseEnabled || QSocketAbstraction::socketState(socket) != QAbstractSocket::ConnectedState) {
// move the pipelined ones back to the main queue
requeueCurrentlyPipelinedRequests();
close();
@@ -538,7 +571,7 @@ void QHttpNetworkConnectionChannel::allDone()
QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
} else if (alreadyPipelinedRequests.isEmpty()) {
if (connectionCloseEnabled)
- if (socket->state() != QAbstractSocket::UnconnectedState)
+ if (QSocketAbstraction::socketState(socket) != QAbstractSocket::UnconnectedState)
close();
if (qobject_cast<QHttpNetworkConnection*>(connection))
QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
@@ -556,7 +589,7 @@ void QHttpNetworkConnectionChannel::detectPipeliningSupport()
// check for not having connection close
&& (!reply->d_func()->isConnectionCloseEnabled())
// check if it is still connected
- && (socket->state() == QAbstractSocket::ConnectedState)
+ && (QSocketAbstraction::socketState(socket) == QAbstractSocket::ConnectedState)
// check for broken servers in server reply header
// this is adapted from http://mxr.mozilla.org/firefox/ident?i=SupportsPipelining
&& (serverHeaderField = reply->headerField("Server"), !serverHeaderField.contains("Microsoft-IIS/4."))
@@ -679,8 +712,8 @@ bool QHttpNetworkConnectionChannel::resetUploadData()
void QHttpNetworkConnectionChannel::setProxy(const QNetworkProxy &networkProxy)
{
- if (socket)
- socket->setProxy(networkProxy);
+ if (auto *s = qobject_cast<QAbstractSocket *>(socket))
+ s->setProxy(networkProxy);
proxy = networkProxy;
}
@@ -841,7 +874,7 @@ void QHttpNetworkConnectionChannel::_q_disconnected()
}
-void QHttpNetworkConnectionChannel::_q_connected()
+void QHttpNetworkConnectionChannel::_q_connected_abstract_socket(QAbstractSocket *absSocket)
{
// For the Happy Eyeballs we need to check if this is the first channel to connect.
if (connection->d_func()->networkLayerState == QHttpNetworkConnectionPrivate::HostLookupPending || connection->d_func()->networkLayerState == QHttpNetworkConnectionPrivate::IPv4or6) {
@@ -852,7 +885,7 @@ void QHttpNetworkConnectionChannel::_q_connected()
else if (networkLayerPreference == QAbstractSocket::IPv6Protocol)
connection->d_func()->networkLayerState = QHttpNetworkConnectionPrivate::IPv6;
else {
- if (socket->peerAddress().protocol() == QAbstractSocket::IPv4Protocol)
+ if (absSocket->peerAddress().protocol() == QAbstractSocket::IPv4Protocol)
connection->d_func()->networkLayerState = QHttpNetworkConnectionPrivate::IPv4;
else
connection->d_func()->networkLayerState = QHttpNetworkConnectionPrivate::IPv6;
@@ -875,7 +908,7 @@ void QHttpNetworkConnectionChannel::_q_connected()
}
// improve performance since we get the request sent by the kernel ASAP
- //socket->setSocketOption(QAbstractSocket::LowDelayOption, 1);
+ //absSocket->setSocketOption(QAbstractSocket::LowDelayOption, 1);
// We have this commented out now. It did not have the effect we wanted. If we want to
// do this properly, Qt has to combine multiple HTTP requests into one buffer
// and send this to the kernel in one syscall and then the kernel immediately sends
@@ -884,7 +917,7 @@ void QHttpNetworkConnectionChannel::_q_connected()
// the requests into one TCP packet.
// not sure yet if it helps, but it makes sense
- socket->setSocketOption(QAbstractSocket::KeepAliveOption, 1);
+ absSocket->setSocketOption(QAbstractSocket::KeepAliveOption, 1);
pipeliningSupported = QHttpNetworkConnectionChannel::PipeliningSupportUnknown;
@@ -893,7 +926,7 @@ void QHttpNetworkConnectionChannel::_q_connected()
if (!connectionPrivate->connectionMonitor.isMonitoring()) {
// Now that we have a pair of addresses, we can start monitoring the
// connection status to handle its loss properly.
- if (connectionPrivate->connectionMonitor.setTargets(socket->localAddress(), socket->peerAddress()))
+ if (connectionPrivate->connectionMonitor.setTargets(absSocket->localAddress(), absSocket->peerAddress()))
connectionPrivate->connectionMonitor.startMonitoring();
}
}
@@ -905,7 +938,7 @@ void QHttpNetworkConnectionChannel::_q_connected()
if (!connection->sslContext()) {
// this socket is making the 1st handshake for this connection,
// we need to set the SSL context so new sockets can reuse it
- if (auto socketSslContext = QSslSocketPrivate::sslContext(static_cast<QSslSocket*>(socket)))
+ if (auto socketSslContext = QSslSocketPrivate::sslContext(static_cast<QSslSocket*>(absSocket)))
connection->setSslContext(std::move(socketSslContext));
}
#endif
@@ -927,7 +960,7 @@ void QHttpNetworkConnectionChannel::_q_connected()
switchedToHttp2 = false;
if (!reply)
- connection->d_func()->dequeueRequest(socket);
+ connection->d_func()->dequeueRequest(absSocket);
if (reply) {
if (tryProtocolUpgrade) {
@@ -940,6 +973,22 @@ void QHttpNetworkConnectionChannel::_q_connected()
}
}
+void QHttpNetworkConnectionChannel::_q_connected_local_socket(QLocalSocket *localSocket)
+{
+ state = QHttpNetworkConnectionChannel::IdleState;
+ if (!reply) // No reply object, try to dequeue a request (which is paired with a reply):
+ connection->d_func()->dequeueRequest(localSocket);
+ if (reply)
+ sendRequest();
+}
+
+void QHttpNetworkConnectionChannel::_q_connected()
+{
+ if (auto *s = qobject_cast<QAbstractSocket *>(socket))
+ _q_connected_abstract_socket(s);
+ else if (auto *s = qobject_cast<QLocalSocket *>(socket))
+ _q_connected_local_socket(s);
+}
void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socketError)
{
@@ -1116,7 +1165,7 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket
//signal emission triggered event loop
if (!socket)
state = QHttpNetworkConnectionChannel::IdleState;
- else if (socket->state() == QAbstractSocket::UnconnectedState)
+ else if (QSocketAbstraction::socketState(socket) == QAbstractSocket::UnconnectedState)
state = QHttpNetworkConnectionChannel::IdleState;
else
state = QHttpNetworkConnectionChannel::ClosingState;
diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h
index c42290feca..853b647ecc 100644
--- a/src/network/access/qhttpnetworkconnectionchannel_p.h
+++ b/src/network/access/qhttpnetworkconnectionchannel_p.h
@@ -19,6 +19,7 @@
#include <QtNetwork/qnetworkrequest.h>
#include <QtNetwork/qnetworkreply.h>
#include <QtNetwork/qabstractsocket.h>
+#include <QtNetwork/qlocalsocket.h>
#include <private/qobject_p.h>
#include <qauthenticator.h>
@@ -71,7 +72,7 @@ public:
ClosingState = 16,
BusyState = (ConnectingState|WritingState|WaitingState|ReadingState|ClosingState)
};
- QAbstractSocket *socket;
+ QIODevice *socket;
bool ssl;
bool isInitialized;
ChannelState state;
@@ -156,6 +157,8 @@ public:
void _q_bytesWritten(qint64 bytes); // proceed sending
void _q_readyRead(); // pending data to read
void _q_disconnected(); // disconnected from host
+ void _q_connected_abstract_socket(QAbstractSocket *socket);
+ void _q_connected_local_socket(QLocalSocket *socket);
void _q_connected(); // start sending request
void _q_error(QAbstractSocket::SocketError); // error from socket
#ifndef QT_NO_NETWORKPROXY
diff --git a/src/network/access/qhttpnetworkrequest.cpp b/src/network/access/qhttpnetworkrequest.cpp
index 7a4ffb1684..06cc0b4464 100644
--- a/src/network/access/qhttpnetworkrequest.cpp
+++ b/src/network/access/qhttpnetworkrequest.cpp
@@ -381,5 +381,15 @@ void QHttpNetworkRequest::setPeerVerifyName(const QString &peerName)
d->peerVerifyName = peerName;
}
+QString QHttpNetworkRequest::fullLocalServerName() const
+{
+ return d->fullLocalServerName;
+}
+
+void QHttpNetworkRequest::setFullLocalServerName(const QString &fullServerName)
+{
+ d->fullLocalServerName = fullServerName;
+}
+
QT_END_NAMESPACE
diff --git a/src/network/access/qhttpnetworkrequest_p.h b/src/network/access/qhttpnetworkrequest_p.h
index 131885f6d2..4444020402 100644
--- a/src/network/access/qhttpnetworkrequest_p.h
+++ b/src/network/access/qhttpnetworkrequest_p.h
@@ -117,6 +117,9 @@ public:
QString peerVerifyName() const;
void setPeerVerifyName(const QString &peerName);
+ QString fullLocalServerName() const;
+ void setFullLocalServerName(const QString &fullServerName);
+
private:
QSharedDataPointer<QHttpNetworkRequestPrivate> d;
friend class QHttpNetworkRequestPrivate;
@@ -140,6 +143,7 @@ public:
QHttpNetworkRequest::Operation operation;
QByteArray customVerb;
+ QString fullLocalServerName; // for local sockets
QHttpNetworkRequest::Priority priority;
mutable QNonContiguousByteDevice* uploadByteDevice;
bool autoDecompress;
diff --git a/src/network/access/qhttpthreaddelegate.cpp b/src/network/access/qhttpthreaddelegate.cpp
index b0ae0dcf44..4e5cf05aef 100644
--- a/src/network/access/qhttpthreaddelegate.cpp
+++ b/src/network/access/qhttpthreaddelegate.cpp
@@ -95,7 +95,9 @@ static QByteArray makeCacheKey(QUrl &url, QNetworkProxy *proxy, const QString &p
QUrl copy = url;
QString scheme = copy.scheme();
bool isEncrypted = scheme == "https"_L1 || scheme == "preconnect-https"_L1;
- copy.setPort(copy.port(isEncrypted ? 443 : 80));
+ const bool isLocalSocket = scheme.startsWith("unix"_L1);
+ if (!isLocalSocket)
+ copy.setPort(copy.port(isEncrypted ? 443 : 80));
if (scheme == "preconnect-http"_L1)
copy.setScheme("http"_L1);
else if (scheme == "preconnect-https"_L1)
@@ -145,9 +147,9 @@ class QNetworkAccessCachedHttpConnection: public QHttpNetworkConnection,
{
// Q_OBJECT
public:
- QNetworkAccessCachedHttpConnection(quint16 connectionCount, const QString &hostName, quint16 port, bool encrypt,
+ QNetworkAccessCachedHttpConnection(quint16 connectionCount, const QString &hostName, quint16 port, bool encrypt, bool isLocalSocket,
QHttpNetworkConnection::ConnectionType connectionType)
- : QHttpNetworkConnection(connectionCount, hostName, port, encrypt, /*parent=*/nullptr, connectionType)
+ : QHttpNetworkConnection(connectionCount, hostName, port, encrypt, isLocalSocket, /*parent=*/nullptr, connectionType)
{
setExpires(true);
setShareable(true);
@@ -244,7 +246,9 @@ void QHttpThreadDelegate::startRequest()
// check if we have an open connection to this host
QUrl urlCopy = httpRequest.url();
- urlCopy.setPort(urlCopy.port(ssl ? 443 : 80));
+ const bool isLocalSocket = urlCopy.scheme().startsWith("unix"_L1);
+ if (!isLocalSocket)
+ urlCopy.setPort(urlCopy.port(ssl ? 443 : 80));
QHttpNetworkConnection::ConnectionType connectionType
= httpRequest.isHTTP2Allowed() ? QHttpNetworkConnection::ConnectionTypeHTTP2
@@ -279,10 +283,19 @@ void QHttpThreadDelegate::startRequest()
} else
#endif // QT_CONFIG(ssl)
{
- urlCopy.setScheme(QStringLiteral("h2"));
+ if (isLocalSocket)
+ urlCopy.setScheme(QStringLiteral("unix+h2"));
+ else
+ urlCopy.setScheme(QStringLiteral("h2"));
}
}
+ QString extraData = httpRequest.peerVerifyName();
+ if (isLocalSocket) {
+ if (QString path = httpRequest.fullLocalServerName(); !path.isEmpty())
+ extraData = path;
+ }
+
#ifndef QT_NO_NETWORKPROXY
if (transparentProxy.type() != QNetworkProxy::NoProxy)
cacheKey = makeCacheKey(urlCopy, &transparentProxy, httpRequest.peerVerifyName());
@@ -295,10 +308,19 @@ void QHttpThreadDelegate::startRequest()
// the http object is actually a QHttpNetworkConnection
httpConnection = static_cast<QNetworkAccessCachedHttpConnection *>(connections.localData()->requestEntryNow(cacheKey));
if (!httpConnection) {
+
+ QString host = urlCopy.host();
+ // Update the host if a unix socket path or named pipe is used:
+ if (isLocalSocket) {
+ if (QString path = httpRequest.fullLocalServerName(); !path.isEmpty())
+ host = path;
+ }
+
// no entry in cache; create an object
// the http object is actually a QHttpNetworkConnection
- httpConnection = new QNetworkAccessCachedHttpConnection(http1Parameters.numberOfConnectionsPerHost(), urlCopy.host(), urlCopy.port(), ssl,
- connectionType);
+ httpConnection = new QNetworkAccessCachedHttpConnection(
+ http1Parameters.numberOfConnectionsPerHost(), host, urlCopy.port(), ssl,
+ isLocalSocket, connectionType);
if (connectionType == QHttpNetworkConnection::ConnectionTypeHTTP2
|| connectionType == QHttpNetworkConnection::ConnectionTypeHTTP2Direct) {
httpConnection->setHttp2Parameters(http2Parameters);
diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp
index 7ef062a54d..ae99721758 100644
--- a/src/network/access/qnetworkaccessmanager.cpp
+++ b/src/network/access/qnetworkaccessmanager.cpp
@@ -1220,6 +1220,13 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera
bool isLocalFile = req.url().isLocalFile();
QString scheme = req.url().scheme();
+ // Remap local+http to unix+http to make further processing easier
+ if (scheme == "local+http"_L1) {
+ scheme = u"unix+http"_s;
+ QUrl url = req.url();
+ url.setScheme(scheme);
+ req.setUrl(url);
+ }
// fast path for GET on file:// URLs
// The QNetworkAccessFileBackend will right now only be used for PUT
@@ -1296,11 +1303,15 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera
u"https",
u"preconnect-https",
#endif
+ u"unix+http",
};
// Since Qt 5 we use the new QNetworkReplyHttpImpl
if (std::find(std::begin(httpSchemes), std::end(httpSchemes), scheme) != std::end(httpSchemes)) {
+
#ifndef QT_NO_SSL
- if (isStrictTransportSecurityEnabled() && d->stsCache.isKnownHost(request.url())) {
+ const bool isLocalSocket = scheme.startsWith("unix"_L1);
+ if (!isLocalSocket && isStrictTransportSecurityEnabled()
+ && d->stsCache.isKnownHost(request.url())) {
QUrl stsUrl(request.url());
// RFC6797, 8.3:
// The UA MUST replace the URI scheme with "https" [RFC2818],
@@ -1391,6 +1402,8 @@ QStringList QNetworkAccessManager::supportedSchemesImplementation() const
// Those ones don't exist in backends
#if QT_CONFIG(http)
schemes << QStringLiteral("http");
+ schemes << QStringLiteral("unix+http");
+ schemes << QStringLiteral("local+http");
#ifndef QT_NO_SSL
if (QSslSocket::supportsSsl())
schemes << QStringLiteral("https");
diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp
index 3e1fe761ee..89458825e9 100644
--- a/src/network/access/qnetworkreplyhttpimpl.cpp
+++ b/src/network/access/qnetworkreplyhttpimpl.cpp
@@ -809,6 +809,13 @@ void QNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpReq
httpRequest.setPeerVerifyName(newHttpRequest.peerVerifyName());
+ if (scheme.startsWith(("unix"_L1))) {
+ if (QVariant path = newHttpRequest.attribute(QNetworkRequest::FullLocalServerNameAttribute);
+ path.isValid() && path.canConvert<QString>()) {
+ httpRequest.setFullLocalServerName(path.toString());
+ }
+ }
+
// Create the HTTP thread delegate
QHttpThreadDelegate *delegate = new QHttpThreadDelegate;
// Propagate Http/2 settings:
@@ -1228,7 +1235,8 @@ void QNetworkReplyHttpImplPrivate::onRedirected(const QUrl &redirectUrl, int htt
if (httpRequest.isFollowRedirects()) // update the reply's url as it could've changed
url = redirectUrl;
- if (managerPrivate->stsEnabled && managerPrivate->stsCache.isKnownHost(url)) {
+ const bool wasLocalSocket = schemeBefore.startsWith("unix"_L1);
+ if (!wasLocalSocket && managerPrivate->stsEnabled && managerPrivate->stsCache.isKnownHost(url)) {
// RFC6797, 8.3:
// The UA MUST replace the URI scheme with "https" [RFC2818],
// and if the URI contains an explicit port component of "80",
@@ -1242,9 +1250,12 @@ void QNetworkReplyHttpImplPrivate::onRedirected(const QUrl &redirectUrl, int htt
url.setPort(443);
}
- const bool isLessSafe = schemeBefore == "https"_L1 && url.scheme() == "http"_L1;
- if (httpRequest.redirectPolicy() == QNetworkRequest::NoLessSafeRedirectPolicy
- && isLessSafe) {
+ // Just to be on the safe side for local sockets, any changes to the scheme
+ // are considered less safe
+ const bool changingLocalScheme = wasLocalSocket && url.scheme() != schemeBefore;
+ const bool isLessSafe = changingLocalScheme
+ || (schemeBefore == "https"_L1 && url.scheme() == "http"_L1);
+ if (httpRequest.redirectPolicy() == QNetworkRequest::NoLessSafeRedirectPolicy && isLessSafe) {
error(QNetworkReply::InsecureRedirectError,
QCoreApplication::translate("QHttp", "Insecure redirect"));
return;
diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp
index 7a1b5426d2..0e1172b15c 100644
--- a/src/network/access/qnetworkrequest.cpp
+++ b/src/network/access/qnetworkrequest.cpp
@@ -324,6 +324,16 @@ QT_IMPL_METATYPE_EXTERN_TAGGED(QNetworkRequest::RedirectPolicy, QNetworkRequest_
same-origin requests. This only affects the WebAssembly platform.
(This value was introduced in 6.5.)
+ \value FullLocalServerNameAttribute
+ Requests only, type: QMetaType::String
+ Holds the full local server name to be used for the underlying
+ QLocalSocket. This attribute is used by the QNetworkAccessManager
+ to connect to a specific local server, when QLocalSocket's behavior for
+ a simple name isn't enough. The URL in the QNetworkRequest must still
+ use unix+http: or local+http: scheme. And the hostname in the URL will
+ be used for the Host header in the HTTP request.
+ (This value was introduced in 6.8.)
+
\value User
Special type. Additional information can be passed in
QVariants with types ranging from User to UserMax. The default
diff --git a/src/network/access/qnetworkrequest.h b/src/network/access/qnetworkrequest.h
index e281c74834..368eb99d95 100644
--- a/src/network/access/qnetworkrequest.h
+++ b/src/network/access/qnetworkrequest.h
@@ -70,6 +70,7 @@ public:
ConnectionCacheExpiryTimeoutSecondsAttribute,
Http2CleartextAllowedAttribute,
UseCredentialsAttribute,
+ FullLocalServerNameAttribute,
User = 1000,
UserMax = 32767
diff --git a/src/network/android/jar/build.gradle b/src/network/android/jar/build.gradle
index 68a9381ad2..ea6d06c257 100644
--- a/src/network/android/jar/build.gradle
+++ b/src/network/android/jar/build.gradle
@@ -7,7 +7,7 @@ buildscript {
}
dependencies {
- classpath 'com.android.tools.build:gradle:8.0.2'
+ classpath 'com.android.tools.build:gradle:8.4.0'
}
}
@@ -26,7 +26,7 @@ android {
compileSdk 34
defaultConfig {
- minSdkVersion 23
+ minSdkVersion 28
}
sourceSets {
diff --git a/src/network/kernel/qnetworkinterface_unix.cpp b/src/network/kernel/qnetworkinterface_unix.cpp
index c0a7d9e00d..39ff8dbb92 100644
--- a/src/network/kernel/qnetworkinterface_unix.cpp
+++ b/src/network/kernel/qnetworkinterface_unix.cpp
@@ -310,12 +310,20 @@ QT_BEGIN_INCLUDE_NAMESPACE
QT_END_INCLUDE_NAMESPACE
# endif
+static int openSocket(int &socket)
+{
+ if (socket == -1)
+ socket = qt_safe_socket(AF_INET, SOCK_DGRAM, 0);
+ return socket;
+}
+
# if defined(Q_OS_LINUX) && __GLIBC__ - 0 >= 2 && __GLIBC_MINOR__ - 0 >= 1 && !defined(QT_LINUXBASE)
# include <netpacket/packet.h>
static QList<QNetworkInterfacePrivate *> createInterfaces(ifaddrs *rawList)
{
Q_UNUSED(getMtu);
+ Q_UNUSED(openSocket);
QList<QNetworkInterfacePrivate *> interfaces;
QDuplicateTracker<QString> seenInterfaces;
QDuplicateTracker<int> seenIndexes;
@@ -387,13 +395,6 @@ QT_BEGIN_INCLUDE_NAMESPACE
#endif // QT_PLATFORM_UIKIT
QT_END_INCLUDE_NAMESPACE
-static int openSocket(int &socket)
-{
- if (socket == -1)
- socket = qt_safe_socket(AF_INET, SOCK_DGRAM, 0);
- return socket;
-}
-
static QNetworkInterface::InterfaceType probeIfType(int socket, int iftype, struct ifmediareq *req)
{
// Determine the interface type.
@@ -537,8 +538,8 @@ static void getAddressExtraInfo(QNetworkAddressEntry *entry, struct sockaddr *sa
static QList<QNetworkInterfacePrivate *> createInterfaces(ifaddrs *rawList)
{
- Q_UNUSED(getMtu);
QList<QNetworkInterfacePrivate *> interfaces;
+ int socket = -1;
// make sure there's one entry for each interface
for (ifaddrs *ptr = rawList; ptr; ptr = ptr->ifa_next) {
@@ -559,9 +560,18 @@ static QList<QNetworkInterfacePrivate *> createInterfaces(ifaddrs *rawList)
iface->index = ifindex;
iface->name = QString::fromLatin1(ptr->ifa_name);
iface->flags = convertFlags(ptr->ifa_flags);
+
+ if ((socket = openSocket(socket)) >= 0) {
+ struct ifreq ifr;
+ qstrncpy(ifr.ifr_name, ptr->ifa_name, sizeof(ifr.ifr_name));
+ iface->mtu = getMtu(socket, &ifr);
+ }
}
}
+ if (socket != -1)
+ qt_safe_close(socket);
+
return interfaces;
}
diff --git a/src/plugins/networkinformation/android/jar/build.gradle b/src/plugins/networkinformation/android/jar/build.gradle
index 68a9381ad2..ea6d06c257 100644
--- a/src/plugins/networkinformation/android/jar/build.gradle
+++ b/src/plugins/networkinformation/android/jar/build.gradle
@@ -7,7 +7,7 @@ buildscript {
}
dependencies {
- classpath 'com.android.tools.build:gradle:8.0.2'
+ classpath 'com.android.tools.build:gradle:8.4.0'
}
}
@@ -26,7 +26,7 @@ android {
compileSdk 34
defaultConfig {
- minSdkVersion 23
+ minSdkVersion 28
}
sourceSets {
diff --git a/src/plugins/platforms/android/CMakeLists.txt b/src/plugins/platforms/android/CMakeLists.txt
index d5a275a76c..aaf62dd7e7 100644
--- a/src/plugins/platforms/android/CMakeLists.txt
+++ b/src/plugins/platforms/android/CMakeLists.txt
@@ -9,7 +9,7 @@ qt_find_package(EGL)
qt_internal_add_plugin(QAndroidIntegrationPlugin
OUTPUT_NAME qtforandroid
PLUGIN_TYPE platforms
- DEFAULT_IF ${QT_QPA_DEFAULT_PLATFORM} MATCHES android
+ DEFAULT_IF "android" IN_LIST QT_QPA_PLATFORMS
SOURCES
androidcontentfileengine.cpp androidcontentfileengine.h
androiddeadlockprotector.h
@@ -41,6 +41,7 @@ qt_internal_add_plugin(QAndroidIntegrationPlugin
qandroidplatformwindow.cpp qandroidplatformwindow.h
qandroidsystemlocale.cpp qandroidsystemlocale.h
androidwindowembedding.cpp androidwindowembedding.h
+ androidbackendregister.cpp androidbackendregister.h
NO_UNITY_BUILD_SOURCES
# Conflicting symbols and macros with androidjnimain.cpp
# TODO: Unify the usage of FIND_AND_CHECK_CLASS, and similar
diff --git a/src/plugins/platforms/android/androidbackendregister.cpp b/src/plugins/platforms/android/androidbackendregister.cpp
new file mode 100644
index 0000000000..bfd86138aa
--- /dev/null
+++ b/src/plugins/platforms/android/androidbackendregister.cpp
@@ -0,0 +1,52 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "androidbackendregister.h"
+
+#include "androidjnimain.h"
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(lcAndroidBackendRegister, "qt.qpa.androidbackendregister")
+
+Q_DECLARE_JNI_CLASS(BackendRegister, "org/qtproject/qt/android/BackendRegister");
+
+bool AndroidBackendRegister::registerNatives()
+{
+ return QtJniTypes::BackendRegister::registerNativeMethods(
+ { Q_JNI_NATIVE_SCOPED_METHOD(registerBackend, AndroidBackendRegister),
+ Q_JNI_NATIVE_SCOPED_METHOD(unregisterBackend, AndroidBackendRegister) });
+}
+
+void AndroidBackendRegister::registerBackend(JNIEnv *, jclass, jclass interfaceClass,
+ jobject interface)
+{
+ if (AndroidBackendRegister *reg = QtAndroid::backendRegister()) {
+ const QJniObject classObject(static_cast<jobject>(interfaceClass));
+ QString name = classObject.callMethod<jstring>("getName").toString();
+ name.replace('.', '/');
+
+ QMutexLocker lock(&reg->m_registerMutex);
+ reg->m_register[name] = QJniObject(interface);
+ } else {
+ qCWarning(lcAndroidBackendRegister)
+ << "AndroidBackendRegister pointer is null, cannot register functionality";
+ }
+}
+
+void AndroidBackendRegister::unregisterBackend(JNIEnv *, jclass, jclass interfaceClass)
+{
+ if (AndroidBackendRegister *reg = QtAndroid::backendRegister()) {
+ const QJniObject classObject(static_cast<jobject>(interfaceClass));
+ QString name = classObject.callMethod<jstring>("getName").toString();
+ name.replace('.', '/');
+
+ QMutexLocker lock(&reg->m_registerMutex);
+ reg->m_register.remove(name);
+ } else {
+ qCWarning(lcAndroidBackendRegister)
+ << "AndroidBackendRegister pointer is null, cannot unregister functionality";
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/android/androidbackendregister.h b/src/plugins/platforms/android/androidbackendregister.h
new file mode 100644
index 0000000000..c186f7e107
--- /dev/null
+++ b/src/plugins/platforms/android/androidbackendregister.h
@@ -0,0 +1,67 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef ANDROIDBACKENDREGISTER_H
+#define ANDROIDBACKENDREGISTER_H
+
+#include <type_traits>
+
+#include <QtCore/qjnienvironment.h>
+#include <QtCore/qjnitypes.h>
+#include <QtCore/qjniobject.h>
+
+#include <QtCore/qstring.h>
+#include <QtCore/qmap.h>
+#include <QtCore/qmutex.h>
+#include <QtCore/qloggingcategory.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(lcAndroidBackendRegister)
+
+template <typename T>
+using ValidInterfaceType = std::enable_if_t<std::is_base_of_v<QtJniTypes::JObjectBase, T>, bool>;
+
+class AndroidBackendRegister
+{
+public:
+ static bool registerNatives();
+
+ template <typename T, ValidInterfaceType<T> = true>
+ [[nodiscard]] T getInterface()
+ {
+ QMutexLocker lock(&m_registerMutex);
+ return m_register.value(QString(QtJniTypes::Traits<T>::className().data()));
+ }
+
+ template <typename Object>
+ using IsObjectType =
+ typename std::disjunction<std::is_base_of<QJniObject, Object>,
+ std::is_base_of<QtJniTypes::JObjectBase, Object>>;
+
+ template <typename Interface, typename Ret, typename... Args,
+ ValidInterfaceType<Interface> = true>
+ auto callInterface(const char *func, Args... args)
+ {
+ if (const auto obj = getInterface<Interface>(); obj.isValid())
+ return obj.template callMethod<Ret, Args...>(func, std::forward<Args>(args)...);
+
+ if constexpr (IsObjectType<Ret>::value)
+ return Ret(QJniObject());
+ if constexpr (!std::is_same_v<Ret, void>)
+ return Ret{};
+ }
+
+private:
+ QMutex m_registerMutex;
+ QMap<QString, QJniObject> m_register;
+
+ static void registerBackend(JNIEnv *, jclass, jclass interfaceClass, jobject interface);
+ Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(registerBackend)
+ static void unregisterBackend(JNIEnv *, jclass, jclass interfaceClass);
+ Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(unregisterBackend)
+};
+
+QT_END_NAMESPACE
+
+#endif // ANDROIDBACKENDREGISTER_H
diff --git a/src/plugins/platforms/android/androidjniaccessibility.cpp b/src/plugins/platforms/android/androidjniaccessibility.cpp
index da5b63ef21..805616e481 100644
--- a/src/plugins/platforms/android/androidjniaccessibility.cpp
+++ b/src/plugins/platforms/android/androidjniaccessibility.cpp
@@ -82,7 +82,7 @@ namespace QtAndroidAccessibility
void initialize()
{
- QtAndroid::qtActivityDelegate().callMethod<void>("initializeAccessibility");
+ QtAndroid::initializeAccessibility();
}
bool isActive()
diff --git a/src/plugins/platforms/android/androidjniinput.cpp b/src/plugins/platforms/android/androidjniinput.cpp
index d074e73b9e..266d027b3c 100644
--- a/src/plugins/platforms/android/androidjniinput.cpp
+++ b/src/plugins/platforms/android/androidjniinput.cpp
@@ -24,6 +24,8 @@ Q_LOGGING_CATEGORY(lcQpaInputMethods, "qt.qpa.input.methods");
using namespace QtAndroid;
Q_DECLARE_JNI_CLASS(QtLayout, "org/qtproject/qt/android/QtLayout")
+Q_DECLARE_JNI_CLASS(QtLayoutInterface, "org/qtproject/qt/android/QtLayoutInterface")
+Q_DECLARE_JNI_CLASS(QtInputInterface, "org/qtproject/qt/android/QtInputInterface")
namespace QtAndroidInput
{
@@ -98,48 +100,48 @@ namespace QtAndroidInput
QJniObject qtLayout()
{
- return qtActivityDelegate().callMethod<QtJniTypes::QtLayout>("getQtLayout");
+ AndroidBackendRegister *reg = QtAndroid::backendRegister();
+ return reg->callInterface<QtJniTypes::QtLayoutInterface, QtJniTypes::QtLayout>(
+ "getQtLayout");
}
void updateSelection(int selStart, int selEnd, int candidatesStart, int candidatesEnd)
{
qCDebug(lcQpaInputMethods) << ">>> UPDATESELECTION" << selStart << selEnd << candidatesStart << candidatesEnd;
- qtInputDelegate().callMethod<void>("updateSelection",
- selStart,
- selEnd,
- candidatesStart,
- candidatesEnd);
+ AndroidBackendRegister *reg = QtAndroid::backendRegister();
+ reg->callInterface<QtJniTypes::QtInputInterface, void>("updateSelection", selStart, selEnd,
+ candidatesStart, candidatesEnd);
}
void showSoftwareKeyboard(int left, int top, int width, int height, int inputHints, int enterKeyType)
{
- qtInputDelegate().callMethod<void>("showSoftwareKeyboard",
- QtAndroidPrivate::activity(),
- qtLayout().object<QtJniTypes::QtLayout>(),
- left,
- top,
- width,
- height,
- inputHints,
- enterKeyType);
+ AndroidBackendRegister *reg = QtAndroid::backendRegister();
+ reg->callInterface<QtJniTypes::QtInputInterface, void>(
+ "showSoftwareKeyboard", QtAndroidPrivate::activity(),
+ qtLayout().object<QtJniTypes::QtLayout>(), left, top, width, height, inputHints,
+ enterKeyType);
qCDebug(lcQpaInputMethods) << "@@@ SHOWSOFTWAREKEYBOARD" << left << top << width << height << inputHints << enterKeyType;
}
void resetSoftwareKeyboard()
{
- qtInputDelegate().callMethod<void>("resetSoftwareKeyboard");
+ AndroidBackendRegister *reg = QtAndroid::backendRegister();
+ reg->callInterface<QtJniTypes::QtInputInterface, void>("resetSoftwareKeyboard");
qCDebug(lcQpaInputMethods) << "@@@ RESETSOFTWAREKEYBOARD";
}
void hideSoftwareKeyboard()
{
- qtInputDelegate().callMethod<void>("hideSoftwareKeyboard");
+ AndroidBackendRegister *reg = QtAndroid::backendRegister();
+ reg->callInterface<QtJniTypes::QtInputInterface, void>("hideSoftwareKeyboard");
qCDebug(lcQpaInputMethods) << "@@@ HIDESOFTWAREKEYBOARD";
}
bool isSoftwareKeyboardVisible()
{
- return qtInputDelegate().callMethod<jboolean>("isSoftwareKeyboardVisible");
+ AndroidBackendRegister *reg = QtAndroid::backendRegister();
+ return reg->callInterface<QtJniTypes::QtInputInterface, jboolean>(
+ "isSoftwareKeyboardVisible");
}
QRect softwareKeyboardRect()
@@ -149,17 +151,17 @@ namespace QtAndroidInput
int getSelectHandleWidth()
{
- return qtInputDelegate().callMethod<jint>("getSelectHandleWidth");
+ AndroidBackendRegister *reg = QtAndroid::backendRegister();
+ return reg->callInterface<QtJniTypes::QtInputInterface, jint>("getSelectHandleWidth");
}
void updateHandles(int mode, QPoint editMenuPos, uint32_t editButtons, QPoint cursor, QPoint anchor, bool rtl)
{
- qtInputDelegate().callMethod<void>("updateHandles",
- QtAndroidPrivate::activity(),
- qtLayout().object<QtJniTypes::QtLayout>(),
- mode, editMenuPos.x(), editMenuPos.y(), editButtons,
- cursor.x(), cursor.y(),
- anchor.x(), anchor.y(), rtl);
+ AndroidBackendRegister *reg = QtAndroid::backendRegister();
+ reg->callInterface<QtJniTypes::QtInputInterface, void>(
+ "updateHandles", QtAndroidPrivate::activity(),
+ qtLayout().object<QtJniTypes::QtLayout>(), mode, editMenuPos.x(), editMenuPos.y(),
+ editButtons, cursor.x(), cursor.y(), anchor.x(), anchor.y(), rtl);
}
// from https://developer.android.com/reference/android/view/MotionEvent#getButtonState()
diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp
index 9fdcf3936b..5bd2b924fc 100644
--- a/src/plugins/platforms/android/androidjnimain.cpp
+++ b/src/plugins/platforms/android/androidjnimain.cpp
@@ -54,9 +54,6 @@ static jobject m_resourcesObj = nullptr;
static jclass m_qtActivityClass = nullptr;
static jclass m_qtServiceClass = nullptr;
-static QtJniTypes::QtActivityDelegateBase m_activityDelegate = nullptr;
-static QtJniTypes::QtInputDelegate m_inputDelegate = nullptr;
-
static int m_pendingApplicationState = -1;
static QBasicMutex m_platformMutex;
@@ -85,7 +82,7 @@ static double m_density = 1.0;
static AndroidAssetsFileEngineHandler *m_androidAssetsFileEngineHandler = nullptr;
static AndroidContentFileEngineHandler *m_androidContentFileEngineHandler = nullptr;
-
+static AndroidBackendRegister *m_backendRegister = nullptr;
static const char m_qtTag[] = "Qt";
static const char m_classErrorMsg[] = "Can't find class \"%s\"";
@@ -93,7 +90,8 @@ static const char m_methodErrorMsg[] = "Can't find method \"%s%s\"";
Q_CONSTINIT static QBasicAtomicInt startQtAndroidPluginCalled = Q_BASIC_ATOMIC_INITIALIZER(0);
-Q_DECLARE_JNI_CLASS(QtEmbeddedDelegateFactory, "org/qtproject/qt/android/QtEmbeddedDelegateFactory")
+Q_DECLARE_JNI_CLASS(QtWindowInterface, "org/qtproject/qt/android/QtWindowInterface")
+Q_DECLARE_JNI_CLASS(QtAccessibilityInterface, "org/qtproject/qt/android/QtAccessibilityInterface");
namespace QtAndroid
{
@@ -184,36 +182,9 @@ namespace QtAndroid
// TODO move calls from here to where they logically belong
void setSystemUiVisibility(SystemUiVisibility uiVisibility)
{
- qtActivityDelegate().callMethod<void>("setSystemUiVisibility", jint(uiVisibility));
- }
-
- // FIXME: avoid direct access to QtActivityDelegate
- QtJniTypes::QtActivityDelegateBase qtActivityDelegate()
- {
- using namespace QtJniTypes;
- if (!m_activityDelegate.isValid()) {
- if (isQtApplication()) {
- auto context = QtAndroidPrivate::activity();
- m_activityDelegate = context.callMethod<QtActivityDelegateBase>("getActivityDelegate");
- } else {
- m_activityDelegate = QJniObject::callStaticMethod<QtActivityDelegateBase>(
- Traits<QtEmbeddedDelegateFactory>::className(),
- "getActivityDelegate",
- QtAndroidPrivate::activity());
- }
- }
-
- return m_activityDelegate;
- }
-
- QtJniTypes::QtInputDelegate qtInputDelegate()
- {
- if (!m_inputDelegate.isValid()) {
- m_inputDelegate = qtActivityDelegate().callMethod<QtJniTypes::QtInputDelegate>(
- "getInputDelegate");
- }
-
- return m_inputDelegate;
+ AndroidBackendRegister *reg = QtAndroid::backendRegister();
+ reg->callInterface<QtJniTypes::QtWindowInterface, void>("setSystemUiVisibility",
+ jint(uiVisibility));
}
bool isQtApplication()
@@ -234,36 +205,46 @@ namespace QtAndroid
return true;
}
+ void initializeAccessibility()
+ {
+ m_backendRegister->callInterface<QtJniTypes::QtAccessibilityInterface, void>(
+ "initializeAccessibility");
+ }
+
void notifyAccessibilityLocationChange(uint accessibilityObjectId)
{
- qtActivityDelegate().callMethod<void>("notifyLocationChange", accessibilityObjectId);
+ m_backendRegister->callInterface<QtJniTypes::QtAccessibilityInterface, void>(
+ "notifyLocationChange", accessibilityObjectId);
}
void notifyObjectHide(uint accessibilityObjectId, uint parentObjectId)
{
- qtActivityDelegate().callMethod<void>("notifyObjectHide",
- accessibilityObjectId, parentObjectId);
+ m_backendRegister->callInterface<QtJniTypes::QtAccessibilityInterface, void>(
+ "notifyObjectHide", accessibilityObjectId, parentObjectId);
}
void notifyObjectShow(uint parentObjectId)
{
- qtActivityDelegate().callMethod<void>("notifyObjectShow",
- parentObjectId);
+ m_backendRegister->callInterface<QtJniTypes::QtAccessibilityInterface, void>(
+ "notifyObjectShow", parentObjectId);
}
void notifyObjectFocus(uint accessibilityObjectId)
{
- qtActivityDelegate().callMethod<void>("notifyObjectFocus", accessibilityObjectId);
+ m_backendRegister->callInterface<QtJniTypes::QtAccessibilityInterface, void>(
+ "notifyObjectFocus", accessibilityObjectId);
}
void notifyValueChanged(uint accessibilityObjectId, jstring value)
{
- qtActivityDelegate().callMethod<void>("notifyValueChanged", accessibilityObjectId, value);
+ m_backendRegister->callInterface<QtJniTypes::QtAccessibilityInterface, void>(
+ "notifyValueChanged", accessibilityObjectId, value);
}
void notifyScrolledEvent(uint accessibilityObjectId)
{
- qtActivityDelegate().callMethod<void>("notifyScrolledEvent", accessibilityObjectId);
+ m_backendRegister->callInterface<QtJniTypes::QtAccessibilityInterface, void>(
+ "notifyScrolledEvent", accessibilityObjectId);
}
void notifyNativePluginIntegrationReady(bool ready)
@@ -387,6 +368,11 @@ namespace QtAndroid
return m_assets;
}
+ AndroidBackendRegister *backendRegister()
+ {
+ return m_backendRegister;
+ }
+
} // namespace QtAndroid
static jboolean startQtAndroidPlugin(JNIEnv *env, jobject /*object*/, jstring paramsString)
@@ -397,6 +383,7 @@ static jboolean startQtAndroidPlugin(JNIEnv *env, jobject /*object*/, jstring pa
m_androidAssetsFileEngineHandler = new AndroidAssetsFileEngineHandler();
m_androidContentFileEngineHandler = new AndroidContentFileEngineHandler();
m_mainLibraryHnd = nullptr;
+ m_backendRegister = new AndroidBackendRegister();
const QStringList argsList = QProcess::splitCommand(QJniObject(paramsString).toString());
@@ -544,6 +531,8 @@ static void terminateQt(JNIEnv *env, jclass /*clazz*/)
m_androidPlatformIntegration = nullptr;
delete m_androidAssetsFileEngineHandler;
m_androidAssetsFileEngineHandler = nullptr;
+ delete m_backendRegister;
+ m_backendRegister = nullptr;
sem_post(&m_exitSemaphore);
}
@@ -891,7 +880,8 @@ Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void */*reserved*/)
|| !QtAndroidDialogHelpers::registerNatives(env)
|| !QAndroidPlatformClipboard::registerNatives(env)
|| !QAndroidPlatformWindow::registerNatives(env)
- || !QtAndroidWindowEmbedding::registerNatives(env)) {
+ || !QtAndroidWindowEmbedding::registerNatives(env)
+ || !AndroidBackendRegister::registerNatives()) {
__android_log_print(ANDROID_LOG_FATAL, "Qt", "registerNatives failed");
return -1;
}
diff --git a/src/plugins/platforms/android/androidjnimain.h b/src/plugins/platforms/android/androidjnimain.h
index 99fff96d2b..9d616b18fb 100644
--- a/src/plugins/platforms/android/androidjnimain.h
+++ b/src/plugins/platforms/android/androidjnimain.h
@@ -13,6 +13,7 @@
#include <QImage>
#include <private/qjnihelpers_p.h>
#include <QtCore/QJniObject>
+#include <androidbackendregister.h>
QT_BEGIN_NAMESPACE
@@ -33,6 +34,7 @@ namespace QtAndroid
{
QBasicMutex *platformInterfaceMutex();
QAndroidPlatformIntegration *androidPlatformIntegration();
+ AndroidBackendRegister *backendRegister();
void setAndroidPlatformIntegration(QAndroidPlatformIntegration *androidPlatformIntegration);
void setQtThread(QThread *thread);
void setViewVisibility(jobject view, bool visible);
@@ -48,9 +50,6 @@ namespace QtAndroid
AAssetManager *assetManager();
jclass applicationClass();
- QtJniTypes::QtActivityDelegateBase qtActivityDelegate();
- QtJniTypes::QtInputDelegate qtInputDelegate();
-
// Keep synchronized with flags in ActivityDelegate.java
enum SystemUiVisibility {
SYSTEM_UI_VISIBILITY_NORMAL = 0,
@@ -63,6 +62,7 @@ namespace QtAndroid
jobject createBitmap(int width, int height, QImage::Format format, JNIEnv *env);
jobject createBitmapDrawable(jobject bitmap, JNIEnv *env = nullptr);
+ void initializeAccessibility();
void notifyAccessibilityLocationChange(uint accessibilityObjectId);
void notifyObjectHide(uint accessibilityObjectId, uint parentObjectId);
void notifyObjectShow(uint parentObjectId);
diff --git a/src/plugins/platforms/android/androidjnimenu.cpp b/src/plugins/platforms/android/androidjnimenu.cpp
index 8bf37d1af2..5f8a0b92e9 100644
--- a/src/plugins/platforms/android/androidjnimenu.cpp
+++ b/src/plugins/platforms/android/androidjnimenu.cpp
@@ -20,6 +20,8 @@ QT_BEGIN_NAMESPACE
using namespace QtAndroid;
+Q_DECLARE_JNI_CLASS(QtMenuInterface, "org/qtproject/qt/android/QtMenuInterface");
+
namespace QtAndroidMenu
{
static QList<QAndroidPlatformMenu *> pendingContextMenus;
@@ -44,12 +46,14 @@ namespace QtAndroidMenu
void resetMenuBar()
{
- qtActivityDelegate().callMethod<void>("resetOptionsMenu");
+ AndroidBackendRegister *reg = QtAndroid::backendRegister();
+ reg->callInterface<QtJniTypes::QtMenuInterface, void>("resetOptionsMenu");
}
void openOptionsMenu()
{
- qtActivityDelegate().callMethod<void>("openOptionsMenu");
+ AndroidBackendRegister *reg = QtAndroid::backendRegister();
+ reg->callInterface<QtJniTypes::QtMenuInterface, void>("openOptionsMenu");
}
void showContextMenu(QAndroidPlatformMenu *menu, const QRect &anchorRect)
@@ -59,16 +63,18 @@ namespace QtAndroidMenu
pendingContextMenus.append(visibleMenu);
visibleMenu = menu;
menu->aboutToShow();
- qtActivityDelegate().callMethod<void>("openContextMenu",
- anchorRect.x(), anchorRect.y(),
- anchorRect.width(), anchorRect.height());
+ AndroidBackendRegister *reg = QtAndroid::backendRegister();
+ reg->callInterface<QtJniTypes::QtMenuInterface, void>("openContextMenu", anchorRect.x(),
+ anchorRect.y(), anchorRect.width(),
+ anchorRect.height());
}
void hideContextMenu(QAndroidPlatformMenu *menu)
{
QMutexLocker lock(&visibleMenuMutex);
if (visibleMenu == menu) {
- qtActivityDelegate().callMethod<void>("closeContextMenu");
+ AndroidBackendRegister *reg = QtAndroid::backendRegister();
+ reg->callInterface<QtJniTypes::QtMenuInterface, void>("closeContextMenu");
pendingContextMenus.clear();
} else {
pendingContextMenus.removeOne(menu);
diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp
index 9e20b7ac4b..4d752a3cc3 100644
--- a/src/plugins/platforms/android/qandroidplatformscreen.cpp
+++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp
@@ -57,6 +57,7 @@ Q_DECLARE_JNI_CLASS(Resources, "android/content/res/Resources")
Q_DECLARE_JNI_CLASS(Size, "android/util/Size")
Q_DECLARE_JNI_CLASS(QtNative, "org/qtproject/qt/android/QtNative")
Q_DECLARE_JNI_CLASS(QtDisplayManager, "org/qtproject/qt/android/QtDisplayManager")
+Q_DECLARE_JNI_CLASS(QtWindowInterface, "org/qtproject/qt/android/QtWindowInterface")
Q_DECLARE_JNI_CLASS(DisplayMode, "android/view/Display$Mode")
@@ -162,7 +163,10 @@ void QAndroidPlatformScreen::addWindow(QAndroidPlatformWindow *window)
return;
m_windowStack.prepend(window);
- QtAndroid::qtActivityDelegate().callMethod<void>("addTopLevelWindow", window->nativeWindow());
+
+ AndroidBackendRegister *reg = QtAndroid::backendRegister();
+ reg->callInterface<QtJniTypes::QtWindowInterface, void>("addTopLevelWindow",
+ window->nativeWindow());
if (window->window()->isVisible())
topVisibleWindowChanged();
@@ -175,7 +179,9 @@ void QAndroidPlatformScreen::removeWindow(QAndroidPlatformWindow *window)
if (m_windowStack.contains(window))
qWarning() << "Failed to remove window";
- QtAndroid::qtActivityDelegate().callMethod<void>("removeTopLevelWindow", window->nativeViewId());
+ AndroidBackendRegister *reg = QtAndroid::backendRegister();
+ reg->callInterface<QtJniTypes::QtWindowInterface, void>("removeTopLevelWindow",
+ window->nativeViewId());
topVisibleWindowChanged();
}
@@ -187,7 +193,10 @@ void QAndroidPlatformScreen::raise(QAndroidPlatformWindow *window)
return;
if (index > 0) {
m_windowStack.move(index, 0);
- QtAndroid::qtActivityDelegate().callMethod<void>("bringChildToFront", window->nativeViewId());
+
+ AndroidBackendRegister *reg = QtAndroid::backendRegister();
+ reg->callInterface<QtJniTypes::QtWindowInterface, void>("bringChildToFront",
+ window->nativeViewId());
}
topVisibleWindowChanged();
}
@@ -198,7 +207,10 @@ void QAndroidPlatformScreen::lower(QAndroidPlatformWindow *window)
if (index == -1 || index == (m_windowStack.size() - 1))
return;
m_windowStack.move(index, m_windowStack.size() - 1);
- QtAndroid::qtActivityDelegate().callMethod<void>("bringChildToBack", window->nativeViewId());
+
+ AndroidBackendRegister *reg = QtAndroid::backendRegister();
+ reg->callInterface<QtJniTypes::QtWindowInterface, void>("bringChildToBack",
+ window->nativeViewId());
topVisibleWindowChanged();
}
diff --git a/src/plugins/platforms/android/qandroidplatformwindow.cpp b/src/plugins/platforms/android/qandroidplatformwindow.cpp
index 979f0fb98a..2482160573 100644
--- a/src/plugins/platforms/android/qandroidplatformwindow.cpp
+++ b/src/plugins/platforms/android/qandroidplatformwindow.cpp
@@ -16,6 +16,10 @@ QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcQpaWindow, "qt.qpa.window")
+Q_DECLARE_JNI_CLASS(QtInputInterface, "org/qtproject/qt/android/QtInputInterface")
+Q_DECLARE_JNI_CLASS(QtInputConnectionListener,
+ "org/qtproject/qt/android/QtInputConnection$QtInputConnectionListener")
+
QAndroidPlatformWindow::QAndroidPlatformWindow(QWindow *window)
: QPlatformWindow(window), m_nativeQtWindow(nullptr),
m_surfaceContainerType(SurfaceContainer::TextureView), m_nativeParentQtWindow(nullptr),
@@ -55,10 +59,13 @@ QAndroidPlatformWindow::QAndroidPlatformWindow(QWindow *window)
m_nativeParentQtWindow = androidParent->nativeWindow();
}
+ AndroidBackendRegister *reg = QtAndroid::backendRegister();
+ QtJniTypes::QtInputConnectionListener listener =
+ reg->callInterface<QtJniTypes::QtInputInterface, QtJniTypes::QtInputConnectionListener>(
+ "getInputConnectionListener");
+
m_nativeQtWindow = QJniObject::construct<QtJniTypes::QtWindow>(
- QNativeInterface::QAndroidApplication::context(),
- m_nativeParentQtWindow,
- QtAndroid::qtInputDelegate());
+ QNativeInterface::QAndroidApplication::context(), m_nativeParentQtWindow, listener);
m_nativeViewId = m_nativeQtWindow.callMethod<jint>("getId");
if (window->isTopLevel())
diff --git a/src/plugins/platforms/cocoa/CMakeLists.txt b/src/plugins/platforms/cocoa/CMakeLists.txt
index 92e681d8fb..491c61703f 100644
--- a/src/plugins/platforms/cocoa/CMakeLists.txt
+++ b/src/plugins/platforms/cocoa/CMakeLists.txt
@@ -7,7 +7,7 @@
qt_internal_add_plugin(QCocoaIntegrationPlugin
OUTPUT_NAME qcocoa
- DEFAULT_IF ${QT_QPA_DEFAULT_PLATFORM} MATCHES cocoa
+ DEFAULT_IF "cocoa" IN_LIST QT_QPA_PLATFORMS
PLUGIN_TYPE platforms
SOURCES
main.mm
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
index c5e40a4087..40c1e90511 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
@@ -36,6 +36,23 @@ void QCocoaAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event)
}
switch (event->type()) {
+ case QAccessible::Announcement: {
+ auto *announcementEvent = static_cast<QAccessibleAnnouncementEvent *>(event);
+ auto priorityLevel = (announcementEvent->priority() == QAccessible::AnnouncementPriority::Assertive)
+ ? NSAccessibilityPriorityHigh
+ : NSAccessibilityPriorityMedium;
+ NSDictionary *announcementInfo = @{
+ NSAccessibilityPriorityKey: [NSNumber numberWithInt:priorityLevel],
+ NSAccessibilityAnnouncementKey: announcementEvent->message().toNSString()
+ };
+ // post event for application element, as the comment for
+ // NSAccessibilityAnnouncementRequestedNotification in the
+ // NSAccessibilityConstants.h header says
+ NSAccessibilityPostNotificationWithUserInfo(NSApp,
+ NSAccessibilityAnnouncementRequestedNotification,
+ announcementInfo);
+ break;
+ }
case QAccessible::Focus: {
NSAccessibilityPostNotification(element, NSAccessibilityFocusedUIElementChangedNotification);
break;
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 4a245a0f8a..d2c9bb0196 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -514,7 +514,7 @@ NSInteger QCocoaWindow::windowLevel(Qt::WindowFlags flags)
auto *nsWindow = transientCocoaWindow->nativeWindow();
// We only upgrade the window level for "special" windows, to work
- // around Qt Designer parenting the designer windows to the widget
+ // around Qt Widgets Designer parenting the designer windows to the widget
// palette window (QTBUG-31779). This should be fixed in designer.
if (type != Qt::Window)
windowLevel = qMax(windowLevel, nsWindow.level);
diff --git a/src/plugins/platforms/eglfs/CMakeLists.txt b/src/plugins/platforms/eglfs/CMakeLists.txt
index a0a6116a45..cb4b5d1eb9 100644
--- a/src/plugins/platforms/eglfs/CMakeLists.txt
+++ b/src/plugins/platforms/eglfs/CMakeLists.txt
@@ -92,7 +92,7 @@ endif()
qt_internal_add_plugin(QEglFSIntegrationPlugin
OUTPUT_NAME qeglfs
PLUGIN_TYPE platforms
- DEFAULT_IF ${QT_QPA_DEFAULT_PLATFORM} MATCHES eglfs
+ DEFAULT_IF "eglfs" IN_LIST QT_QPA_PLATFORMS
SOURCES
qeglfsmain.cpp
DEFINES
diff --git a/src/plugins/platforms/ios/CMakeLists.txt b/src/plugins/platforms/ios/CMakeLists.txt
index 4cc3efc91e..51c1b52cf3 100644
--- a/src/plugins/platforms/ios/CMakeLists.txt
+++ b/src/plugins/platforms/ios/CMakeLists.txt
@@ -5,10 +5,23 @@
## QIOSIntegrationPlugin Plugin:
#####################################################################
+if(VISIONOS)
+ include(SwiftIntegration.cmake)
+
+ qt_install(TARGETS QIOSIntegrationPluginSwift
+ EXPORT "${INSTALL_CMAKE_NAMESPACE}QIOSIntegrationPluginTargets"
+ DESTINATION "${INSTALL_LIBDIR}"
+ )
+ qt_internal_add_targets_to_additional_targets_export_file(
+ TARGETS QIOSIntegrationPluginSwift
+ EXPORT_NAME_PREFIX "${INSTALL_CMAKE_NAMESPACE}QIOSIntegrationPlugin"
+ )
+endif()
+
qt_internal_add_plugin(QIOSIntegrationPlugin
OUTPUT_NAME qios
STATIC # Force static, even in shared builds
- DEFAULT_IF ${QT_QPA_DEFAULT_PLATFORM} MATCHES ios
+ DEFAULT_IF "ios" IN_LIST QT_QPA_PLATFORMS
PLUGIN_TYPE platforms
SOURCES
plugin.mm
@@ -86,3 +99,7 @@ qt_internal_extend_target(QIOSIntegrationPlugin CONDITION NOT (TVOS OR VISIONOS)
)
add_subdirectory(optional)
+
+if(VISIONOS)
+ target_link_libraries(QIOSIntegrationPlugin PRIVATE QIOSIntegrationPluginSwift)
+endif()
diff --git a/src/plugins/platforms/ios/SwiftIntegration.cmake b/src/plugins/platforms/ios/SwiftIntegration.cmake
new file mode 100644
index 0000000000..d52edb3ad2
--- /dev/null
+++ b/src/plugins/platforms/ios/SwiftIntegration.cmake
@@ -0,0 +1,78 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+set(CMAKE_Swift_COMPILER_TARGET arm64-apple-xros)
+if($CACHE{CMAKE_OSX_SYSROOT} MATCHES "^[a-z]+simulator$")
+ set(CMAKE_Swift_COMPILER_TARGET "${CMAKE_Swift_COMPILER_TARGET}-simulator")
+endif()
+
+cmake_policy(SET CMP0157 NEW)
+enable_language(Swift)
+
+# Verify that we have a new enough compiler
+if("${CMAKE_Swift_COMPILER_VERSION}" VERSION_LESS 5.9)
+ message(FATAL_ERROR "Swift 5.9 required for C++ interoperability")
+endif()
+
+get_target_property(QT_CORE_INCLUDES Qt6::Core INTERFACE_INCLUDE_DIRECTORIES)
+get_target_property(QT_GUI_INCLUDES Qt6::Gui INTERFACE_INCLUDE_DIRECTORIES)
+get_target_property(QT_CORE_PRIVATE_INCLUDES Qt6::CorePrivate INTERFACE_INCLUDE_DIRECTORIES)
+get_target_property(QT_GUI_PRIVATE_INCLUDES Qt6::GuiPrivate INTERFACE_INCLUDE_DIRECTORIES)
+
+set(target QIOSIntegrationPluginSwift)
+# Swift library
+set(SWIFT_SOURCES
+ "${CMAKE_CURRENT_SOURCE_DIR}/qiosapplication.swift"
+)
+add_library(${target} STATIC ${SWIFT_SOURCES})
+set_target_properties(${target} PROPERTIES
+ Swift_MODULE_NAME ${target})
+target_include_directories(${target} PUBLIC
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ "${QT_CORE_INCLUDES}"
+ "${QT_GUI_INCLUDES}"
+ "${QT_CORE_PRIVATE_INCLUDES}"
+ "${QT_GUI_PRIVATE_INCLUDES}"
+
+)
+target_compile_options(${target} PUBLIC
+ $<$<COMPILE_LANGUAGE:Swift>:-cxx-interoperability-mode=default>
+ $<$<COMPILE_LANGUAGE:Swift>:-Xcc -std=c++17>)
+
+# Swift to C++ bridging header
+set(SWIFT_BRIDGING_HEADER "${CMAKE_CURRENT_BINARY_DIR}/qiosswiftintegration.h")
+list(TRANSFORM QT_CORE_INCLUDES PREPEND "-I")
+list(TRANSFORM QT_GUI_INCLUDES PREPEND "-I")
+list(TRANSFORM QT_CORE_PRIVATE_INCLUDES PREPEND "-I")
+list(TRANSFORM QT_GUI_PRIVATE_INCLUDES PREPEND "-I")
+add_custom_command(
+ COMMAND
+ ${CMAKE_Swift_COMPILER} -frontend -typecheck
+ ${SWIFT_SOURCES}
+ -I ${CMAKE_CURRENT_SOURCE_DIR}
+ ${QT_CORE_INCLUDES}
+ ${QT_GUI_INCLUDES}
+ ${QT_CORE_PRIVATE_INCLUDES}
+ ${QT_GUI_PRIVATE_INCLUDES}
+ -sdk ${CMAKE_OSX_SYSROOT}
+ -module-name ${target}
+ -cxx-interoperability-mode=default
+ -Xcc -std=c++17
+ -emit-clang-header-path "${SWIFT_BRIDGING_HEADER}"
+ -target ${CMAKE_Swift_COMPILER_TARGET}
+ OUTPUT
+ "${SWIFT_BRIDGING_HEADER}"
+ DEPENDS
+ ${SWIFT_SOURCES}
+ )
+
+set(header_target "${target}Header")
+add_custom_target(${header_target}
+ DEPENDS "${SWIFT_BRIDGING_HEADER}"
+)
+# Make sure the "'__bridge_transfer' casts have no effect when not using ARC"
+# warning doesn't break warnings-are-error builds.
+target_compile_options(${target} INTERFACE
+ -Wno-error=arc-bridge-casts-disallowed-in-nonarc)
+
+add_dependencies(${target} ${header_target})
diff --git a/src/plugins/platforms/ios/module.modulemap b/src/plugins/platforms/ios/module.modulemap
new file mode 100644
index 0000000000..af42b3e1f5
--- /dev/null
+++ b/src/plugins/platforms/ios/module.modulemap
@@ -0,0 +1,4 @@
+module QIOSIntegrationPlugin {
+ header "qiosapplicationdelegate.h"
+ header "qiosintegration.h"
+}
diff --git a/src/plugins/platforms/ios/qiosapplication.swift b/src/plugins/platforms/ios/qiosapplication.swift
new file mode 100644
index 0000000000..6f75ebd0b5
--- /dev/null
+++ b/src/plugins/platforms/ios/qiosapplication.swift
@@ -0,0 +1,82 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import SwiftUI
+import CompositorServices
+import QIOSIntegrationPlugin
+import RealityKit
+
+struct QIOSSwiftApplication: App {
+ @UIApplicationDelegateAdaptor private var appDelegate: QIOSApplicationDelegate
+
+ var body: some SwiftUI.Scene {
+ WindowGroup() {
+ ImmersiveSpaceControlView()
+ }
+
+ ImmersiveSpace(id: "QIOSImmersiveSpace") {
+ CompositorLayer(configuration: QIOSLayerConfiguration()) { layerRenderer in
+ QIOSIntegration.instance().renderCompositorLayer(layerRenderer)
+ }
+ }
+ // CompositorLayer immersive spaces are always full, and should not need
+ // to set the immersion style, but lacking this we get a warning in the
+ // console about not being able to "configure an immersive space with
+ // selected style 'AutomaticImmersionStyle' since it is not in the list
+ // of supported styles for this type of content: 'FullImmersionStyle'."
+ .immersionStyle(selection: .constant(.full), in: .full)
+ }
+}
+
+public struct QIOSLayerConfiguration: CompositorLayerConfiguration {
+ public func makeConfiguration(capabilities: LayerRenderer.Capabilities,
+ configuration: inout LayerRenderer.Configuration) {
+ // Use reflection to pull out underlying C handles
+ // FIXME: Use proper bridging APIs when available
+ let capabilitiesMirror = Mirror(reflecting: capabilities)
+ let configurationMirror = Mirror(reflecting: configuration)
+ QIOSIntegration.instance().configureCompositorLayer(
+ capabilitiesMirror.descendant("c_capabilities") as? cp_layer_renderer_capabilities_t,
+ configurationMirror.descendant("box", "value") as? cp_layer_renderer_configuration_t
+ )
+ }
+}
+
+public func runSwiftAppMain() {
+ QIOSSwiftApplication.main()
+}
+
+public class ImmersiveState: ObservableObject {
+ static let shared = ImmersiveState()
+ @Published var showImmersiveSpace: Bool = false
+}
+
+struct ImmersiveSpaceControlView: View {
+ @ObservedObject private var immersiveState = ImmersiveState.shared
+
+ @Environment(\.openImmersiveSpace) var openImmersiveSpace
+ @Environment(\.dismissImmersiveSpace) var dismissImmersiveSpace
+
+ var body: some View {
+ VStack {}
+ .onChange(of: immersiveState.showImmersiveSpace) { _, newValue in
+ Task {
+ if newValue {
+ await openImmersiveSpace(id: "QIOSImmersiveSpace")
+ } else {
+ await dismissImmersiveSpace()
+ }
+ }
+ }
+ }
+}
+
+public class ImmersiveSpaceManager : NSObject {
+ @objc public static func openImmersiveSpace() {
+ ImmersiveState.shared.showImmersiveSpace = true
+ }
+
+ @objc public static func dismissImmersiveSpace() {
+ ImmersiveState.shared.showImmersiveSpace = false
+ }
+}
diff --git a/src/plugins/platforms/ios/qiosapplicationdelegate.h b/src/plugins/platforms/ios/qiosapplicationdelegate.h
index 39bb9fdedb..7e12d64cbf 100644
--- a/src/plugins/platforms/ios/qiosapplicationdelegate.h
+++ b/src/plugins/platforms/ios/qiosapplicationdelegate.h
@@ -1,6 +1,9 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+#ifndef QIOSAPPLICATIONDELEGATE_H
+#define QIOSAPPLICATIONDELEGATE_H
+
#import <UIKit/UIKit.h>
#import <QtGui/QtGui>
@@ -8,3 +11,5 @@
@interface QIOSApplicationDelegate : UIResponder <UIApplicationDelegate>
@end
+
+#endif // QIOSAPPLICATIONDELEGATE_H
diff --git a/src/plugins/platforms/ios/qioseventdispatcher.h b/src/plugins/platforms/ios/qioseventdispatcher.h
index b40024ec19..5eee0556f5 100644
--- a/src/plugins/platforms/ios/qioseventdispatcher.h
+++ b/src/plugins/platforms/ios/qioseventdispatcher.h
@@ -16,6 +16,8 @@ public:
static QIOSEventDispatcher* create();
bool processPostedEvents() override;
+ static bool isQtApplication();
+
protected:
explicit QIOSEventDispatcher(QObject *parent = nullptr);
};
diff --git a/src/plugins/platforms/ios/qioseventdispatcher.mm b/src/plugins/platforms/ios/qioseventdispatcher.mm
index 24d9d88294..710a834bfd 100644
--- a/src/plugins/platforms/ios/qioseventdispatcher.mm
+++ b/src/plugins/platforms/ios/qioseventdispatcher.mm
@@ -5,6 +5,10 @@
#include "qiosapplicationdelegate.h"
#include "qiosglobal.h"
+#if defined(Q_OS_VISIONOS)
+#include "qiosswiftintegration.h"
+#endif
+
#include <QtCore/qprocessordetection.h>
#include <QtCore/private/qcoreapplication_p.h>
#include <QtCore/private/qthread_p.h>
@@ -173,12 +177,16 @@ namespace
QAppleLogActivity UIApplicationMain;
QAppleLogActivity applicationDidFinishLaunching;
} logActivity;
+
+ static bool s_isQtApplication = false;
}
using namespace QT_PREPEND_NAMESPACE(QtPrivate);
extern "C" int qt_main_wrapper(int argc, char *argv[])
{
+ s_isQtApplication = true;
+
@autoreleasepool {
size_t defaultStackSize = 512 * kBytesPerKiloByte; // Same as secondary threads
@@ -202,8 +210,16 @@ extern "C" int qt_main_wrapper(int argc, char *argv[])
logActivity.UIApplicationMain = QT_APPLE_LOG_ACTIVITY(
lcEventDispatcher().isDebugEnabled(), "UIApplicationMain").enter();
+#if defined(Q_OS_VISIONOS)
+ Q_UNUSED(argc);
+ Q_UNUSED(argv);
+ qCDebug(lcEventDispatcher) << "Starting Swift app";
+ QIOSIntegrationPluginSwift::runSwiftAppMain();
+ Q_UNREACHABLE();
+#else
qCDebug(lcEventDispatcher) << "Running UIApplicationMain";
return UIApplicationMain(argc, argv, nil, NSStringFromClass([QIOSApplicationDelegate class]));
+#endif
}
}
@@ -424,6 +440,11 @@ QIOSEventDispatcher::QIOSEventDispatcher(QObject *parent)
QWindowSystemInterface::setSynchronousWindowSystemEvents(true);
}
+bool QIOSEventDispatcher::isQtApplication()
+{
+ return s_isQtApplication;
+}
+
/*!
Override of the CoreFoundation posted events runloop source callback
so that we can send window system (QPA) events in addition to sending
diff --git a/src/plugins/platforms/ios/qiosglobal.mm b/src/plugins/platforms/ios/qiosglobal.mm
index 25ccf2961b..1722e09aaa 100644
--- a/src/plugins/platforms/ios/qiosglobal.mm
+++ b/src/plugins/platforms/ios/qiosglobal.mm
@@ -5,6 +5,8 @@
#include "qiosapplicationdelegate.h"
#include "qiosviewcontroller.h"
#include "qiosscreen.h"
+#include "quiwindow.h"
+#include "qioseventdispatcher.h"
#include <QtCore/private/qcore_mac_p.h>
@@ -17,17 +19,13 @@ Q_LOGGING_CATEGORY(lcQpaWindowScene, "qt.qpa.window.scene");
bool isQtApplication()
{
- if (qt_apple_isApplicationExtension())
- return false;
-
// Returns \c true if the plugin is in full control of the whole application. This means
// that we control the application delegate and the top view controller, and can take
// actions that impacts all parts of the application. The opposite means that we are
// embedded inside a native iOS application, and should be more focused on playing along
// with native UIControls, and less inclined to change structures that lies outside the
// scope of our QWindows/UIViews.
- static bool isQt = ([qt_apple_sharedApplication().delegate isKindOfClass:[QIOSApplicationDelegate class]]);
- return isQt;
+ return QIOSEventDispatcher::isQtApplication();
}
bool isRunningOnVisionOS()
@@ -126,9 +124,15 @@ UIView *rootViewForScreen(QScreen *screen)
Q_UNUSED(iosScreen);
#endif
- UIWindow *uiWindow = windowScene.keyWindow;
- if (!uiWindow && windowScene.windows.count)
- uiWindow = windowScene.windows[0];
+ UIWindow *uiWindow = qt_objc_cast<QUIWindow*>(windowScene.keyWindow);
+ if (!uiWindow) {
+ for (UIWindow *win in windowScene.windows) {
+ if (qt_objc_cast<QUIWindow*>(win)) {
+ uiWindow = win;
+ break;
+ }
+ }
+ }
return uiWindow.rootViewController.view;
}
diff --git a/src/plugins/platforms/ios/qiosintegration.h b/src/plugins/platforms/ios/qiosintegration.h
index 2c7d33cc94..53f64c1748 100644
--- a/src/plugins/platforms/ios/qiosintegration.h
+++ b/src/plugins/platforms/ios/qiosintegration.h
@@ -16,11 +16,24 @@
#include "qiostextinputoverlay.h"
#endif
+#if defined(Q_OS_VISIONOS)
+#include <swift/bridging>
+#endif
+
QT_BEGIN_NAMESPACE
+using namespace QNativeInterface;
+
class QIOSServices;
-class QIOSIntegration : public QPlatformNativeInterface, public QPlatformIntegration
+class
+#if defined(Q_OS_VISIONOS)
+ SWIFT_IMMORTAL_REFERENCE
+#endif
+QIOSIntegration : public QPlatformNativeInterface, public QPlatformIntegration
+#if defined(Q_OS_VISIONOS)
+ , public QVisionOSApplication
+#endif
{
Q_OBJECT
public:
@@ -77,6 +90,17 @@ public:
QIOSApplicationState applicationState;
+#if defined(Q_OS_VISIONOS)
+ void openImmersiveSpace() override;
+ void dismissImmersiveSpace() override;
+
+ using CompositorLayer = QVisionOSApplication::ImmersiveSpaceCompositorLayer;
+ void setImmersiveSpaceCompositorLayer(CompositorLayer *layer) override;
+
+ void configureCompositorLayer(cp_layer_renderer_capabilities_t, cp_layer_renderer_configuration_t);
+ void renderCompositorLayer(cp_layer_renderer_t);
+#endif
+
private:
QPlatformFontDatabase *m_fontDatabase;
#if QT_CONFIG(clipboard)
@@ -90,6 +114,10 @@ private:
#if !defined(Q_OS_TVOS) && !defined(Q_OS_VISIONOS)
QIOSTextInputOverlay m_textInputOverlay;
#endif
+
+#if defined(Q_OS_VISIONOS)
+ CompositorLayer *m_immersiveSpaceCompositorLayer = nullptr;
+#endif
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm
index 7cd21f83f6..2c32957c03 100644
--- a/src/plugins/platforms/ios/qiosintegration.mm
+++ b/src/plugins/platforms/ios/qiosintegration.mm
@@ -17,6 +17,10 @@
#include "qiosservices.h"
#include "qiosoptionalplugininterface.h"
+#if defined(Q_OS_VISIONOS)
+#include "qiosswiftintegration.h"
+#endif
+
#include <QtGui/qpointingdevice.h>
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/private/qrhibackingstore_p.h>
@@ -296,6 +300,39 @@ void QIOSIntegration::setApplicationBadge(qint64 number)
// ---------------------------------------------------------
+#if defined(Q_OS_VISIONOS)
+void QIOSIntegration::openImmersiveSpace()
+{
+ [ImmersiveSpaceManager openImmersiveSpace];
+}
+
+void QIOSIntegration::dismissImmersiveSpace()
+{
+ [ImmersiveSpaceManager dismissImmersiveSpace];
+}
+
+void QIOSIntegration::setImmersiveSpaceCompositorLayer(CompositorLayer *layer)
+{
+ m_immersiveSpaceCompositorLayer = layer;
+}
+
+void QIOSIntegration::configureCompositorLayer(cp_layer_renderer_capabilities_t capabilities,
+ cp_layer_renderer_configuration_t configuration)
+{
+ if (m_immersiveSpaceCompositorLayer)
+ m_immersiveSpaceCompositorLayer->configure(capabilities, configuration);
+}
+
+void QIOSIntegration::renderCompositorLayer(cp_layer_renderer_t renderer)
+{
+ if (m_immersiveSpaceCompositorLayer)
+ m_immersiveSpaceCompositorLayer->render(renderer);
+}
+
+#endif
+
+// ---------------------------------------------------------
+
void *QIOSIntegration::nativeResourceForWindow(const QByteArray &resource, QWindow *window)
{
if (!window || !window->handle())
diff --git a/src/plugins/platforms/linuxfb/CMakeLists.txt b/src/plugins/platforms/linuxfb/CMakeLists.txt
index 9f75f53828..ba18cea50c 100644
--- a/src/plugins/platforms/linuxfb/CMakeLists.txt
+++ b/src/plugins/platforms/linuxfb/CMakeLists.txt
@@ -8,7 +8,7 @@
qt_internal_add_plugin(QLinuxFbIntegrationPlugin
OUTPUT_NAME qlinuxfb
PLUGIN_TYPE platforms
- DEFAULT_IF ${QT_QPA_DEFAULT_PLATFORM} MATCHES linuxfb
+ DEFAULT_IF "linuxfb" IN_LIST QT_QPA_PLATFORMS
SOURCES
main.cpp
qlinuxfbintegration.cpp qlinuxfbintegration.h
diff --git a/src/plugins/platforms/minimal/CMakeLists.txt b/src/plugins/platforms/minimal/CMakeLists.txt
index f3683deccf..18d8828134 100644
--- a/src/plugins/platforms/minimal/CMakeLists.txt
+++ b/src/plugins/platforms/minimal/CMakeLists.txt
@@ -10,7 +10,7 @@ qt_find_package(WrapFreetype PROVIDED_TARGETS WrapFreetype::WrapFreetype)
qt_internal_add_plugin(QMinimalIntegrationPlugin
OUTPUT_NAME qminimal
PLUGIN_TYPE platforms
- DEFAULT_IF ${QT_QPA_DEFAULT_PLATFORM} MATCHES minimal
+ DEFAULT_IF "minimal" IN_LIST QT_QPA_PLATFORMS
SOURCES
main.cpp
qminimalbackingstore.cpp qminimalbackingstore.h
diff --git a/src/plugins/platforms/minimalegl/CMakeLists.txt b/src/plugins/platforms/minimalegl/CMakeLists.txt
index a6ec8be781..b93f325b8f 100644
--- a/src/plugins/platforms/minimalegl/CMakeLists.txt
+++ b/src/plugins/platforms/minimalegl/CMakeLists.txt
@@ -10,7 +10,7 @@ qt_find_package(EGL)
qt_internal_add_plugin(QMinimalEglIntegrationPlugin
OUTPUT_NAME qminimalegl
PLUGIN_TYPE platforms
- DEFAULT_IF ${QT_QPA_DEFAULT_PLATFORM} MATCHES minimalegl
+ DEFAULT_IF "minimalegl" IN_LIST QT_QPA_PLATFORMS
SOURCES
main.cpp
qminimaleglintegration.cpp qminimaleglintegration.h
diff --git a/src/plugins/platforms/offscreen/CMakeLists.txt b/src/plugins/platforms/offscreen/CMakeLists.txt
index 09ad9a384d..907c2c9cc6 100644
--- a/src/plugins/platforms/offscreen/CMakeLists.txt
+++ b/src/plugins/platforms/offscreen/CMakeLists.txt
@@ -8,7 +8,7 @@
qt_internal_add_plugin(QOffscreenIntegrationPlugin
OUTPUT_NAME qoffscreen
PLUGIN_TYPE platforms
- DEFAULT_IF ${QT_QPA_DEFAULT_PLATFORM} MATCHES offscreen
+ DEFAULT_IF "offscreen" IN_LIST QT_QPA_PLATFORMS
SOURCES
main.cpp
qoffscreencommon.cpp qoffscreencommon.h
diff --git a/src/plugins/platforms/qnx/CMakeLists.txt b/src/plugins/platforms/qnx/CMakeLists.txt
index 9fb412d8a4..0f9deaa00b 100644
--- a/src/plugins/platforms/qnx/CMakeLists.txt
+++ b/src/plugins/platforms/qnx/CMakeLists.txt
@@ -8,7 +8,7 @@
qt_internal_add_plugin(QQnxIntegrationPlugin
OUTPUT_NAME qqnx
PLUGIN_TYPE platforms
- DEFAULT_IF ${QT_QPA_DEFAULT_PLATFORM} MATCHES qnx
+ DEFAULT_IF "qnx" IN_LIST QT_QPA_PLATFORMS
SOURCES
main.cpp main.h
qqnxabstractcover.h
diff --git a/src/plugins/platforms/qnx/qqnxintegration.cpp b/src/plugins/platforms/qnx/qqnxintegration.cpp
index cc10f6a00e..b308c956f2 100644
--- a/src/plugins/platforms/qnx/qqnxintegration.cpp
+++ b/src/plugins/platforms/qnx/qqnxintegration.cpp
@@ -49,6 +49,7 @@
#include <qpa/qwindowsysteminterface.h>
#include <QtGui/private/qguiapplication_p.h>
+#include <QtGui/private/qrhibackingstore_p.h>
#if !defined(QT_NO_OPENGL)
#include "qqnxglcontext.h"
@@ -328,8 +329,19 @@ QPlatformWindow *QQnxIntegration::createPlatformWindow(QWindow *window) const
QPlatformBackingStore *QQnxIntegration::createPlatformBackingStore(QWindow *window) const
{
- qCDebug(lcQpaQnx) << Q_FUNC_INFO;
- return new QQnxRasterBackingStore(window);
+ QSurface::SurfaceType surfaceType = window->surfaceType();
+ qCDebug(lcQpaQnx) << Q_FUNC_INFO << surfaceType;
+ switch (surfaceType) {
+ case QSurface::RasterSurface:
+ return new QQnxRasterBackingStore(window);
+#if !defined(QT_NO_OPENGL)
+ // Return a QRhiBackingStore for non-raster surface windows
+ case QSurface::OpenGLSurface:
+ return new QRhiBackingStore(window);
+#endif
+ default:
+ return nullptr;
+ }
}
#if !defined(QT_NO_OPENGL)
diff --git a/src/plugins/platforms/vkkhrdisplay/CMakeLists.txt b/src/plugins/platforms/vkkhrdisplay/CMakeLists.txt
index 719e5c45e6..406487f1e9 100644
--- a/src/plugins/platforms/vkkhrdisplay/CMakeLists.txt
+++ b/src/plugins/platforms/vkkhrdisplay/CMakeLists.txt
@@ -6,7 +6,7 @@ qt_find_package(WrapFreetype PROVIDED_TARGETS WrapFreetype::WrapFreetype)
qt_internal_add_plugin(QVkKhrDisplayIntegrationPlugin
OUTPUT_NAME qvkkhrdisplay
PLUGIN_TYPE platforms
- DEFAULT_IF ${QT_QPA_DEFAULT_PLATFORM} MATCHES vkkhrdisplay
+ DEFAULT_IF "vkkhrdisplay" IN_LIST QT_QPA_PLATFORMS
SOURCES
main.cpp
qvkkhrdisplayintegration.cpp qvkkhrdisplayintegration.h
diff --git a/src/plugins/platforms/vnc/CMakeLists.txt b/src/plugins/platforms/vnc/CMakeLists.txt
index 25cb399bd0..34370807ae 100644
--- a/src/plugins/platforms/vnc/CMakeLists.txt
+++ b/src/plugins/platforms/vnc/CMakeLists.txt
@@ -8,7 +8,7 @@
qt_internal_add_plugin(QVncIntegrationPlugin
OUTPUT_NAME qvnc
PLUGIN_TYPE platforms
- DEFAULT_IF ${QT_QPA_DEFAULT_PLATFORM} MATCHES vnc
+ DEFAULT_IF "vnc" IN_LIST QT_QPA_PLATFORMS
SOURCES
main.cpp
qvnc.cpp qvnc_p.h
diff --git a/src/plugins/platforms/wasm/CMakeLists.txt b/src/plugins/platforms/wasm/CMakeLists.txt
index 90c7ec2118..775946aaf9 100644
--- a/src/plugins/platforms/wasm/CMakeLists.txt
+++ b/src/plugins/platforms/wasm/CMakeLists.txt
@@ -7,7 +7,7 @@
qt_internal_add_plugin(QWasmIntegrationPlugin
OUTPUT_NAME qwasm
- DEFAULT_IF ${QT_QPA_DEFAULT_PLATFORM} MATCHES wasm
+ DEFAULT_IF "wasm" IN_LIST QT_QPA_PLATFORMS
PLUGIN_TYPE platforms
SOURCES
main.cpp
diff --git a/src/plugins/platforms/wasm/qwasmevent.cpp b/src/plugins/platforms/wasm/qwasmevent.cpp
index c1d6ce3a2a..e418263655 100644
--- a/src/plugins/platforms/wasm/qwasmevent.cpp
+++ b/src/plugins/platforms/wasm/qwasmevent.cpp
@@ -106,7 +106,7 @@ KeyEvent::KeyEvent(EventType type, emscripten::val event) : Event(type, event)
const auto code = event["code"].as<std::string>();
const auto webKey = event["key"].as<std::string>();
deadKey = isDeadKeyEvent(webKey.c_str());
-
+ autoRepeat = event["repeat"].as<bool>();
modifiers = KeyboardModifier::getForEvent(event);
key = webKeyToQtKey(code, webKey, deadKey, modifiers);
diff --git a/src/plugins/platforms/wasm/qwasmevent.h b/src/plugins/platforms/wasm/qwasmevent.h
index 6ada5393e3..bd0fb39f11 100644
--- a/src/plugins/platforms/wasm/qwasmevent.h
+++ b/src/plugins/platforms/wasm/qwasmevent.h
@@ -153,6 +153,7 @@ struct KeyEvent : public Event
QFlags<Qt::KeyboardModifier> modifiers;
bool deadKey;
QString text;
+ bool autoRepeat;
};
struct MouseEvent : public Event
diff --git a/src/plugins/platforms/wasm/qwasmwindow.cpp b/src/plugins/platforms/wasm/qwasmwindow.cpp
index b8197c5113..0513f46e5b 100644
--- a/src/plugins/platforms/wasm/qwasmwindow.cpp
+++ b/src/plugins/platforms/wasm/qwasmwindow.cpp
@@ -502,7 +502,7 @@ bool QWasmWindow::processKey(const KeyEvent &event)
const auto result = QWindowSystemInterface::handleKeyEvent(
0, event.type == EventType::KeyDown ? QEvent::KeyPress : QEvent::KeyRelease, event.key,
- event.modifiers, event.text);
+ event.modifiers, event.text, event.autoRepeat);
return clipboardResult == ProcessKeyboardResult::NativeClipboardEventAndCopiedDataNeeded
? ProceedToNativeEvent
: result;
diff --git a/src/plugins/platforms/wasm/wasm_shell.html b/src/plugins/platforms/wasm/wasm_shell.html
index 702ea1f59d..6e93955552 100644
--- a/src/plugins/platforms/wasm/wasm_shell.html
+++ b/src/plugins/platforms/wasm/wasm_shell.html
@@ -1,3 +1,8 @@
+<!--
+Copyright (C) 2024 The Qt Company Ltd.
+SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+-->
+
<!doctype html>
<html lang="en-us">
<head>
diff --git a/src/plugins/platforms/windows/CMakeLists.txt b/src/plugins/platforms/windows/CMakeLists.txt
index 4b92317978..8cd84e208b 100644
--- a/src/plugins/platforms/windows/CMakeLists.txt
+++ b/src/plugins/platforms/windows/CMakeLists.txt
@@ -8,7 +8,7 @@
qt_internal_add_plugin(QWindowsIntegrationPlugin
OUTPUT_NAME qwindows
PLUGIN_TYPE platforms
- DEFAULT_IF ${QT_QPA_DEFAULT_PLATFORM} MATCHES windows
+ DEFAULT_IF "windows" IN_LIST QT_QPA_PLATFORMS
SOURCES
main.cpp
qtwindowsglobal.h
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index de65a2171d..8c0261d568 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -201,6 +201,8 @@ QWindowsContext::~QWindowsContext()
if (d->m_powerDummyWindow)
DestroyWindow(d->m_powerDummyWindow);
+ d->m_screenManager.destroyWindow();
+
unregisterWindowClasses();
if (d->m_oleInitializeResult == S_OK || d->m_oleInitializeResult == S_FALSE) {
#ifdef QT_USE_FACTORY_CACHE_REGISTRATION
diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp
index a50f9fd4b0..1f22fb4f60 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.cpp
+++ b/src/plugins/platforms/windows/qwindowsscreen.cpp
@@ -698,11 +698,15 @@ void QWindowsScreenManager::initialize()
handleScreenChanges();
}
-QWindowsScreenManager::~QWindowsScreenManager()
+void QWindowsScreenManager::destroyWindow()
{
+ qCDebug(lcQpaScreen) << "Destroying display change observer" << m_displayChangeObserver;
DestroyWindow(m_displayChangeObserver);
+ m_displayChangeObserver = nullptr;
}
+QWindowsScreenManager::~QWindowsScreenManager() = default;
+
bool QWindowsScreenManager::isSingleScreen()
{
return QWindowsContext::instance()->screenManager().screens().size() < 2;
diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h
index 0467ab2a0c..ea6a29efe3 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.h
+++ b/src/plugins/platforms/windows/qwindowsscreen.h
@@ -105,6 +105,7 @@ public:
QWindowsScreenManager();
void initialize();
+ void destroyWindow();
~QWindowsScreenManager();
void clearScreens();
diff --git a/src/plugins/platforms/windows/qwindowstheme.h b/src/plugins/platforms/windows/qwindowstheme.h
index 96ae6197b4..a89fb1e5bd 100644
--- a/src/plugins/platforms/windows/qwindowstheme.h
+++ b/src/plugins/platforms/windows/qwindowstheme.h
@@ -33,7 +33,6 @@ public:
Qt::ColorScheme colorScheme() const override;
void requestColorScheme(Qt::ColorScheme scheme) override;
- Qt::ColorScheme requestedColorScheme() const { return s_colorSchemeOverride; }
static void handleSettingsChanged();
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index ee0b88ba54..acfff64751 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -855,12 +855,6 @@ static inline bool shouldApplyDarkFrame(const QWindow *w)
if (!QWindowsIntegration::instance()->darkModeHandling().testFlag(QWindowsApplication::DarkModeWindowFrames))
return false;
- // the application explicitly overrides the color scheme
- if (const auto requestedColorScheme = QWindowsTheme::instance()->requestedColorScheme();
- requestedColorScheme != Qt::ColorScheme::Unknown) {
- return requestedColorScheme == Qt::ColorScheme::Dark;
- }
-
// if the application supports a dark border, and the palette is dark (window background color
// is darker than the text), then turn dark-border support on, otherwise use a light border.
auto *dWindow = QWindowPrivate::get(const_cast<QWindow*>(w));
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp
index 1abb412ccd..5892493281 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp
@@ -127,6 +127,9 @@ void QWindowsUiaAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event
return;
switch (event->type()) {
+ case QAccessible::Announcement:
+ QWindowsUiaMainProvider::raiseNotification(static_cast<QAccessibleAnnouncementEvent *>(event));
+ break;
case QAccessible::Focus:
QWindowsUiaMainProvider::notifyFocusChange(event);
break;
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
index 95ddbcced6..be88ab4ae8 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
@@ -204,6 +204,24 @@ void QWindowsUiaMainProvider::notifyTextChange(QAccessibleEvent *event)
}
}
+void QWindowsUiaMainProvider::raiseNotification(QAccessibleAnnouncementEvent *event)
+{
+ if (QAccessibleInterface *accessible = event->accessibleInterface()) {
+ if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
+ BSTR message = bStrFromQString(event->message());
+ QAccessible::AnnouncementPriority prio = event->priority();
+ NotificationProcessing processing = (prio == QAccessible::AnnouncementPriority::Assertive)
+ ? NotificationProcessing_ImportantAll
+ : NotificationProcessing_All;
+ BSTR activityId = bStrFromQString(QString::fromLatin1(""));
+ UiaRaiseNotificationEvent(provider, NotificationKind_Other, processing, message, activityId);
+
+ ::SysFreeString(message);
+ ::SysFreeString(activityId);
+ }
+ }
+}
+
HRESULT STDMETHODCALLTYPE QWindowsUiaMainProvider::QueryInterface(REFIID iid, LPVOID *iface)
{
HRESULT result = QComObject::QueryInterface(iid, iface);
@@ -370,6 +388,93 @@ void QWindowsUiaMainProvider::fillVariantArrayForRelation(QAccessibleInterface*
pRetVal->parray = elements;
}
+void QWindowsUiaMainProvider::setAriaProperties(QAccessibleInterface *accessible, VARIANT *pRetVal)
+{
+ Q_ASSERT(accessible);
+
+ QAccessibleAttributesInterface *attributesIface = accessible->attributesInterface();
+ if (!attributesIface)
+ return;
+
+ QString ariaString;
+ const QList<QAccessible::Attribute> attrKeys = attributesIface->attributeKeys();
+ for (qsizetype i = 0; i < attrKeys.size(); ++i) {
+ if (i != 0)
+ ariaString += QStringLiteral(";");
+ const QAccessible::Attribute key = attrKeys.at(i);
+ const QVariant value = attributesIface->attributeValue(key);
+ // see "Core Accessibility API Mappings" spec: https://www.w3.org/TR/core-aam-1.2/
+ switch (key) {
+ case QAccessible::Attribute::Custom:
+ {
+ // forward custom attributes as-is
+ Q_ASSERT((value.canConvert<QHash<QString, QString>>()));
+ const QHash<QString, QString> attrMap = value.value<QHash<QString, QString>>();
+ for (auto [name, val] : attrMap.asKeyValueRange()) {
+ if (name != *attrMap.keyBegin())
+ ariaString += QStringLiteral(";");
+ ariaString += name + QStringLiteral("=") + val;
+ }
+ break;
+ }
+ case QAccessible::Attribute::Level:
+ Q_ASSERT(value.canConvert<int>());
+ ariaString += QStringLiteral("level=") + QString::number(value.toInt());
+ break;
+ default:
+ break;
+ }
+ }
+
+ setVariantString(ariaString, pRetVal);
+}
+
+void QWindowsUiaMainProvider::setStyle(QAccessibleInterface *accessible, VARIANT *pRetVal)
+{
+ Q_ASSERT(accessible);
+
+ QAccessibleAttributesInterface *attributesIface = accessible->attributesInterface();
+ if (!attributesIface)
+ return;
+
+ // currently, only heading styles are implemented here
+ if (accessible->role() != QAccessible::Role::Heading)
+ return;
+
+ const QVariant levelVariant = attributesIface->attributeValue(QAccessible::Attribute::Level);
+ if (!levelVariant.isValid())
+ return;
+
+ Q_ASSERT(levelVariant.canConvert<int>());
+ // UIA only has styles for heading levels 1-9
+ const int level = levelVariant.toInt();
+ if (level < 1 || level > 9)
+ return;
+
+ const int styleId = styleIdForHeadingLevel(level);
+ setVariantI4(styleId, pRetVal);
+}
+
+int QWindowsUiaMainProvider::styleIdForHeadingLevel(int headingLevel)
+{
+ // only heading levels 1-9 have a corresponding UIA style ID
+ Q_ASSERT(headingLevel > 0 && headingLevel <= 9);
+
+ static constexpr int styles[] = {
+ StyleId_Heading1,
+ StyleId_Heading2,
+ StyleId_Heading3,
+ StyleId_Heading4,
+ StyleId_Heading5,
+ StyleId_Heading6,
+ StyleId_Heading7,
+ StyleId_Heading8,
+ StyleId_Heading9,
+ };
+
+ return styles[headingLevel - 1];
+}
+
HRESULT QWindowsUiaMainProvider::GetPropertyValue(PROPERTYID idProp, VARIANT *pRetVal)
{
qCDebug(lcQpaUiAutomation) << __FUNCTION__ << idProp;
@@ -393,6 +498,9 @@ HRESULT QWindowsUiaMainProvider::GetPropertyValue(PROPERTYID idProp, VARIANT *pR
// Accelerator key.
setVariantString(accessible->text(QAccessible::Accelerator), pRetVal);
break;
+ case UIA_AriaPropertiesPropertyId:
+ setAriaProperties(accessible, pRetVal);
+ break;
case UIA_AutomationIdPropertyId:
// Automation ID, which can be used by tools to select a specific control in the UI.
setVariantString(automationIdForAccessible(accessible), pRetVal);
@@ -493,6 +601,9 @@ HRESULT QWindowsUiaMainProvider::GetPropertyValue(PROPERTYID idProp, VARIANT *pR
setVariantString(name, pRetVal);
break;
}
+ case UIA_StyleIdAttributeId:
+ setStyle(accessible, pRetVal);
+ break;
default:
break;
}
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h
index 99db0ed318..dafe877974 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h
@@ -34,6 +34,7 @@ public:
static void notifyNameChange(QAccessibleEvent *event);
static void notifySelectionChange(QAccessibleEvent *event);
static void notifyTextChange(QAccessibleEvent *event);
+ static void raiseNotification(QAccessibleAnnouncementEvent *event);
// IUnknown
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id, LPVOID *iface) override;
@@ -60,6 +61,10 @@ public:
private:
QString automationIdForAccessible(const QAccessibleInterface *accessible);
static void fillVariantArrayForRelation(QAccessibleInterface *accessible, QAccessible::Relation relation, VARIANT *pRetVal);
+ static void setAriaProperties(QAccessibleInterface *accessible, VARIANT *pRetVal);
+ static void setStyle(QAccessibleInterface *accessible, VARIANT *pRetVal);
+ /** Returns the UIA style ID for a heading level from 1 to 9. */
+ static int styleIdForHeadingLevel(int headingLevel);
static QMutex m_mutex;
};
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiautomation.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiautomation.cpp
index 1593a07202..6954a881d0 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiautomation.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiautomation.cpp
@@ -69,6 +69,14 @@ HRESULT WINAPI UiaRaiseAutomationEvent(IRawElementProviderSimple *pProvider, EVE
return func.invoke(pProvider, id);
}
+HRESULT WINAPI UiaRaiseNotificationEvent(
+ IRawElementProviderSimple *pProvider, NotificationKind notificationKind,
+ NotificationProcessing notificationProcessing, BSTR displayString, BSTR activityId)
+{
+ static auto func = winapi_func("uiautomationcore", FN(UiaRaiseNotificationEvent));
+ return func.invoke(pProvider, notificationKind, notificationProcessing, displayString, activityId);
+}
+
#endif // defined(__MINGW32__) || defined(__MINGW64__)
#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiautomation.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiautomation.h
index a192b9b0fb..4eb37bafa0 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiautomation.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiautomation.h
@@ -14,8 +14,19 @@
#define UIA_SelectionPattern2Id 10034
#define UIA_IsReadOnlyAttributeId 40015
#define UIA_StrikethroughStyleAttributeId 40026
+#define UIA_StyleIdAttributeId 40034
#define UIA_CaretPositionAttributeId 40038
+#define StyleId_Heading1 70001
+#define StyleId_Heading2 70002
+#define StyleId_Heading3 70003
+#define StyleId_Heading4 70004
+#define StyleId_Heading5 70005
+#define StyleId_Heading6 70006
+#define StyleId_Heading7 70007
+#define StyleId_Heading8 70008
+#define StyleId_Heading9 70009
+
enum CaretPosition {
CaretPosition_Unknown = 0,
CaretPosition_EndOfLine = 1,
diff --git a/src/plugins/platforms/xcb/CMakeLists.txt b/src/plugins/platforms/xcb/CMakeLists.txt
index e8fb442dd4..96758e7181 100644
--- a/src/plugins/platforms/xcb/CMakeLists.txt
+++ b/src/plugins/platforms/xcb/CMakeLists.txt
@@ -164,7 +164,7 @@ endif()
qt_internal_add_plugin(QXcbIntegrationPlugin
OUTPUT_NAME qxcb
PLUGIN_TYPE platforms
- DEFAULT_IF ${QT_QPA_DEFAULT_PLATFORM} MATCHES xcb
+ DEFAULT_IF "xcb" IN_LIST QT_QPA_PLATFORMS
SOURCES
qxcbmain.cpp
DEFINES
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
index 06f4b66edb..0ce337726e 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -23,6 +23,7 @@ QXcbVirtualDesktop::QXcbVirtualDesktop(QXcbConnection *connection, xcb_screen_t
: QXcbObject(connection)
, m_screen(screen)
, m_number(number)
+ , m_xSettings(new QXcbXSettings(this))
{
const QByteArray cmAtomName = "_NET_WM_CM_S" + QByteArray::number(m_number);
m_net_wm_cm_atom = connection->internAtom(cmAtomName.constData());
@@ -129,10 +130,6 @@ void QXcbVirtualDesktop::setPrimaryScreen(QPlatformScreen *s)
QXcbXSettings *QXcbVirtualDesktop::xSettings() const
{
- if (!m_xSettings) {
- QXcbVirtualDesktop *self = const_cast<QXcbVirtualDesktop *>(this);
- self->m_xSettings = new QXcbXSettings(self);
- }
return m_xSettings;
}
diff --git a/src/plugins/sqldrivers/ibase/qsql_ibase.cpp b/src/plugins/sqldrivers/ibase/qsql_ibase.cpp
index f6eed5e227..6df7aa9507 100644
--- a/src/plugins/sqldrivers/ibase/qsql_ibase.cpp
+++ b/src/plugins/sqldrivers/ibase/qsql_ibase.cpp
@@ -3,11 +3,13 @@
#include "qsql_ibase_p.h"
#include <QtCore/qcoreapplication.h>
+#include <QtCore/qendian.h>
#include <QtCore/qdatetime.h>
#include <QtCore/qtimezone.h>
#include <QtCore/qdeadlinetimer.h>
#include <QtCore/qdebug.h>
#include <QtCore/qlist.h>
+#include <QtCore/private/qlocale_tools_p.h>
#include <QtCore/qloggingcategory.h>
#include <QtCore/qmap.h>
#include <QtCore/qmutex.h>
@@ -41,6 +43,10 @@ using namespace Qt::StringLiterals;
#define blr_boolean_dtype blr_bool
#endif
+#if (defined(QT_SUPPORTS_INT128) || defined(Q_CC_MSVC)) && (FB_API_VER >= 40)
+#define IBASE_INT128_SUPPORTED
+#endif
+
constexpr qsizetype QIBaseChunkSize = SHRT_MAX / 2;
#if (FB_API_VER >= 40)
@@ -100,6 +106,9 @@ static void initDA(XSQLDA *sqlda)
case SQL_TIMESTAMP:
#if (FB_API_VER >= 40)
case SQL_TIMESTAMP_TZ:
+#ifdef IBASE_INT128_SUPPORTED
+ case SQL_INT128:
+#endif
#endif
case SQL_TYPE_TIME:
case SQL_TYPE_DATE:
@@ -347,21 +356,14 @@ public:
QSqlQuery qry(q->createResult());
qry.setForwardOnly(true);
qry.exec(QString("select * from RDB$TIME_ZONES"_L1));
- if (qry.lastError().type()) {
- q->setLastError(QSqlError(
- QCoreApplication::translate("QIBaseDriver",
- "failed to query time zone mapping from system table"),
- qry.lastError().databaseText(),
- QSqlError::StatementError,
- qry.lastError().nativeErrorCode()));
-
+ if (qry.lastError().isValid()) {
+ qCInfo(lcIbase) << "Table 'RDB$TIME_ZONES' not found - not timezone support available";
return;
}
while (qry.next()) {
- auto record = qry.record();
- quint16 fbTzId = record.value(0).value<quint16>();
- QByteArray ianaId = record.value(1).toByteArray().simplified();
+ quint16 fbTzId = qry.value(0).value<quint16>();
+ QByteArray ianaId = qry.value(1).toByteArray().simplified();
qFbTzIdToIanaIdMap()->insert(fbTzId, ianaId);
qIanaIdToFbTzIdMap()->insert(ianaId, fbTzId);
}
@@ -408,6 +410,32 @@ protected:
QSqlRecord record() const override;
template<typename T>
+ static QString numberToHighPrecision(T val, int scale)
+ {
+ const bool negative = val < 0;
+ QString number;
+#ifdef IBASE_INT128_SUPPORTED
+ if constexpr (std::is_same_v<qinternalint128, T>) {
+ number = negative ? qint128toBasicLatin(val * -1)
+ : qint128toBasicLatin(val);
+ } else
+#endif
+ number = negative ? QString::number(qAbs(val))
+ : QString::number(val);
+ auto len = number.size();
+ scale *= -1;
+ if (scale >= len) {
+ number = QString(scale - len + 1, u'0') + number;
+ len = number.size();
+ }
+ const auto sepPos = len - scale;
+ number = number.left(sepPos) + u'.' + number.mid(sepPos);
+ if (negative)
+ number = u'-' + number;
+ return number;
+ }
+
+ template<typename T>
QVariant applyScale(T val, int scale) const
{
if (scale >= 0)
@@ -420,28 +448,36 @@ protected:
return QVariant(qint64(val * pow(10.0, scale)));
case QSql::LowPrecisionDouble:
return QVariant(double(val * pow(10.0, scale)));
- case QSql::HighPrecision: {
- const bool negative = val < 0;
- QString number;
- if constexpr (std::is_signed_v<T> || negative)
- number = QString::number(qAbs(val));
- else
- number = QString::number(val);
- auto len = number.size();
- scale *= -1;
- if (scale >= len) {
- number = QString(scale - len + 1, u'0') + number;
- len = number.size();
- }
- const auto sepPos = len - scale;
- number = number.left(sepPos) + u'.' + number.mid(sepPos);
- if (negative)
- number = u'-' + number;
- return QVariant(number);
- }
+ case QSql::HighPrecision:
+ return QVariant(numberToHighPrecision(val, scale));
}
return QVariant(val);
}
+
+ template<typename T>
+ void setWithScale(const QVariant &val, int scale, char *data)
+ {
+ auto ptr = reinterpret_cast<T *>(data);
+ if (scale < 0) {
+ double d = floor(0.5 + val.toDouble() * pow(10.0, scale * -1));
+#ifdef IBASE_INT128_SUPPORTED
+ if constexpr (std::is_same_v<qinternalint128, T>) {
+ quint64 lower = quint64(d);
+ quint64 tmp = quint64(std::numeric_limits<quint32>::max()) + 1;
+ d /= tmp;
+ d /= tmp;
+ quint64 higher = quint64(d);
+ qinternalint128 result = higher;
+ result <<= 64;
+ result += lower;
+ *ptr = static_cast<T>(result);
+ } else
+#endif
+ *ptr = static_cast<T>(d);
+ }
+ else
+ *ptr = val.value<T>();
+ }
};
class QIBaseResultPrivate: public QSqlCachedResultPrivate
@@ -1102,32 +1138,25 @@ bool QIBaseResult::exec()
}
switch(d->inda->sqlvar[para].sqltype & ~1) {
case SQL_INT64:
- if (d->inda->sqlvar[para].sqlscale < 0)
- *((qint64*)d->inda->sqlvar[para].sqldata) =
- (qint64)floor(0.5 + val.toDouble() * pow(10.0, d->inda->sqlvar[para].sqlscale * -1));
- else
- *((qint64*)d->inda->sqlvar[para].sqldata) = val.toLongLong();
+ setWithScale<qint64>(val, d->inda->sqlvar[para].sqlscale, d->inda->sqlvar[para].sqldata);
break;
+#ifdef IBASE_INT128_SUPPORTED
+ case SQL_INT128:
+ setWithScale<qinternalint128>(val, d->inda->sqlvar[para].sqlscale,
+ d->inda->sqlvar[para].sqldata);
+ break;
+#endif
case SQL_LONG:
- if (d->inda->sqlvar[para].sqllen == 4) {
- if (d->inda->sqlvar[para].sqlscale < 0)
- *((qint32*)d->inda->sqlvar[para].sqldata) =
- (qint32)floor(0.5 + val.toDouble() * pow(10.0, d->inda->sqlvar[para].sqlscale * -1));
- else
- *((qint32*)d->inda->sqlvar[para].sqldata) = (qint32)val.toInt();
- } else {
- *((qint64*)d->inda->sqlvar[para].sqldata) = val.toLongLong();
- }
+ if (d->inda->sqlvar[para].sqllen == 4)
+ setWithScale<qint32>(val, d->inda->sqlvar[para].sqlscale, d->inda->sqlvar[para].sqldata);
+ else
+ setWithScale<qint64>(val, 0, d->inda->sqlvar[para].sqldata);
break;
case SQL_SHORT:
- if (d->inda->sqlvar[para].sqlscale < 0)
- *((short*)d->inda->sqlvar[para].sqldata) =
- (short)floor(0.5 + val.toDouble() * pow(10.0, d->inda->sqlvar[para].sqlscale * -1));
- else
- *((short*)d->inda->sqlvar[para].sqldata) = (short)val.toInt();
+ setWithScale<qint16>(val, d->inda->sqlvar[para].sqlscale, d->inda->sqlvar[para].sqldata);
break;
case SQL_FLOAT:
- *((float*)d->inda->sqlvar[para].sqldata) = (float)val.toDouble();
+ *((float*)d->inda->sqlvar[para].sqldata) = val.toFloat();
break;
case SQL_DOUBLE:
*((double*)d->inda->sqlvar[para].sqldata) = val.toDouble();
@@ -1282,6 +1311,17 @@ bool QIBaseResult::gotoNext(QSqlCachedResult::ValueCache& row, int rowIdx)
row[idx] = applyScale(val, scale);
break;
}
+#ifdef IBASE_INT128_SUPPORTED
+ case SQL_INT128: {
+ Q_ASSERT(d->sqlda->sqlvar[i].sqllen == sizeof(qinternalint128));
+ const qinternalint128 val128 = qFromUnaligned<qinternalint128>(buf);
+ const auto scale = d->sqlda->sqlvar[i].sqlscale;
+ row[idx] = numberToHighPrecision(val128, scale);
+ if (numericalPrecisionPolicy() != QSql::HighPrecision)
+ row[idx] = applyScale(row[idx].toDouble(), 0);
+ break;
+ }
+#endif
case SQL_LONG:
if (d->sqlda->sqlvar[i].sqllen == 4) {
const auto val = *(qint32 *)buf;
diff --git a/src/plugins/styles/modernwindows/qwindows11style.cpp b/src/plugins/styles/modernwindows/qwindows11style.cpp
index 784f491681..0501e54ee0 100644
--- a/src/plugins/styles/modernwindows/qwindows11style.cpp
+++ b/src/plugins/styles/modernwindows/qwindows11style.cpp
@@ -14,7 +14,9 @@
#include <QtWidgets/qgraphicsview.h>
#include <QtWidgets/qlistview.h>
#include <QtWidgets/qmenu.h>
+#if QT_CONFIG(mdiarea)
#include <QtWidgets/qmdiarea.h>
+#endif
#include <QtWidgets/qtextedit.h>
#include <QtWidgets/qtreeview.h>
@@ -134,6 +136,8 @@ static void drawArrow(const QStyle *style, const QStyleOptionToolButton *toolbut
*/
QWindows11Style::QWindows11Style() : QWindowsVistaStyle(*new QWindows11StylePrivate)
{
+ highContrastTheme = QGuiApplicationPrivate::styleHints->colorScheme() == Qt::ColorScheme::Unknown;
+ colorSchemeIndex = QGuiApplicationPrivate::styleHints->colorScheme() == Qt::ColorScheme::Light ? 0 : 1;
}
/*!
@@ -142,6 +146,8 @@ QWindows11Style::QWindows11Style() : QWindowsVistaStyle(*new QWindows11StylePriv
*/
QWindows11Style::QWindows11Style(QWindows11StylePrivate &dd) : QWindowsVistaStyle(dd)
{
+ highContrastTheme = QGuiApplicationPrivate::styleHints->colorScheme() == Qt::ColorScheme::Unknown;
+ colorSchemeIndex = QGuiApplicationPrivate::styleHints->colorScheme() == Qt::ColorScheme::Light ? 0 : 1;
}
/*!
@@ -1738,6 +1744,10 @@ int QWindows11Style::styleHint(StyleHint hint, const QStyleOption *opt,
return 0;
case QStyle::SH_ItemView_ShowDecorationSelected:
return 1;
+ case QStyle::SH_Slider_AbsoluteSetButtons:
+ return Qt::LeftButton;
+ case QStyle::SH_Slider_PageSetButtons:
+ return 0;
default:
return QWindowsVistaStyle::styleHint(hint, opt, widget, returnData);
}
@@ -2043,7 +2053,11 @@ void QWindows11Style::polish(QWidget* widget)
pal.setColor(QPalette::Base, pal.window().color());
widget->setPalette(pal);
} else if (const auto *scrollarea = qobject_cast<QAbstractScrollArea *>(widget);
- scrollarea && !qobject_cast<QMdiArea *>(widget)) {
+ scrollarea
+#if QT_CONFIG(mdiarea)
+ && !qobject_cast<QMdiArea *>(widget)
+#endif
+ ) {
QPalette pal = scrollarea->viewport()->palette();
const QPalette originalPalette = pal;
pal.setColor(scrollarea->viewport()->backgroundRole(), Qt::transparent);
@@ -2062,7 +2076,11 @@ void QWindows11Style::unpolish(QWidget *widget)
{
QWindowsVistaStyle::unpolish(widget);
if (const auto *scrollarea = qobject_cast<QAbstractScrollArea *>(widget);
- scrollarea && !qobject_cast<QMdiArea *>(widget)) {
+ scrollarea
+#if QT_CONFIG(mdiarea)
+ && !qobject_cast<QMdiArea *>(widget)
+#endif
+ ) {
const QPalette pal = scrollarea->viewport()->property("_q_original_background_palette").value<QPalette>();
scrollarea->viewport()->setPalette(pal);
scrollarea->viewport()->setProperty("_q_original_background_palette", QVariant());
diff --git a/src/printsupport/CMakeLists.txt b/src/printsupport/CMakeLists.txt
index 25aad04caf..43a0c6b54b 100644
--- a/src/printsupport/CMakeLists.txt
+++ b/src/printsupport/CMakeLists.txt
@@ -14,7 +14,7 @@ qt_internal_add_module(PrintSupport
kernel/qplatformprintplugin.cpp kernel/qplatformprintplugin.h
kernel/qprint.cpp kernel/qprint_p.h
kernel/qprintdevice.cpp kernel/qprintdevice_p.h
- kernel/qprintengine.h
+ kernel/qprintengine.cpp kernel/qprintengine.h
kernel/qprintengine_pdf.cpp kernel/qprintengine_pdf_p.h
kernel/qprinter.cpp kernel/qprinter.h kernel/qprinter_p.h
kernel/qprinterinfo.cpp kernel/qprinterinfo.h kernel/qprinterinfo_p.h
diff --git a/src/printsupport/kernel/qprintengine.cpp b/src/printsupport/kernel/qprintengine.cpp
new file mode 100644
index 0000000000..b9afb28292
--- /dev/null
+++ b/src/printsupport/kernel/qprintengine.cpp
@@ -0,0 +1,15 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include <QtPrintSupport/qprintengine.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PRINTER
+
+QPrintEngine::~QPrintEngine()
+ = default;
+
+#endif // QT_NO_PRINTER
+
+QT_END_NAMESPACE
diff --git a/src/printsupport/kernel/qprintengine.h b/src/printsupport/kernel/qprintengine.h
index 65d9ed9a06..a18930c9a9 100644
--- a/src/printsupport/kernel/qprintengine.h
+++ b/src/printsupport/kernel/qprintengine.h
@@ -19,7 +19,8 @@ QT_BEGIN_NAMESPACE
class Q_PRINTSUPPORT_EXPORT QPrintEngine
{
public:
- virtual ~QPrintEngine() {}
+ virtual ~QPrintEngine();
+
enum PrintEnginePropertyKey {
PPK_CollateCopies,
PPK_ColorMode,
diff --git a/src/sql/kernel/qsqldatabase.cpp b/src/sql/kernel/qsqldatabase.cpp
index fdbb16a589..6aab93bd34 100644
--- a/src/sql/kernel/qsqldatabase.cpp
+++ b/src/sql/kernel/qsqldatabase.cpp
@@ -239,6 +239,8 @@ void QSqlDatabasePrivate::disable()
Destroys the SQL driver creator object.
*/
+QSqlDriverCreatorBase::~QSqlDriverCreatorBase()
+ = default;
/*!
\fn QSqlDriver *QSqlDriverCreatorBase::createObject() const
diff --git a/src/sql/kernel/qsqldatabase.h b/src/sql/kernel/qsqldatabase.h
index 5059dbba83..073ca89c52 100644
--- a/src/sql/kernel/qsqldatabase.h
+++ b/src/sql/kernel/qsqldatabase.h
@@ -23,7 +23,7 @@ class QThread;
class Q_SQL_EXPORT QSqlDriverCreatorBase
{
public:
- virtual ~QSqlDriverCreatorBase() {}
+ virtual ~QSqlDriverCreatorBase();
virtual QSqlDriver *createObject() const = 0;
};
diff --git a/src/sql/models/qsqlquerymodel.cpp b/src/sql/models/qsqlquerymodel.cpp
index 6f91fb9739..1aae088c64 100644
--- a/src/sql/models/qsqlquerymodel.cpp
+++ b/src/sql/models/qsqlquerymodel.cpp
@@ -618,7 +618,7 @@ bool QSqlQueryModel::insertColumns(int column, int count, const QModelIndex &par
d->colOffsets.append(nVal);
Q_ASSERT(d->colOffsets.size() >= d->rec.count());
}
- for (int i = column + 1; i < d->colOffsets.size(); ++i)
+ for (qsizetype i = column + 1; i < d->colOffsets.size(); ++i)
++d->colOffsets[i];
}
endInsertColumns();
@@ -644,10 +644,9 @@ bool QSqlQueryModel::removeColumns(int column, int count, const QModelIndex &par
beginRemoveColumns(parent, column, column + count - 1);
- int i;
- for (i = 0; i < count; ++i)
+ for (int i = 0; i < count; ++i)
d->rec.remove(column);
- for (i = column; i < d->colOffsets.size(); ++i)
+ for (qsizetype i = column; i < d->colOffsets.size(); ++i)
d->colOffsets[i] -= count;
endRemoveColumns();
diff --git a/src/sql/models/qsqlrelationaltablemodel.cpp b/src/sql/models/qsqlrelationaltablemodel.cpp
index c086d88ffe..1218514778 100644
--- a/src/sql/models/qsqlrelationaltablemodel.cpp
+++ b/src/sql/models/qsqlrelationaltablemodel.cpp
@@ -21,7 +21,7 @@ QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals;
-class QSqlRelationalTableModelSql: public QSqlTableModelSql
+class QSqlRelationalTableModelSql: public QSqlQueryModelSql
{
public:
inline const static QString relTablePrefix(int i) { return QString::number(i).prepend("relTblAl_"_L1); }
@@ -108,12 +108,12 @@ struct QRelation
void populateModel();
- bool isDictionaryInitialized();
+ bool isDictionaryInitialized() const;
void populateDictionary();
void clearDictionary();
void clear();
- bool isValid();
+ bool isValid() const;
QSqlRelation rel;
QRelatedTableModel *model;
@@ -158,7 +158,7 @@ void QRelation::populateModel()
}
}
-bool QRelation::isDictionaryInitialized()
+bool QRelation::isDictionaryInitialized() const
{
return m_dictInitialized;
}
@@ -204,7 +204,7 @@ void QRelation::clear()
clearDictionary();
}
-bool QRelation::isValid()
+bool QRelation::isValid() const
{
return (rel.isValid() && m_parent != nullptr);
}
@@ -253,10 +253,8 @@ public:
void QSqlRelationalTableModelPrivate::clearChanges()
{
- for (int i = 0; i < relations.size(); ++i) {
- QRelation &rel = relations[i];
+ for (auto &rel : relations)
rel.clear();
- }
}
void QSqlRelationalTableModelPrivate::revertCachedRow(int row)
@@ -277,8 +275,8 @@ int QSqlRelationalTableModelPrivate::nameToIndex(const QString &name) const
void QSqlRelationalTableModelPrivate::clearCache()
{
- for (int i = 0; i < relations.size(); ++i)
- relations[i].clearDictionary();
+ for (auto &rel : relations)
+ rel.clearDictionary();
QSqlTableModelPrivate::clearCache();
}
diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp
index 265d7782a0..0d17194287 100644
--- a/src/sql/models/qsqltablemodel.cpp
+++ b/src/sql/models/qsqltablemodel.cpp
@@ -19,12 +19,7 @@ QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals;
-using SqlTm = QSqlTableModelSql;
-
-QSqlTableModelPrivate::~QSqlTableModelPrivate()
-{
-
-}
+using SqlTm = QSqlQueryModelSql;
/*! \internal
Populates our record with values.
@@ -143,11 +138,10 @@ bool QSqlTableModelPrivate::exec(const QString &stmt, bool prepStatement,
return false;
}
}
- int i;
- for (i = 0; i < rec.count(); ++i)
+ for (int i = 0; i < rec.count(); ++i)
if (rec.isGenerated(i))
editQuery.addBindValue(rec.value(i));
- for (i = 0; i < whereValues.count(); ++i)
+ for (int i = 0; i < whereValues.count(); ++i)
if (whereValues.isGenerated(i) && !whereValues.isNull(i))
editQuery.addBindValue(whereValues.value(i));
@@ -475,10 +469,8 @@ QVariant QSqlTableModel::headerData(int section, Qt::Orientation orientation, in
bool QSqlTableModel::isDirty() const
{
Q_D(const QSqlTableModel);
- QSqlTableModelPrivate::CacheMap::ConstIterator i = d->cache.constBegin();
- const QSqlTableModelPrivate::CacheMap::ConstIterator e = d->cache.constEnd();
- for (; i != e; ++i) {
- if (!i.value().submitted())
+ for (const auto &val : std::as_const(d->cache)) {
+ if (!val.submitted())
return true;
}
return false;
@@ -1360,8 +1352,7 @@ bool QSqlTableModel::setRecord(int row, const QSqlRecord &values)
return false;
// Check field names and remember mapping
- typedef QMap<int, int> Map;
- Map map;
+ QMap<int, int> map;
for (int i = 0; i < values.count(); ++i) {
int idx = d->nameToIndex(values.fieldName(i));
if (idx == -1)
@@ -1374,18 +1365,16 @@ bool QSqlTableModel::setRecord(int row, const QSqlRecord &values)
mrow = QSqlTableModelPrivate::ModifiedRow(QSqlTableModelPrivate::Update,
QSqlQueryModel::record(row));
- Map::const_iterator i = map.constBegin();
- const Map::const_iterator e = map.constEnd();
- for ( ; i != e; ++i) {
+ for (const auto i : map.asKeyValueRange()) {
// have to use virtual setData() here rather than mrow.setValue()
EditStrategy strategy = d->strategy;
d->strategy = OnManualSubmit;
- QModelIndex cIndex = createIndex(row, i.value());
- setData(cIndex, values.value(i.key()));
+ QModelIndex cIndex = createIndex(row, i.second);
+ setData(cIndex, values.value(i.first));
d->strategy = strategy;
// setData() sets generated to TRUE, but source record should prevail.
- if (!values.isGenerated(i.key()))
- mrow.recRef().setGenerated(i.value(), false);
+ if (!values.isGenerated(i.first))
+ mrow.recRef().setGenerated(i.second, false);
}
if (d->strategy != OnManualSubmit)
diff --git a/src/sql/models/qsqltablemodel_p.h b/src/sql/models/qsqltablemodel_p.h
index 9c6425ded4..864c977ebb 100644
--- a/src/sql/models/qsqltablemodel_p.h
+++ b/src/sql/models/qsqltablemodel_p.h
@@ -35,7 +35,6 @@ public:
strategy(QSqlTableModel::OnRowChange),
busyInsertingRows(false)
{}
- ~QSqlTableModelPrivate();
void clear();
virtual void clearCache();
@@ -154,11 +153,6 @@ public:
CacheMap cache;
};
-class QSqlTableModelSql: public QSqlQueryModelSql
-{
-public:
-};
-
QT_END_NAMESPACE
#endif // QSQLTABLEMODEL_P_H
diff --git a/src/testlib/qsignalspy.cpp b/src/testlib/qsignalspy.cpp
index a45ca59378..116ce87c3e 100644
--- a/src/testlib/qsignalspy.cpp
+++ b/src/testlib/qsignalspy.cpp
@@ -216,7 +216,7 @@ QSignalSpy::ObjectSignal QSignalSpy::verify(const QObject *obj, QMetaMethod sign
return {};
}
-QList<int> QSignalSpy::makeArgs(const QMetaMethod &member, const QObject *obj)
+static QList<int> makeArgs(QMetaMethod member, const QObject *obj)
{
QList<int> result;
result.reserve(member.parameterCount());
@@ -250,7 +250,8 @@ public:
};
QSignalSpy::QSignalSpy(ObjectSignal os)
- : args(os.obj ? makeArgs(os.sig, os.obj) : QList<int>{})
+ : sig(os.sig.methodSignature()),
+ args(os.obj ? makeArgs(os.sig, os.obj) : QList<int>{})
{
if (!os.obj)
return;
@@ -266,8 +267,6 @@ QSignalSpy::QSignalSpy(ObjectSignal os)
}
d_ptr = std::move(i);
-
- sig = os.sig.methodSignature();
}
/*!
diff --git a/src/testlib/qsignalspy.h b/src/testlib/qsignalspy.h
index 591545b4d5..b8df2a4deb 100644
--- a/src/testlib/qsignalspy.h
+++ b/src/testlib/qsignalspy.h
@@ -41,7 +41,7 @@ public:
: QSignalSpy(verify(obj, signal)) {}
Q_TESTLIB_EXPORT ~QSignalSpy();
- inline bool isValid() const { return !sig.isEmpty(); }
+ bool isValid() const noexcept { return d_ptr != nullptr; }
inline QByteArray signal() const { return sig; }
bool wait(int timeout)
@@ -55,11 +55,10 @@ private:
Q_TESTLIB_EXPORT static ObjectSignal verify(const QObject *obj, QMetaMethod signal);
Q_TESTLIB_EXPORT static ObjectSignal verify(const QObject *obj, const char *aSignal);
- Q_TESTLIB_EXPORT static QList<int> makeArgs(const QMetaMethod &member, const QObject *obj);
Q_TESTLIB_EXPORT void appendArgs(void **a);
// the full, normalized signal name
- QByteArray sig;
+ const QByteArray sig;
// holds the QMetaType types for the argument list of the signal
const QList<int> args;
diff --git a/src/testlib/qtestevent.h b/src/testlib/qtestevent.h
index 8f092cf8c9..3b75e07f62 100644
--- a/src/testlib/qtestevent.h
+++ b/src/testlib/qtestevent.h
@@ -28,6 +28,9 @@ QT_BEGIN_NAMESPACE
# define QT_ONLY_WIDGETLIB_USES Q_DECL_UNUSED_MEMBER
#endif
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_CLANG("-Wweak-vtables") // QTBUG-1044486
+
class QTestEvent
{
public:
@@ -36,13 +39,15 @@ public:
#endif
virtual QTestEvent *clone() const = 0;
- virtual ~QTestEvent() {}
+ virtual ~QTestEvent() = default; // ### FIXME: weak vtable (QTBUG-104486)
};
#ifdef QT_GUI_LIB
class QTestKeyEvent: public QTestEvent
{
public:
+ ~QTestKeyEvent() override = default; // ### FIXME: weak vtable (QTBUG-104486)
+
inline QTestKeyEvent(QTest::KeyAction action, Qt::Key key, Qt::KeyboardModifiers modifiers, int delay)
: _action(action), _delay(delay), _modifiers(modifiers), _ascii(0), _key(key) {}
inline QTestKeyEvent(QTest::KeyAction action, char ascii, Qt::KeyboardModifiers modifiers, int delay)
@@ -71,6 +76,8 @@ protected:
class QTestKeyClicksEvent: public QTestEvent
{
public:
+ ~QTestKeyClicksEvent() override = default; // ### FIXME: weak vtables (QTBUG-104486)
+
inline QTestKeyClicksEvent(const QString &keys, Qt::KeyboardModifiers modifiers, int delay)
: _keys(keys), _modifiers(modifiers), _delay(delay) {}
inline QTestEvent *clone() const override { return new QTestKeyClicksEvent(*this); }
@@ -91,6 +98,8 @@ private:
class QTestMouseEvent: public QTestEvent
{
public:
+ ~QTestMouseEvent() override = default; // ### FIXME: weak vtables (QTBUG-104486)
+
inline QTestMouseEvent(QTest::MouseAction action, Qt::MouseButton button,
Qt::KeyboardModifiers modifiers, QPoint position, int delay)
: _action(action), _button(button), _modifiers(modifiers), _pos(position), _delay(delay) {}
@@ -117,6 +126,8 @@ class QTestDelayEvent: public QTestEvent
{
public:
inline QTestDelayEvent(int msecs): _delay(msecs) {}
+ ~QTestDelayEvent() override = default; // ### FIXME: weak vtables (QTBUG-104486)
+
inline QTestEvent *clone() const override { return new QTestDelayEvent(*this); }
#ifdef QT_WIDGETS_LIB
@@ -190,6 +201,8 @@ public:
#undef QT_ONLY_WIDGETLIB_USES
+QT_WARNING_POP // Clang -Wweak-vtables
+
QT_END_NAMESPACE
Q_DECLARE_METATYPE(QTestEventList)
diff --git a/src/tools/androiddeployqt/main.cpp b/src/tools/androiddeployqt/main.cpp
index 6125b405b5..b5751e9a40 100644
--- a/src/tools/androiddeployqt/main.cpp
+++ b/src/tools/androiddeployqt/main.cpp
@@ -44,15 +44,16 @@ static const bool mustReadOutputAnyway = true; // pclose seems to return the wro
static QStringList dependenciesForDepfile;
-FILE *openProcess(const QString &command)
+auto openProcess(const QString &command)
{
#if defined(Q_OS_WIN32)
QString processedCommand = u'\"' + command + u'\"';
#else
const QString& processedCommand = command;
#endif
-
- return popen(processedCommand.toLocal8Bit().constData(), QT_POPEN_READ);
+ struct Closer { void operator()(FILE *proc) const { if (proc) (void)pclose(proc); } };
+ using UP = std::unique_ptr<FILE, Closer>;
+ return UP{popen(processedCommand.toLocal8Bit().constData(), QT_POPEN_READ)};
}
struct QtDependency
@@ -104,6 +105,7 @@ struct Options
, installApk(false)
, uninstallApk(false)
, qmlImportScannerBinaryPath()
+ , buildAar(false)
{}
enum DeploymentMechanism
@@ -163,7 +165,7 @@ struct Options
// Versioning
QString versionName;
QString versionCode;
- QByteArray minSdkVersion{"23"};
+ QByteArray minSdkVersion{"28"};
QByteArray targetSdkVersion{"34"};
// lib c++ path
@@ -239,6 +241,7 @@ struct Options
// Override qml import scanner path
QString qmlImportScannerBinaryPath;
bool qmlSkipImportScanning = false;
+ bool buildAar;
};
static const QHash<QByteArray, QByteArray> elfArchitectures = {
@@ -310,23 +313,21 @@ QString fileArchitecture(const Options &options, const QString &path)
readElf = "%1 --needed-libs %2"_L1.arg(shellQuote(readElf), shellQuote(path));
- FILE *readElfCommand = openProcess(readElf);
+ auto readElfCommand = openProcess(readElf);
if (!readElfCommand) {
fprintf(stderr, "Cannot execute command %s\n", qPrintable(readElf));
return {};
}
char buffer[512];
- while (fgets(buffer, sizeof(buffer), readElfCommand) != nullptr) {
+ while (fgets(buffer, sizeof(buffer), readElfCommand.get()) != nullptr) {
QByteArray line = QByteArray::fromRawData(buffer, qstrlen(buffer));
line = line.trimmed();
if (line.startsWith("Arch: ")) {
auto it = elfArchitectures.find(line.mid(6));
- pclose(readElfCommand);
return it != elfArchitectures.constEnd() ? QString::fromLatin1(it.value()) : QString{};
}
}
- pclose(readElfCommand);
return {};
}
@@ -527,6 +528,8 @@ Options parseOptions()
options.protectedAuthenticationPath = true;
} else if (argument.compare("--aux-mode"_L1, Qt::CaseInsensitive) == 0) {
options.auxMode = true;
+ } else if (argument.compare("--build-aar"_L1, Qt::CaseInsensitive) == 0) {
+ options.buildAar = true;
} else if (argument.compare("--qml-importscanner-binary"_L1, Qt::CaseInsensitive) == 0) {
options.qmlImportScannerBinaryPath = arguments.at(++i).trimmed();
} else if (argument.compare("--no-rcc-bundle-cleanup"_L1,
@@ -538,6 +541,23 @@ Options parseOptions()
}
}
+ if (options.buildAar) {
+ if (options.installApk || options.uninstallApk) {
+ fprintf(stderr, "Warning: Skipping %s, AAR packages are not installable.\n",
+ options.uninstallApk ? "--reinstall" : "--install");
+ options.installApk = false;
+ options.uninstallApk = false;
+ }
+ if (options.buildAAB) {
+ fprintf(stderr, "Warning: Skipping -aab as --build-aar is present.\n");
+ options.buildAAB = false;
+ }
+ if (!options.keyStore.isEmpty()) {
+ fprintf(stderr, "Warning: Skipping --sign, signing AAR packages is not supported.\n");
+ options.keyStore.clear();
+ }
+ }
+
if (options.buildDirectory.isEmpty() && !options.depFilePath.isEmpty())
options.helpRequested = true;
@@ -645,6 +665,9 @@ Optional arguments:
--apk <path/where/to/copy/the/apk>: Path where to copy the built apk.
+ --build-aar: Build an AAR package. This option skips --aab, --install,
+ --reinstall, and --sign options if they are provided.
+
--qml-importscanner-binary <path/to/qmlimportscanner>: Override the
default qmlimportscanner binary path. By default the
qmlimportscanner binary is located using the Qt directory
@@ -732,18 +755,72 @@ bool copyFileIfNewer(const QString &sourceFileName,
return true;
}
-QString cleanPackageName(QString packageName)
+struct GradleBuildConfigs {
+ QString appNamespace;
+ bool setsLegacyPackaging = false;
+ bool usesIntegerCompileSdkVersion = false;
+};
+
+GradleBuildConfigs gradleBuildConfigs(const QString &path)
+{
+ GradleBuildConfigs configs;
+
+ QFile file(path);
+ if (!file.open(QIODevice::ReadOnly))
+ return configs;
+
+ auto isComment = [](const QByteArray &trimmed) {
+ return trimmed.startsWith("//") || trimmed.startsWith('*') || trimmed.startsWith("/*");
+ };
+
+ auto extractValue = [](const QByteArray &trimmed) {
+ int idx = trimmed.indexOf('=');
+
+ if (idx == -1)
+ idx = trimmed.indexOf(' ');
+
+ if (idx > -1)
+ return trimmed.mid(idx + 1).trimmed();
+
+ return QByteArray();
+ };
+
+ const auto lines = file.readAll().split('\n');
+ for (const auto &line : lines) {
+ const QByteArray trimmedLine = line.trimmed();
+ if (isComment(trimmedLine))
+ continue;
+ if (trimmedLine.contains("useLegacyPackaging")) {
+ configs.setsLegacyPackaging = true;
+ } else if (trimmedLine.contains("compileSdkVersion androidCompileSdkVersion.toInteger()")) {
+ configs.usesIntegerCompileSdkVersion = true;
+ } else if (trimmedLine.contains("namespace")) {
+ configs.appNamespace = QString::fromUtf8(extractValue(trimmedLine));
+ }
+ }
+
+ return configs;
+}
+
+QString cleanPackageName(QString packageName, bool *cleaned = nullptr)
{
auto isLegalChar = [] (QChar c) -> bool {
ushort ch = c.unicode();
return (ch >= '0' && ch <= '9') ||
(ch >= 'A' && ch <= 'Z') ||
(ch >= 'a' && ch <= 'z') ||
- ch == '.';
+ ch == '.' || ch == '_';
};
+
+ if (cleaned)
+ *cleaned = false;
+
for (QChar &c : packageName) {
- if (!isLegalChar(c))
+ if (!isLegalChar(c)) {
c = u'_';
+ if (cleaned)
+ *cleaned = true;
+ }
}
static QStringList keywords;
@@ -778,12 +855,16 @@ QString cleanPackageName(QString packageName)
QChar c = word[0];
if ((c >= u'0' && c <= u'9') || c == u'_') {
packageName.insert(index + 1, u'a');
+ if (cleaned)
+ *cleaned = true;
index = next + 1;
continue;
}
}
if (keywords.contains(word)) {
packageName.insert(next, "_"_L1);
+ if (cleaned)
+ *cleaned = true;
index = next + 1;
} else {
index = next;
@@ -813,18 +894,31 @@ QString detectLatestAndroidPlatform(const QString &sdkPath)
return latestPlatform.baseName();
}
-QString packageNameFromAndroidManifest(const QString &androidManifestPath)
+QString extractPackageName(Options *options)
{
- QFile androidManifestXml(androidManifestPath);
+ {
+ const QString gradleBuildFile = options->androidSourceDirectory + "/build.gradle"_L1;
+ QString packageName = gradleBuildConfigs(gradleBuildFile).appNamespace;
+
+ if (!packageName.isEmpty() && packageName != "androidPackageName"_L1)
+ return packageName;
+ }
+
+ QFile androidManifestXml(options->androidSourceDirectory + "/AndroidManifest.xml"_L1);
if (androidManifestXml.open(QIODevice::ReadOnly)) {
QXmlStreamReader reader(&androidManifestXml);
while (!reader.atEnd()) {
reader.readNext();
- if (reader.isStartElement() && reader.name() == "manifest"_L1)
- return cleanPackageName(reader.attributes().value("package"_L1).toString());
+ if (reader.isStartElement() && reader.name() == "manifest"_L1) {
+ QString packageName = reader.attributes().value("package"_L1).toString();
+ if (!packageName.isEmpty() && packageName != "org.qtproject.example"_L1)
+ return packageName;
+ break;
+ }
}
}
- return {};
+
+ return QString();
}
bool parseCmakeBoolean(const QJsonValue &value)
@@ -1222,6 +1316,24 @@ bool readInputFile(Options *options)
}
{
+ const QJsonValue androidPackageName = jsonObject.value("android-package-name"_L1);
+ const QString extractedPackageName = extractPackageName(options);
+ if (!extractedPackageName.isEmpty())
+ options->packageName = extractedPackageName;
+ else if (!androidPackageName.isUndefined())
+ options->packageName = androidPackageName.toString();
+ else
+ options->packageName = "org.qtproject.example.%1"_L1.arg(options->applicationBinary);
+
+ bool cleaned;
+ options->packageName = cleanPackageName(options->packageName, &cleaned);
+ if (cleaned) {
+ fprintf(stderr, "Warning: Package name contained illegal characters and was cleaned "
+ "to \"%s\"\n", qPrintable(options->packageName));
+ }
+ }
+
+ {
using ItFlag = QDirListing::IteratorFlag;
const QJsonValue deploymentDependencies = jsonObject.value("deployment-dependencies"_L1);
if (!deploymentDependencies.isUndefined()) {
@@ -1278,9 +1390,6 @@ bool readInputFile(Options *options)
options->isZstdCompressionEnabled = zstdCompressionFlag.toBool();
}
}
- options->packageName = packageNameFromAndroidManifest(options->androidSourceDirectory + "/AndroidManifest.xml"_L1);
- if (options->packageName.isEmpty())
- options->packageName = cleanPackageName("org.qtproject.example.%1"_L1.arg(options->applicationBinary));
return true;
}
@@ -1380,6 +1489,9 @@ bool copyAndroidTemplate(const Options &options)
if (!copyAndroidTemplate(options, "/src/android/templates"_L1))
return false;
+ if (options.buildAar)
+ return copyAndroidTemplate(options, "/src/android/templates_aar"_L1);
+
return true;
}
@@ -1735,16 +1847,10 @@ bool updateAndroidManifest(Options &options)
reader.readNext();
if (reader.isStartElement()) {
- if (reader.name() == "manifest"_L1) {
- if (!reader.attributes().hasAttribute("package"_L1)) {
- fprintf(stderr, "Invalid android manifest file: %s\n", qPrintable(androidManifestPath));
- return false;
- }
- options.packageName = reader.attributes().value("package"_L1).toString();
- } else if (reader.name() == "uses-sdk"_L1) {
+ if (reader.name() == "uses-sdk"_L1) {
if (reader.attributes().hasAttribute("android:minSdkVersion"_L1))
- if (reader.attributes().value("android:minSdkVersion"_L1).toInt() < 23) {
- fprintf(stderr, "Invalid minSdkVersion version, minSdkVersion must be >= 23\n");
+ if (reader.attributes().value("android:minSdkVersion"_L1).toInt() < 28) {
+ fprintf(stderr, "Invalid minSdkVersion version, minSdkVersion must be >= 28\n");
return false;
}
} else if ((reader.name() == "application"_L1 ||
@@ -2014,7 +2120,7 @@ QStringList getQtLibsFromElf(const Options &options, const QString &fileName)
readElf = "%1 --needed-libs %2"_L1.arg(shellQuote(readElf), shellQuote(fileName));
- FILE *readElfCommand = openProcess(readElf);
+ auto readElfCommand = openProcess(readElf);
if (!readElfCommand) {
fprintf(stderr, "Cannot execute command %s\n", qPrintable(readElf));
return QStringList();
@@ -2024,7 +2130,7 @@ QStringList getQtLibsFromElf(const Options &options, const QString &fileName)
bool readLibs = false;
char buffer[512];
- while (fgets(buffer, sizeof(buffer), readElfCommand) != nullptr) {
+ while (fgets(buffer, sizeof(buffer), readElfCommand.get()) != nullptr) {
QByteArray line = QByteArray::fromRawData(buffer, qstrlen(buffer));
QString library;
line = line.trimmed();
@@ -2034,7 +2140,6 @@ QStringList getQtLibsFromElf(const Options &options, const QString &fileName)
if (it == elfArchitectures.constEnd() || *it != options.currentArchitecture.toLatin1()) {
if (options.verbose)
fprintf(stdout, "Skipping \"%s\", architecture mismatch\n", qPrintable(fileName));
- pclose(readElfCommand);
return {};
}
}
@@ -2049,8 +2154,6 @@ QStringList getQtLibsFromElf(const Options &options, const QString &fileName)
ret += libraryName;
}
- pclose(readElfCommand);
-
return ret;
}
@@ -2188,7 +2291,7 @@ bool scanImports(Options *options, QSet<QString> *usedDependencies)
qmlImportScanner.toLocal8Bit().constData());
}
- FILE *qmlImportScannerCommand = popen(qmlImportScanner.toLocal8Bit().constData(), QT_POPEN_READ);
+ auto qmlImportScannerCommand = openProcess(qmlImportScanner);
if (qmlImportScannerCommand == 0) {
fprintf(stderr, "Couldn't run qmlimportscanner.\n");
return false;
@@ -2196,13 +2299,12 @@ bool scanImports(Options *options, QSet<QString> *usedDependencies)
QByteArray output;
char buffer[512];
- while (fgets(buffer, sizeof(buffer), qmlImportScannerCommand) != 0)
+ while (fgets(buffer, sizeof(buffer), qmlImportScannerCommand.get()) != nullptr)
output += QByteArray(buffer, qstrlen(buffer));
QJsonDocument jsonDocument = QJsonDocument::fromJson(output);
if (jsonDocument.isNull()) {
fprintf(stderr, "Invalid json output from qmlimportscanner.\n");
- pclose(qmlImportScannerCommand);
return false;
}
@@ -2211,7 +2313,6 @@ bool scanImports(Options *options, QSet<QString> *usedDependencies)
QJsonValue value = jsonArray.at(i);
if (!value.isObject()) {
fprintf(stderr, "Invalid format of qmlimportscanner output.\n");
- pclose(qmlImportScannerCommand);
return false;
}
@@ -2257,7 +2358,6 @@ bool scanImports(Options *options, QSet<QString> *usedDependencies)
if (importPathOfThisImport.isEmpty()) {
fprintf(stderr, "Import found outside of import paths: %s.\n", qPrintable(info.absoluteFilePath()));
- pclose(qmlImportScannerCommand);
return false;
}
@@ -2325,7 +2425,6 @@ bool scanImports(Options *options, QSet<QString> *usedDependencies)
}
}
- pclose(qmlImportScannerCommand);
return true;
}
@@ -2344,17 +2443,17 @@ bool runCommand(const Options &options, const QString &command)
if (options.verbose)
fprintf(stdout, "Running command '%s'\n", qPrintable(command));
- FILE *runCommand = openProcess(command);
+ auto runCommand = openProcess(command);
if (runCommand == nullptr) {
fprintf(stderr, "Cannot run command '%s'\n", qPrintable(command));
return false;
}
char buffer[4096];
- while (fgets(buffer, sizeof(buffer), runCommand) != nullptr) {
+ while (fgets(buffer, sizeof(buffer), runCommand.get()) != nullptr) {
if (options.verbose)
fprintf(stdout, "%s", buffer);
}
- pclose(runCommand);
+ runCommand.reset();
fflush(stdout);
fflush(stderr);
return true;
@@ -2505,7 +2604,8 @@ bool containsApplicationBinary(Options *options)
return true;
}
-FILE *runAdb(const Options &options, const QString &arguments)
+auto runAdb(const Options &options, const QString &arguments)
+ -> decltype(openProcess({}))
{
QString adb = execSuffixAppended(options.sdkPath + "/platform-tools/adb"_L1);
if (!QFile::exists(adb)) {
@@ -2521,7 +2621,7 @@ FILE *runAdb(const Options &options, const QString &arguments)
if (options.verbose)
fprintf(stdout, "Running command \"%s\"\n", adb.toLocal8Bit().constData());
- FILE *adbCommand = openProcess(adb);
+ auto adbCommand = openProcess(adb);
if (adbCommand == 0) {
fprintf(stderr, "Cannot start adb: %s\n", qPrintable(adb));
return 0;
@@ -2745,38 +2845,6 @@ void checkAndWarnGradleLongPaths(const QString &outputDirectory)
}
#endif
-struct GradleFlags {
- bool setsLegacyPackaging = false;
- bool usesIntegerCompileSdkVersion = false;
-};
-
-GradleFlags gradleBuildFlags(const QString &path)
-{
- GradleFlags flags;
-
- QFile file(path);
- if (!file.open(QIODevice::ReadOnly))
- return flags;
-
- auto isComment = [](const QByteArray &line) {
- const auto trimmed = line.trimmed();
- return trimmed.startsWith("//") || trimmed.startsWith('*') || trimmed.startsWith("/*");
- };
-
- const auto lines = file.readAll().split('\n');
- for (const auto &line : lines) {
- if (isComment(line))
- continue;
- if (line.contains("useLegacyPackaging")) {
- flags.setsLegacyPackaging = true;
- } else if (line.contains("compileSdkVersion androidCompileSdkVersion.toInteger()")) {
- flags.usesIntegerCompileSdkVersion = true;
- }
- }
-
- return flags;
-}
-
bool buildAndroidProject(const Options &options)
{
GradleProperties localProperties;
@@ -2789,8 +2857,8 @@ bool buildAndroidProject(const Options &options)
GradleProperties gradleProperties = readGradleProperties(gradlePropertiesPath);
const QString gradleBuildFilePath = options.outputDirectory + "build.gradle"_L1;
- GradleFlags gradleFlags = gradleBuildFlags(gradleBuildFilePath);
- if (!gradleFlags.setsLegacyPackaging)
+ GradleBuildConfigs gradleConfigs = gradleBuildConfigs(gradleBuildFilePath);
+ if (!gradleConfigs.setsLegacyPackaging)
gradleProperties["android.bundle.enableUncompressedNativeLibs"] = "false";
gradleProperties["buildDir"] = "build";
@@ -2809,7 +2877,7 @@ bool buildAndroidProject(const Options &options)
QByteArray sdkPlatformVersion;
// Provide the integer version only if build.gradle explicitly converts to Integer,
// to avoid regression to existing projects that build for sdk platform of form android-xx.
- if (gradleFlags.usesIntegerCompileSdkVersion) {
+ if (gradleConfigs.usesIntegerCompileSdkVersion) {
const QByteArray tmp = options.androidPlatform.split(u'-').last().toLocal8Bit();
bool ok;
tmp.toInt(&ok);
@@ -2824,6 +2892,7 @@ bool buildAndroidProject(const Options &options)
if (sdkPlatformVersion.isEmpty())
sdkPlatformVersion = options.androidPlatform.toLocal8Bit();
+ gradleProperties["androidPackageName"] = options.packageName.toLocal8Bit();
gradleProperties["androidCompileSdkVersion"] = sdkPlatformVersion;
gradleProperties["qtMinSdkVersion"] = options.minSdkVersion;
gradleProperties["qtTargetSdkVersion"] = options.targetSdkVersion;
@@ -2839,6 +2908,9 @@ bool buildAndroidProject(const Options &options)
abiList.append(it.key());
}
gradleProperties["qtTargetAbiList"] = abiList.toLocal8Bit();// armeabi-v7a or arm64-v8a or ...
+ gradleProperties["qtGradlePluginType"] = options.buildAar
+ ? "com.android.library"
+ : "com.android.application";
if (!mergeGradleProperties(gradlePropertiesPath, gradleProperties))
return false;
@@ -2864,19 +2936,19 @@ bool buildAndroidProject(const Options &options)
if (options.verbose)
commandLine += " --info"_L1;
- FILE *gradleCommand = openProcess(commandLine);
+ auto gradleCommand = openProcess(commandLine);
if (gradleCommand == 0) {
fprintf(stderr, "Cannot run gradle command: %s\n.", qPrintable(commandLine));
return false;
}
char buffer[512];
- while (fgets(buffer, sizeof(buffer), gradleCommand) != 0) {
+ while (fgets(buffer, sizeof(buffer), gradleCommand.get()) != nullptr) {
fprintf(stdout, "%s", buffer);
fflush(stdout);
}
- int errorCode = pclose(gradleCommand);
+ const int errorCode = pclose(gradleCommand.release());
if (errorCode != 0) {
fprintf(stderr, "Building the android package failed!\n");
if (!options.verbose)
@@ -2902,18 +2974,18 @@ bool uninstallApk(const Options &options)
fprintf(stdout, "Uninstalling old Android package %s if present.\n", qPrintable(options.packageName));
- FILE *adbCommand = runAdb(options, " uninstall "_L1 + shellQuote(options.packageName));
+ auto adbCommand = runAdb(options, " uninstall "_L1 + shellQuote(options.packageName));
if (adbCommand == 0)
return false;
if (options.verbose || mustReadOutputAnyway) {
char buffer[512];
- while (fgets(buffer, sizeof(buffer), adbCommand) != 0)
+ while (fgets(buffer, sizeof(buffer), adbCommand.get()) != nullptr)
if (options.verbose)
fprintf(stdout, "%s", buffer);
}
- int returnCode = pclose(adbCommand);
+ const int returnCode = pclose(adbCommand.release());
if (returnCode != 0) {
fprintf(stderr, "Warning: Uninstall failed!\n");
if (!options.verbose)
@@ -2926,39 +2998,43 @@ bool uninstallApk(const Options &options)
enum PackageType {
AAB,
+ AAR,
UnsignedAPK,
SignedAPK
};
-QString packagePath(const Options &options, PackageType pt)
-{
- QString path(options.outputDirectory);
- path += "/build/outputs/%1/"_L1.arg(pt >= UnsignedAPK ? QStringLiteral("apk") : QStringLiteral("bundle"));
- QString buildType(options.releasePackage ? "release/"_L1 : "debug/"_L1);
- if (QDir(path + buildType).exists())
- path += buildType;
- path += QDir(options.outputDirectory).dirName() + u'-';
- if (options.releasePackage) {
- path += "release-"_L1;
- if (pt >= UnsignedAPK) {
- if (pt == UnsignedAPK)
- path += "un"_L1;
- path += "signed.apk"_L1;
- } else {
- path.chop(1);
- path += ".aab"_L1;
- }
- } else {
- path += "debug"_L1;
- if (pt >= UnsignedAPK) {
- if (pt == SignedAPK)
- path += "-signed"_L1;
- path += ".apk"_L1;
- } else {
- path += ".aab"_L1;
- }
- }
- return path;
+QString packagePath(const Options &options, PackageType packageType)
+{
+ // The package type is always AAR if option.buildAar has been set
+ if (options.buildAar)
+ packageType = AAR;
+
+ static const QHash<PackageType, QLatin1StringView> packageTypeToPath{
+ { AAB, "bundle"_L1 }, { AAR, "aar"_L1 }, { UnsignedAPK, "apk"_L1 }, { SignedAPK, "apk"_L1 }
+ };
+ static const QHash<PackageType, QLatin1StringView> packageTypeToExtension{
+ { AAB, "aab"_L1 }, { AAR, "aar"_L1 }, { UnsignedAPK, "apk"_L1 }, { SignedAPK, "apk"_L1 }
+ };
+
+ const QString buildType(options.releasePackage ? "release"_L1 : "debug"_L1);
+ QString signedSuffix;
+ if (packageType == SignedAPK)
+ signedSuffix = "-signed"_L1;
+ else if (packageType == UnsignedAPK && options.releasePackage)
+ signedSuffix = "-unsigned"_L1;
+
+ QString dirPath(options.outputDirectory);
+ dirPath += "/build/outputs/%1/"_L1.arg(packageTypeToPath[packageType]);
+ if (QDir(dirPath + buildType).exists())
+ dirPath += buildType;
+
+ const QString fileName = "/%1-%2%3.%4"_L1.arg(
+ QDir(options.outputDirectory).dirName(),
+ buildType,
+ signedSuffix,
+ packageTypeToExtension[packageType]);
+
+ return dirPath + fileName;
}
bool installApk(const Options &options)
@@ -2971,20 +3047,20 @@ bool installApk(const Options &options)
if (options.verbose)
fprintf(stdout, "Installing Android package to device.\n");
- FILE *adbCommand = runAdb(options, " install -r "_L1
- + packagePath(options, options.keyStore.isEmpty() ? UnsignedAPK
- : SignedAPK));
+ auto adbCommand = runAdb(options, " install -r "_L1
+ + packagePath(options, options.keyStore.isEmpty() ? UnsignedAPK
+ : SignedAPK));
if (adbCommand == 0)
return false;
if (options.verbose || mustReadOutputAnyway) {
char buffer[512];
- while (fgets(buffer, sizeof(buffer), adbCommand) != 0)
+ while (fgets(buffer, sizeof(buffer), adbCommand.get()) != nullptr)
if (options.verbose)
fprintf(stdout, "%s", buffer);
}
- int returnCode = pclose(adbCommand);
+ const int returnCode = pclose(adbCommand.release());
if (returnCode != 0) {
fprintf(stderr, "Installing to device failed!\n");
if (!options.verbose)
@@ -3102,7 +3178,7 @@ bool signAAB(const Options &options)
QString command = jarSignerTool + " %1 %2"_L1.arg(shellQuote(file))
.arg(shellQuote(options.keyStoreAlias));
- FILE *jarSignerCommand = openProcess(command);
+ auto jarSignerCommand = openProcess(command);
if (jarSignerCommand == 0) {
fprintf(stderr, "Couldn't run jarsigner.\n");
return false;
@@ -3110,11 +3186,11 @@ bool signAAB(const Options &options)
if (options.verbose) {
char buffer[512];
- while (fgets(buffer, sizeof(buffer), jarSignerCommand) != 0)
+ while (fgets(buffer, sizeof(buffer), jarSignerCommand.get()) != nullptr)
fprintf(stdout, "%s", buffer);
}
- int errorCode = pclose(jarSignerCommand);
+ const int errorCode = pclose(jarSignerCommand.release());
if (errorCode != 0) {
fprintf(stderr, "jarsigner command failed.\n");
if (!options.verbose)
@@ -3142,17 +3218,17 @@ bool signPackage(const Options &options)
return false;
auto zipalignRunner = [](const QString &zipAlignCommandLine) {
- FILE *zipAlignCommand = openProcess(zipAlignCommandLine);
+ auto zipAlignCommand = openProcess(zipAlignCommandLine);
if (zipAlignCommand == 0) {
fprintf(stderr, "Couldn't run zipalign.\n");
return false;
}
char buffer[512];
- while (fgets(buffer, sizeof(buffer), zipAlignCommand) != 0)
+ while (fgets(buffer, sizeof(buffer), zipAlignCommand.get()) != nullptr)
fprintf(stdout, "%s", buffer);
- return pclose(zipAlignCommand) == 0;
+ return pclose(zipAlignCommand.release()) == 0;
};
const QString verifyZipAlignCommandLine =
@@ -3209,17 +3285,17 @@ bool signPackage(const Options &options)
apkSignCommand += " %1"_L1.arg(shellQuote(packagePath(options, SignedAPK)));
auto apkSignerRunner = [](const QString &command, bool verbose) {
- FILE *apkSigner = openProcess(command);
+ auto apkSigner = openProcess(command);
if (apkSigner == 0) {
fprintf(stderr, "Couldn't run apksigner.\n");
return false;
}
char buffer[512];
- while (fgets(buffer, sizeof(buffer), apkSigner) != 0)
+ while (fgets(buffer, sizeof(buffer), apkSigner.get()) != nullptr)
fprintf(stdout, "%s", buffer);
- int errorCode = pclose(apkSigner);
+ const int errorCode = pclose(apkSigner.release());
if (errorCode != 0) {
fprintf(stderr, "apksigner command failed.\n");
if (!verbose)
diff --git a/src/tools/moc/main.cpp b/src/tools/moc/main.cpp
index bb51352519..89fb367ca7 100644
--- a/src/tools/moc/main.cpp
+++ b/src/tools/moc/main.cpp
@@ -19,7 +19,8 @@
#include <qcoreapplication.h>
#include <qcommandlineoption.h>
#include <qcommandlineparser.h>
-#include <qscopedpointer.h>
+
+#include <memory>
QT_BEGIN_NAMESPACE
@@ -58,10 +59,21 @@ void error(const char *msg = "Invalid argument")
fprintf(stderr, "moc: %s\n", msg);
}
-struct ScopedPointerFileCloser
+static auto openFileForWriting(const QString &name)
{
- static inline void cleanup(FILE *handle) { if (handle) fclose(handle); }
-};
+ struct Closer { void operator()(FILE *handle) const { fclose(handle); } };
+ using R = std::unique_ptr<FILE, Closer>;
+
+#ifdef _MSC_VER
+ FILE *file;
+ if (_wfopen_s(&file, reinterpret_cast<const wchar_t *>(name.utf16()), L"w") != 0)
+ return R{};
+ return R{file};
+#else
+ return R{fopen(QFile::encodeName(name).constData(), "w")};
+#endif
+}
+using File = decltype(openFileForWriting({}));
static inline bool hasNext(const Symbols &symbols, int i)
{ return (i < symbols.size()); }
@@ -178,7 +190,7 @@ int runMoc(int argc, char **argv)
QString filename;
QString output;
QFile in;
- FILE *out = nullptr;
+ File out;
// Note that moc isn't translated.
// If you use this code as an example for a translated app, make sure to translate the strings.
@@ -528,16 +540,12 @@ int runMoc(int argc, char **argv)
// 3. and output meta object code
- QScopedPointer<FILE, ScopedPointerFileCloser> jsonOutput;
+ File jsonOutput;
bool outputToFile = true;
if (output.size()) { // output file specified
-#if defined(_MSC_VER)
- if (_wfopen_s(&out, reinterpret_cast<const wchar_t *>(output.utf16()), L"w") != 0)
-#else
- out = fopen(QFile::encodeName(output).constData(), "w"); // create output file
+ out = openFileForWriting(output);
if (!out)
-#endif
{
const auto fopen_errno = errno;
fprintf(stderr, "moc: Cannot create %s. Error: %s\n",
@@ -548,37 +556,29 @@ int runMoc(int argc, char **argv)
if (parser.isSet(jsonOption)) {
const QString jsonOutputFileName = output + ".json"_L1;
- FILE *f;
-#if defined(_MSC_VER)
- if (_wfopen_s(&f, reinterpret_cast<const wchar_t *>(jsonOutputFileName.utf16()), L"w") != 0)
-#else
- f = fopen(QFile::encodeName(jsonOutputFileName).constData(), "w");
- if (!f)
-#endif
- {
+ jsonOutput = openFileForWriting(jsonOutputFileName);
+ if (!jsonOutput) {
const auto fopen_errno = errno;
fprintf(stderr, "moc: Cannot create JSON output file %s. Error: %s\n",
QFile::encodeName(jsonOutputFileName).constData(),
strerror(fopen_errno));
}
- jsonOutput.reset(f);
}
} else { // use stdout
- out = stdout;
+ out.reset(stdout);
outputToFile = false;
}
if (pp.preprocessOnly) {
- fprintf(out, "%s\n", composePreprocessorOutput(moc.symbols).constData());
+ fprintf(out.get(), "%s\n", composePreprocessorOutput(moc.symbols).constData());
} else {
if (moc.classList.isEmpty())
moc.note("No relevant classes found. No output generated.");
else
- moc.generate(out, jsonOutput.data());
+ moc.generate(out.get(), jsonOutput.get());
}
- if (output.size())
- fclose(out);
+ out.reset();
if (parser.isSet(depFileOption)) {
// 4. write a Make-style dependency file (can also be consumed by Ninja).
@@ -596,26 +596,17 @@ int runMoc(int argc, char **argv)
fprintf(stderr, "moc: Writing to stdout, but no depfile path specified.\n");
}
- QScopedPointer<FILE, ScopedPointerFileCloser> depFileHandle;
- FILE *depFileHandleRaw;
-#if defined(_MSC_VER)
- if (_wfopen_s(&depFileHandleRaw,
- reinterpret_cast<const wchar_t *>(depOutputFileName.utf16()), L"w") != 0)
-#else
- depFileHandleRaw = fopen(QFile::encodeName(depOutputFileName).constData(), "w");
- if (!depFileHandleRaw)
-#endif
- {
+ File depFileHandle = openFileForWriting(depOutputFileName);
+ if (!depFileHandle) {
const auto fopen_errno = errno;
fprintf(stderr, "moc: Cannot create dep output file '%s'. Error: %s\n",
QFile::encodeName(depOutputFileName).constData(),
strerror(fopen_errno));
}
- depFileHandle.reset(depFileHandleRaw);
- if (!depFileHandle.isNull()) {
+ if (depFileHandle) {
// First line is the path to the generated file.
- fprintf(depFileHandle.data(), "%s: ",
+ fprintf(depFileHandle.get(), "%s: ",
escapeAndEncodeDependencyPath(depRuleName).constData());
QByteArrayList dependencies;
@@ -647,7 +638,7 @@ int runMoc(int argc, char **argv)
// Join dependencies, output them, and output a final new line.
const auto dependenciesJoined = dependencies.join(QByteArrayLiteral(" \\\n "));
- fprintf(depFileHandle.data(), "%s\n", dependenciesJoined.constData());
+ fprintf(depFileHandle.get(), "%s\n", dependenciesJoined.constData());
}
}
diff --git a/src/tools/rcc/rcc.cpp b/src/tools/rcc/rcc.cpp
index 2bda7f2977..0fdba3671d 100644
--- a/src/tools/rcc/rcc.cpp
+++ b/src/tools/rcc/rcc.cpp
@@ -21,7 +21,7 @@
# include <zstd.h>
#endif
-// Note: A copy of this file is used in Qt Designer (qttools/src/designer/src/lib/shared/rcc.cpp)
+// Note: A copy of this file is used in Qt Widgets Designer (qttools/src/designer/src/lib/shared/rcc.cpp)
QT_BEGIN_NAMESPACE
diff --git a/src/tools/rcc/rcc.h b/src/tools/rcc/rcc.h
index 60af1c67cf..bfc3503da8 100644
--- a/src/tools/rcc/rcc.h
+++ b/src/tools/rcc/rcc.h
@@ -2,7 +2,7 @@
// Copyright (C) 2018 Intel Corporation.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-// Note: A copy of this file is used in Qt Designer (qttools/src/designer/src/lib/shared/rcc_p.h)
+// Note: A copy of this file is used in Qt Widgets Designer (qttools/src/designer/src/lib/shared/rcc_p.h)
#ifndef RCC_H
#define RCC_H
diff --git a/src/tools/syncqt/CMakeLists.txt b/src/tools/syncqt/CMakeLists.txt
index b3ab091aa4..b54dd72774 100644
--- a/src/tools/syncqt/CMakeLists.txt
+++ b/src/tools/syncqt/CMakeLists.txt
@@ -1,3 +1,5 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
if(NOT QT_INTERNAL_AVOID_OVERRIDING_SYNCQT_CONFIG)
qt_internal_get_configs_for_flag_manipulation(configs)
qt_internal_remove_known_optimization_flags(LANGUAGES CXX CONFIGS ${configs})
diff --git a/src/tools/syncqt/main.cpp b/src/tools/syncqt/main.cpp
index 5df7b03fd5..ab646e6cd1 100644
--- a/src/tools/syncqt/main.cpp
+++ b/src/tools/syncqt/main.cpp
@@ -1428,13 +1428,12 @@ public:
// - <class|stuct> StructName
// - template <> class ClassName
// - class ClassName : [public|protected|private] BaseClassName
- // - class ClassName [final|Q_DECL_FINAL|sealed]
+ // - class ClassName [QT_TEXT_STREAM_FINAL|Q_DECL_FINAL|final|sealed]
// And possible combinations of the above variants.
static const std::regex ClassRegex(
- "^ *(template *<.*> *)?(class|struct) +([^ <>]* "
- "+)?((?!Q_DECL_FINAL|final|sealed)[^<\\s\\:]+) ?(<[^>\\:]*> "
- "?)?\\s*(?:Q_DECL_FINAL|final|sealed)?\\s*((,|:)\\s*(public|protected|private)? "
- "*.*)? *$");
+ "^ *(template *<.*> *)?(class|struct +)([^<>:]*\\s+)?" // Preceding part
+ "((?!Q[A-Z_0-9]*_FINAL|final|sealed)Q[a-zA-Z0-9_]+)" // Actual symbol
+ "(\\s+Q[A-Z_0-9]*_FINAL|\\s+final|\\s+sealed)?\\s*(:|$).*"); // Trailing part
// This regex checks if line contains function pointer typedef declaration like:
// - typedef void (* QFunctionPointerType)(int, char);
@@ -1445,10 +1444,6 @@ public:
// - typedef AnySymbol<char> QAnySymbolType;
static const std::regex TypedefRegex("^ *typedef\\s+(.*)\\s+(Q\\w+); *$");
- // This regex checks if symbols is the Qt public symbol. Assume that Qt public symbols start
- // with the capital 'Q'.
- static const std::regex QtClassRegex("^Q\\w+$");
-
std::smatch match;
if (std::regex_match(line, match, FunctionPointerRegex)) {
symbol = match[1].str();
@@ -1456,8 +1451,6 @@ public:
symbol = match[2].str();
} else if (std::regex_match(line, match, ClassRegex)) {
symbol = match[4].str();
- if (!std::regex_match(symbol, QtClassRegex))
- symbol.clear();
} else {
return false;
}
diff --git a/src/tools/uic/cpp/cppwriteinitialization.cpp b/src/tools/uic/cpp/cppwriteinitialization.cpp
index 205d6a50a9..c9356a4111 100644
--- a/src/tools/uic/cpp/cppwriteinitialization.cpp
+++ b/src/tools/uic/cpp/cppwriteinitialization.cpp
@@ -2155,7 +2155,7 @@ QString WriteInitialization::pixCall(const DomProperty *p) const
s = p->elementPixmap()->text();
break;
default:
- qWarning("%s: Warning: Unknown icon format encountered. The ui-file was generated with a too-recent version of Designer.",
+ qWarning("%s: Warning: Unknown icon format encountered. The ui-file was generated with a too-recent version of Qt Widgets Designer.",
qPrintable(m_option.messagePrefix()));
return "QIcon()"_L1;
break;
diff --git a/src/tools/uic/uic.cpp b/src/tools/uic/uic.cpp
index fb0a37d21d..1b10e1d722 100644
--- a/src/tools/uic/uic.cpp
+++ b/src/tools/uic/uic.cpp
@@ -165,7 +165,7 @@ DomUI *Uic::parseUiFile(QXmlStreamReader &reader)
&& !ui) {
const double version = versionFromUiAttribute(reader);
if (version < 4.0) {
- const QString msg = QString::fromLatin1("uic: File generated with too old version of Qt Designer (%1)").arg(version);
+ const QString msg = QString::fromLatin1("uic: File generated with too old version of Qt Widgets Designer (%1)").arg(version);
fprintf(stderr, "%s\n", qPrintable(msg));
return nullptr;
}
@@ -202,7 +202,7 @@ bool Uic::write(QIODevice *in)
double version = ui->attributeVersion().toDouble();
if (version < 4.0) {
- fprintf(stderr, "uic: File generated with too old version of Qt Designer\n");
+ fprintf(stderr, "uic: File generated with too old version of Qt Widgets Designer\n");
return false;
}
diff --git a/src/tools/windeployqt/main.cpp b/src/tools/windeployqt/main.cpp
index 084345a4d8..dca9132e15 100644
--- a/src/tools/windeployqt/main.cpp
+++ b/src/tools/windeployqt/main.cpp
@@ -139,8 +139,10 @@ static Platform platformFromMkSpec(const QString &xSpec)
return WindowsDesktopClangMsvc;
if (xSpec.contains("arm"_L1))
return WindowsDesktopMsvcArm;
+ if (xSpec.contains("G++"_L1))
+ return WindowsDesktopMinGW;
- return xSpec.contains("g++"_L1) ? WindowsDesktopMinGW : WindowsDesktopMsvcIntel;
+ return WindowsDesktopMsvc;
}
return UnknownPlatform;
}
@@ -1928,6 +1930,24 @@ int main(int argc, char **argv)
}
options.platform = platformFromMkSpec(xSpec);
+ // We are on MSVC and not crosscompiling. We need the host arch
+ if (options.platform == WindowsDesktopMsvc) {
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ switch (si.wProcessorArchitecture) {
+ case PROCESSOR_ARCHITECTURE_INTEL:
+ case PROCESSOR_ARCHITECTURE_IA64:
+ case PROCESSOR_ARCHITECTURE_AMD64:
+ options.platform |= IntelBased;
+ break;
+ case PROCESSOR_ARCHITECTURE_ARM:
+ case PROCESSOR_ARCHITECTURE_ARM64:
+ options.platform |= ArmBased;
+ break;
+ default:
+ options.platform = UnknownPlatform;
+ }
+ }
if (options.platform == UnknownPlatform) {
std::wcerr << "Unsupported platform " << xSpec << '\n';
return 1;
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index 6eff4abfb0..dfc69c7d93 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -6107,6 +6107,13 @@ void QWidget::setWindowTitle(const QString &title)
if (QWidget::windowTitle() == title && !title.isEmpty() && !title.isNull())
return;
+#if QT_CONFIG(accessibility)
+ QString oldAccessibleName;
+ const QAccessibleInterface *accessible = QAccessible::queryAccessibleInterface(this);
+ if (accessible)
+ oldAccessibleName = accessible->text(QAccessible::Name);
+#endif
+
Q_D(QWidget);
d->topData()->caption = title;
d->setWindowTitle_helper(title);
@@ -6115,6 +6122,13 @@ void QWidget::setWindowTitle(const QString &title)
QCoreApplication::sendEvent(this, &e);
emit windowTitleChanged(title);
+
+#if QT_CONFIG(accessibility)
+ if (accessible && accessible->text(QAccessible::Name) != oldAccessibleName) {
+ QAccessibleEvent event(this, QAccessible::NameChanged);
+ QAccessible::updateAccessibility(&event);
+ }
+#endif
}
@@ -7079,7 +7093,6 @@ void QWidgetPrivate::reparentFocusWidgets(QWidget * oldtlw)
if (focus_child)
focus_child->clearFocus();
- insertIntoFocusChain(QWidgetPrivate::FocusDirection::Previous, q->window());
reparentFocusChildren(QWidgetPrivate::FocusDirection::Next);
}
@@ -7694,11 +7707,15 @@ QMargins QWidgetPrivate::safeAreaMargins() const
return QMargins();
// Or, if one of our ancestors are in a layout that does not have WA_LayoutOnEntireRect
- // set, then we know that the layout has already taken care of placing us inside the
- // safe area, by taking the contents rect of its parent widget into account.
+ // set, and the widget respects the safe area, then we know that the layout has already
+ // taken care of placing us inside the safe area, by taking the contents rect of its
+ // parent widget into account.
const QWidget *assumedSafeWidget = nullptr;
for (const QWidget *w = q; w != nativeWidget; w = w->parentWidget()) {
QWidget *parentWidget = w->parentWidget();
+ if (!parentWidget->testAttribute(Qt::WA_ContentsMarginsRespectsSafeArea))
+ continue; // Layout can't help us
+
if (parentWidget->testAttribute(Qt::WA_LayoutOnEntireRect))
continue; // Layout not going to help us
@@ -13351,32 +13368,61 @@ void QWidgetPrivate::initFocusChain()
void QWidgetPrivate::reparentFocusChildren(FocusDirection direction)
{
Q_Q(QWidget);
- QWidgetList focusChildrenInsideChain;
- QDuplicateTracker<QWidget *> seen;
- QWidget *widget = q->nextInFocusChain();
- while (q->isAncestorOf(widget)
- && !seen.hasSeen(widget)
- && widget != q->window()) {
- if (widget->focusPolicy() != Qt::NoFocus)
- focusChildrenInsideChain << widget;
-
- widget = direction == FocusDirection::Next ? widget->nextInFocusChain()
- : widget->previousInFocusChain();
- }
-
- const QWidgetList children = q->findChildren<QWidget *>(Qt::FindDirectChildrenOnly);
- QWidgetList focusChildrenOutsideChain;
- for (auto *child : children) {
- if (!focusChildrenInsideChain.contains(child))
- focusChildrenOutsideChain << child;
- }
- if (focusChildrenOutsideChain.isEmpty())
- return;
- QWidget *previous = q;
- for (auto *child : focusChildrenOutsideChain) {
- child->d_func()->insertIntoFocusChain(direction, previous);
- previous = child;
+ // separate the focus chain into new (children of myself) and old (the rest)
+ QWidget *firstOld = nullptr;
+ QWidget *lastOld = nullptr; // last in the old list
+ QWidget *lastNew = q; // last in the new list
+ bool prevWasNew = true;
+ QWidget *widget = nextPrevElementInFocusChain(direction);
+
+ // For efficiency, do not maintain the list invariant inside the loop.
+ // Append items to the relevant list, and we optimize by not changing pointers,
+ // when subsequent items are going into the same list.
+ while (widget != q) {
+ bool currentIsNew = q->isAncestorOf(widget);
+ if (currentIsNew) {
+ if (!prevWasNew) {
+ // previous was old => append to new list
+ FOCUS_NEXT(lastNew) = widget;
+ FOCUS_PREV(widget) = lastNew;
+ }
+ lastNew = widget;
+ } else {
+ if (prevWasNew) {
+ // prev was new => append to old list, if it exists
+ if (lastOld) {
+ FOCUS_NEXT(lastOld) = widget;
+ FOCUS_PREV(widget) = lastOld;
+ } else {
+ // start the old list
+ firstOld = widget;
+ }
+ }
+ lastOld = widget;
+ }
+ widget = widget->d_func()->nextPrevElementInFocusChain(direction);
+ prevWasNew = currentIsNew;
+ }
+
+ // repair old list:
+ if (firstOld) {
+ FOCUS_NEXT(lastOld) = firstOld;
+ FOCUS_PREV(firstOld) = lastOld;
+ }
+
+ if (!q->isWindow()) {
+ QWidget *topLevel = q->window();
+ // insert new chain into toplevel's chain
+ QWidget *prev = FOCUS_PREV(topLevel);
+ FOCUS_PREV(topLevel) = lastNew;
+ FOCUS_NEXT(prev) = q;
+ FOCUS_PREV(q) = prev;
+ FOCUS_NEXT(lastNew) = topLevel;
+ } else {
+ // repair new list
+ FOCUS_NEXT(lastNew) = q;
+ FOCUS_PREV(q) = lastNew;
}
}
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp
index e7f0a84004..03dde9ca69 100644
--- a/src/widgets/kernel/qwidgetwindow.cpp
+++ b/src/widgets/kernel/qwidgetwindow.cpp
@@ -505,9 +505,6 @@ void QWidgetWindow::handleNonClientAreaMouseEvent(QMouseEvent *e)
void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
{
- static const QEvent::Type contextMenuTrigger =
- QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::ContextMenuOnMouseRelease).toBool() ?
- QEvent::MouseButtonRelease : QEvent::MouseButtonPress;
if (QApplicationPrivate::inPopupMode()) {
QPointer<QWidget> activePopupWidget = QApplication::activePopupWidget();
QPointF mapped = event->position();
@@ -624,7 +621,7 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
}
qt_replay_popup_mouse_event = false;
#ifndef QT_NO_CONTEXTMENU
- } else if (event->type() == contextMenuTrigger
+ } else if (event->type() == QGuiApplicationPrivate::contextMenuEventType()
&& event->button() == Qt::RightButton
&& (openPopupCount == oldOpenPopupCount)) {
QWidget *receiver = activePopupWidget;
@@ -637,7 +634,6 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
QApplication::forwardEvent(receiver, &e, event);
}
#else
- Q_UNUSED(contextMenuTrigger);
Q_UNUSED(oldOpenPopupCount);
}
#endif
@@ -684,7 +680,8 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
event->setAccepted(translated.isAccepted());
}
#ifndef QT_NO_CONTEXTMENU
- if (event->type() == contextMenuTrigger && event->button() == Qt::RightButton
+ if (event->type() == QGuiApplicationPrivate::contextMenuEventType()
+ && event->button() == Qt::RightButton
&& m_widget->rect().contains(event->position().toPoint())) {
QContextMenuEvent e(QContextMenuEvent::Mouse, mapped, event->globalPosition().toPoint(), event->modifiers());
QGuiApplication::forwardEvent(receiver, &e, event);
diff --git a/src/widgets/styles/images/standardbutton-apply-128.png b/src/widgets/styles/images/standardbutton-apply-128.png
index 85f07a57ef..35eb54bfd0 100644
--- a/src/widgets/styles/images/standardbutton-apply-128.png
+++ b/src/widgets/styles/images/standardbutton-apply-128.png
Binary files differ
diff --git a/src/widgets/styles/images/standardbutton-apply-16.png b/src/widgets/styles/images/standardbutton-apply-16.png
index 8f11ce6504..1f97b52566 100644
--- a/src/widgets/styles/images/standardbutton-apply-16.png
+++ b/src/widgets/styles/images/standardbutton-apply-16.png
Binary files differ
diff --git a/src/widgets/styles/images/standardbutton-apply-32.png b/src/widgets/styles/images/standardbutton-apply-32.png
index e8f7853a1e..0837fae244 100644
--- a/src/widgets/styles/images/standardbutton-apply-32.png
+++ b/src/widgets/styles/images/standardbutton-apply-32.png
Binary files differ
diff --git a/src/widgets/styles/images/standardbutton-no-128.png b/src/widgets/styles/images/standardbutton-no-128.png
index 491c048ebd..4d9cdb1566 100644
--- a/src/widgets/styles/images/standardbutton-no-128.png
+++ b/src/widgets/styles/images/standardbutton-no-128.png
Binary files differ
diff --git a/src/widgets/styles/images/standardbutton-no-16.png b/src/widgets/styles/images/standardbutton-no-16.png
index 812d3f57dd..a04af9c37a 100644
--- a/src/widgets/styles/images/standardbutton-no-16.png
+++ b/src/widgets/styles/images/standardbutton-no-16.png
Binary files differ
diff --git a/src/widgets/styles/images/standardbutton-no-32.png b/src/widgets/styles/images/standardbutton-no-32.png
index 9548d59196..01d4401a2b 100644
--- a/src/widgets/styles/images/standardbutton-no-32.png
+++ b/src/widgets/styles/images/standardbutton-no-32.png
Binary files differ
diff --git a/src/widgets/styles/images/standardbutton-ok-128.png b/src/widgets/styles/images/standardbutton-ok-128.png
index 63cc5279ae..b204b6f272 100644
--- a/src/widgets/styles/images/standardbutton-ok-128.png
+++ b/src/widgets/styles/images/standardbutton-ok-128.png
Binary files differ
diff --git a/src/widgets/styles/images/standardbutton-yes-128.png b/src/widgets/styles/images/standardbutton-yes-128.png
index 79c8296016..6266e5bc6a 100644
--- a/src/widgets/styles/images/standardbutton-yes-128.png
+++ b/src/widgets/styles/images/standardbutton-yes-128.png
Binary files differ
diff --git a/src/widgets/styles/images/standardbutton-yes-16.png b/src/widgets/styles/images/standardbutton-yes-16.png
index cc16dbbec3..f66b5da6f2 100644
--- a/src/widgets/styles/images/standardbutton-yes-16.png
+++ b/src/widgets/styles/images/standardbutton-yes-16.png
Binary files differ
diff --git a/src/widgets/styles/images/standardbutton-yes-32.png b/src/widgets/styles/images/standardbutton-yes-32.png
index e3340c6453..6685d19e9f 100644
--- a/src/widgets/styles/images/standardbutton-yes-32.png
+++ b/src/widgets/styles/images/standardbutton-yes-32.png
Binary files differ
diff --git a/src/widgets/styles/qstylehelper.cpp b/src/widgets/styles/qstylehelper.cpp
index 02827de847..b4616b8c24 100644
--- a/src/widgets/styles/qstylehelper.cpp
+++ b/src/widgets/styles/qstylehelper.cpp
@@ -202,7 +202,7 @@ QPolygonF calcLines(const QStyleOptionSlider *dial)
qreal xc = width / 2 + 0.5;
qreal yc = height / 2 + 0.5;
const int ns = dial->tickInterval;
- if (!ns) // Invalid values may be set by Qt Designer.
+ if (!ns) // Invalid values may be set by Qt Widgets Designer.
return poly;
int notches = (dial->maximum + ns - 1 - dial->minimum) / ns;
if (notches <= 0)
diff --git a/src/widgets/widgets/qdialogbuttonbox.cpp b/src/widgets/widgets/qdialogbuttonbox.cpp
index 30c68ad18b..0b6a4df41a 100644
--- a/src/widgets/widgets/qdialogbuttonbox.cpp
+++ b/src/widgets/widgets/qdialogbuttonbox.cpp
@@ -374,7 +374,7 @@ QPushButton *QDialogButtonBoxPrivate::createButton(QDialogButtonBox::StandardBut
button->setIcon(style->standardIcon(QStyle::StandardPixmap(icon), nullptr, q));
if (style != QApplication::style()) // Propagate style
button->setStyle(style);
- standardButtonHash.insert(button, sbutton);
+ standardButtonMap.insert(button, sbutton);
QPlatformDialogHelper::ButtonRole role = QPlatformDialogHelper::buttonRole(static_cast<QPlatformDialogHelper::StandardButton>(sbutton));
if (Q_UNLIKELY(role == QPlatformDialogHelper::InvalidRole))
qWarning("QDialogButtonBox::createButton: Invalid ButtonRole, button not added");
@@ -426,10 +426,10 @@ void QDialogButtonBoxPrivate::createStandardButtons(QDialogButtonBox::StandardBu
void QDialogButtonBoxPrivate::retranslateStrings()
{
- for (auto &&[key, value] : std::as_const(standardButtonHash).asKeyValueRange()) {
- const QString text = QGuiApplicationPrivate::platformTheme()->standardButtonText(value);
+ for (const auto &it : std::as_const(standardButtonMap)) {
+ const QString text = QGuiApplicationPrivate::platformTheme()->standardButtonText(it.second);
if (!text.isEmpty())
- key->setText(text);
+ it.first->setText(text);
}
}
@@ -644,7 +644,7 @@ void QDialogButtonBox::clear()
Q_D(QDialogButtonBox);
// Remove the created standard buttons, they should be in the other lists, which will
// do the deletion
- d->standardButtonHash.clear();
+ d->standardButtonMap.clear();
for (int i = 0; i < NRoles; ++i) {
QList<QAbstractButton *> &list = d->buttonLists[i];
for (auto button : std::as_const(list)) {
@@ -680,7 +680,11 @@ QList<QAbstractButton *> QDialogButtonBoxPrivate::visibleButtons() const
QList<QAbstractButton *> QDialogButtonBoxPrivate::allButtons() const
{
- return visibleButtons() << hiddenButtons.keys();
+ QList<QAbstractButton *> ret(visibleButtons());
+ ret.reserve(ret.size() + hiddenButtons.size());
+ for (const auto &it : hiddenButtons)
+ ret.push_back(it.first);
+ return ret;
}
/*!
@@ -718,9 +722,9 @@ void QDialogButtonBox::removeButton(QAbstractButton *button)
Removes \param button.
\param reason determines the behavior following the removal:
\list
- \li \c ManualRemove disconnects all signals and removes the button from standardButtonHash.
- \li \c HideEvent keeps connections alive, standard buttons remain in standardButtonHash.
- \li \c Destroyed removes the button from standardButtonHash. Signals remain untouched, because
+ \li \c ManualRemove disconnects all signals and removes the button from standardButtonMap.
+ \li \c HideEvent keeps connections alive, standard buttons remain in standardButtonMap.
+ \li \c Destroyed removes the button from standardButtonMap. Signals remain untouched, because
the button might already be only a QObject, the destructor of which handles disconnecting.
\endlist
*/
@@ -744,7 +748,7 @@ void QDialogButtonBoxPrivate::removeButton(QAbstractButton *button, RemoveReason
button->removeEventFilter(filter.get());
Q_FALLTHROUGH();
case RemoveReason::Destroyed:
- standardButtonHash.remove(reinterpret_cast<QPushButton *>(button));
+ standardButtonMap.remove(reinterpret_cast<QPushButton *>(button));
break;
case RemoveReason::HideEvent:
break;
@@ -818,8 +822,9 @@ void QDialogButtonBox::setStandardButtons(StandardButtons buttons)
{
Q_D(QDialogButtonBox);
// Clear out all the old standard buttons, then recreate them.
- const auto toDelete = std::exchange(d->standardButtonHash, {});
- qDeleteAll(toDelete.keyBegin(), toDelete.keyEnd());
+ const auto oldButtons = d->standardButtonMap.keys();
+ d->standardButtonMap.clear();
+ qDeleteAll(oldButtons);
d->createStandardButtons(buttons);
}
@@ -828,11 +833,8 @@ QDialogButtonBox::StandardButtons QDialogButtonBox::standardButtons() const
{
Q_D(const QDialogButtonBox);
StandardButtons standardButtons = NoButton;
- QHash<QPushButton *, StandardButton>::const_iterator it = d->standardButtonHash.constBegin();
- while (it != d->standardButtonHash.constEnd()) {
- standardButtons |= it.value();
- ++it;
- }
+ for (const auto value : d->standardButtonMap.values())
+ standardButtons |= value;
return standardButtons;
}
@@ -845,7 +847,12 @@ QDialogButtonBox::StandardButtons QDialogButtonBox::standardButtons() const
QPushButton *QDialogButtonBox::button(StandardButton which) const
{
Q_D(const QDialogButtonBox);
- return d->standardButtonHash.key(which);
+
+ for (const auto &it : std::as_const(d->standardButtonMap)) {
+ if (it.second == which)
+ return it.first;
+ }
+ return nullptr;
}
/*!
@@ -857,7 +864,7 @@ QPushButton *QDialogButtonBox::button(StandardButton which) const
QDialogButtonBox::StandardButton QDialogButtonBox::standardButton(QAbstractButton *button) const
{
Q_D(const QDialogButtonBox);
- return d->standardButtonHash.value(static_cast<QPushButton *>(button));
+ return d->standardButtonMap.value(static_cast<QPushButton *>(button));
}
void QDialogButtonBoxPrivate::handleButtonClicked()
@@ -965,16 +972,13 @@ bool QDialogButtonBox::centerButtons() const
*/
void QDialogButtonBox::changeEvent(QEvent *event)
{
- typedef QHash<QPushButton *, QDialogButtonBox::StandardButton> StandardButtonHash;
-
Q_D(QDialogButtonBox);
switch (event->type()) {
case QEvent::StyleChange: // Propagate style
- if (!d->standardButtonHash.empty()) {
+ if (!d->standardButtonMap.empty()) {
QStyle *newStyle = style();
- const StandardButtonHash::iterator end = d->standardButtonHash.end();
- for (StandardButtonHash::iterator it = d->standardButtonHash.begin(); it != end; ++it)
- it.key()->setStyle(newStyle);
+ for (auto key : d->standardButtonMap.keys())
+ key->setStyle(newStyle);
}
#ifdef Q_OS_MAC
Q_FALLTHROUGH();
diff --git a/src/widgets/widgets/qdialogbuttonbox_p.h b/src/widgets/widgets/qdialogbuttonbox_p.h
index c3d7e03489..e439819c49 100644
--- a/src/widgets/widgets/qdialogbuttonbox_p.h
+++ b/src/widgets/widgets/qdialogbuttonbox_p.h
@@ -16,6 +16,7 @@
//
#include <private/qwidget_p.h>
+#include <private/qflatmap_p.h>
#include <qdialogbuttonbox.h>
QT_BEGIN_NAMESPACE
@@ -42,8 +43,8 @@ public:
QDialogButtonBoxPrivate(Qt::Orientation orient);
QList<QAbstractButton *> buttonLists[QDialogButtonBox::NRoles];
- QHash<QPushButton *, QDialogButtonBox::StandardButton> standardButtonHash;
- QHash<QAbstractButton *, QDialogButtonBox::ButtonRole> hiddenButtons;
+ QVarLengthFlatMap<QPushButton *, QDialogButtonBox::StandardButton, 8> standardButtonMap;
+ QVarLengthFlatMap<QAbstractButton *, QDialogButtonBox::ButtonRole, 8> hiddenButtons;
Qt::Orientation orientation;
QDialogButtonBox::ButtonLayout layoutPolicy;
diff --git a/src/widgets/widgets/qframe.cpp b/src/widgets/widgets/qframe.cpp
index db8dc20be2..1973fd24ee 100644
--- a/src/widgets/widgets/qframe.cpp
+++ b/src/widgets/widgets/qframe.cpp
@@ -32,7 +32,13 @@ QFramePrivate::~QFramePrivate()
inline void QFramePrivate::init()
{
+ Q_Q(QFrame);
setLayoutItemMargins(QStyle::SE_FrameLayoutItem);
+
+ // The frameRect property is implemented in terms of the widget's
+ // contentsRect, which conflicts with the implicit inclusion of
+ // the safe area margins in the contentsRect.
+ q->setAttribute(Qt::WA_ContentsMarginsRespectsSafeArea, false);
}
/*!
diff --git a/tests/auto/cmake/test_moc_macro_target/check_moc_parameters.cmake b/tests/auto/cmake/test_moc_macro_target/check_moc_parameters.cmake
index 4ca8fab119..5388816c07 100644
--- a/tests/auto/cmake/test_moc_macro_target/check_moc_parameters.cmake
+++ b/tests/auto/cmake/test_moc_macro_target/check_moc_parameters.cmake
@@ -1,4 +1,6 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
function(check_parameters file_path)
file(READ ${file_path} file_content)
foreach(compile_option IN ITEMS "-DDEFINE_CMDLINE_SIGNAL" "-DMY_OPTION")
diff --git a/tests/auto/cmake/test_qt_add_resources_rebuild/sample/CMakeLists.txt b/tests/auto/cmake/test_qt_add_resources_rebuild/sample/CMakeLists.txt
index 0a40a948c6..1696eae261 100644
--- a/tests/auto/cmake/test_qt_add_resources_rebuild/sample/CMakeLists.txt
+++ b/tests/auto/cmake/test_qt_add_resources_rebuild/sample/CMakeLists.txt
@@ -1,3 +1,5 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(sample LANGUAGES CXX)
diff --git a/tests/auto/corelib/global/CMakeLists.txt b/tests/auto/corelib/global/CMakeLists.txt
index 7970116672..6072a18e81 100644
--- a/tests/auto/corelib/global/CMakeLists.txt
+++ b/tests/auto/corelib/global/CMakeLists.txt
@@ -16,6 +16,7 @@ if(NOT INTEGRITY)
add_subdirectory(qnativeinterface)
endif()
add_subdirectory(qrandomgenerator)
+add_subdirectory(qlibraryinfo)
add_subdirectory(qlogging)
add_subdirectory(qtendian)
add_subdirectory(qglobalstatic)
diff --git a/tests/auto/corelib/global/q20/CMakeLists.txt b/tests/auto/corelib/global/q20/CMakeLists.txt
index bd28f8b999..141f94d9f7 100644
--- a/tests/auto/corelib/global/q20/CMakeLists.txt
+++ b/tests/auto/corelib/global/q20/CMakeLists.txt
@@ -1 +1,3 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
add_subdirectory(memory)
diff --git a/tests/auto/corelib/global/qcomparehelpers/tst_qcomparehelpers.cpp b/tests/auto/corelib/global/qcomparehelpers/tst_qcomparehelpers.cpp
index f140c23ed0..cb114bc90b 100644
--- a/tests/auto/corelib/global/qcomparehelpers/tst_qcomparehelpers.cpp
+++ b/tests/auto/corelib/global/qcomparehelpers/tst_qcomparehelpers.cpp
@@ -597,4 +597,4 @@ void tst_QCompareHelpers::builtinOrder()
}
QTEST_MAIN(tst_QCompareHelpers)
-#include "tst_qcomparehelpers.moc"
+#include "moc_tst_qcomparehelpers.cpp"
diff --git a/tests/auto/corelib/global/qlibraryinfo/CMakeLists.txt b/tests/auto/corelib/global/qlibraryinfo/CMakeLists.txt
new file mode 100644
index 0000000000..18642c6838
--- /dev/null
+++ b/tests/auto/corelib/global/qlibraryinfo/CMakeLists.txt
@@ -0,0 +1,17 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qlibraryinfo LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
+
+qt_internal_add_test(tst_qlibraryinfo SOURCES tst_qlibraryinfo.cpp
+ LIBRARIES
+ Qt::CorePrivate
+
+)
+
+qt_add_resources(tst_qlibraryinfo "qtconffiles" PREFIX "/" FILES empty.qt.conf partial.qt.conf)
diff --git a/tests/auto/corelib/global/qlibraryinfo/empty.qt.conf b/tests/auto/corelib/global/qlibraryinfo/empty.qt.conf
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/auto/corelib/global/qlibraryinfo/empty.qt.conf
diff --git a/tests/auto/corelib/global/qlibraryinfo/partial.qt.conf b/tests/auto/corelib/global/qlibraryinfo/partial.qt.conf
new file mode 100644
index 0000000000..bba214c2a6
--- /dev/null
+++ b/tests/auto/corelib/global/qlibraryinfo/partial.qt.conf
@@ -0,0 +1,2 @@
+[Paths]
+QmlImports = "/path/to/myqml"
diff --git a/tests/auto/corelib/global/qlibraryinfo/tst_qlibraryinfo.cpp b/tests/auto/corelib/global/qlibraryinfo/tst_qlibraryinfo.cpp
new file mode 100644
index 0000000000..1224652bf1
--- /dev/null
+++ b/tests/auto/corelib/global/qlibraryinfo/tst_qlibraryinfo.cpp
@@ -0,0 +1,66 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QTest>
+#include <QtCore/qlibraryinfo.h>
+#include <QtCore/qscopeguard.h>
+#include <QtCore/private/qlibraryinfo_p.h>
+
+
+class tst_QLibraryInfo : public QObject
+{
+ Q_OBJECT
+private slots:
+ void initTestCase();
+ void cleanup();
+ void path_data();
+ void path();
+};
+
+void tst_QLibraryInfo::initTestCase()
+{
+#if !QT_CONFIG(settings)
+ QSKIP("QSettings support is required for the test to run.");
+#endif
+}
+
+void tst_QLibraryInfo::cleanup()
+{
+ QLibraryInfoPrivate::setQtconfManualPath(nullptr);
+ QLibraryInfoPrivate::reload();
+}
+
+void tst_QLibraryInfo::path_data()
+{
+ QTest::addColumn<QString>("qtConfPath");
+ QTest::addColumn<QLibraryInfo::LibraryPath>("path");
+ QTest::addColumn<QString>("expected");
+
+ // TODO: deal with bundle on macOs?
+ QString baseDir = QCoreApplication::applicationDirPath();
+
+ // empty means we fall-back to default entries
+ QTest::addRow("empty_qmlimports") << ":/empty.qt.conf" << QLibraryInfo::QmlImportsPath << (baseDir + "/qml");
+ QTest::addRow("empty_Data") << ":/empty.qt.conf" << QLibraryInfo::DataPath << baseDir;
+
+ // partial override; use given entry if provided, otherwise default
+ QTest::addRow("partial_qmlimports") << ":/partial.qt.conf" << QLibraryInfo::QmlImportsPath << "/path/to/myqml";
+ QTest::addRow("partial_Data") << ":/partial.qt.conf" << QLibraryInfo::DataPath << baseDir;
+}
+
+void tst_QLibraryInfo::path()
+{
+ QFETCH(QString, qtConfPath);
+ QFETCH(QLibraryInfo::LibraryPath, path);
+ QFETCH(QString, expected);
+
+ QLibraryInfoPrivate::setQtconfManualPath(&qtConfPath);
+ QLibraryInfoPrivate::reload();
+ QString value = QLibraryInfo::path(path);
+ QCOMPARE(value, expected);
+
+}
+
+QTEST_GUILESS_MAIN(tst_QLibraryInfo)
+
+#include "tst_qlibraryinfo.moc"
diff --git a/tests/auto/corelib/global/qxp/CMakeLists.txt b/tests/auto/corelib/global/qxp/CMakeLists.txt
index 2178f446db..8292462d17 100644
--- a/tests/auto/corelib/global/qxp/CMakeLists.txt
+++ b/tests/auto/corelib/global/qxp/CMakeLists.txt
@@ -1,2 +1,4 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
add_subdirectory(function_ref)
add_subdirectory(is_virtual_base_of)
diff --git a/tests/auto/corelib/io/CMakeLists.txt b/tests/auto/corelib/io/CMakeLists.txt
index 7fdf4b52b0..291dbfb413 100644
--- a/tests/auto/corelib/io/CMakeLists.txt
+++ b/tests/auto/corelib/io/CMakeLists.txt
@@ -25,7 +25,7 @@ add_subdirectory(qloggingcategory)
add_subdirectory(qnodebug)
add_subdirectory(qsavefile)
add_subdirectory(qstandardpaths)
-if(NOT QNX)
+if(NOT QNX AND NOT VXWORKS)
add_subdirectory(qstorageinfo)
endif()
add_subdirectory(qtemporarydir)
diff --git a/tests/auto/corelib/io/largefile/tst_largefile.cpp b/tests/auto/corelib/io/largefile/tst_largefile.cpp
index 6fa3569c4f..f5af3bde63 100644
--- a/tests/auto/corelib/io/largefile/tst_largefile.cpp
+++ b/tests/auto/corelib/io/largefile/tst_largefile.cpp
@@ -46,6 +46,10 @@ public:
// This means that files are limited to 2 GB − 1 bytes.
// Limit max size to 256MB
maxSizeBits = 28; // 256 MiB
+ #elif defined(Q_OS_VXWORKS)
+ // VxWorks doesn't support sparse files, also, default /tmp directory is a RAM-disk which
+ // limits its capacity.
+ maxSizeBits = 28; // 256 MiB
#elif defined (Q_OS_WASM)
maxSizeBits = 28; // 256 MiB
#elif defined(QT_LARGEFILE_SUPPORT)
@@ -494,6 +498,7 @@ void tst_LargeFile::mapFile()
// 32-bit: limited to 44-bit offsets (when sizeof(off_t) == 8)
//Windows: memory-mapping beyond EOF is not allowed
//wasm: as for linux
+//VxWorks: memory-mapping beyond EOF is not allowed
void tst_LargeFile::mapOffsetOverflow()
{
enum {
@@ -506,6 +511,9 @@ void tst_LargeFile::mapOffsetOverflow()
#elif (defined(Q_OS_LINUX) || defined(Q_OS_ANDROID)) && (Q_PROCESSOR_WORDSIZE == 4)
Succeeds = true,
MaxOffset = sizeof(QT_OFF_T) > 4 ? 43 : 30
+#elif defined(Q_OS_VXWORKS)
+ Succeeds = false,
+ MaxOffset = 8 * sizeof(QT_OFF_T) - 1
#else
Succeeds = true,
MaxOffset = 8 * sizeof(QT_OFF_T) - 1
diff --git a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp
index f7d531f61f..563e4c2a83 100644
--- a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp
+++ b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp
@@ -1217,9 +1217,16 @@ void tst_QFileInfo::setFileTimes()
QCOMPARE(file.write(data), data.size());
QCOMPARE(file.size(), data.size());
- const QDateTime before = QDateTime::currentDateTimeUtc().addMSecs(-5000);
+ QDateTime before = QDateTime::currentDateTimeUtc().addMSecs(-5000);
+
QVERIFY(file.setFileTime(before, QFile::FileModificationTime));
const QDateTime mtime = file.fileTime(QFile::FileModificationTime).toUTC();
+ if (mtime.time().msec() == 0)
+ {
+ const QTime beforeTime = before.time();
+ const QTime beforeTimeWithMSCutOff{beforeTime.hour(), beforeTime.minute(), beforeTime.second(), 0};
+ before.setTime(beforeTimeWithMSCutOff);
+ }
QCOMPARE(mtime, before);
}
diff --git a/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp b/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp
index a5b0087f9c..184eef3f15 100644
--- a/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp
+++ b/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp
@@ -26,14 +26,18 @@
using namespace std::chrono_literals;
#if defined(Q_OS_QNX)
-// Longer polling times on QNX, otherwise the tests fail on the CI
+constexpr bool isQNX = true;
+#else
+constexpr bool isQNX = false;
+#endif
+
+#if defined(Q_OS_QNX) || defined(Q_OS_VXWORKS)
+// Longer polling times on QNX and VxWorks, otherwise the tests fail on the CI
constexpr auto nativeEngineTimeout = 1s;
constexpr auto pollingEngineTimeout = 1s;
-constexpr bool isQNX = true;
#else
constexpr auto nativeEngineTimeout = 0ms;
constexpr auto pollingEngineTimeout = 20ms;
-constexpr bool isQNX = false;
#endif
/* All tests need to run in temporary directories not used
diff --git a/tests/auto/corelib/io/qresourceengine/generateResources.sh b/tests/auto/corelib/io/qresourceengine/generateResources.sh
index 18d1e0b80f..ab05f1c35a 100755
--- a/tests/auto/corelib/io/qresourceengine/generateResources.sh
+++ b/tests/auto/corelib/io/qresourceengine/generateResources.sh
@@ -1,6 +1,6 @@
+#!/bin/sh
# Copyright (C) 2016 Intel Corporation.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-#!/bin/sh
count=`awk '/ZERO_FILE_LEN/ { print $3 }' tst_qresourceengine.cpp`
dd if=/dev/zero of=zero.txt bs=1 count=$count
rcc --binary -o uncompressed.rcc --no-compress compressed.qrc
diff --git a/tests/auto/corelib/io/qurl/tst_qurl.cpp b/tests/auto/corelib/io/qurl/tst_qurl.cpp
index bd454fb695..2024968435 100644
--- a/tests/auto/corelib/io/qurl/tst_qurl.cpp
+++ b/tests/auto/corelib/io/qurl/tst_qurl.cpp
@@ -3776,13 +3776,13 @@ void tst_QUrl::setComponents_data()
<< PrettyDecoded << QString() << "foo:/path";
QTest::newRow("host-empty") << QUrl("foo://example.com/path")
<< int(Host) << "" << Tolerant << true
- << PrettyDecoded << QString() << "foo:///path";
+ << PrettyDecoded << "" << "foo:///path";
QTest::newRow("authority-null") << QUrl("foo://example.com/path")
<< int(Authority) << QString() << Tolerant << true
<< PrettyDecoded << QString() << "foo:/path";
QTest::newRow("authority-empty") << QUrl("foo://example.com/path")
<< int(Authority) << "" << Tolerant << true
- << PrettyDecoded << QString() << "foo:///path";
+ << PrettyDecoded << "" << "foo:///path";
QTest::newRow("query-null") << QUrl("http://example.com/?q=foo")
<< int(Query) << QString() << Tolerant << true
<< PrettyDecoded << QString() << "http://example.com/";
@@ -3840,10 +3840,10 @@ void tst_QUrl::setComponents_data()
<< PrettyDecoded << QString() << QString();
QTest::newRow("invalid-authority-1") << QUrl("http://example.com")
<< int(Authority) << "-not-valid-" << Tolerant << false
- << PrettyDecoded << QString() << QString();
+ << PrettyDecoded << "" << QString();
QTest::newRow("invalid-authority-2") << QUrl("http://example.com")
<< int(Authority) << "%31%30.%30.%30.%31" << Strict << false
- << PrettyDecoded << QString() << QString();
+ << PrettyDecoded << "" << QString();
QTest::newRow("invalid-path-0") << QUrl("http://example.com")
<< int(Path) << "{}" << Strict << false
diff --git a/tests/auto/corelib/itemmodels/qabstractitemmodel/tst_qabstractitemmodel.cpp b/tests/auto/corelib/itemmodels/qabstractitemmodel/tst_qabstractitemmodel.cpp
index 6b1e4ce9ba..c48b79b260 100644
--- a/tests/auto/corelib/itemmodels/qabstractitemmodel/tst_qabstractitemmodel.cpp
+++ b/tests/auto/corelib/itemmodels/qabstractitemmodel/tst_qabstractitemmodel.cpp
@@ -993,9 +993,9 @@ void tst_QAbstractItemModel::complexChangesWithPersistent()
void tst_QAbstractItemModel::modelIndexComparisons()
{
- QTestPrivate::testEqualityOperatorsCompile<QModelIndex>();
- QTestPrivate::testEqualityOperatorsCompile<QPersistentModelIndex>();
- QTestPrivate::testEqualityOperatorsCompile<QPersistentModelIndex, QModelIndex>();
+ QTestPrivate::testAllComparisonOperatorsCompile<QModelIndex>();
+ QTestPrivate::testAllComparisonOperatorsCompile<QPersistentModelIndex>();
+ QTestPrivate::testAllComparisonOperatorsCompile<QPersistentModelIndex, QModelIndex>();
QtTestModel model(3, 3);
@@ -1003,13 +1003,28 @@ void tst_QAbstractItemModel::modelIndexComparisons()
QModelIndex mi22 = model.index(2, 2);
QPersistentModelIndex pmi11 = mi11;
QPersistentModelIndex pmi22 = mi22;
+ QPersistentModelIndex pmiU;
QT_TEST_EQUALITY_OPS(mi11, mi11, true);
QT_TEST_EQUALITY_OPS(mi11, mi22, false);
+ QT_TEST_ALL_COMPARISON_OPS(mi11, mi11, Qt::strong_ordering::equal);
+ QT_TEST_ALL_COMPARISON_OPS(mi11, mi22, Qt::strong_ordering::less);
+ QT_TEST_ALL_COMPARISON_OPS(mi22, mi11, Qt::strong_ordering::greater);
QT_TEST_EQUALITY_OPS(pmi11, pmi11, true);
QT_TEST_EQUALITY_OPS(pmi11, pmi22, false);
QT_TEST_EQUALITY_OPS(pmi11, mi11, true);
QT_TEST_EQUALITY_OPS(pmi11, mi22, false);
+
+ QT_TEST_ALL_COMPARISON_OPS(pmi11, pmi11, Qt::strong_ordering::equal);
+ QT_TEST_ALL_COMPARISON_OPS(pmi11, pmi22, Qt::strong_ordering::less);
+ // Disengaged QPMIs are sorted randomly (based on address of their Private)
+ // So all we can check here is QPMIs with d == nullptr, which should reliably
+ // come before any others.
+ QT_TEST_ALL_COMPARISON_OPS(pmiU, pmiU, Qt::strong_ordering::equal);
+ QT_TEST_ALL_COMPARISON_OPS(pmi11, pmiU, Qt::strong_ordering::greater);
+ QT_TEST_ALL_COMPARISON_OPS(pmi11, mi11, Qt::strong_ordering::equal);
+ QT_TEST_ALL_COMPARISON_OPS(pmi11, mi22, Qt::strong_ordering::less);
+ QT_TEST_ALL_COMPARISON_OPS(pmiU, mi11, Qt::strong_ordering::less);
}
void tst_QAbstractItemModel::testMoveSameParentDown_data()
diff --git a/tests/auto/corelib/kernel/qelapsedtimer/CMakeLists.txt b/tests/auto/corelib/kernel/qelapsedtimer/CMakeLists.txt
index 9a40a2f905..eccde38df2 100644
--- a/tests/auto/corelib/kernel/qelapsedtimer/CMakeLists.txt
+++ b/tests/auto/corelib/kernel/qelapsedtimer/CMakeLists.txt
@@ -14,4 +14,6 @@ endif()
qt_internal_add_test(tst_qelapsedtimer
SOURCES
tst_qelapsedtimer.cpp
+ LIBRARIES
+ Qt::TestPrivate
)
diff --git a/tests/auto/corelib/kernel/qelapsedtimer/tst_qelapsedtimer.cpp b/tests/auto/corelib/kernel/qelapsedtimer/tst_qelapsedtimer.cpp
index 7623fd2e43..7a2b12b2eb 100644
--- a/tests/auto/corelib/kernel/qelapsedtimer/tst_qelapsedtimer.cpp
+++ b/tests/auto/corelib/kernel/qelapsedtimer/tst_qelapsedtimer.cpp
@@ -5,6 +5,7 @@
#include <QtCore/QString>
#include <QtCore/QElapsedTimer>
#include <QTest>
+#include <QtTest/private/qcomparisontesthelper_p.h>
#include <QTimer>
static const int minResolution = 100; // the minimum resolution for the tests
@@ -22,6 +23,7 @@ class tst_QElapsedTimer : public QObject
Q_OBJECT
private Q_SLOTS:
+ void compareCompiles();
void statics();
void validity();
void basics();
@@ -29,6 +31,11 @@ private Q_SLOTS:
void msecsTo();
};
+void tst_QElapsedTimer::compareCompiles()
+{
+ QTestPrivate::testAllComparisonOperatorsCompile<QElapsedTimer>();
+}
+
void tst_QElapsedTimer::statics()
{
// these have been required since Qt 6.6
@@ -77,6 +84,7 @@ void tst_QElapsedTimer::basics()
QVERIFY(!(t1 < t1));
QCOMPARE(t1.msecsTo(t1), qint64(0));
QCOMPARE(t1.secsTo(t1), qint64(0));
+ QT_TEST_ALL_COMPARISON_OPS(t1, t1, Qt::strong_ordering::equal);
quint64 value1 = t1.msecsSinceReference();
qDebug() << "value1:" << value1 << "t1:" << t1;
@@ -141,10 +149,16 @@ void tst_QElapsedTimer::msecsTo()
QTest::qSleep(minResolution);
QElapsedTimer t2;
t2.start();
-
- QVERIFY(t1 != t2);
- QVERIFY(!(t1 == t2));
- QVERIFY(t1 < t2);
+ QTest::qSleep(minResolution);
+ QElapsedTimer t3;
+ t3.start();
+
+ QT_TEST_EQUALITY_OPS(t1, t2, false);
+ QT_TEST_EQUALITY_OPS(QElapsedTimer(), QElapsedTimer(), true);
+ QT_TEST_EQUALITY_OPS(QElapsedTimer(), t2, false);
+ QT_TEST_ALL_COMPARISON_OPS(t1, t2, Qt::strong_ordering::less);
+ QT_TEST_ALL_COMPARISON_OPS(t3, t2, Qt::strong_ordering::greater);
+ QT_TEST_ALL_COMPARISON_OPS(t3, QElapsedTimer(), Qt::strong_ordering::greater);
auto diff = t1.msecsTo(t2);
QVERIFY2(diff > 0, QString("difference t1 and t2 is %1").arg(diff).toLatin1());
diff --git a/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp b/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp
index e67bab7da4..3bf6211a53 100644
--- a/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp
+++ b/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp
@@ -335,7 +335,7 @@ void tst_QMetaProperty::conversion()
void tst_QMetaProperty::enumsFlags()
{
// QTBUG-83689, verify that enumerations and flags can be assigned from int,
- // which is important for Qt Designer.
+ // which is important for Qt Widgets Designer.
EnumFlagsTester t;
auto mo = t.metaObject();
diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
index 23d41cafb2..a8e2c7bda3 100644
--- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
+++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
@@ -544,6 +544,9 @@ void tst_QVariant::isNull()
var3 = QVariant(QMetaType::fromType<QString>());
QVERIFY( var3.isNull() );
+ var3.setValue(QString());
+ QVERIFY( !var3.isNull() );
+
QVariant var4( 0 );
QVERIFY( !var4.isNull() );
diff --git a/tests/auto/corelib/platform/windows/qcomobject/tst_qcomobject.cpp b/tests/auto/corelib/platform/windows/qcomobject/tst_qcomobject.cpp
index 5ad961ee66..3c609238fc 100644
--- a/tests/auto/corelib/platform/windows/qcomobject/tst_qcomobject.cpp
+++ b/tests/auto/corelib/platform/windows/qcomobject/tst_qcomobject.cpp
@@ -69,6 +69,7 @@ struct QComObjectTraits<IDirect>
};
} // namespace QtPrivate
+QT_END_NAMESPACE
class tst_QComObject : public QObject
{
@@ -263,6 +264,4 @@ void tst_QComObject::Release_decrementsReferenceCountByOne()
QTEST_MAIN(tst_QComObject)
# include "tst_qcomobject.moc"
-QT_END_NAMESPACE
-
#endif // Q_OS_WIN
diff --git a/tests/auto/corelib/plugin/qpluginloader/machtest/CMakeLists.txt b/tests/auto/corelib/plugin/qpluginloader/machtest/CMakeLists.txt
index 6cb69fc46d..daf922b42c 100644
--- a/tests/auto/corelib/plugin/qpluginloader/machtest/CMakeLists.txt
+++ b/tests/auto/corelib/plugin/qpluginloader/machtest/CMakeLists.txt
@@ -1,3 +1,5 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
set_directory_properties(PROPERTIES
_qt_good_targets ""
_qt_stub_targets ""
diff --git a/tests/auto/corelib/plugin/quuid/test/CMakeLists.txt b/tests/auto/corelib/plugin/quuid/test/CMakeLists.txt
index 1e1e820b14..ec6c1979f7 100644
--- a/tests/auto/corelib/plugin/quuid/test/CMakeLists.txt
+++ b/tests/auto/corelib/plugin/quuid/test/CMakeLists.txt
@@ -9,6 +9,8 @@ qt_internal_add_test(tst_quuid
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../"
SOURCES
../tst_quuid.cpp
+ LIBRARIES
+ Qt::TestPrivate
)
## Scopes:
diff --git a/tests/auto/corelib/plugin/quuid/tst_quuid.cpp b/tests/auto/corelib/plugin/quuid/tst_quuid.cpp
index c5ce490b61..08a5b826e9 100644
--- a/tests/auto/corelib/plugin/quuid/tst_quuid.cpp
+++ b/tests/auto/corelib/plugin/quuid/tst_quuid.cpp
@@ -3,6 +3,7 @@
#include <QTest>
+#include <QtTest/private/qcomparisontesthelper_p.h>
#if QT_CONFIG(process)
#include <QProcess>
#endif
@@ -17,6 +18,7 @@ class tst_QUuid : public QObject
private slots:
void initTestCase();
+ void compareCompiles();
void fromChar();
void toString();
void fromString_data();
@@ -89,20 +91,28 @@ void tst_QUuid::initTestCase()
uuidD = QUuid(0x21f7f8de, 0x8051, 0x5b89, 0x86, 0x80, 0x01, 0x95, 0xef, 0x79, 0x8b, 0x6a);
}
+void tst_QUuid::compareCompiles()
+{
+ QTestPrivate::testAllComparisonOperatorsCompile<QUuid>();
+#if defined(Q_OS_WIN)
+ QTestPrivate::testEqualityOperatorsCompile<QUuid, GUID>();
+#endif
+}
+
void tst_QUuid::fromChar()
{
- QCOMPARE(uuidA, QUuid("{fc69b59e-cc34-4436-a43c-ee95d128b8c5}"));
- QCOMPARE(uuidA, QUuid("fc69b59e-cc34-4436-a43c-ee95d128b8c5}"));
- QCOMPARE(uuidA, QUuid("{fc69b59e-cc34-4436-a43c-ee95d128b8c5"));
- QCOMPARE(uuidA, QUuid("fc69b59e-cc34-4436-a43c-ee95d128b8c5"));
- QCOMPARE(QUuid(), QUuid("{fc69b59e-cc34-4436-a43c-ee95d128b8c"));
- QCOMPARE(QUuid(), QUuid("{fc69b59e-cc34"));
- QCOMPARE(QUuid(), QUuid("fc69b59e-cc34-"));
- QCOMPARE(QUuid(), QUuid("fc69b59e-cc34"));
- QCOMPARE(QUuid(), QUuid("cc34"));
- QCOMPARE(QUuid(), QUuid(nullptr));
-
- QCOMPARE(uuidB, QUuid(QString("{1ab6e93a-b1cb-4a87-ba47-ec7e99039a7b}")));
+ QT_TEST_EQUALITY_OPS(uuidA, QUuid("{fc69b59e-cc34-4436-a43c-ee95d128b8c5}"), true);
+ QT_TEST_EQUALITY_OPS(uuidA, QUuid("fc69b59e-cc34-4436-a43c-ee95d128b8c5}"), true);
+ QT_TEST_EQUALITY_OPS(uuidA, QUuid("{fc69b59e-cc34-4436-a43c-ee95d128b8c5"), true);
+ QT_TEST_EQUALITY_OPS(uuidA, QUuid("fc69b59e-cc34-4436-a43c-ee95d128b8c5"), true);
+ QT_TEST_EQUALITY_OPS(QUuid(), QUuid("{fc69b59e-cc34-4436-a43c-ee95d128b8c"), true);
+ QT_TEST_EQUALITY_OPS(QUuid(), QUuid("{fc69b59e-cc34"), true);
+ QT_TEST_EQUALITY_OPS(QUuid(), QUuid("fc69b59e-cc34-"), true);
+ QT_TEST_EQUALITY_OPS(QUuid(), QUuid("fc69b59e-cc34"), true);
+ QT_TEST_EQUALITY_OPS(QUuid(), QUuid("cc34"), true);
+ QT_TEST_EQUALITY_OPS(QUuid(), QUuid(nullptr), true);
+
+ QT_TEST_EQUALITY_OPS(uuidB, QUuid(QString("{1ab6e93a-b1cb-4a87-ba47-ec7e99039a7b}")), true);
}
void tst_QUuid::toString()
@@ -162,21 +172,21 @@ void tst_QUuid::fromString()
const auto inputL1 = input.toLatin1();
const auto inputU8 = input.toUtf8();
- QCOMPARE(expected, QUuid(input));
- QCOMPARE(expected, QUuid(inputU8));
- QCOMPARE(expected, QUuid(inputL1));
+ QT_TEST_EQUALITY_OPS(expected, QUuid(input), true);
+ QT_TEST_EQUALITY_OPS(expected, QUuid(inputU8), true);
+ QT_TEST_EQUALITY_OPS(expected, QUuid(inputL1), true);
- QCOMPARE(expected, QUuid::fromString(input));
+ QT_TEST_EQUALITY_OPS(expected, QUuid::fromString(input), true);
// for QLatin1String, construct one whose data() is not NUL-terminated:
const auto longerInputL1 = inputL1 + '5'; // the '5' makes the premature end check incorrectly succeed
const auto inputL1S = QLatin1String(longerInputL1.data(), inputL1.size());
- QCOMPARE(expected, QUuid::fromString(inputL1S));
+ QT_TEST_EQUALITY_OPS(expected, QUuid::fromString(inputL1S), true);
// for QUtf8StringView, too:
const auto longerInputU8 = inputU8 + '5'; // the '5' makes the premature end check incorrectly succeed
const auto inputU8S = QUtf8StringView(longerInputU8.data(), inputU8.size());
- QCOMPARE(expected, QUuid::fromString(inputU8S));
+ QT_TEST_EQUALITY_OPS(expected, QUuid::fromString(inputU8S), true);
}
void tst_QUuid::toByteArray()
@@ -196,27 +206,30 @@ void tst_QUuid::toByteArray()
void tst_QUuid::fromByteArray()
{
- QCOMPARE(uuidA, QUuid(QByteArray("{fc69b59e-cc34-4436-a43c-ee95d128b8c5}")));
- QCOMPARE(uuidA, QUuid(QByteArray("fc69b59e-cc34-4436-a43c-ee95d128b8c5}")));
- QCOMPARE(uuidA, QUuid(QByteArray("{fc69b59e-cc34-4436-a43c-ee95d128b8c5")));
- QCOMPARE(uuidA, QUuid(QByteArray("fc69b59e-cc34-4436-a43c-ee95d128b8c5")));
- QCOMPARE(QUuid(), QUuid(QByteArray("{fc69b59e-cc34-4436-a43c-ee95d128b8c")));
+ QT_TEST_EQUALITY_OPS(uuidA, QUuid(QByteArray("{fc69b59e-cc34-4436-a43c-ee95d128b8c5}")), true);
+ QT_TEST_EQUALITY_OPS(uuidA, QUuid(QByteArray("fc69b59e-cc34-4436-a43c-ee95d128b8c5}")), true);
+ QT_TEST_EQUALITY_OPS(uuidA, QUuid(QByteArray("{fc69b59e-cc34-4436-a43c-ee95d128b8c5")), true);
+ QT_TEST_EQUALITY_OPS(uuidA, QUuid(QByteArray("fc69b59e-cc34-4436-a43c-ee95d128b8c5")), true);
+ QT_TEST_EQUALITY_OPS(QUuid(), QUuid(QByteArray("{fc69b59e-cc34-4436-a43c-ee95d128b8c")), true);
- QCOMPARE(uuidB, QUuid(QByteArray("{1ab6e93a-b1cb-4a87-ba47-ec7e99039a7b}")));
+ QT_TEST_EQUALITY_OPS(uuidB, QUuid(QByteArray("{1ab6e93a-b1cb-4a87-ba47-ec7e99039a7b}")), true);
}
void tst_QUuid::toRfc4122()
{
QCOMPARE(uuidA.toRfc4122(), QByteArray::fromHex("fc69b59ecc344436a43cee95d128b8c5"));
-
QCOMPARE(uuidB.toRfc4122(), QByteArray::fromHex("1ab6e93ab1cb4a87ba47ec7e99039a7b"));
}
void tst_QUuid::fromRfc4122()
{
- QCOMPARE(uuidA, QUuid::fromRfc4122(QByteArray::fromHex("fc69b59ecc344436a43cee95d128b8c5")));
+ QT_TEST_EQUALITY_OPS(
+ uuidA,
+ QUuid::fromRfc4122(QByteArray::fromHex("fc69b59ecc344436a43cee95d128b8c5")), true);
- QCOMPARE(uuidB, QUuid::fromRfc4122(QByteArray::fromHex("1ab6e93ab1cb4a87ba47ec7e99039a7b")));
+ QT_TEST_EQUALITY_OPS(
+ uuidB, QUuid::fromRfc4122(QByteArray::fromHex("1ab6e93ab1cb4a87ba47ec7e99039a7b")),
+ true);
}
void tst_QUuid::id128()
@@ -234,15 +247,15 @@ void tst_QUuid::id128()
0xba, 0x47, 0xec, 0x7e, 0x99, 0x03, 0x9a, 0x7b,
} };
- QCOMPARE(QUuid(bytesA), uuidA);
- QCOMPARE(QUuid(bytesB), uuidB);
+ QT_TEST_EQUALITY_OPS(QUuid(bytesA), uuidA, true);
+ QT_TEST_EQUALITY_OPS(QUuid(bytesB), uuidB, true);
QVERIFY(memcmp(uuidA.toBytes().data, bytesA.data, sizeof(QUuid::Id128Bytes)) == 0);
QVERIFY(memcmp(uuidB.toBytes().data, bytesB.data, sizeof(QUuid::Id128Bytes)) == 0);
QUuid::Id128Bytes leBytesA = {};
for (int i = 0; i < 16; i++)
leBytesA.data[15 - i] = bytesA.data[i];
- QCOMPARE(QUuid(leBytesA, QSysInfo::LittleEndian), uuidA);
+ QT_TEST_EQUALITY_OPS(QUuid(leBytesA, QSysInfo::LittleEndian), uuidA, true);
QVERIFY(memcmp(uuidA.toBytes(QSysInfo::LittleEndian).data, leBytesA.data, sizeof(leBytesA)) == 0);
// check the new q{To,From}{Big,Little}Endian() overloads
@@ -271,16 +284,16 @@ void tst_QUuid::uint128()
constexpr QUuid uuid = QUuid::fromUInt128(be);
static_assert(uuid.toUInt128() == be, "Round-trip through QUuid failed");
- QCOMPARE(uuid, uuidA);
+ QT_TEST_EQUALITY_OPS(uuid, uuidA, true);
QCOMPARE(uuid.toUInt128(), be);
quint128 le = qFromBigEndian(be);
QCOMPARE(uuid.toUInt128(QSysInfo::LittleEndian), le);
- QCOMPARE(QUuid::fromUInt128(le, QSysInfo::LittleEndian), uuidA);
+ QT_TEST_EQUALITY_OPS(QUuid::fromUInt128(le, QSysInfo::LittleEndian), uuidA, true);
QUuid::Id128Bytes bytes = { .data128 = { qToBigEndian(u) } };
QUuid uuid2(bytes);
- QCOMPARE(uuid2, uuid);
+ QT_TEST_EQUALITY_OPS(uuid2, uuid, true);
// verify that toBytes() and toUInt128() provide bytewise similar result
constexpr quint128 val = uuid.toUInt128();
@@ -294,11 +307,11 @@ void tst_QUuid::uint128()
void tst_QUuid::createUuidV3OrV5()
{
//"www.widgets.com" is also from RFC4122
- QCOMPARE(uuidC, QUuid::createUuidV3(uuidNS, QByteArray("www.widgets.com")));
- QCOMPARE(uuidC, QUuid::createUuidV3(uuidNS, QString("www.widgets.com")));
+ QT_TEST_EQUALITY_OPS(uuidC, QUuid::createUuidV3(uuidNS, QByteArray("www.widgets.com")), true);
+ QT_TEST_EQUALITY_OPS(uuidC, QUuid::createUuidV3(uuidNS, QString("www.widgets.com")), true);
- QCOMPARE(uuidD, QUuid::createUuidV5(uuidNS, QByteArray("www.widgets.com")));
- QCOMPARE(uuidD, QUuid::createUuidV5(uuidNS, QString("www.widgets.com")));
+ QT_TEST_EQUALITY_OPS(uuidD, QUuid::createUuidV5(uuidNS, QByteArray("www.widgets.com")), true);
+ QT_TEST_EQUALITY_OPS(uuidD, QUuid::createUuidV5(uuidNS, QString("www.widgets.com")), true);
}
void tst_QUuid::check_QDataStream()
@@ -314,7 +327,7 @@ void tst_QUuid::check_QDataStream()
QDataStream in(&ar,QIODevice::ReadOnly);
in.setByteOrder(QDataStream::BigEndian);
in >> tmp;
- QCOMPARE(uuidA, tmp);
+ QT_TEST_EQUALITY_OPS(uuidA, tmp, true);
}
{
QDataStream out(&ar,QIODevice::WriteOnly);
@@ -325,7 +338,7 @@ void tst_QUuid::check_QDataStream()
QDataStream in(&ar,QIODevice::ReadOnly);
in.setByteOrder(QDataStream::LittleEndian);
in >> tmp;
- QCOMPARE(uuidA, tmp);
+ QT_TEST_EQUALITY_OPS(uuidA, tmp, true);
}
}
@@ -340,14 +353,14 @@ void tst_QUuid::isNull()
void tst_QUuid::equal()
{
- QVERIFY( !(uuidA == uuidB) );
+ QT_TEST_EQUALITY_OPS(uuidA, uuidB, false);
QUuid copy(uuidA);
- QCOMPARE(uuidA, copy);
+ QT_TEST_EQUALITY_OPS(uuidA, copy, true);
QUuid assigned;
assigned = uuidA;
- QCOMPARE(uuidA, assigned);
+ QT_TEST_EQUALITY_OPS(uuidA, assigned, true);
}
@@ -384,10 +397,12 @@ void tst_QUuid::less()
QVERIFY( uuidB <= uuidA);
QVERIFY(!(uuidA < uuidB) );
QVERIFY(!(uuidA <= uuidB));
+ QT_TEST_ALL_COMPARISON_OPS(uuidB, uuidA, Qt::strong_ordering::less);
QUuid null_uuid;
QVERIFY(null_uuid < uuidA); // Null uuid is always less than a valid one
QVERIFY(null_uuid <= uuidA);
+ QT_TEST_ALL_COMPARISON_OPS(null_uuid, uuidA, Qt::strong_ordering::less);
QVERIFY(null_uuid <= null_uuid);
QVERIFY(uuidA <= uuidA);
@@ -400,6 +415,7 @@ void tst_QUuid::more()
QVERIFY( uuidA >= uuidB);
QVERIFY(!(uuidB > uuidA));
QVERIFY(!(uuidB >= uuidA));
+ QT_TEST_ALL_COMPARISON_OPS(uuidA, uuidB, Qt::strong_ordering::greater);
QUuid null_uuid;
QVERIFY(!(null_uuid > uuidA)); // Null uuid is always less than a valid one
@@ -407,6 +423,7 @@ void tst_QUuid::more()
QVERIFY(null_uuid >= null_uuid);
QVERIFY(uuidA >= uuidA);
+ QT_TEST_ALL_COMPARISON_OPS(uuidA, uuidA, Qt::strong_ordering::equal);
}
@@ -512,7 +529,7 @@ void tst_QUuid::qvariant()
QUuid uuid2 = v.value<QUuid>();
QVERIFY(!uuid2.isNull());
- QCOMPARE(uuid, uuid2);
+ QT_TEST_EQUALITY_OPS(uuid, uuid2, true);
}
void tst_QUuid::qvariant_conversion()
@@ -544,7 +561,7 @@ void tst_QUuid::qvariant_conversion()
QVariant sv = QVariant::fromValue(uuid.toByteArray());
QCOMPARE(sv.metaType(), QMetaType(QMetaType::QByteArray));
QVERIFY(sv.canConvert<QUuid>());
- QCOMPARE(sv.value<QUuid>(), uuid);
+ QT_TEST_EQUALITY_OPS(sv.value<QUuid>(), uuid, true);
}
}
diff --git a/tests/auto/corelib/text/qbytearrayview/CMakeLists.txt b/tests/auto/corelib/text/qbytearrayview/CMakeLists.txt
index c78a81c7bd..8922ae2267 100644
--- a/tests/auto/corelib/text/qbytearrayview/CMakeLists.txt
+++ b/tests/auto/corelib/text/qbytearrayview/CMakeLists.txt
@@ -15,3 +15,10 @@ qt_internal_add_test(tst_qbytearrayview
SOURCES
tst_qbytearrayview.cpp
)
+
+if(QT_FEATURE_sanitize_undefined)
+ qt_internal_extend_target(tst_qbytearrayview
+ DEFINES
+ QT_SANITIZE_UNDEFINED # GCC (in)famously doesn't provide a predefined macro for this
+ )
+endif()
diff --git a/tests/auto/corelib/text/qbytearrayview/tst_qbytearrayview.cpp b/tests/auto/corelib/text/qbytearrayview/tst_qbytearrayview.cpp
index 894f0430dd..702e1840da 100644
--- a/tests/auto/corelib/text/qbytearrayview/tst_qbytearrayview.cpp
+++ b/tests/auto/corelib/text/qbytearrayview/tst_qbytearrayview.cpp
@@ -262,10 +262,9 @@ void tst_QByteArrayView::constExpr() const
static_assert(!bv2.empty());
static_assert(bv2.size() == 5);
}
-#if !defined(Q_CC_GNU) || defined(Q_CC_CLANG)
+#if !defined(Q_CC_GNU_ONLY) || !defined(QT_SANITIZE_UNDEFINED)
// Below checks are disabled because of a compilation issue with GCC and
// -fsanitize=undefined. See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71962.
- // Note: Q_CC_GNU is also defined for Clang, so we need to check that too.
{
static constexpr char hello[] = "Hello";
constexpr QByteArrayView bv(hello);
@@ -307,6 +306,9 @@ void tst_QByteArrayView::constExpr() const
static_assert(bv.back() == 'o');
static_assert(bv.last() == 'o');
+ constexpr auto bv2 = QByteArrayView::fromArray(hello);
+ QCOMPARE_EQ(bv, bv2);
+
constexpr std::string_view sv = bv;
static_assert(bv.size() == sv.size());
#ifdef AMBIGUOUS_CALL // QTBUG-108805
@@ -416,7 +418,7 @@ void tst_QByteArrayView::fromArray() const
{
static constexpr char hello[] = "Hello\0abc\0\0.";
- constexpr QByteArrayView bv = QByteArrayView::fromArray(hello);
+ const QByteArrayView bv = QByteArrayView::fromArray(hello);
QCOMPARE(bv.size(), 13);
QVERIFY(!bv.empty());
QVERIFY(!bv.isEmpty());
diff --git a/tests/auto/corelib/text/qlocale/tst_qlocale.cpp b/tests/auto/corelib/text/qlocale/tst_qlocale.cpp
index c9668cd4d4..eb2d73b9b2 100644
--- a/tests/auto/corelib/text/qlocale/tst_qlocale.cpp
+++ b/tests/auto/corelib/text/qlocale/tst_qlocale.cpp
@@ -4178,6 +4178,8 @@ void tst_QLocale::mySystemLocale()
qDebug("\n\t%s", qPrintable(QLocale::system().uiLanguages().join(u"\n\t")));
});
QCOMPARE(QLocale::system().uiLanguages(), uiLanguages);
+ QCOMPARE(QLocale::system().uiLanguages(QLocale::TagSeparator::Underscore),
+ uiLanguages.replaceInStrings(u"-", u"_"));
reporter.dismiss();
}
diff --git a/tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp b/tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp
index 35a734cf02..77ca8f221b 100644
--- a/tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp
+++ b/tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp
@@ -1112,6 +1112,10 @@ auto overload_s_v(QStringView s) { return s; }
auto overload_sr_v(QString &&s) { return std::move(s); }
auto overload_sr_v(QStringView s) { return s; }
+Q_WEAK_OVERLOAD
+auto overload_s_bav(const QString &s) { return s; }
+auto overload_s_bav(QByteArrayView s) { return s; }
+
} // unnamed namespace
template<typename T>
@@ -1174,6 +1178,15 @@ void tst_QStringApiSymmetry::overload()
overload_sr_v(CT());
}
}
+
+ if constexpr (std::is_convertible_v<T, QString> || std::is_convertible_v<T, QByteArrayView>) {
+ overload_s_bav(t);
+ overload_s_bav(ct);
+ if constexpr (!std::is_array_v<T>) {
+ overload_s_bav(T());
+ overload_s_bav(CT());
+ }
+ }
QT_WARNING_POP
}
diff --git a/tests/auto/corelib/text/qstringview/CMakeLists.txt b/tests/auto/corelib/text/qstringview/CMakeLists.txt
index ba5f540838..b541cdd0ed 100644
--- a/tests/auto/corelib/text/qstringview/CMakeLists.txt
+++ b/tests/auto/corelib/text/qstringview/CMakeLists.txt
@@ -18,5 +18,12 @@ qt_internal_add_test(tst_qstringview
Qt::CorePrivate
)
+if(QT_FEATURE_sanitize_undefined)
+ qt_internal_extend_target(tst_qstringview
+ DEFINES
+ QT_SANITIZE_UNDEFINED # GCC (in)famously doesn't provide a predefined macro for this
+ )
+endif()
+
## Scopes:
#####################################################################
diff --git a/tests/auto/corelib/text/qstringview/tst_qstringview.cpp b/tests/auto/corelib/text/qstringview/tst_qstringview.cpp
index df3ef94371..3f87ffc9fc 100644
--- a/tests/auto/corelib/text/qstringview/tst_qstringview.cpp
+++ b/tests/auto/corelib/text/qstringview/tst_qstringview.cpp
@@ -359,6 +359,30 @@ void tst_QStringView::constExpr() const
static_assert(sv3.isEmpty());
static_assert(sv3.size() == 0);
}
+#if !defined(Q_CC_GNU_ONLY) || !defined(QT_SANITIZE_UNDEFINED)
+ // Below checks are disabled because of a compilation issue with GCC and
+ // -fsanitize=undefined. See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71962.
+ {
+ static constexpr char16_t hello[] = u"Hello";
+ constexpr QStringView sv(hello);
+ static_assert(sv.size() == 5);
+ static_assert(!sv.empty());
+ static_assert(!sv.isEmpty());
+ static_assert(!sv.isNull());
+ static_assert(*sv.utf16() == 'H');
+ static_assert(sv[0] == QLatin1Char('H'));
+ static_assert(sv.at(0) == QLatin1Char('H'));
+ static_assert(sv.front() == QLatin1Char('H'));
+ static_assert(sv.first() == QLatin1Char('H'));
+ static_assert(sv[4] == QLatin1Char('o'));
+ static_assert(sv.at(4) == QLatin1Char('o'));
+ static_assert(sv.back() == QLatin1Char('o'));
+ static_assert(sv.last() == QLatin1Char('o'));
+
+ constexpr auto sv2 = QStringView::fromArray(hello);
+ QCOMPARE_EQ(sv, sv2.chopped(1));
+ }
+#endif // -fsanitize=undefined
}
void tst_QStringView::basics() const
@@ -430,7 +454,7 @@ void tst_QStringView::fromArray() const
{
static constexpr char16_t hello[] = u"Hello\0abc\0\0.";
- constexpr QStringView sv = QStringView::fromArray(hello);
+ const QStringView sv = QStringView::fromArray(hello);
QCOMPARE(sv.size(), 13);
QVERIFY(!sv.empty());
QVERIFY(!sv.isEmpty());
diff --git a/tests/auto/corelib/thread/qresultstore/CMakeLists.txt b/tests/auto/corelib/thread/qresultstore/CMakeLists.txt
index 0f9d8d9e52..5abfc14ac6 100644
--- a/tests/auto/corelib/thread/qresultstore/CMakeLists.txt
+++ b/tests/auto/corelib/thread/qresultstore/CMakeLists.txt
@@ -16,4 +16,5 @@ qt_internal_add_test(tst_qresultstore
tst_qresultstore.cpp
LIBRARIES
Qt::CorePrivate
+ Qt::TestPrivate
)
diff --git a/tests/auto/corelib/thread/qresultstore/tst_qresultstore.cpp b/tests/auto/corelib/thread/qresultstore/tst_qresultstore.cpp
index 265b2cd1f6..722184a72a 100644
--- a/tests/auto/corelib/thread/qresultstore/tst_qresultstore.cpp
+++ b/tests/auto/corelib/thread/qresultstore/tst_qresultstore.cpp
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QTest>
-
+#include <QtTest/private/qcomparisontesthelper_p.h>
#include <qresultstore.h>
using namespace QtPrivate;
@@ -23,6 +23,7 @@ class tst_QtConcurrentResultStore : public QObject
public slots:
void init();
private slots:
+ void compareCompiles();
void construction();
void iterators();
void addResult();
@@ -52,6 +53,11 @@ void tst_QtConcurrentResultStore::init()
vec1 = QList<int> { 4, 5 };
}
+void tst_QtConcurrentResultStore::compareCompiles()
+{
+ QTestPrivate::testEqualityOperatorsCompile<ResultIteratorBase>();
+}
+
void tst_QtConcurrentResultStore::construction()
{
ResultStoreBase store;
@@ -74,17 +80,20 @@ void tst_QtConcurrentResultStore::iterators()
storebase.addResult(1, &int1); // ResultStoreBase does not take ownership, only ResultStore<> does.
ResultIteratorBase it = storebase.begin();
QCOMPARE(it.resultIndex(), 0);
- QCOMPARE(it, storebase.begin());
+ QT_TEST_EQUALITY_OPS(it, storebase.begin(), true);
QVERIFY(it != storebase.end());
++it;
QCOMPARE(it.resultIndex(), 1);
QVERIFY(it != storebase.begin());
QVERIFY(it != storebase.end());
+ QT_TEST_EQUALITY_OPS(it, storebase.begin(), false);
+ QT_TEST_EQUALITY_OPS(it, storebase.end(), false);
++it;
QVERIFY(it != storebase.begin());
QCOMPARE(it, storebase.end());
+ QT_TEST_EQUALITY_OPS(it, storebase.end(), true);
}
}
@@ -147,8 +156,8 @@ void tst_QtConcurrentResultStore::addResults()
store.addResults(-1, &vec1);
ResultIteratorBase it = store.begin();
QCOMPARE(it.resultIndex(), 0);
- QCOMPARE(it, store.begin());
- QVERIFY(it != store.end());
+ QT_TEST_EQUALITY_OPS(it, store.begin(), true);
+ QT_TEST_EQUALITY_OPS(it, store.end(), false);
++it;
QCOMPARE(it.resultIndex(), 1);
@@ -162,7 +171,7 @@ void tst_QtConcurrentResultStore::addResults()
QCOMPARE(it.resultIndex(), 3);
++it;
- QCOMPARE(it, store.end());
+ QT_TEST_EQUALITY_OPS(it, store.end(), true);
QList<int> empty;
const auto countBefore = store.count();
@@ -184,22 +193,22 @@ void tst_QtConcurrentResultStore::resultIndex()
ResultIteratorBase it = store.begin();
QCOMPARE(it.resultIndex(), 0);
- QVERIFY(it == store.begin());
- QVERIFY(it != store.end());
+ QT_TEST_EQUALITY_OPS(it, store.begin(), true);
+ QT_TEST_EQUALITY_OPS(it, store.end(), false);
++it;
QCOMPARE(it.resultIndex(), 1);
- QVERIFY(it != store.begin());
- QVERIFY(it != store.end());
+ QT_TEST_EQUALITY_OPS(it, store.begin(), false);
+ QT_TEST_EQUALITY_OPS(it, store.end(), false);
++it;
QCOMPARE(it.resultIndex(), 2);
- QVERIFY(it != store.end());
+ QT_TEST_EQUALITY_OPS(it, store.end(), false);
++it;
QCOMPARE(it.resultIndex(), 3);
- QVERIFY(it != store.end());
+ QT_TEST_EQUALITY_OPS(it, store.end(), false);
++it;
- QVERIFY(it == store.end());
+ QT_TEST_EQUALITY_OPS(it, store.end(), true);
QCOMPARE(store.resultAt(0).value<int>(), int0);
QCOMPARE(store.resultAt(1).value<int>(), vec0[0]);
diff --git a/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp b/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp
index d2e8f63f24..7f6bc96aa6 100644
--- a/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp
+++ b/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp
@@ -1280,7 +1280,7 @@ void tst_QTimeZone::utcTest()
void tst_QTimeZone::icuTest()
{
-#if defined(QT_BUILD_INTERNAL) && QT_CONFIG(icu)
+#if defined(QT_BUILD_INTERNAL) && QT_CONFIG(icu) && !defined(Q_OS_UNIX)
// Known datetimes
qint64 std = QDateTime(QDate(2012, 1, 1), QTime(0, 0), QTimeZone::UTC).toMSecsSinceEpoch();
qint64 dst = QDateTime(QDate(2012, 6, 1), QTime(0, 0), QTimeZone::UTC).toMSecsSinceEpoch();
@@ -1323,7 +1323,7 @@ void tst_QTimeZone::icuTest()
if (QTest::currentTestFailed())
return;
testEpochTranPrivate(QIcuTimeZonePrivate("America/Toronto"));
-#endif // icu
+#endif // ICU not on Unix
}
void tst_QTimeZone::tzTest()
@@ -1527,7 +1527,7 @@ void tst_QTimeZone::tzTest()
QDateTime dt(QDate(2016, 3, 28), QTime(0, 0), UTC);
QCOMPARE(tzBarnaul.data(dt.toMSecsSinceEpoch()).abbreviation, QString("+07"));
}
-#endif // QT_BUILD_INTERNAL && Q_OS_UNIX && !Q_OS_DARWIN
+#endif // QT_BUILD_INTERNAL && Q_OS_UNIX && !Q_OS_DARWIN && !Q_OS_ANDROID
}
void tst_QTimeZone::macTest()
diff --git a/tests/auto/corelib/tools/qcryptographichash/tst_qcryptographichash.cpp b/tests/auto/corelib/tools/qcryptographichash/tst_qcryptographichash.cpp
index c08afd67c4..fe1a9b828a 100644
--- a/tests/auto/corelib/tools/qcryptographichash/tst_qcryptographichash.cpp
+++ b/tests/auto/corelib/tools/qcryptographichash/tst_qcryptographichash.cpp
@@ -20,6 +20,8 @@ private slots:
void repeated_result();
void intermediary_result_data();
void intermediary_result();
+ void static_hash_data() { intermediary_result_data(); }
+ void static_hash();
void sha1();
void sha3_data();
void sha3();
@@ -29,9 +31,9 @@ private slots:
void blake2();
void files_data();
void files();
- void hashLength_data();
+ void hashLength_data() { all_methods(true); }
void hashLength();
- void addDataAcceptsNullByteArrayView_data() { hashLength_data(); }
+ void addDataAcceptsNullByteArrayView_data() { all_methods(false); }
void addDataAcceptsNullByteArrayView();
void move();
void swap();
@@ -40,6 +42,7 @@ private slots:
void moreThan4GiBOfData();
void keccakBufferOverflow();
private:
+ void all_methods(bool includingNumAlgorithms) const;
void ensureLargeData();
std::vector<char> large;
};
@@ -197,6 +200,17 @@ void tst_QCryptographicHash::intermediary_result()
hash.reset();
}
+void tst_QCryptographicHash::static_hash()
+{
+ QFETCH(const int, algo);
+ QFETCH(const QByteArray, first);
+ QFETCH(const QByteArray, hash_first);
+
+ const auto _algo = QCryptographicHash::Algorithm(algo);
+
+ QCOMPARE(QCryptographicHash::hash(first, _algo), hash_first);
+}
+
void tst_QCryptographicHash::sha1()
{
@@ -474,12 +488,14 @@ void tst_QCryptographicHash::files()
}
}
-void tst_QCryptographicHash::hashLength_data()
+void tst_QCryptographicHash::all_methods(bool inclNumAlgos) const
{
QTest::addColumn<QCryptographicHash::Algorithm>("algorithm");
auto metaEnum = QMetaEnum::fromType<QCryptographicHash::Algorithm>();
for (int i = 0, value = metaEnum.value(i); value != -1; value = metaEnum.value(++i)) {
auto algorithm = QCryptographicHash::Algorithm(value);
+ if (!inclNumAlgos && algorithm == QCryptographicHash::Algorithm::NumAlgorithms)
+ continue;
QTest::addRow("%s", metaEnum.key(i)) << algorithm;
}
}
diff --git a/tests/auto/corelib/tools/qsize/CMakeLists.txt b/tests/auto/corelib/tools/qsize/CMakeLists.txt
index 91de696ddd..4a4c96b52c 100644
--- a/tests/auto/corelib/tools/qsize/CMakeLists.txt
+++ b/tests/auto/corelib/tools/qsize/CMakeLists.txt
@@ -14,4 +14,6 @@ endif()
qt_internal_add_test(tst_qsize
SOURCES
tst_qsize.cpp
+ LIBRARIES
+ Qt::TestPrivate
)
diff --git a/tests/auto/corelib/tools/qsize/tst_qsize.cpp b/tests/auto/corelib/tools/qsize/tst_qsize.cpp
index c9699c5e76..d379275dd8 100644
--- a/tests/auto/corelib/tools/qsize/tst_qsize.cpp
+++ b/tests/auto/corelib/tools/qsize/tst_qsize.cpp
@@ -24,6 +24,7 @@ CHECK(const &&);
#undef CHECK
#include <QTest>
+#include <QtTest/private/qcomparisontesthelper_p.h>
#include <qsize.h>
#include <array>
@@ -34,6 +35,10 @@ class tst_QSize : public QObject
{
Q_OBJECT
private slots:
+ void compareCompiles();
+ void compare_data();
+ void compare();
+
void getSetCheck();
void scale();
@@ -55,6 +60,38 @@ private slots:
void structuredBinding();
};
+void tst_QSize::compareCompiles()
+{
+ QTestPrivate::testEqualityOperatorsCompile<QSize>();
+}
+
+void tst_QSize::compare_data()
+{
+ QTest::addColumn<QSize>("lhs");
+ QTest::addColumn<QSize>("rhs");
+ QTest::addColumn<bool>("result");
+
+ auto row = [](QSize lhs, QSize rhs, bool res) {
+ QTest::addRow("(%d, %d) vs (%d, %d)", lhs.width(), lhs.height(), rhs.width(), rhs.height())
+ << lhs << rhs << res;
+ };
+
+ row(QSize(0, 0), QSize(0, 0), true);
+ row(QSize(1, 0), QSize(0, 1), false);
+ row(QSize(-1, -1), QSize(-1, -1), true);
+ row(QSize(-1, -1), QSize(1, 1), false);
+ row(QSize(INT_MIN, INT_MAX), QSize(INT_MAX, INT_MIN), false);
+}
+
+void tst_QSize::compare()
+{
+ QFETCH(QSize, lhs);
+ QFETCH(QSize, rhs);
+ QFETCH(bool, result);
+
+ QT_TEST_EQUALITY_OPS(lhs, rhs, result);
+}
+
// Testing get/set functions
void tst_QSize::getSetCheck()
{
diff --git a/tests/auto/corelib/tools/qsizef/CMakeLists.txt b/tests/auto/corelib/tools/qsizef/CMakeLists.txt
index 9adaafe2ea..d8a1c7f46e 100644
--- a/tests/auto/corelib/tools/qsizef/CMakeLists.txt
+++ b/tests/auto/corelib/tools/qsizef/CMakeLists.txt
@@ -14,4 +14,6 @@ endif()
qt_internal_add_test(tst_qsizef
SOURCES
tst_qsizef.cpp
+ LIBRARIES
+ Qt::TestPrivate
)
diff --git a/tests/auto/corelib/tools/qsizef/tst_qsizef.cpp b/tests/auto/corelib/tools/qsizef/tst_qsizef.cpp
index ee33fa13b6..bb087e89de 100644
--- a/tests/auto/corelib/tools/qsizef/tst_qsizef.cpp
+++ b/tests/auto/corelib/tools/qsizef/tst_qsizef.cpp
@@ -24,17 +24,30 @@ CHECK(const &&);
#undef CHECK
#include <QTest>
+#include <QtTest/private/qcomparisontesthelper_p.h>
#include <qsize.h>
Q_DECLARE_METATYPE(QMarginsF)
+static constexpr qreal qreal_min = std::numeric_limits<qreal>::min();
+
class tst_QSizeF : public QObject
{
Q_OBJECT
private slots:
+ void compareCompiles();
+ void compare_data();
+ void compare();
+
+ void fuzzyCompare_data();
+ void fuzzyCompare();
+
void isNull_data();
void isNull();
+ void fuzzyIsNull_data();
+ void fuzzyIsNull();
+
void scale();
void expandedTo();
@@ -52,6 +65,61 @@ private slots:
void structuredBinding();
};
+void tst_QSizeF::compareCompiles()
+{
+ QTestPrivate::testEqualityOperatorsCompile<QSizeF>();
+ QTestPrivate::testEqualityOperatorsCompile<QSizeF, QSize>();
+}
+
+void tst_QSizeF::compare_data()
+{
+ QTest::addColumn<QSizeF>("lhs");
+ QTest::addColumn<QSizeF>("rhs");
+ QTest::addColumn<bool>("result");
+ QTest::addColumn<bool>("mixedResult");
+
+ auto row = [&](QSizeF lhs, QSizeF rhs, bool res, bool mixedRes) {
+ QString str;
+ QDebug dbg(&str);
+ dbg.nospace() << "(" << lhs.width() << ", " << lhs.height() << ") vs "
+ << "(" << rhs.width() << ", " << rhs.height() << ")";
+ QTest::addRow("%s", str.toLatin1().constData()) << lhs << rhs << res << mixedRes;
+ };
+
+ row(QSizeF(0.0, 0.0), QSizeF(0.0, 0.0), true, true);
+ row(QSizeF(1.0, 2.0), QSizeF(1.0, 2.0), true, true);
+ row(QSizeF(1.0, -1.0), QSizeF(-1.0, 1.0), false, false);
+ row(QSizeF(0.1, 1.1), QSizeF(0.1, 1.1), true, false);
+ row(QSizeF(qreal_min, 0.0), QSizeF(0.0, -qreal_min), true, true);
+}
+
+void tst_QSizeF::compare()
+{
+ QFETCH(QSizeF, lhs);
+ QFETCH(QSizeF, rhs);
+ QFETCH(bool, result);
+ QFETCH(bool, mixedResult);
+
+ QT_TEST_EQUALITY_OPS(lhs, rhs, result);
+
+ const QSize rhsFixed = rhs.toSize();
+ QT_TEST_EQUALITY_OPS(lhs, rhsFixed, mixedResult);
+}
+
+void tst_QSizeF::fuzzyCompare_data()
+{
+ compare_data();
+}
+
+void tst_QSizeF::fuzzyCompare()
+{
+ QFETCH(QSizeF, lhs);
+ QFETCH(QSizeF, rhs);
+ QFETCH(bool, result);
+
+ QCOMPARE_EQ(qFuzzyCompare(lhs, rhs), result);
+}
+
void tst_QSizeF::isNull_data()
{
QTest::addColumn<qreal>("width");
@@ -66,6 +134,7 @@ void tst_QSizeF::isNull_data()
QTest::newRow("0, -0.1") << qreal(0) << qreal(-0.1) << false;
QTest::newRow("0.1, 0") << qreal(0.1) << qreal(0) << false;
QTest::newRow("0, 0.1") << qreal(0) << qreal(0.1) << false;
+ QTest::newRow("qreal_min, -qreal_min") << qreal_min << -qreal_min << false;
}
void tst_QSizeF::isNull()
@@ -80,6 +149,33 @@ void tst_QSizeF::isNull()
QCOMPARE(size.isNull(), isNull);
}
+void tst_QSizeF::fuzzyIsNull_data()
+{
+ QTest::addColumn<qreal>("width");
+ QTest::addColumn<qreal>("height");
+ QTest::addColumn<bool>("fuzzyNull");
+
+ QTest::newRow("0, 0") << qreal(0.0) << qreal(0.0) << true;
+ QTest::newRow("-0, -0") << qreal(-0.0) << qreal(-0.0) << true;
+ QTest::newRow("0, -0") << qreal(0) << qreal(-0.0) << true;
+ QTest::newRow("-0, 0") << qreal(-0.0) << qreal(0) << true;
+ QTest::newRow("-0.1, 0") << qreal(-0.1) << qreal(0) << false;
+ QTest::newRow("0, -0.1") << qreal(0) << qreal(-0.1) << false;
+ QTest::newRow("0.1, 0") << qreal(0.1) << qreal(0) << false;
+ QTest::newRow("0, 0.1") << qreal(0) << qreal(0.1) << false;
+ QTest::newRow("qreal_min, -qreal_min") << qreal_min << -qreal_min << true;
+}
+
+void tst_QSizeF::fuzzyIsNull()
+{
+ QFETCH(qreal, width);
+ QFETCH(qreal, height);
+ QFETCH(bool, fuzzyNull);
+
+ QSizeF size(width, height);
+ QCOMPARE(qFuzzyIsNull(size), fuzzyNull);
+}
+
void tst_QSizeF::scale() {
QSizeF t1(10.4, 12.8);
t1.scale(60.6, 60.6, Qt::IgnoreAspectRatio);
diff --git a/tests/auto/corelib/tools/qspan/tst_qspan.cpp b/tests/auto/corelib/tools/qspan/tst_qspan.cpp
index 91d2ecf739..c7456ac7f2 100644
--- a/tests/auto/corelib/tools/qspan/tst_qspan.cpp
+++ b/tests/auto/corelib/tools/qspan/tst_qspan.cpp
@@ -141,6 +141,9 @@ private:
void from_variable_size_container_impl(C &&c) const;
};
+template <typename T>
+const void *as_const_void(T *p) noexcept { return static_cast<const void *>(p); }
+
#define RETURN_IF_FAILED() \
do { if (QTest::currentTestFailed()) return; } while (false)
@@ -149,7 +152,7 @@ void tst_QSpan::onlyZeroExtentSpansHaveDefaultCtors() const
static_assert(std::is_nothrow_default_constructible_v<QSpan<int, 0>>);
static_assert(std::is_nothrow_default_constructible_v<QSpan<const int, 0>>);
static_assert(std::is_nothrow_default_constructible_v<QSpan<int>>);
- static_assert(std::is_nothrow_default_constructible_v<QSpan<const int, 0>>);
+ static_assert(std::is_nothrow_default_constructible_v<QSpan<const int>>);
QSpan<int, 0> si;
check_null_span(si);
@@ -173,7 +176,7 @@ void tst_QSpan::onlyZeroExtentSpansHaveDefaultCtors() const
void tst_QSpan::zeroExtentSpansMaintainADataPointer() const
{
- int i;
+ int i = 0;
QSpan<int, 0> si{&i, 0};
QCOMPARE(si.data(), &i);
check_empty_span_incl_subspans(si);
@@ -334,6 +337,8 @@ void tst_QSpan::from_container_impl(C &&c) const
const auto c_data = QSpanPrivate::adl_data(c);
using V = std::remove_reference_t<QSpanPrivate::range_reference_t<C>>;
+ constexpr auto ExpectedBytesExtent
+ = ExpectedExtent == q20::dynamic_extent ? q20::dynamic_extent : ExpectedExtent * sizeof(V);
{
QSpan si = c; // CTAD
static_assert(std::is_same_v<decltype(si), QSpan<V, ExpectedExtent>>);
@@ -344,6 +349,20 @@ void tst_QSpan::from_container_impl(C &&c) const
check_nonempty_span(si, c_size);
RETURN_IF_FAILED();
+ auto bi = as_bytes(si);
+ static_assert(std::is_same_v<decltype(bi), QSpan<const std::byte, ExpectedBytesExtent>>);
+ QCOMPARE_EQ(bi.size(), si.size_bytes());
+ QCOMPARE_EQ(as_const_void(bi.data()),
+ as_const_void(si.data()));
+
+ if constexpr (!std::is_const_v<V>) { // e.g. std::initializer_list<int>
+ auto wbi = as_writable_bytes(si);
+ static_assert(std::is_same_v<decltype(wbi), QSpan<std::byte, ExpectedBytesExtent>>);
+ QCOMPARE_EQ(wbi.size(), si.size_bytes());
+ QCOMPARE_EQ(as_const_void(wbi.data()),
+ as_const_void(si.data()));
+ }
+
QSpan<const int> sci = c;
QCOMPARE_EQ(sci.size(), c_size);
@@ -351,6 +370,12 @@ void tst_QSpan::from_container_impl(C &&c) const
check_nonempty_span(sci, c_size);
RETURN_IF_FAILED();
+
+ auto bci = as_bytes(sci);
+ static_assert(std::is_same_v<decltype(bci), QSpan<const std::byte>>);
+ QCOMPARE_EQ(bci.size(), sci.size_bytes());
+ QCOMPARE_EQ(as_const_void(bci.data()),
+ as_const_void(sci.data()));
}
{
QSpan sci = std::as_const(c); // CTAD
@@ -361,6 +386,12 @@ void tst_QSpan::from_container_impl(C &&c) const
check_nonempty_span(sci, c_size);
RETURN_IF_FAILED();
+
+ auto bci = as_bytes(sci);
+ static_assert(std::is_same_v<decltype(bci), QSpan<const std::byte, ExpectedBytesExtent>>);
+ QCOMPARE_EQ(bci.size(), sci.size_bytes());
+ QCOMPARE_EQ(as_const_void(bci.data()),
+ as_const_void(sci.data()));
}
}
diff --git a/tests/auto/gui/painting/qregion/tst_qregion.cpp b/tests/auto/gui/painting/qregion/tst_qregion.cpp
index 3d60e62fc1..934725844a 100644
--- a/tests/auto/gui/painting/qregion/tst_qregion.cpp
+++ b/tests/auto/gui/painting/qregion/tst_qregion.cpp
@@ -138,12 +138,15 @@ void tst_QRegion::rects()
QRegion region(rect);
QVERIFY(region.isEmpty());
QCOMPARE(region.begin(), region.end());
+ QVERIFY(region.rects().isEmpty());
}
{
QRect rect(10, -20, 30, 40);
QRegion region(rect);
QCOMPARE(region.end(), region.begin() + 1);
QCOMPARE(*region.begin(), rect);
+ QCOMPARE(region.rects().size(), 1);
+ QCOMPARE(region.rects()[0], rect);
}
{
QRect r(QPoint(10, 10), QPoint(40, 40));
@@ -190,6 +193,7 @@ void tst_QRegion::setRects()
QCOMPARE(region, QRegion());
QCOMPARE(region.begin(), region.end());
QVERIFY(!region.boundingRect().isValid());
+ QVERIFY(region.rects().isEmpty());
}
{
QRegion region;
@@ -197,12 +201,15 @@ void tst_QRegion::setRects()
region.setRects(&rect, 1);
QCOMPARE(region.begin(), region.end());
QVERIFY(!region.boundingRect().isValid());
+ QVERIFY(region.rects().isEmpty());
}
{
QRegion region;
QRect rect(10, -20, 30, 40);
region.setRects(&rect, 1);
QCOMPARE(region.end(), region.begin() + 1);
+ QCOMPARE(region.rects().size(), 1);
+ QCOMPARE(region.rects()[0], rect);
QCOMPARE(*region.begin(), rect);
}
}
@@ -316,10 +323,12 @@ void tst_QRegion::emptyPolygonRegion()
QRegion r(pa);
QTEST(r.isEmpty(), "isEmpty");
QTEST(int(std::distance(r.begin(), r.end())), "numRects");
- QList<QRect> rects;
- std::copy(r.begin(), r.end(), std::back_inserter(rects));
+ QList<QRect> rects{r.begin(), r.end()};
QTEST(int(rects.size()), "numRects");
QTEST(rects, "rects");
+ const auto span = r.rects();
+ rects.assign(span.begin(), span.end());
+ QTEST(rects, "rects");
}
@@ -862,6 +871,7 @@ void tst_QRegion::isEmpty()
QCOMPARE(region, QRegion());
QCOMPARE(region.rectCount(), 0);
QCOMPARE(region.boundingRect(), QRect());
+ QVERIFY(region.rects().isEmpty());
}
void tst_QRegion::regionFromPath()
@@ -877,6 +887,10 @@ void tst_QRegion::regionFromPath()
QCOMPARE(rgn.begin()[0], QRect(0, 0, 10, 10));
QCOMPARE(rgn.begin()[1], QRect(0, 100, 100, 1000));
+ QCOMPARE(rgn.rects().size(), 2);
+ QCOMPARE(rgn.rects()[0], QRect(0, 0, 10, 10));
+ QCOMPARE(rgn.rects()[1], QRect(0, 100, 100, 1000));
+
QCOMPARE(rgn.boundingRect(), QRect(0, 0, 100, 1100));
}
@@ -893,6 +907,12 @@ void tst_QRegion::regionFromPath()
QCOMPARE(rgn.begin()[2], QRect(90, 10, 10, 80));
QCOMPARE(rgn.begin()[3], QRect(0, 90, 100, 10));
+ QCOMPARE(rgn.rects().size(), 4);
+ QCOMPARE(rgn.rects()[0], QRect(0, 0, 100, 10));
+ QCOMPARE(rgn.rects()[1], QRect(0, 10, 10, 80));
+ QCOMPARE(rgn.rects()[2], QRect(90, 10, 10, 80));
+ QCOMPARE(rgn.rects()[3], QRect(0, 90, 100, 10));
+
QCOMPARE(rgn.boundingRect(), QRect(0, 0, 100, 100));
}
}
diff --git a/tests/auto/gui/text/qcssparser/tst_qcssparser.cpp b/tests/auto/gui/text/qcssparser/tst_qcssparser.cpp
index a438d7ebc8..203fe003a0 100644
--- a/tests/auto/gui/text/qcssparser/tst_qcssparser.cpp
+++ b/tests/auto/gui/text/qcssparser/tst_qcssparser.cpp
@@ -56,6 +56,10 @@ private slots:
void quotedAndUnquotedIdentifiers();
void whitespaceValues_data();
void whitespaceValues();
+ void strokeLineCapValues_data();
+ void strokeLineCapValues();
+ void strokeLineJoinValues_data();
+ void strokeLineJoinValues();
};
void tst_QCssParser::scanner_data()
@@ -1759,6 +1763,57 @@ void tst_QCssParser::whitespaceValues()
QCOMPARE(rule.declarations.at(0).d->values.first().toString(), value);
}
+void tst_QCssParser::strokeLineCapValues_data()
+{
+ QTest::addColumn<QString>("value");
+
+ QTest::newRow("flatcap") << "flatcap";
+ QTest::newRow("roundcap") << "roundcap";
+ QTest::newRow("squarecap") << "squarecap";
+}
+
+void tst_QCssParser::strokeLineCapValues()
+{
+ QFETCH(QString, value);
+ QCss::Parser parser(QString("foo { -qt-stroke-linecap: %1 }").arg(value));
+ QCss::StyleSheet sheet;
+ QVERIFY(parser.parse(&sheet));
+
+ QCss::StyleRule rule = (!sheet.styleRules.isEmpty()) ?
+ sheet.styleRules.at(0) : *sheet.nameIndex.begin();
+ QCOMPARE(rule.declarations.size(), 1);
+
+ QCOMPARE(rule.declarations.at(0).d->property, QLatin1String("-qt-stroke-linecap"));
+ QCOMPARE(rule.declarations.at(0).d->values.first().type, QCss::Value::KnownIdentifier);
+ QCOMPARE(rule.declarations.at(0).d->values.first().toString(), value);
+}
+
+void tst_QCssParser::strokeLineJoinValues_data()
+{
+ QTest::addColumn<QString>("value");
+
+ QTest::newRow("beveljoin") << "beveljoin";
+ QTest::newRow("miterjoin") << "miterjoin";
+ QTest::newRow("roundjoin") << "roundjoin";
+ QTest::newRow("svgmiterjoin") << "svgmiterjoin";
+}
+
+void tst_QCssParser::strokeLineJoinValues()
+{
+ QFETCH(QString, value);
+ QCss::Parser parser(QString("foo { -qt-stroke-linejoin: %1 }").arg(value));
+ QCss::StyleSheet sheet;
+ QVERIFY(parser.parse(&sheet));
+
+ QCss::StyleRule rule = (!sheet.styleRules.isEmpty()) ?
+ sheet.styleRules.at(0) : *sheet.nameIndex.begin();
+ QCOMPARE(rule.declarations.size(), 1);
+
+ QCOMPARE(rule.declarations.at(0).d->property, QLatin1String("-qt-stroke-linejoin"));
+ QCOMPARE(rule.declarations.at(0).d->values.first().type, QCss::Value::KnownIdentifier);
+ QCOMPARE(rule.declarations.at(0).d->values.first().toString(), value);
+}
+
QTEST_MAIN(tst_QCssParser)
#include "tst_qcssparser.moc"
diff --git a/tests/auto/gui/text/qfontdatabase/CMakeLists.txt b/tests/auto/gui/text/qfontdatabase/CMakeLists.txt
index 18b96ded5d..0cb6e8d7c8 100644
--- a/tests/auto/gui/text/qfontdatabase/CMakeLists.txt
+++ b/tests/auto/gui/text/qfontdatabase/CMakeLists.txt
@@ -47,6 +47,8 @@ set(testdata_resource_files
"../../../shared/resources/testfont_open.otf"
"../../../shared/resources/testfont_variable.ttf"
"LED_REAL.TTF"
+ "QtTestLimitedFont-Regular.ttf"
+ "QtTestFallbackFont-Regular.ttf"
)
qt_internal_add_resource(tst_qfontdatabase "testdata"
diff --git a/tests/auto/gui/text/qfontdatabase/QtTestFallbackFont-Regular.ttf b/tests/auto/gui/text/qfontdatabase/QtTestFallbackFont-Regular.ttf
new file mode 100644
index 0000000000..ae21fec9a5
--- /dev/null
+++ b/tests/auto/gui/text/qfontdatabase/QtTestFallbackFont-Regular.ttf
Binary files differ
diff --git a/tests/auto/gui/text/qfontdatabase/QtTestLimitedFont-Regular.ttf b/tests/auto/gui/text/qfontdatabase/QtTestLimitedFont-Regular.ttf
new file mode 100644
index 0000000000..2891f8aeff
--- /dev/null
+++ b/tests/auto/gui/text/qfontdatabase/QtTestLimitedFont-Regular.ttf
Binary files differ
diff --git a/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp b/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp
index 849e7432d1..8733f64d97 100644
--- a/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp
+++ b/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp
@@ -78,6 +78,8 @@ private:
QString m_testFontCondensed;
QString m_testFontItalic;
QString m_testFontVariable;
+ QString m_limitedFont;
+ QString m_fallbackFont;
};
tst_QFontDatabase::tst_QFontDatabase()
@@ -91,11 +93,15 @@ void tst_QFontDatabase::initTestCase()
m_testFontCondensed = QFINDTESTDATA("testfont_condensed.ttf");
m_testFontItalic = QFINDTESTDATA("testfont_italic.ttf");
m_testFontVariable = QFINDTESTDATA("testfont_variable.ttf");
+ m_limitedFont = QFINDTESTDATA("QtTestLimitedFont-Regular.ttf");
+ m_fallbackFont = QFINDTESTDATA("QtTestFallbackFont-Regular.ttf");
QVERIFY(!m_ledFont.isEmpty());
QVERIFY(!m_testFont.isEmpty());
QVERIFY(!m_testFontCondensed.isEmpty());
QVERIFY(!m_testFontItalic.isEmpty());
QVERIFY(!m_testFontVariable.isEmpty());
+ QVERIFY(!m_limitedFont.isEmpty());
+ QVERIFY(!m_fallbackFont.isEmpty());
}
void tst_QFontDatabase::styles_data()
@@ -391,8 +397,14 @@ void tst_QFontDatabase::condensedFontWidthNoFontMerging()
void tst_QFontDatabase::condensedFontWidth()
{
- QFontDatabase::addApplicationFont(m_testFont);
- QFontDatabase::addApplicationFont(m_testFontCondensed);
+ int testFontId = QFontDatabase::addApplicationFont(m_testFont);
+ int testFontCondensedId = QFontDatabase::addApplicationFont(m_testFontCondensed);
+ auto cleanup = qScopeGuard([&testFontId, &testFontCondensedId] {
+ if (testFontId >= 0)
+ QFontDatabase::removeApplicationFont(testFontId);
+ if (testFontCondensedId >= 0)
+ QFontDatabase::removeApplicationFont(testFontCondensedId);
+ });
QVERIFY(QFontDatabase::hasFamily("QtBidiTestFont"));
if (!QFontDatabase::hasFamily("QtBidiTestFontCondensed"))
@@ -410,10 +422,16 @@ void tst_QFontDatabase::condensedFontWidth()
void tst_QFontDatabase::condensedFontMatching()
{
QFontDatabase::removeAllApplicationFonts();
- QFontDatabase::addApplicationFont(m_testFontCondensed);
+ int testFontCondensedId = QFontDatabase::addApplicationFont(m_testFontCondensed);
if (!QFontDatabase::hasFamily("QtBidiTestFont"))
QSKIP("This platform doesn't support preferred font family names (QTBUG-53478)");
- QFontDatabase::addApplicationFont(m_testFont);
+ int testFontId = QFontDatabase::addApplicationFont(m_testFont);
+ auto cleanup = qScopeGuard([&testFontId, &testFontCondensedId] {
+ if (testFontId >= 0)
+ QFontDatabase::removeApplicationFont(testFontId);
+ if (testFontCondensedId >= 0)
+ QFontDatabase::removeApplicationFont(testFontCondensedId);
+ });
// Test we correctly get the condensed font using different font matching methods:
QFont tfcByStretch("QtBidiTestFont");
@@ -561,11 +579,17 @@ void tst_QFontDatabase::addApplicationFontFallback()
{
int ledId = -1;
int id = -1;
- auto cleanup = qScopeGuard([&id, &ledId] {
+ int limitedId = -1;
+ int fallbackId = -1;
+ auto cleanup = qScopeGuard([&id, &ledId, &limitedId, &fallbackId] {
if (id >= 0)
QFontDatabase::removeApplicationFont(id);
if (ledId >= 0)
QFontDatabase::removeApplicationFont(ledId);
+ if (limitedId >= 0)
+ QFontDatabase::removeApplicationFont(limitedId);
+ if (fallbackId >= 0)
+ QFontDatabase::removeApplicationFont(fallbackId);
});
const QChar hebrewChar(0x05D0); // Hebrew 'aleph'
@@ -633,6 +657,107 @@ void tst_QFontDatabase::addApplicationFontFallback()
QCOMPARE(hebrewFontNow, defaultHebrewFont);
}
+ limitedId = QFontDatabase::addApplicationFont(m_limitedFont);
+ QVERIFY(limitedId >= 0);
+
+ fallbackId = QFontDatabase::addApplicationFont(m_fallbackFont);
+ QVERIFY(fallbackId >= 0);
+
+ QFontDatabase::addApplicationFallbackFontFamily(QChar::Script_Common, u"QtTestFallbackFont"_s);
+
+ // The fallback for Common will be used also for Latin, because Latin and Common are
+ // considered the same script by the font matching engine.
+ {
+ QTextLayout layout;
+ layout.setText(u"A'B,"_s);
+ layout.setFont(QFont(u"QtTestLimitedFont"_s));
+ layout.beginLayout();
+ layout.createLine();
+ layout.endLayout();
+
+ QList<QGlyphRun> glyphRuns = layout.glyphRuns();
+ QVERIFY(glyphRuns.size() > 1);
+ for (int i = 0; i < glyphRuns.size(); ++i) {
+ QVERIFY(glyphRuns.at(i).rawFont().familyName() == u"QtTestFallbackFont"_s
+ || glyphRuns.at(i).rawFont().familyName() == u"QtTestLimitedFont"_s);
+ }
+ }
+
+ // When the text only consists of common script characters, the fallback font will also be used.
+ {
+ QTextLayout layout;
+ layout.setText(u"',"_s);
+ layout.setFont(QFont(u"QtTestLimitedFont"_s));
+ layout.beginLayout();
+ layout.createLine();
+ layout.endLayout();
+
+ QList<QGlyphRun> glyphRuns = layout.glyphRuns();
+ QCOMPARE(glyphRuns.size(), 2);
+ for (int i = 0; i < glyphRuns.size(); ++i) {
+ QVERIFY(glyphRuns.at(i).rawFont().familyName() == u"QtTestFallbackFont"_s
+ || glyphRuns.at(i).rawFont().familyName() == u"QtTestLimitedFont"_s);
+ }
+ }
+
+ QVERIFY(QFontDatabase::removeApplicationFallbackFontFamily(QChar::Script_Common, u"QtTestFallbackFont"_s));
+ QFontDatabase::addApplicationFallbackFontFamily(QChar::Script_Latin, u"QtTestFallbackFont"_s);
+
+ // Latin fallback works just the same as Common fallback
+ {
+ QTextLayout layout;
+ layout.setText(u"A'B,"_s);
+ layout.setFont(QFont(u"QtTestLimitedFont"_s));
+ layout.beginLayout();
+ layout.createLine();
+ layout.endLayout();
+
+ QList<QGlyphRun> glyphRuns = layout.glyphRuns();
+ QCOMPARE(glyphRuns.size(), 2);
+ for (int i = 0; i < glyphRuns.size(); ++i) {
+ QVERIFY(glyphRuns.at(i).rawFont().familyName() == u"QtTestFallbackFont"_s
+ || glyphRuns.at(i).rawFont().familyName() == u"QtTestLimitedFont"_s);
+ }
+ }
+
+ // When the common character is placed next to a Cyrillic characters, it gets adapted to this,
+ // so the fallback font will not be selected, even if it supports the character in question
+ {
+ QTextLayout layout;
+ layout.setText(u"A'Б,"_s);
+ layout.setFont(QFont(u"QtTestLimitedFont"_s));
+ layout.beginLayout();
+ layout.createLine();
+ layout.endLayout();
+
+ QList<QGlyphRun> glyphRuns = layout.glyphRuns();
+ QCOMPARE(glyphRuns.size(), 2);
+ for (int i = 0; i < glyphRuns.size(); ++i) {
+ QVERIFY(glyphRuns.at(i).rawFont().familyName() != u"QtTestFallbackFont"_s);
+ }
+ }
+
+ QFontDatabase::addApplicationFallbackFontFamily(QChar::Script_Cyrillic, u"QtTestFallbackFont"_s);
+
+ // When we set the fallback font for Cyrillic as well, it gets selected
+ {
+ QTextLayout layout;
+ layout.setText(u"A'Б,"_s);
+ layout.setFont(QFont(u"QtTestLimitedFont"_s));
+ layout.beginLayout();
+ layout.createLine();
+ layout.endLayout();
+
+ QList<QGlyphRun> glyphRuns = layout.glyphRuns();
+ QCOMPARE(glyphRuns.size(), 2);
+ for (int i = 0; i < glyphRuns.size(); ++i) {
+ QVERIFY(glyphRuns.at(i).rawFont().familyName() == u"QtTestFallbackFont"_s
+ || glyphRuns.at(i).rawFont().familyName() == u"QtTestLimitedFont"_s);
+ }
+ }
+
+ QVERIFY(QFontDatabase::removeApplicationFallbackFontFamily(QChar::Script_Cyrillic, u"QtTestFallbackFont"_s));
+ QVERIFY(QFontDatabase::removeApplicationFallbackFontFamily(QChar::Script_Latin, u"QtTestFallbackFont"_s));
}
QTEST_MAIN(tst_QFontDatabase)
diff --git a/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp b/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp
index 335ee06e2f..600b45575f 100644
--- a/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp
+++ b/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp
@@ -4053,20 +4053,107 @@ void tst_QTextDocument::restoreStrokeFromHtml()
QTextDocument document;
QTextCursor textCursor(&document);
QTextCharFormat textOutline;
- textOutline.setTextOutline(QPen(Qt::red, 2.3));
- textCursor.insertText("Outlined text", textOutline);
+
+ // Set stroke color and width
+ {
+ QPen pen(Qt::red, 2.3, Qt::SolidLine);
+ textOutline.setTextOutline(pen);
+ textCursor.insertText("Outlined text", textOutline);
+ }
+
+ // Set Cap and Join styles
+ {
+ QPen pen;
+ pen.setCapStyle(Qt::FlatCap);
+ pen.setJoinStyle(Qt::RoundJoin);
+ textOutline.setTextOutline(pen);
+ textCursor.insertBlock();
+ textCursor.insertText("Cap and Join Style", textOutline);
+ }
+
+ // Set Miter limit
+ {
+ QPen pen;
+ pen.setJoinStyle(Qt::MiterJoin);
+ pen.setMiterLimit(4);
+ textOutline.setTextOutline(pen);
+ textCursor.insertBlock();
+ textCursor.insertText("Miter Limit", textOutline);
+ }
+
+ // Set Dash Array and Dash Offset
+ {
+ QPen pen;
+ QList<qreal> pattern;
+ const int dash = 2;
+ const int gap = 4;
+ pattern << dash << gap << dash << gap << dash << gap;
+ pen.setDashPattern(pattern);
+ pen.setDashOffset(3);
+ textOutline.setTextOutline(pen);
+ textCursor.insertBlock();
+ textCursor.insertText("Dash Pattern", textOutline);
+ }
+
{
QTextDocument otherDocument;
otherDocument.setHtml(document.toHtml());
- QCOMPARE(otherDocument.blockCount(), 1);
- QTextBlock block = otherDocument.firstBlock();
- QTextFragment fragment = block.begin().fragment();
- QCOMPARE(fragment.text(), QStringLiteral("Outlined text"));
- QTextCharFormat fmt = fragment.charFormat();
- QVERIFY(fmt.hasProperty(QTextCharFormat::TextOutline));
- QPen pen = fmt.textOutline();
- QCOMPARE(pen.color(), QColor(Qt::red));
- QCOMPARE(pen.widthF(), 2.3);
+ QCOMPARE(otherDocument.blockCount(), document.blockCount());
+
+ QTextBlock block;
+ QTextFragment fragment;
+ QTextCharFormat fmt;
+ QPen pen;
+
+ {
+ block = otherDocument.findBlockByNumber(0);
+ fragment = block.begin().fragment();
+ QCOMPARE(fragment.text(), QStringLiteral("Outlined text"));
+ fmt = fragment.charFormat();
+ QVERIFY(fmt.hasProperty(QTextCharFormat::TextOutline));
+ pen = fmt.textOutline();
+ QCOMPARE(pen.color(), QColor(Qt::red));
+ QCOMPARE(pen.widthF(), 2.3);
+ }
+
+ {
+ block = otherDocument.findBlockByNumber(1);
+ qDebug() << block.text();
+ fragment = block.begin().fragment();
+ QCOMPARE(fragment.text(), QStringLiteral("Cap and Join Style"));
+ fmt = fragment.charFormat();
+ QVERIFY(fmt.hasProperty(QTextCharFormat::TextOutline));
+ pen = fmt.textOutline();
+ QCOMPARE(pen.capStyle(), Qt::FlatCap);
+ QCOMPARE(pen.joinStyle(), Qt::RoundJoin);
+ }
+
+ {
+ block = otherDocument.findBlockByNumber(2);
+ fragment = block.begin().fragment();
+ QCOMPARE(fragment.text(), QStringLiteral("Miter Limit"));
+ fmt = fragment.charFormat();
+ QVERIFY(fmt.hasProperty(QTextCharFormat::TextOutline));
+ pen = fmt.textOutline();
+ QCOMPARE(pen.joinStyle(), Qt::MiterJoin);
+ QCOMPARE(pen.miterLimit(), 4);
+ }
+
+
+ {
+ block = otherDocument.findBlockByNumber(3);
+ fragment = block.begin().fragment();
+ QCOMPARE(fragment.text(), QStringLiteral("Dash Pattern"));
+ fmt = fragment.charFormat();
+ QVERIFY(fmt.hasProperty(QTextCharFormat::TextOutline));
+ pen = fmt.textOutline();
+ QCOMPARE(pen.dashOffset(), 3);
+ QList<qreal> pattern;
+ const int dash = 2;
+ const int gap = 4;
+ pattern << dash << gap << dash << gap << dash << gap;
+ QCOMPARE(pen.dashPattern(), pattern);
+ }
}
}
diff --git a/tests/auto/gui/text/qtextmarkdownwriter/data/example.md b/tests/auto/gui/text/qtextmarkdownwriter/data/example.md
index 15b30598e6..8fdad207ae 100644
--- a/tests/auto/gui/text/qtextmarkdownwriter/data/example.md
+++ b/tests/auto/gui/text/qtextmarkdownwriter/data/example.md
@@ -40,7 +40,7 @@ numerals in the same list structure:
1. Introduction
2. Qt Tools
1) Qt Assistant
- 2) Qt Designer
+ 2) Qt Widgets Designer
1. Form Editor
2. Component Architecture
3) Qt Linguist
@@ -70,7 +70,7 @@ column spans, text formatting within cells, and size constraints for columns.
|-------------|------------------------------------|---------------------------|-------------------------|
|9:00 - 11:00 |Introduction to Qt |||
|11:00 - 13:00|Using qmake |Object-oriented Programming|Layouts in Qt |
-|13:00 - 15:00|Qt Designer Tutorial |Extreme Programming |Writing Custom Styles |
+|13:00 - 15:00|Qt Widgets Designer Tutorial |Extreme Programming |Writing Custom Styles |
|15:00 - 17:00|Qt Linguist and Internationalization|Test-Driven Development | |
*Try adding text to the cells in the table and experiment with the alignment of
diff --git a/tests/auto/gui/util/qdesktopservices/tst_qdesktopservices.cpp b/tests/auto/gui/util/qdesktopservices/tst_qdesktopservices.cpp
index e08b299209..e75626eda7 100644
--- a/tests/auto/gui/util/qdesktopservices/tst_qdesktopservices.cpp
+++ b/tests/auto/gui/util/qdesktopservices/tst_qdesktopservices.cpp
@@ -42,10 +42,6 @@ public slots:
}
};
-#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0)
-# define CAN_IMPLICITLY_UNSET
-#endif
-
void tst_qdesktopservices::handlers()
{
MyUrlHandler fooHandler;
@@ -53,12 +49,10 @@ void tst_qdesktopservices::handlers()
QDesktopServices::setUrlHandler(QString("foo"), &fooHandler, "handle");
QDesktopServices::setUrlHandler(QString("bar"), &barHandler, "handle");
-#ifndef CAN_IMPLICITLY_UNSET
const auto unsetHandlers = qScopeGuard([] {
QDesktopServices::unsetUrlHandler(u"bar"_s);
QDesktopServices::unsetUrlHandler(u"foo"_s);
});
-#endif
QUrl fooUrl("foo://blub/meh");
QUrl barUrl("bar://hmm/hmmmm");
@@ -68,15 +62,6 @@ void tst_qdesktopservices::handlers()
QCOMPARE(fooHandler.lastHandledUrl.toString(), fooUrl.toString());
QCOMPARE(barHandler.lastHandledUrl.toString(), barUrl.toString());
-
-#ifdef CAN_IMPLICITLY_UNSET
- for (int i = 0; i < 2; ++i)
- QTest::ignoreMessage(QtWarningMsg,
- "Please call QDesktopServices::unsetUrlHandler() before destroying a "
- "registered URL handler object.\n"
- "Support for destroying a registered URL handler object is deprecated, "
- "and will be removed in Qt 6.6.");
-#endif
}
QTEST_MAIN(tst_qdesktopservices)
diff --git a/tests/auto/network/access/CMakeLists.txt b/tests/auto/network/access/CMakeLists.txt
index 3ae66e1308..d1130f832e 100644
--- a/tests/auto/network/access/CMakeLists.txt
+++ b/tests/auto/network/access/CMakeLists.txt
@@ -13,6 +13,7 @@ add_subdirectory(qnetworkreply)
add_subdirectory(qnetworkcachemetadata)
add_subdirectory(qabstractnetworkcache)
if(QT_FEATURE_http)
+ add_subdirectory(qnetworkreply_local)
add_subdirectory(qnetworkrequestfactory)
add_subdirectory(qrestaccessmanager)
endif()
diff --git a/tests/auto/network/access/http2/tst_http2.cpp b/tests/auto/network/access/http2/tst_http2.cpp
index d9e82330b2..396a6f2fda 100644
--- a/tests/auto/network/access/http2/tst_http2.cpp
+++ b/tests/auto/network/access/http2/tst_http2.cpp
@@ -1277,7 +1277,7 @@ void tst_Http2::unsupportedAuthenticateChallenge()
bool authenticationRequested = false;
connect(manager.get(), &QNetworkAccessManager::authenticationRequired, reply.get(),
- [&](QNetworkReply *, QAuthenticator *auth) {
+ [&](QNetworkReply *, QAuthenticator *) {
authenticationRequested = true;
});
diff --git a/tests/auto/network/access/qnetworkreply_local/CMakeLists.txt b/tests/auto/network/access/qnetworkreply_local/CMakeLists.txt
new file mode 100644
index 0000000000..13a60afb13
--- /dev/null
+++ b/tests/auto/network/access/qnetworkreply_local/CMakeLists.txt
@@ -0,0 +1,9 @@
+qt_internal_add_test(tst_qnetworkreply_local
+ SOURCES
+ minihttpserver.h
+ tst_qnetworkreply_local.cpp
+ LIBRARIES
+ Qt::CorePrivate
+ Qt::NetworkPrivate
+ BUNDLE_ANDROID_OPENSSL_LIBS
+)
diff --git a/tests/auto/network/access/qnetworkreply_local/minihttpserver.h b/tests/auto/network/access/qnetworkreply_local/minihttpserver.h
new file mode 100644
index 0000000000..eb0697a6f8
--- /dev/null
+++ b/tests/auto/network/access/qnetworkreply_local/minihttpserver.h
@@ -0,0 +1,246 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef MINIHTTPSERVER_H
+#define MINIHTTPSERVER_H
+
+#include <QtNetwork/qtnetworkglobal.h>
+
+#include <QtNetwork/qtcpserver.h>
+#include <QtNetwork/qtcpsocket.h>
+#include <QtNetwork/qlocalsocket.h>
+#if QT_CONFIG(ssl)
+# include <QtNetwork/qsslsocket.h>
+#endif
+#if QT_CONFIG(localserver)
+# include <QtNetwork/qlocalserver.h>
+#endif
+
+#include <QtCore/qpointer.h>
+#include <QtCore/qhash.h>
+
+#include <utility>
+
+static inline QByteArray default200Response()
+{
+ return QByteArrayLiteral("HTTP/1.1 200 OK\r\n"
+ "Content-Type: text/plain\r\n"
+ "Content-Length: 12\r\n"
+ "\r\n"
+ "Hello World!");
+}
+class MiniHttpServerV2 : public QObject
+{
+ Q_OBJECT
+
+public:
+ struct State;
+
+#if QT_CONFIG(localserver)
+ void bind(QLocalServer *server)
+ {
+ Q_ASSERT(!localServer);
+ localServer = server;
+ connect(server, &QLocalServer::newConnection, this,
+ &MiniHttpServerV2::incomingLocalConnection);
+ }
+#endif
+
+ void bind(QTcpServer *server)
+ {
+ Q_ASSERT(!tcpServer);
+ tcpServer = server;
+ connect(server, &QTcpServer::pendingConnectionAvailable, this,
+ &MiniHttpServerV2::incomingConnection);
+ }
+
+ void setDataToTransmit(QByteArray data) { dataToTransmit = std::move(data); }
+
+ void clearServerState()
+ {
+ auto copy = std::exchange(clientStates, {});
+ for (auto [socket, _] : copy.asKeyValueRange()) {
+ if (auto *tcpSocket = qobject_cast<QTcpSocket *>(socket))
+ tcpSocket->disconnectFromHost();
+ else if (auto *localSocket = qobject_cast<QLocalSocket *>(socket))
+ localSocket->disconnectFromServer();
+ else
+ Q_UNREACHABLE_RETURN();
+ socket->deleteLater();
+ }
+ }
+
+ bool hasPendingConnections() const
+ {
+ return
+#if QT_CONFIG(localserver)
+ (localServer && localServer->hasPendingConnections()) ||
+#endif
+ (tcpServer && tcpServer->hasPendingConnections());
+ }
+
+ QString addressForScheme(QStringView scheme) const
+ {
+ using namespace Qt::StringLiterals;
+ if (scheme.startsWith("unix"_L1) || scheme.startsWith("local"_L1)) {
+#if QT_CONFIG(localserver)
+ if (localServer)
+ return localServer->serverName();
+#endif
+ } else if (scheme == "http"_L1) {
+ if (tcpServer)
+ return "%1:%2"_L1.arg(tcpServer->serverAddress().toString(),
+ QString::number(tcpServer->serverPort()));
+ }
+ return {};
+ }
+
+ QList<State> peerStates() const { return clientStates.values(); }
+
+protected:
+#if QT_CONFIG(localserver)
+ void incomingLocalConnection()
+ {
+ auto *socket = localServer->nextPendingConnection();
+ connectSocketSignals(socket);
+ }
+#endif
+
+ void incomingConnection()
+ {
+ auto *socket = tcpServer->nextPendingConnection();
+ connectSocketSignals(socket);
+ }
+
+ void reply(QIODevice *socket)
+ {
+ Q_ASSERT(socket);
+ if (dataToTransmit.isEmpty()) {
+ emit socket->bytesWritten(0); // emulate having written the data
+ return;
+ }
+ if (!stopTransfer)
+ socket->write(dataToTransmit);
+ }
+
+private:
+ void connectSocketSignals(QIODevice *socket)
+ {
+ connect(socket, &QIODevice::readyRead, this, [this, socket]() { readyReadSlot(socket); });
+ connect(socket, &QIODevice::bytesWritten, this,
+ [this, socket]() { bytesWrittenSlot(socket); });
+#if QT_CONFIG(ssl)
+ if (auto *sslSocket = qobject_cast<QSslSocket *>(socket))
+ connect(sslSocket, &QSslSocket::sslErrors, this, &MiniHttpServerV2::slotSslErrors);
+#endif
+
+ if (auto *tcpSocket = qobject_cast<QTcpSocket *>(socket)) {
+ connect(tcpSocket, &QAbstractSocket::errorOccurred, this, &MiniHttpServerV2::slotError);
+ } else if (auto *localSocket = qobject_cast<QLocalSocket *>(socket)) {
+ connect(localSocket, &QLocalSocket::errorOccurred, this,
+ [this](QLocalSocket::LocalSocketError error) {
+ slotError(QAbstractSocket::SocketError(error));
+ });
+ } else {
+ Q_UNREACHABLE_RETURN();
+ }
+ }
+
+ void parseContentLength(State &st, QByteArrayView header)
+ {
+ qsizetype index = header.indexOf("\r\ncontent-length:");
+ if (index == -1)
+ return;
+ st.foundContentLength = true;
+
+ index += sizeof("\r\ncontent-length:") - 1;
+ const auto *end = std::find(header.cbegin() + index, header.cend(), '\r');
+ QByteArrayView num = header.mid(index, std::distance(header.cbegin() + index, end));
+ bool ok = false;
+ st.contentLength = num.toInt(&ok);
+ if (!ok)
+ st.contentLength = -1;
+ }
+
+private slots:
+#if QT_CONFIG(ssl)
+ void slotSslErrors(const QList<QSslError> &errors)
+ {
+ QTcpSocket *currentClient = qobject_cast<QTcpSocket *>(sender());
+ Q_ASSERT(currentClient);
+ qDebug() << "slotSslErrors" << currentClient->errorString() << errors;
+ }
+#endif
+ void slotError(QAbstractSocket::SocketError err)
+ {
+ QTcpSocket *currentClient = qobject_cast<QTcpSocket *>(sender());
+ Q_ASSERT(currentClient);
+ qDebug() << "slotError" << err << currentClient->errorString();
+ }
+
+public slots:
+
+ void readyReadSlot(QIODevice *socket)
+ {
+ if (stopTransfer)
+ return;
+ State &st = clientStates[socket];
+ st.receivedData += socket->readAll();
+ const qsizetype doubleEndlPos = st.receivedData.indexOf("\r\n\r\n");
+
+ if (doubleEndlPos != -1) {
+ const qsizetype endOfHeader = doubleEndlPos + 4;
+ st.contentRead = st.receivedData.size() - endOfHeader;
+
+ if (!st.checkedContentLength) {
+ parseContentLength(st, QByteArrayView(st.receivedData).first(endOfHeader));
+ st.checkedContentLength = true;
+ }
+
+ if (st.contentRead < st.contentLength)
+ return;
+
+ // multiple requests incoming, remove the bytes of the current one
+ if (multiple)
+ st.receivedData.remove(0, endOfHeader);
+
+ reply(socket);
+ }
+ }
+
+ void bytesWrittenSlot(QIODevice *socket)
+ {
+ // Disconnect and delete in next cycle (else Windows clients will fail with
+ // RemoteHostClosedError).
+ if (doClose && socket->bytesToWrite() == 0) {
+ disconnect(socket, nullptr, this, nullptr);
+ socket->deleteLater();
+ }
+ }
+
+private:
+ QByteArray dataToTransmit = default200Response();
+
+ QTcpServer *tcpServer = nullptr;
+#if QT_CONFIG(localserver)
+ QLocalServer *localServer = nullptr;
+#endif
+
+ QHash<QIODevice *, State> clientStates;
+
+public:
+ struct State
+ {
+ QByteArray receivedData;
+ qsizetype contentLength = 0;
+ qsizetype contentRead = 0;
+ bool checkedContentLength = false;
+ bool foundContentLength = false;
+ };
+
+ bool doClose = true;
+ bool multiple = false;
+ bool stopTransfer = false;
+};
+
+#endif // MINIHTTPSERVER_H
diff --git a/tests/auto/network/access/qnetworkreply_local/tst_qnetworkreply_local.cpp b/tests/auto/network/access/qnetworkreply_local/tst_qnetworkreply_local.cpp
new file mode 100644
index 0000000000..6d78c81593
--- /dev/null
+++ b/tests/auto/network/access/qnetworkreply_local/tst_qnetworkreply_local.cpp
@@ -0,0 +1,177 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QtNetwork/qtnetworkglobal.h>
+
+#include <QtTest/qtest.h>
+
+#include <QtNetwork/qnetworkreply.h>
+#include <QtNetwork/qnetworkaccessmanager.h>
+
+#include "minihttpserver.h"
+
+using namespace Qt::StringLiterals;
+
+/*
+ The tests here are meant to be self-contained, using servers in the same
+ process if needed. This enables externals to more easily run the tests too.
+*/
+class tst_QNetworkReply_local : public QObject
+{
+ Q_OBJECT
+private slots:
+ void initTestCase_data();
+
+ void get();
+ void post();
+
+#if QT_CONFIG(localserver)
+ void fullServerName_data();
+ void fullServerName();
+#endif
+};
+
+void tst_QNetworkReply_local::initTestCase_data()
+{
+ QTest::addColumn<QString>("scheme");
+
+ QTest::newRow("http") << "http";
+#if QT_CONFIG(localserver)
+ QTest::newRow("unix") << "unix+http";
+ QTest::newRow("local") << "local+http"; // equivalent to unix, but test that it works
+#endif
+}
+
+static std::unique_ptr<MiniHttpServerV2> getServerForCurrentScheme()
+{
+ auto server = std::make_unique<MiniHttpServerV2>();
+ QFETCH_GLOBAL(QString, scheme);
+ if (scheme.startsWith("unix"_L1) || scheme.startsWith("local"_L1)) {
+#if QT_CONFIG(localserver)
+ QLocalServer *localServer = new QLocalServer(server.get());
+ localServer->listen(u"qt_networkreply_test_"_s
+ % QLatin1StringView(QTest::currentTestFunction())
+ % QString::number(QCoreApplication::applicationPid()));
+ server->bind(localServer);
+#endif
+ } else if (scheme == "http") {
+ QTcpServer *tcpServer = new QTcpServer(server.get());
+ tcpServer->listen(QHostAddress::LocalHost, 0);
+ server->bind(tcpServer);
+ }
+ return server;
+}
+
+static QUrl getUrlForCurrentScheme(MiniHttpServerV2 *server)
+{
+ QFETCH_GLOBAL(QString, scheme);
+ const QString address = server->addressForScheme(scheme);
+ const QString urlString = QLatin1StringView("%1://%2").arg(scheme, address);
+ return { urlString };
+}
+
+void tst_QNetworkReply_local::get()
+{
+ std::unique_ptr<MiniHttpServerV2> server = getServerForCurrentScheme();
+ const QUrl url = getUrlForCurrentScheme(server.get());
+
+ QNetworkAccessManager manager;
+ std::unique_ptr<QNetworkReply> reply(manager.get(QNetworkRequest(url)));
+
+ const bool res = QTest::qWaitFor([reply = reply.get()] { return reply->isFinished(); });
+ QVERIFY(res);
+
+ QCOMPARE(reply->readAll(), QByteArray("Hello World!"));
+ QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200);
+}
+
+void tst_QNetworkReply_local::post()
+{
+ std::unique_ptr<MiniHttpServerV2> server = getServerForCurrentScheme();
+ const QUrl url = getUrlForCurrentScheme(server.get());
+
+ QNetworkAccessManager manager;
+ const QByteArray payload = "Hello from the other side!"_ba;
+ QNetworkRequest req(url);
+ req.setHeader(QNetworkRequest::ContentTypeHeader, "text/plain");
+ std::unique_ptr<QNetworkReply> reply(manager.post(req, payload));
+
+ const bool res = QTest::qWaitFor([reply = reply.get()] { return reply->isFinished(); });
+ QVERIFY(res);
+
+ QCOMPARE(reply->readAll(), QByteArray("Hello World!"));
+ QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200);
+
+ auto states = server->peerStates();
+ QCOMPARE(states.size(), 1);
+
+ const auto &firstRequest = states.at(0);
+
+ QVERIFY(firstRequest.checkedContentLength);
+ QCOMPARE(firstRequest.contentLength, payload.size());
+ QCOMPARE_GT(firstRequest.receivedData.size(), payload.size() + 4);
+ QCOMPARE(firstRequest.receivedData.last(payload.size() + 4), "\r\n\r\n" + payload);
+}
+
+#if QT_CONFIG(localserver)
+void tst_QNetworkReply_local::fullServerName_data()
+{
+#if defined(Q_OS_ANDROID) || defined(QT_PLATFORM_UIKIT)
+ QSKIP("While partially supported, the test as-is doesn't make sense on this platform.");
+#else
+
+ QTest::addColumn<QString>("hostAndPath");
+
+ QTest::newRow("dummy-host") << u"://irrelevant/test"_s;
+ QTest::newRow("no-host") << u":///test"_s;
+#endif
+}
+
+void tst_QNetworkReply_local::fullServerName()
+{
+ QFETCH_GLOBAL(QString, scheme);
+ if (!scheme.startsWith("unix"_L1) && !scheme.startsWith("local"_L1))
+ return; // only relevant for local sockets
+
+ MiniHttpServerV2 server;
+ QLocalServer localServer;
+
+ QString path;
+#ifdef Q_OS_WIN
+ path = uR"(\\.\pipe\qt_networkreply_test_fullServerName)"_s
+ % QString::number(QCoreApplication::applicationPid());
+#else
+ path = u"/tmp/qt_networkreply_test_fullServerName"_s
+ % QString::number(QCoreApplication::applicationPid()) % u".sock"_s;
+#endif
+
+ QVERIFY(localServer.listen(path));
+ server.bind(&localServer);
+
+ QFETCH(QString, hostAndPath);
+ QUrl url(scheme % hostAndPath);
+ QNetworkRequest req(url);
+ req.setAttribute(QNetworkRequest::FullLocalServerNameAttribute, path);
+
+ QNetworkAccessManager manager;
+ std::unique_ptr<QNetworkReply> reply(manager.get(req));
+
+ const bool res = QTest::qWaitFor([reply = reply.get()] { return reply->isFinished(); });
+ QVERIFY(res);
+
+ QCOMPARE(reply->readAll(), QByteArray("Hello World!"));
+ QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200);
+
+ const QByteArray receivedData = server.peerStates().at(0).receivedData;
+ const QByteArray expectedGet = "GET " % url.path().toUtf8() % " HTTP/1.1\r\n";
+ QVERIFY(receivedData.startsWith(expectedGet));
+
+ const QByteArray expectedHost = "host: " % url.host().toUtf8() % "\r\n";
+ QVERIFY(receivedData.contains(expectedHost));
+}
+#endif
+
+QTEST_MAIN(tst_QNetworkReply_local)
+
+#include "tst_qnetworkreply_local.moc"
+#include "moc_minihttpserver.cpp"
diff --git a/tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp b/tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp
index 141ca25021..e5bbf3467c 100644
--- a/tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp
+++ b/tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp
@@ -197,6 +197,14 @@ void tst_QNetworkInterface::localAddress_data()
} else if (!ipv6 || entry.prefixLength() != 64) {
continue;
} else {
+#ifdef Q_OS_ANDROID
+ // Android seem to not allow IPv6 connection from interfaces other than wlan,
+ // if it's connected, and wlan is connected by default on Android emulators,
+ // so prefer selecting wlan in this test.
+ const QString scopeId = addr.scopeId();
+ if (!scopeId.isEmpty() && !scopeId.startsWith("wlan"))
+ continue;
+#endif
// add a random node in this IPv6 network
quint64 randomid = qFromBigEndian(Q_UINT64_C(0x8f41f072e5733caa));
QIPv6Address ip6 = addr.toIPv6Address();
diff --git a/tests/auto/other/android_deployment_settings/CMakeLists.txt b/tests/auto/other/android_deployment_settings/CMakeLists.txt
index f2ba135328..9ef457189a 100644
--- a/tests/auto/other/android_deployment_settings/CMakeLists.txt
+++ b/tests/auto/other/android_deployment_settings/CMakeLists.txt
@@ -30,6 +30,7 @@ set_target_properties(${target} PROPERTIES
QT_ANDROID_SDK_BUILD_TOOLS_REVISION "23.0.2"
QT_ANDROID_MIN_SDK_VERSION "1"
QT_ANDROID_TARGET_SDK_VERSION "2"
+ QT_ANDROID_PACKAGE_NAME "org.qtproject.android_deployment_settings_test"
QT_ANDROID_DEPLOYMENT_DEPENDENCIES "dep1.so;dep2.so;dep3.so"
QT_ANDROID_DEPLOYMENT_SETTINGS_FILE "attempt_to_rewrite.json"
QT_ANDROID_EXTRA_LIBS
@@ -53,6 +54,7 @@ set_target_properties(${target} PROPERTIES
QT_ANDROID_SDK_BUILD_TOOLS_REVISION "23.0.2"
QT_ANDROID_MIN_SDK_VERSION "1"
QT_ANDROID_TARGET_SDK_VERSION "2"
+ QT_ANDROID_PACKAGE_NAME "org.qtproject.android_deployment_settings_test"
QT_ANDROID_DEPLOYMENT_DEPENDENCIES "dep1.so;dep2.so;dep3.so"
QT_ANDROID_EXTRA_LIBS
"some/path/to/lib1.so;some/path\\to/lib2.so;some\\path\\to\\lib3.so;some/path/to/lib4.so"
diff --git a/tests/auto/other/android_deployment_settings/tst_android_deployment_settings.cpp b/tests/auto/other/android_deployment_settings/tst_android_deployment_settings.cpp
index d68d08b58e..f8428aaf43 100644
--- a/tests/auto/other/android_deployment_settings/tst_android_deployment_settings.cpp
+++ b/tests/auto/other/android_deployment_settings/tst_android_deployment_settings.cpp
@@ -76,6 +76,8 @@ void tst_android_deployment_settings::DeploymentSettings_data()
<< "1";
QTest::newRow("android-target-sdk-version") << "android-target-sdk-version"
<< "2";
+ QTest::newRow("android-package-name") << "android-package-name"
+ << "org.qtproject.android_deployment_settings_test";
}
void tst_android_deployment_settings::DeploymentSettings()
diff --git a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
index 5fd695e2e6..cab88e2fc0 100644
--- a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
+++ b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
@@ -966,6 +966,13 @@ void tst_QAccessibility::mainWindowTest()
QCOMPARE(iface->text(QAccessible::Name), name);
QCOMPARE(iface->role(), QAccessible::Window);
QVERIFY(iface->state().active);
+
+ QTestAccessibility::clearEvents();
+ QLatin1String newName = QLatin1String("Main window with updated title");
+ mw->setWindowTitle(newName);
+ QCOMPARE(iface->text(QAccessible::Name), QLatin1String(newName));
+ QAccessibleEvent event(mw, QAccessible::NameChanged);
+ QVERIFY(QTestAccessibility::containsEvent(&event));
}
QTestAccessibility::clearEvents();
diff --git a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
index 56fb5cd05f..92bedfab06 100644
--- a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
+++ b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
@@ -256,6 +256,9 @@ private slots:
void ibaseDateTimeWithTZ();
void ibaseTimeStampTzArray_data() { generic_data("QIBASE"); }
void ibaseTimeStampTzArray();
+ void ibaseInt128_data() { generic_data("QIBASE"); }
+ void ibaseInt128();
+
void psqlJsonOperator_data() { generic_data("QPSQL"); }
void psqlJsonOperator();
@@ -1875,52 +1878,54 @@ void tst_QSqlQuery::oci_rawField()
// Test whether we can fetch values with more than DOUBLE precision
// note that SQLite highest precision is that of a double, although
// you can define field with higher precision:
+// Test whether we can fetch values with more than DOUBLE precision
+// note that SQLite highest precision is that of a double, although
+// you can define field with higher precision:
void tst_QSqlQuery::precision()
{
QFETCH(QString, dbName);
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
const QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db);
- if (dbType == QSqlDriver::Interbase)
- QSKIP("DB unable to store high precision");
const auto tidier = qScopeGuard([db, oldPrecision = db.driver()->numericalPrecisionPolicy()]() {
db.driver()->setNumericalPrecisionPolicy(oldPrecision);
});
+ int digits = 21;
+ int decimals = 20;
+ std::array<QLatin1String, 2> precStrings = { "1.2345678901234567891"_L1,
+ "-1.2345678901234567891"_L1 };
+ if (dbType == QSqlDriver::SQLite) {
+ // SQLite 3.45 does not return more, even when speicfied
+ digits = 17;
+ decimals = 16;
+ precStrings = { "1.2345678901234567"_L1, "-1.2345678901234567"_L1 };
+ } else if (dbType == QSqlDriver::Sybase)
+ decimals = 18;
db.driver()->setNumericalPrecisionPolicy(QSql::HighPrecision);
TableScope ts(db, "qtest_precision", __FILE__);
- static const QLatin1String precStr("1.2345678901234567891");
-
- {
- // need a new scope for SQLITE
- QSqlQuery q(db);
- QVERIFY_SQL(q, exec(QLatin1String(tst_Databases::isMSAccess(db)
- ? "CREATE TABLE %1 (col1 number)"
- : "CREATE TABLE %1 (col1 numeric(21, 20))")
- .arg(ts.tableName())));
-
- QVERIFY_SQL(q, exec(QLatin1String("INSERT INTO %1 (col1) VALUES (%2)")
- .arg(ts.tableName(), precStr)));
+ QSqlQuery q(db);
+ QString stmt = "CREATE TABLE %1 (col1 numeric("_L1 + QString::number(digits) + ", "_L1 +
+ QString::number(decimals) + "))"_L1;
+ if (tst_Databases::isMSAccess(db))
+ stmt = "CREATE TABLE %1 (col1 number)"_L1;
+ QVERIFY_SQL(q, exec(stmt.arg(ts.tableName())));
+ for (const auto &precStr : precStrings) {
+ QVERIFY_SQL(q, exec("DELETE FROM %1"_L1.arg(ts.tableName())));
+ QVERIFY_SQL(q, exec("INSERT INTO %1 (col1) VALUES (%2)"_L1.arg(ts.tableName(), precStr)));
QVERIFY_SQL(q, exec("SELECT * FROM " + ts.tableName()));
QVERIFY(q.next());
const QString val = q.value(0).toString();
if (!val.startsWith(precStr)) {
int i = 0;
- while (i < val.size() && precStr[i] != 0 && precStr[i] == val[i].toLatin1())
+ while (i < val.size() && precStr[i] != 0 && precStr[i] == val[i])
++i;
-
- // TDS has crappy precisions by default
- if (dbType == QSqlDriver::Sybase) {
- if (i < 18)
- qWarning("TDS didn't return the right precision");
- } else {
- qWarning() << tst_Databases::dbToString(db) << "didn't return the right precision ("
- << i << "out of 21)," << val;
- }
+ qWarning() << tst_Databases::dbToString(db) << "didn't return the right precision ("
+ << i << "out of " << digits << ")," << val;
}
- } // SQLITE scope
+ }
}
void tst_QSqlQuery::nullResult()
@@ -5034,6 +5039,54 @@ void tst_QSqlQuery::ibaseTimeStampTzArray()
#endif // QT_CONFIG(timezone)
}
+void tst_QSqlQuery::ibaseInt128()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ TableScope ts(db, "int128test", __FILE__);
+ db.setNumericalPrecisionPolicy(QSql::HighPrecision);
+ QSqlQuery q(db);
+ if (!q.exec("CREATE TABLE " + ts.tableName() + " (id INT PRIMARY KEY, price NUMERIC(20, 4))"))
+ QSKIP("Need at least Firebird 4 for this test - skipping");
+
+ QVERIFY_SQL(q, exec("INSERT INTO " + ts.tableName() + "(id,price) values(1,40001.1234)"));
+ QVERIFY_SQL(q, prepare("INSERT INTO " + ts.tableName() + "(id,price) values(2,:amount)"));
+ q.bindValue(":amount", 12345.67890);
+ QVERIFY_SQL(q, exec());
+ {
+ QSqlQuery q2(db);
+ q2.setNumericalPrecisionPolicy(QSql::LowPrecisionDouble);
+ QVERIFY_SQL(q2, exec("SELECT price FROM " + ts.tableName() + " ORDER BY id"));
+ QVERIFY_SQL(q2, next());
+ QCOMPARE(q2.value(0).metaType().id(), QMetaType::Double);
+ QCOMPARE(q2.value(0).toDouble(), 40001.1234);
+ QVERIFY_SQL(q2, next());
+ QCOMPARE(q2.value(0).metaType().id(), QMetaType::Double);
+ QCOMPARE(q2.value(0).toDouble(), 12345.6789);
+ QVERIFY_SQL(q2, exec("SELECT sum(price) FROM " + ts.tableName()));
+ QVERIFY_SQL(q2, next());
+ QCOMPARE(q2.value(0).metaType().id(), QMetaType::Double);
+ QCOMPARE(q2.value(0).toDouble(), 52346.8023);
+ }
+ {
+ QSqlQuery q2(db);
+ q2.setNumericalPrecisionPolicy(QSql::HighPrecision);
+ QVERIFY_SQL(q2, exec("SELECT price FROM " + ts.tableName() + " ORDER BY id"));
+ QVERIFY_SQL(q2, next());
+ QCOMPARE(q2.value(0).metaType().id(), QMetaType::QString);
+ QCOMPARE(q2.value(0).toString(), "40001.1234");
+ QVERIFY_SQL(q2, next());
+ QCOMPARE(q2.value(0).metaType().id(), QMetaType::QString);
+ QCOMPARE(q2.value(0).toString(), "12345.6789");
+ QVERIFY_SQL(q2, exec("SELECT sum(price) FROM " + ts.tableName()));
+ QVERIFY_SQL(q2, next());
+ QCOMPARE(q2.value(0).metaType().id(), QMetaType::QString);
+ QCOMPARE(q2.value(0).toString(), "52346.8023");
+ }
+}
+
void tst_QSqlQuery::ibase_executeBlock()
{
QFETCH(QString, dbName);
diff --git a/tests/auto/testlib/selftests/eventloop/CMakeLists.txt b/tests/auto/testlib/selftests/eventloop/CMakeLists.txt
index 46b794f895..afaf766f69 100644
--- a/tests/auto/testlib/selftests/eventloop/CMakeLists.txt
+++ b/tests/auto/testlib/selftests/eventloop/CMakeLists.txt
@@ -1,3 +1,5 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## eventloop Binary:
#####################################################################
diff --git a/tests/auto/testlib/selftests/failcleanup/CMakeLists.txt b/tests/auto/testlib/selftests/failcleanup/CMakeLists.txt
index 0b582ffdc3..10805ba6f7 100644
--- a/tests/auto/testlib/selftests/failcleanup/CMakeLists.txt
+++ b/tests/auto/testlib/selftests/failcleanup/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (C) 2022 The Qt Company Ltd.
+# Copyright (C) 2024 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
diff --git a/tests/auto/testlib/selftests/failcleanuptestcase/CMakeLists.txt b/tests/auto/testlib/selftests/failcleanuptestcase/CMakeLists.txt
index 1a1417f76c..cb11a577f6 100644
--- a/tests/auto/testlib/selftests/failcleanuptestcase/CMakeLists.txt
+++ b/tests/auto/testlib/selftests/failcleanuptestcase/CMakeLists.txt
@@ -1,3 +1,5 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## failcleanuptestcase Binary:
#####################################################################
diff --git a/tests/auto/testlib/selftests/skipblacklisted/CMakeLists.txt b/tests/auto/testlib/selftests/skipblacklisted/CMakeLists.txt
index cc1a2ff469..0cdcf2c063 100644
--- a/tests/auto/testlib/selftests/skipblacklisted/CMakeLists.txt
+++ b/tests/auto/testlib/selftests/skipblacklisted/CMakeLists.txt
@@ -1,3 +1,5 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## skipblacklisted Binary:
#####################################################################
diff --git a/tests/auto/testlib/selftests/skipcleanuptestcase/CMakeLists.txt b/tests/auto/testlib/selftests/skipcleanuptestcase/CMakeLists.txt
index 88aae42acd..5c531b46b5 100644
--- a/tests/auto/testlib/selftests/skipcleanuptestcase/CMakeLists.txt
+++ b/tests/auto/testlib/selftests/skipcleanuptestcase/CMakeLists.txt
@@ -1,3 +1,5 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## skipcleanuptestcase Binary:
#####################################################################
diff --git a/tests/auto/wasm/selenium/CMakeLists.txt b/tests/auto/wasm/selenium/CMakeLists.txt
index 335b6d23d9..445030878e 100644
--- a/tests/auto/wasm/selenium/CMakeLists.txt
+++ b/tests/auto/wasm/selenium/CMakeLists.txt
@@ -1,3 +1,5 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_qwasmwindow_harness LANGUAGES CXX)
diff --git a/tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp b/tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp
index c91a0803ee..fad75ec045 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp
@@ -2976,11 +2976,6 @@ static QSizeF wfh(Qt::SizeHint /*which*/, const QSizeF &constraint)
return result;
}
-bool qFuzzyCompare(const QSizeF &a, const QSizeF &b)
-{
- return qFuzzyCompare(a.width(), b.width()) && qFuzzyCompare(a.height(), b.height());
-}
-
void tst_QGraphicsGridLayout::heightForWidth()
{
QGraphicsWidget *widget = new QGraphicsWidget;
diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
index 3447c9af28..666cb70da9 100644
--- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
+++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
@@ -477,6 +477,10 @@ private slots:
void reparentWindowHandles_data();
void reparentWindowHandles();
+#ifndef QT_NO_CONTEXTMENU
+ void contextMenuTrigger();
+#endif
+
private:
const QString m_platform;
QSize m_testWidgetSize;
@@ -1898,6 +1902,7 @@ void tst_QWidget::focusChainOnReparent()
}
QWidget window2;
+ child22->setParent(child21);
child2->setParent(&window2);
QWidget *expectedNewChain[5] = {&window2, child2, child21, child22, &window2};
@@ -11149,6 +11154,10 @@ void tst_QWidget::hoverPosition()
QVERIFY(QTest::qWaitForWindowExposed(&root));
const QPoint middle(50, 50);
+ // wait until we got the correct global pos
+ QPoint expectedGlobalPos = root.geometry().topLeft() + QPoint(100, 100) + middle;
+ if (!QTest::qWaitFor([&]{ return expectedGlobalPos == h.mapToGlobal(middle); }))
+ QSKIP("Can't move cursor");
QPoint curpos = h.mapToGlobal(middle);
QCursor::setPos(curpos);
if (!QTest::qWaitFor([curpos]{ return QCursor::pos() == curpos; }))
@@ -14040,5 +14049,41 @@ void tst_QWidget::reparentWindowHandles()
}
}
+#ifndef QT_NO_CONTEXTMENU
+void tst_QWidget::contextMenuTrigger()
+{
+ class ContextMenuWidget : public QWidget
+ {
+ public:
+ int events = 0;
+
+ protected:
+ void contextMenuEvent(QContextMenuEvent *) override { ++events; }
+ };
+
+ const Qt::ContextMenuTrigger wasTrigger = QGuiApplication::styleHints()->contextMenuTrigger();
+ auto restoreTriggerGuard = qScopeGuard([wasTrigger]{
+ QGuiApplication::styleHints()->setContextMenuTrigger(wasTrigger);
+ });
+
+ ContextMenuWidget widget;
+ widget.show();
+ QVERIFY(!qApp->topLevelWindows().empty());
+ auto *window = qApp->topLevelWindows()[0];
+ QVERIFY(window);
+ QCOMPARE(widget.events, 0);
+ QGuiApplication::styleHints()->setContextMenuTrigger(Qt::ContextMenuTrigger::Press);
+ QTest::mousePress(window, Qt::RightButton);
+ QCOMPARE(widget.events, 1);
+ QTest::mouseRelease(window, Qt::RightButton);
+ QCOMPARE(widget.events, 1);
+ QGuiApplication::styleHints()->setContextMenuTrigger(Qt::ContextMenuTrigger::Release);
+ QTest::mousePress(window, Qt::RightButton);
+ QCOMPARE(widget.events, 1);
+ QTest::mouseRelease(window, Qt::RightButton);
+ QCOMPARE(widget.events, 2);
+}
+#endif
+
QTEST_MAIN(tst_QWidget)
#include "tst_qwidget.moc"
diff --git a/tests/auto/xml/CMakeLists.txt b/tests/auto/xml/CMakeLists.txt
index 4b8cc88d78..92ac1870f6 100644
--- a/tests/auto/xml/CMakeLists.txt
+++ b/tests/auto/xml/CMakeLists.txt
@@ -1 +1,3 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
add_subdirectory(dom)
diff --git a/tests/benchmarks/corelib/io/qdir/CMakeLists.txt b/tests/benchmarks/corelib/io/qdir/CMakeLists.txt
index f1800fc0cd..00991de9a9 100644
--- a/tests/benchmarks/corelib/io/qdir/CMakeLists.txt
+++ b/tests/benchmarks/corelib/io/qdir/CMakeLists.txt
@@ -1,2 +1,4 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
add_subdirectory(10000)
add_subdirectory(tree)
diff --git a/tests/benchmarks/corelib/itemmodels/CMakeLists.txt b/tests/benchmarks/corelib/itemmodels/CMakeLists.txt
index cff884ebcc..8dc331aee2 100644
--- a/tests/benchmarks/corelib/itemmodels/CMakeLists.txt
+++ b/tests/benchmarks/corelib/itemmodels/CMakeLists.txt
@@ -1,3 +1,5 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
if(QT_FEATURE_proxymodel)
add_subdirectory(qsortfilterproxymodel)
diff --git a/tests/benchmarks/network/access/qdecompresshelper/main.cpp b/tests/benchmarks/network/access/qdecompresshelper/main.cpp
index 09c24af668..7f8b09ef0e 100644
--- a/tests/benchmarks/network/access/qdecompresshelper/main.cpp
+++ b/tests/benchmarks/network/access/qdecompresshelper/main.cpp
@@ -51,13 +51,14 @@ void tst_QDecompressHelper::decompress()
file.seek(0);
QDecompressHelper helper;
helper.setEncoding(encoding);
+ helper.setDecompressedSafetyCheckThreshold(-1);
QVERIFY(helper.isValid());
helper.feed(file.readAll());
qsizetype bytes = 0;
+ QByteArray out(64 * 1024, Qt::Uninitialized);
while (helper.hasData()) {
- QByteArray out(64 * 1024, Qt::Uninitialized);
qsizetype bytesRead = helper.read(out.data(), out.size());
bytes += bytesRead;
}
diff --git a/tests/manual/android_content_uri/CMakeLists.txt b/tests/manual/android_content_uri/CMakeLists.txt
index 44df410b4f..368e023ba6 100644
--- a/tests/manual/android_content_uri/CMakeLists.txt
+++ b/tests/manual/android_content_uri/CMakeLists.txt
@@ -1,3 +1,5 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(android_content_uri LANGUAGES CXX)
diff --git a/tests/manual/dialogs/wizardpanel.cpp b/tests/manual/dialogs/wizardpanel.cpp
index 6fa7d1803a..5e413960e3 100644
--- a/tests/manual/dialogs/wizardpanel.cpp
+++ b/tests/manual/dialogs/wizardpanel.cpp
@@ -229,7 +229,7 @@ Wizard::Wizard(QWidget *parent, Qt::WindowFlags flags)
addPage(new WizardPage(tr("Page 3"), this));
}
-// A dialog using a Wizard as child widget (emulating Qt Designer).
+// A dialog using a Wizard as child widget (emulating Qt Widgets Designer).
class WizardEmbeddingDialog : public QDialog {
public:
explicit WizardEmbeddingDialog(QWidget *parent = nullptr);
diff --git a/tests/manual/examples/corelib/permissions/android/AndroidManifest.xml b/tests/manual/examples/corelib/permissions/android/AndroidManifest.xml
index ec25a929ae..baf025d4bb 100644
--- a/tests/manual/examples/corelib/permissions/android/AndroidManifest.xml
+++ b/tests/manual/examples/corelib/permissions/android/AndroidManifest.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="org.qtproject.example"
+ package="org.qtproject.example.permissions"
android:installLocation="auto"
android:versionCode="-- %%INSERT_VERSION_CODE%% --"
android:versionName="-- %%INSERT_VERSION_NAME%% --">
@@ -35,7 +35,6 @@
<activity
android:name="org.qtproject.qt.android.bindings.QtActivity"
android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density"
- android:label="-- %%INSERT_APP_NAME%% --"
android:launchMode="singleTop"
android:screenOrientation="unspecified"
android:exported="true">
diff --git a/tests/manual/examples/widgets/richtext/textedit/example.html b/tests/manual/examples/widgets/richtext/textedit/example.html
index ebae3362e9..038f71acfe 100644
--- a/tests/manual/examples/widgets/richtext/textedit/example.html
+++ b/tests/manual/examples/widgets/richtext/textedit/example.html
@@ -19,7 +19,7 @@ hr { height: 1px; border-width: 0; }
<ol style="-qt-list-indent: 1;"><li style=" font-size:11pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Introduction</li>
<li style=" font-size:11pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Qt Tools </li></ol>
<ol type=a style="-qt-list-indent: 2;"><li style=" font-size:11pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Qt Assistant</li>
-<li style=" font-size:11pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Qt Designer</li>
+<li style=" font-size:11pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Qt Widgets Designer</li>
<ol type=A style="-qt-list-indent: 3;"><li style=" font-size:11pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Form Editor</li>
<li style=" font-size:11pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Component Architecture</li></ol>
<li style=" font-size:11pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Qt Linguist</li></ol>
@@ -64,7 +64,7 @@ hr { height: 1px; border-width: 0; }
<td>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">13:00 - 15:00 </span></p></td>
<td>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-style:italic;">Qt Designer</span> Tutorial </p></td>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-style:italic;">Qt Widgets Designer</span> Tutorial </p></td>
<td rowspan="2">
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Extreme Programming </p></td>
<td>
diff --git a/tests/manual/examples/widgets/richtext/textedit/example.md b/tests/manual/examples/widgets/richtext/textedit/example.md
index 15f3c3cacf..8a5eed72f6 100644
--- a/tests/manual/examples/widgets/richtext/textedit/example.md
+++ b/tests/manual/examples/widgets/richtext/textedit/example.md
@@ -43,7 +43,7 @@ numerals in the same list structure:
1. Introduction
2. Qt Tools
1) Qt Assistant
- 2) Qt Designer
+ 2) Qt Widgets Designer
1. Form Editor
2. Component Architecture
3) Qt Linguist
@@ -78,7 +78,7 @@ column spans, text formatting within cells, and size constraints for columns.
| ------------: | ----------------- | ---------------------- | ------------------------- |
| 9:00 - 11:00 | Introduction to Qt |||
| 11:00 - 13:00 | Using qmake | Object-oriented Programming | Layouts in Qt |
-| 13:00 - 15:00 | Qt Designer Tutorial | Extreme Programming | Writing Custom Styles |
+| 13:00 - 15:00 | Qt Widgets Designer Tutorial | Extreme Programming | Writing Custom Styles |
| 15:00 - 17:00 | Qt Linguist and Internationalization | &nbsp; | &nbsp; |
*Try adding text to the cells in the table and experiment with the alignment of
diff --git a/tests/manual/examples/widgets/scroller/CMakeLists.txt b/tests/manual/examples/widgets/scroller/CMakeLists.txt
index fb9ebc2848..cd920bd361 100644
--- a/tests/manual/examples/widgets/scroller/CMakeLists.txt
+++ b/tests/manual/examples/widgets/scroller/CMakeLists.txt
@@ -1 +1,3 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
qt_internal_add_example(graphicsview)
diff --git a/tests/manual/examples/widgets/tools/plugandpaint/plugins/CMakeLists.txt b/tests/manual/examples/widgets/tools/plugandpaint/plugins/CMakeLists.txt
index 9a2d66d99e..c468cdc191 100644
--- a/tests/manual/examples/widgets/tools/plugandpaint/plugins/CMakeLists.txt
+++ b/tests/manual/examples/widgets/tools/plugandpaint/plugins/CMakeLists.txt
@@ -1,2 +1,4 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
add_subdirectory(basictools)
add_subdirectory(extrafilters)
diff --git a/tests/manual/highdpi/CMakeLists.txt b/tests/manual/highdpi/CMakeLists.txt
index d32e2a52fc..1d5d0ad1ff 100644
--- a/tests/manual/highdpi/CMakeLists.txt
+++ b/tests/manual/highdpi/CMakeLists.txt
@@ -1,3 +1,5 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
add_subdirectory(dprgadget)
add_subdirectory(kitchensink)
diff --git a/tests/manual/highdpi/dprgadget/CMakeLists.txt b/tests/manual/highdpi/dprgadget/CMakeLists.txt
index 2c6bd91f0d..5cd0d5812e 100644
--- a/tests/manual/highdpi/dprgadget/CMakeLists.txt
+++ b/tests/manual/highdpi/dprgadget/CMakeLists.txt
@@ -1,3 +1,5 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## dprgadget Binary:
diff --git a/tests/manual/highdpi/kitchensink/CMakeLists.txt b/tests/manual/highdpi/kitchensink/CMakeLists.txt
index 8caf85983e..e7558c19e0 100644
--- a/tests/manual/highdpi/kitchensink/CMakeLists.txt
+++ b/tests/manual/highdpi/kitchensink/CMakeLists.txt
@@ -1,3 +1,5 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## kitchensink Binary:
diff --git a/tests/manual/highdpi/pixelgadget/CMakeLists.txt b/tests/manual/highdpi/pixelgadget/CMakeLists.txt
index 2cc04225df..f808786b2a 100644
--- a/tests/manual/highdpi/pixelgadget/CMakeLists.txt
+++ b/tests/manual/highdpi/pixelgadget/CMakeLists.txt
@@ -1,3 +1,5 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## pixelgadget Binary:
diff --git a/tests/manual/highdpi/screengadget/CMakeLists.txt b/tests/manual/highdpi/screengadget/CMakeLists.txt
index d9045541bb..f4a7aad306 100644
--- a/tests/manual/highdpi/screengadget/CMakeLists.txt
+++ b/tests/manual/highdpi/screengadget/CMakeLists.txt
@@ -1,3 +1,5 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## screengadget Binary:
diff --git a/tests/manual/inputdevices/CMakeLists.txt b/tests/manual/inputdevices/CMakeLists.txt
index 9440705a9b..54dd2556fb 100644
--- a/tests/manual/inputdevices/CMakeLists.txt
+++ b/tests/manual/inputdevices/CMakeLists.txt
@@ -1,3 +1,5 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
project(inputdevices)
cmake_minimum_required(VERSION 3.19)
diff --git a/tests/manual/permissions/android/AndroidManifest.xml b/tests/manual/permissions/android/AndroidManifest.xml
index 041c920ad1..db577e6c27 100644
--- a/tests/manual/permissions/android/AndroidManifest.xml
+++ b/tests/manual/permissions/android/AndroidManifest.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="org.qtproject.example"
+ package="org.qtproject.example.tst_manual_permissions"
android:installLocation="auto"
android:versionCode="-- %%INSERT_VERSION_CODE%% --"
android:versionName="-- %%INSERT_VERSION_NAME%% --">
@@ -31,7 +31,6 @@
<activity
android:name="org.qtproject.qt.android.bindings.QtActivity"
android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density"
- android:label="-- %%INSERT_APP_NAME%% --"
android:launchMode="singleTop"
android:screenOrientation="unspecified"
android:exported="true">
diff --git a/tests/manual/rhi/hdr/CMakeLists.txt b/tests/manual/rhi/hdr/CMakeLists.txt
index cf6e7662a4..dc7bcb906c 100644
--- a/tests/manual/rhi/hdr/CMakeLists.txt
+++ b/tests/manual/rhi/hdr/CMakeLists.txt
@@ -1,3 +1,5 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
qt_internal_add_manual_test(hdr
GUI
SOURCES
diff --git a/tests/manual/rhi/imguirenderer/CMakeLists.txt b/tests/manual/rhi/imguirenderer/CMakeLists.txt
index 619c351d7f..8c04918d06 100644
--- a/tests/manual/rhi/imguirenderer/CMakeLists.txt
+++ b/tests/manual/rhi/imguirenderer/CMakeLists.txt
@@ -1,3 +1,5 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
qt_internal_add_manual_test(imguirenderer
GUI
SOURCES
diff --git a/tests/manual/wasm/a11y/CMakeLists.txt b/tests/manual/wasm/a11y/CMakeLists.txt
index 5268d53c8b..dee39e1f5f 100644
--- a/tests/manual/wasm/a11y/CMakeLists.txt
+++ b/tests/manual/wasm/a11y/CMakeLists.txt
@@ -1,3 +1,5 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
if(QT_FEATURE_widgets)
add_subdirectory(basic_widgets)
endif()
diff --git a/tests/manual/wasm/a11y/basic_widgets/CMakeLists.txt b/tests/manual/wasm/a11y/basic_widgets/CMakeLists.txt
index 11534bdf68..a028f96e1c 100644
--- a/tests/manual/wasm/a11y/basic_widgets/CMakeLists.txt
+++ b/tests/manual/wasm/a11y/basic_widgets/CMakeLists.txt
@@ -1,3 +1,5 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
qt_internal_add_manual_test(a11y_basic_widgets
GUI
SOURCES
diff --git a/tests/manual/wasm/eventloop/eventloop_auto/CMakeLists.txt b/tests/manual/wasm/eventloop/eventloop_auto/CMakeLists.txt
index 9bfa875be7..88ddfac4c8 100644
--- a/tests/manual/wasm/eventloop/eventloop_auto/CMakeLists.txt
+++ b/tests/manual/wasm/eventloop/eventloop_auto/CMakeLists.txt
@@ -1,3 +1,5 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
include_directories(../../qtwasmtestlib/)
# default buid
diff --git a/tests/manual/wasm/network/echo_client_mainthread/CMakeLists.txt b/tests/manual/wasm/network/echo_client_mainthread/CMakeLists.txt
index 05416c0b66..4b81661c79 100644
--- a/tests/manual/wasm/network/echo_client_mainthread/CMakeLists.txt
+++ b/tests/manual/wasm/network/echo_client_mainthread/CMakeLists.txt
@@ -1,3 +1,5 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
qt_internal_add_manual_test(echo_client_mainthread
GUI
SOURCES
diff --git a/tests/manual/wasm/network/echo_client_secondarythread/CMakeLists.txt b/tests/manual/wasm/network/echo_client_secondarythread/CMakeLists.txt
index a1f2bef254..d240e9e70b 100644
--- a/tests/manual/wasm/network/echo_client_secondarythread/CMakeLists.txt
+++ b/tests/manual/wasm/network/echo_client_secondarythread/CMakeLists.txt
@@ -1,3 +1,5 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
qt_internal_add_manual_test(echo_client_secondarythread
GUI
SOURCES
diff --git a/tests/manual/wasm/network/echo_server/CMakeLists.txt b/tests/manual/wasm/network/echo_server/CMakeLists.txt
index cf98163fb8..72ec413a0e 100644
--- a/tests/manual/wasm/network/echo_server/CMakeLists.txt
+++ b/tests/manual/wasm/network/echo_server/CMakeLists.txt
@@ -1,3 +1,5 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
project(echo_server)
cmake_minimum_required(VERSION 3.19)
diff --git a/tests/manual/wasm/network/sockify_sockets_auto/CMakeLists.txt b/tests/manual/wasm/network/sockify_sockets_auto/CMakeLists.txt
index fb9a9f8543..68a3993778 100644
--- a/tests/manual/wasm/network/sockify_sockets_auto/CMakeLists.txt
+++ b/tests/manual/wasm/network/sockify_sockets_auto/CMakeLists.txt
@@ -1,3 +1,5 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
qt_internal_add_manual_test(sockify_sockets_auto
SOURCES
main.cpp
diff --git a/tests/manual/wasm/qstdweb/CMakeLists.txt b/tests/manual/wasm/qstdweb/CMakeLists.txt
index 5242999ec4..39039c3910 100644
--- a/tests/manual/wasm/qstdweb/CMakeLists.txt
+++ b/tests/manual/wasm/qstdweb/CMakeLists.txt
@@ -1,3 +1,5 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
qt_internal_add_manual_test(promise_auto
SOURCES
promise_main.cpp
@@ -94,4 +96,3 @@ add_custom_command(
${CMAKE_CURRENT_BINARY_DIR}/qtwasmtestlib.js)
target_link_options(iodevices_auto PRIVATE -sASYNCIFY -Os)
-
diff --git a/tests/manual/xembed/CMakeLists.txt b/tests/manual/xembed/CMakeLists.txt
index f486f202a5..44bb2ea818 100644
--- a/tests/manual/xembed/CMakeLists.txt
+++ b/tests/manual/xembed/CMakeLists.txt
@@ -1,3 +1,5 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
if(QT_FEATURE_gtk3)
add_subdirectory(gtk-container)
diff --git a/tests/manual/xembed/gtk-container/CMakeLists.txt b/tests/manual/xembed/gtk-container/CMakeLists.txt
index c109bbc95b..34a802c142 100644
--- a/tests/manual/xembed/gtk-container/CMakeLists.txt
+++ b/tests/manual/xembed/gtk-container/CMakeLists.txt
@@ -1,3 +1,5 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
qt_find_package(GTK3)
qt_find_package(X11)
diff --git a/tests/testserver/echo/echo.sh b/tests/testserver/echo/echo.sh
index 516b476357..d8fedb1a89 100755
--- a/tests/testserver/echo/echo.sh
+++ b/tests/testserver/echo/echo.sh
@@ -1,6 +1,6 @@
+#!/usr/bin/env bash
# Copyright (C) 2024 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-#!/usr/bin/env bash
# Disabled by default, enable it.
sed -i 's/disable\t\t= yes/disable = no/' /etc/xinetd.d/echo
diff --git a/util/edid/qedidvendortable.py b/util/edid/qedidvendortable.py
index e1c5750695..0991d75db7 100755
--- a/util/edid/qedidvendortable.py
+++ b/util/edid/qedidvendortable.py
@@ -8,12 +8,12 @@ import urllib.request
# 'https://git.fedorahosted.org/cgit/hwdata.git/plain/pnp.ids'
# which is discontinued. For now there seems to be a fork at:
url = 'https://github.com/vcrhonek/hwdata/raw/master/pnp.ids'
-
+# REUSE-IgnoreStart
copyright = """
// Copyright (C) 2017 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
"""
-
+# REUSE-IgnoreEnd
notice = """/*
* This lookup table was generated from {}
*
diff --git a/util/gradientgen/gradientgen.cpp b/util/gradientgen/gradientgen.cpp
index a4c5531cc5..23b20d0505 100644
--- a/util/gradientgen/gradientgen.cpp
+++ b/util/gradientgen/gradientgen.cpp
@@ -17,13 +17,13 @@
#include <QColor>
using namespace std;
-
+// REUSE-IgnoreStart
static const char LICENSE_HEADER[] =
R"(
// Copyright (C) 2019 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
)";
-
+// REUSE-IgnoreEnd
class Printer {
Q_DISABLE_COPY_MOVE(Printer)
public:
diff --git a/util/locale_database/cldr.py b/util/locale_database/cldr.py
index 9e0bae9667..b610a1cfec 100644
--- a/util/locale_database/cldr.py
+++ b/util/locale_database/cldr.py
@@ -405,6 +405,59 @@ enumdata.py (keeping the old name as an alias):
+ '\n')
grumble('\n')
+ def bcp47Aliases(self):
+ """Reads the mapping from CLDR IDs to IANA IDs
+
+ CLDR identifies timezones in various ways but its standard
+ 'name' for them, here described as a CLDR ID, has the form of
+ an IANA ID. CLDR IDs are stable across time, where IANA IDs
+ may be revised over time, for example Asia/Calcutta became
+ Asia/Kolkata. When a new zone is added to CLDR, it gets the
+ then-current IANA ID as its CLDR ID; if it is later
+ superseded, CLDR continues using the old ID, so we need a
+ mapping from that to current IANA IDs. Helpfully, CLDR
+ provides information about aliasing among time-zone IDs.
+
+ The file common/bcp47/timezone.xml has keyword/key/type
+ elements with attributes:
+
+ name -- zone code (ignore)
+ description -- long name for exemplar location, including
+ territory
+
+ and some of:
+
+ deprecated -- ignore entry if present (has no alias)
+ preferred -- only present if deprecated
+ since -- version at which this entry was added (ignore)
+ alias -- space-joined sequence of IANA-form IDs; first is CLDR ID
+ iana -- if present, repeats the alias entry that's the modern IANA ID
+
+ This returns a pair (alias, naming) wherein: alias is a
+ mapping from IANA-format IDs to actual IANA IDs, that maps
+ each alias to the contemporary ID used by IANA; and naming is
+ a mapping from IANA ID to the description it and its aliases
+ shared in their keyword/key/type entry."""
+ # File has the same form as supplements:
+ root = Supplement(Node(self.__xml('common/bcp47/timezone.xml')))
+
+ # If we ever need a mapping back to CLDR ID, we can make
+ # (description, space-joined-list) the naming values.
+ alias, naming = {}, {} # { alias: iana }, { iana: description }
+ for item, attrs in root.find('keyword/key/type', exclude=('deprecated',)):
+ assert 'description' in attrs, item
+ assert 'alias' in attrs, item
+ names = attrs['alias'].split()
+ assert not any(name in alias for name in names), item
+ # CLDR ID is names[0]; if IANA now uses another name for
+ # it, this is given as the iana attribute.
+ ianaid, fullName = attrs.get('iana', names[0]), attrs['description']
+ alias.update({name: ianaid for name in names})
+ assert not ianaid in naming
+ naming[ianaid] = fullName
+
+ return alias, naming
+
def readWindowsTimeZones(self, lookup): # For use by cldr2qtimezone.py
"""Digest CLDR's MS-Win time-zone name mapping.
diff --git a/util/locale_database/cldr2qtimezone.py b/util/locale_database/cldr2qtimezone.py
index 485177c0bd..a2ee301929 100755
--- a/util/locale_database/cldr2qtimezone.py
+++ b/util/locale_database/cldr2qtimezone.py
@@ -48,17 +48,18 @@ class ByteArrayData:
class ZoneIdWriter (SourceFileEditor):
# All the output goes into namespace QtTimeZoneCldr.
- def write(self, version, defaults, windowsIds):
+ def write(self, version, alias, defaults, windowsIds):
self.__writeWarning(version)
- windows, iana = self.__writeTables(self.writer.write, defaults, windowsIds)
+ windows, iana, aliased = self.__writeTables(self.writer.write, alias, defaults, windowsIds)
windows.write(self.writer.write, 'windowsIdData')
iana.write(self.writer.write, 'ianaIdData')
+ aliased.write(self.writer.write, 'aliasIdData')
def __writeWarning(self, version):
self.writer.write(f"""
/*
This part of the file was generated on {datetime.date.today()} from the
- Common Locale Data Repository v{version} file supplemental/windowsZones.xml
+ Common Locale Data Repository v{version}
http://www.unicode.org/cldr/
@@ -69,8 +70,19 @@ class ZoneIdWriter (SourceFileEditor):
""")
@staticmethod
- def __writeTables(out, defaults, windowsIds):
- windowsIdData, ianaIdData = ByteArrayData(), ByteArrayData()
+ def __writeTables(out, alias, defaults, windowsIds):
+ aliasIdData = ByteArrayData()
+ ianaIdData, windowsIdData = ByteArrayData(), ByteArrayData()
+
+ # Write IANA alias table
+ out('// Alias ID Index, Alias ID Index\n')
+ out('static constexpr AliasData aliasMappingTable[] = {\n')
+ for name, iana in sorted(alias.items()):
+ if name != iana:
+ out(' {{ {:6d},{:6d} }}, // {} -> {}\n'.format(
+ aliasIdData.append(name),
+ aliasIdData.append(iana), name, iana))
+ out('};\n\n')
# Write Windows/IANA table
out('// Windows ID Key, Territory Enum, IANA ID Index\n')
@@ -111,7 +123,7 @@ class ZoneIdWriter (SourceFileEditor):
ianaIdData.append(' '.join(names)), offset, names[0]))
out('};\n')
- return windowsIdData, ianaIdData
+ return windowsIdData, ianaIdData, aliasIdData
def main(out, err):
@@ -145,9 +157,23 @@ def main(out, err):
if not dataFilePath.is_file():
parser.error(f'No such file: {dataFilePath}')
+ access = CldrAccess(cldrPath)
+ try:
+ alias, ignored = access.bcp47Aliases()
+ # TODO: ignored maps IANA IDs to an extra-long name of the zone
+ except IOError as e:
+ parser.error(
+ f'Failed to open common/bcp47/timezone.xml: {e}')
+ return 1
+ except Error as e:
+ err.write('\n'.join(textwrap.wrap(
+ f'Failed to read bcp47/timezone.xml: {e}',
+ subsequent_indent=' ', width=80)) + '\n')
+ return 1
+
try:
- version, defaults, winIds = CldrAccess(cldrPath).readWindowsTimeZones(
- dict((name, ind) for ind, name in enumerate((x[0] for x in windowsIdList), 1)))
+ version, defaults, winIds = access.readWindowsTimeZones(
+ {name: ind for ind, name in enumerate((x[0] for x in windowsIdList), 1)})
except IOError as e:
parser.error(
f'Failed to open common/supplemental/windowsZones.xml: {e}')
@@ -158,11 +184,11 @@ def main(out, err):
subsequent_indent=' ', width=80)) + '\n')
return 1
- out.write('Input file parsed, now writing data\n')
+ out.write('Input files parsed, now writing data\n')
try:
with ZoneIdWriter(dataFilePath, qtPath) as writer:
- writer.write(version, defaults, winIds)
+ writer.write(version, alias, defaults, winIds)
except Exception as e:
err.write(f'\nError while updating timezone data: {e}\n')
return 1