diff options
Diffstat (limited to 'src')
396 files changed, 4443 insertions, 1935 deletions
diff --git a/src/3rdparty/freetype/REUSE.toml b/src/3rdparty/freetype/REUSE.toml index f2fc6b3e2bc..6cc074c1947 100644 --- a/src/3rdparty/freetype/REUSE.toml +++ b/src/3rdparty/freetype/REUSE.toml @@ -10,5 +10,5 @@ SPDX-License-Identifier = "FTL OR GPL-2.0-only" path = ["CMakeLists.txt"] precedence = "override" SPDX-FileCopyrightText = ["Copyright (C) 2013-2024 by David Turner, Robert Wilhelm, and Werner Lemberg.", -"Copyright (C) 2024 The Qt Company Ltd."] +"Copyright (C) The Qt Company Ltd."] SPDX-License-Identifier = "FTL OR GPL-2.0-only" diff --git a/src/3rdparty/freetype/docs/REUSE.toml b/src/3rdparty/freetype/docs/REUSE.toml index 873ff919050..84576882473 100644 --- a/src/3rdparty/freetype/docs/REUSE.toml +++ b/src/3rdparty/freetype/docs/REUSE.toml @@ -46,5 +46,5 @@ SPDX-License-Identifier = "GPL-2.0-only" path = "REUSE.toml" comment = "The copyrights inside those files are not related to the file" precedence = "override" -SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." +SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd." SPDX-License-Identifier = "BSD-3-Clause" diff --git a/src/3rdparty/freetype/src/pcf/REUSE.toml b/src/3rdparty/freetype/src/pcf/REUSE.toml index 4eecd7a22bc..52d5b551e34 100644 --- a/src/3rdparty/freetype/src/pcf/REUSE.toml +++ b/src/3rdparty/freetype/src/pcf/REUSE.toml @@ -24,5 +24,5 @@ SPDX-License-Identifier = "FTL OR GPL-2.0-only" path = ["REUSE.toml"] comment = "The copyrights inside those files are not related to the file" precedence = "override" -SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." +SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd." SPDX-License-Identifier = "BSD-3-Clause" diff --git a/src/3rdparty/freetype/src/sdf/REUSE.toml b/src/3rdparty/freetype/src/sdf/REUSE.toml index f25732fce90..ff7ddb872db 100644 --- a/src/3rdparty/freetype/src/sdf/REUSE.toml +++ b/src/3rdparty/freetype/src/sdf/REUSE.toml @@ -11,5 +11,5 @@ SPDX-License-Identifier = "FTL OR GPL-2.0-only" path = "REUSE.toml" comment = "The copyrights inside those files are not related to the file" precedence = "override" -SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." +SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd." SPDX-License-Identifier = "BSD-3-Clause" diff --git a/src/3rdparty/gradle/gradle.properties b/src/3rdparty/gradle/gradle.properties index 4fe1674abd3..3472b396d96 100644 --- a/src/3rdparty/gradle/gradle.properties +++ b/src/3rdparty/gradle/gradle.properties @@ -16,3 +16,6 @@ org.gradle.parallel=true # Allow AndroidX usage android.useAndroidX=true + +# User-defined properties +@EXTRA_PROPERTIES@ diff --git a/src/3rdparty/libpng/ANNOUNCE b/src/3rdparty/libpng/ANNOUNCE index 90c766594e7..516e078082d 100644 --- a/src/3rdparty/libpng/ANNOUNCE +++ b/src/3rdparty/libpng/ANNOUNCE @@ -1,5 +1,5 @@ -libpng 1.6.49 - June 12, 2025 -============================= +libpng 1.6.50 - July 1, 2025 +============================ This is a public release of libpng, intended for use in production code. @@ -9,13 +9,13 @@ Files available for download Source files with LF line endings (for Unix/Linux): - * libpng-1.6.49.tar.xz (LZMA-compressed, recommended) - * libpng-1.6.49.tar.gz (deflate-compressed) + * libpng-1.6.50.tar.xz (LZMA-compressed, recommended) + * libpng-1.6.50.tar.gz (deflate-compressed) Source files with CRLF line endings (for Windows): - * lpng1649.7z (LZMA-compressed, recommended) - * lpng1649.zip (deflate-compressed) + * lpng1650.7z (LZMA-compressed, recommended) + * lpng1650.zip (deflate-compressed) Other information: @@ -25,13 +25,18 @@ Other information: * TRADEMARK.md -Changes from version 1.6.48 to version 1.6.49 +Changes from version 1.6.49 to version 1.6.50 --------------------------------------------- - * Added SIMD-optimized code for the RISC-V Vector Extension (RVV). - (Contributed by Manfred Schlaegl, Dragos Tiselice and Filip Wasil) - * Added various fixes and improvements to the build scripts and to - the sample code. + * Improved the detection of the RVV Extension on the RISC-V platform. + (Contributed by Filip Wasil) + * Replaced inline ASM with C intrinsics in the RVV code. + (Contributed by Filip Wasil) + * Fixed a decoder defect in which unknown chunks trailing IDAT, set + to go through the unknown chunk handler, incorrectly triggered + out-of-place IEND errors. + (Contributed by John Bowler) + * Fixed the CMake file for cross-platform builds that require `libm`. Send comments/corrections/commendations to png-mng-implement at lists.sf.net. diff --git a/src/3rdparty/libpng/CHANGES b/src/3rdparty/libpng/CHANGES index 0c0fa6dc70b..b6499b1f34c 100644 --- a/src/3rdparty/libpng/CHANGES +++ b/src/3rdparty/libpng/CHANGES @@ -6267,6 +6267,17 @@ Version 1.6.49 [June 12, 2025] Added various fixes and improvements to the build scripts and to the sample code. +Version 1.6.50 [July 1, 2025] + Improved the detection of the RVV Extension on the RISC-V platform. + (Contributed by Filip Wasil) + Replaced inline ASM with C intrinsics in the RVV code. + (Contributed by Filip Wasil) + Fixed a decoder defect in which unknown chunks trailing IDAT, set + to go through the unknown chunk handler, incorrectly triggered + out-of-place IEND errors. + (Contributed by John Bowler) + Fixed the CMake file for cross-platform builds that require `libm`. + Send comments/corrections/commendations to png-mng-implement at lists.sf.net. Subscription is required; visit https://lists.sourceforge.net/lists/listinfo/png-mng-implement diff --git a/src/3rdparty/libpng/README b/src/3rdparty/libpng/README index 9f2b2d0ed53..2eb633ac0fb 100644 --- a/src/3rdparty/libpng/README +++ b/src/3rdparty/libpng/README @@ -1,4 +1,4 @@ -README for libpng version 1.6.49 +README for libpng version 1.6.50 ================================ See the note about version numbers near the top of `png.h`. diff --git a/src/3rdparty/libpng/libpng-manual.txt b/src/3rdparty/libpng/libpng-manual.txt index f4e151f0c23..6c07e1022b6 100644 --- a/src/3rdparty/libpng/libpng-manual.txt +++ b/src/3rdparty/libpng/libpng-manual.txt @@ -9,7 +9,7 @@ libpng-manual.txt - A description on how to use and modify libpng Based on: - libpng version 1.6.36, December 2018, through 1.6.49 - June 2025 + libpng version 1.6.36, December 2018, through 1.6.50 - July 2025 Updated and distributed by Cosmin Truta Copyright (c) 2018-2025 Cosmin Truta @@ -65,18 +65,22 @@ Libpng was written as a companion to the PNG specification, as a way of reducing the amount of time and effort it takes to support the PNG file format in application programs. -The PNG specification (second edition), November 2003, is available as +The PNG specification (Third Edition), June 2025, is available as +a W3C Recommendation at +<https://www.w3.org/TR/2025/REC-png-3-20250624/>. + +The PNG specification (Second Edition), November 2003, is available as a W3C Recommendation and as an ISO Standard (ISO/IEC 15948:2004 (E)) at <https://www.w3.org/TR/2003/REC-PNG-20031110/>. The W3C and ISO documents have identical technical content. The PNG-1.2 specification is available at -<https://png-mng.sourceforge.io/pub/png/spec/1.2/>. -It is technically equivalent -to the PNG specification (second edition) but has some additional material. +<https://www.libpng.org/pub/png/spec/1.2/>. +It is technically equivalent to the PNG specification (Second Edition) +but has some additional material. The PNG-1.0 specification is available as RFC 2083 at -<https://png-mng.sourceforge.io/pub/png/spec/1.0/> and as a +<https://www.libpng.org/pub/png/spec/1.0/> and as a W3C Recommendation at <https://www.w3.org/TR/REC-png-961001>. Some additional chunks are described in the special-purpose public chunks diff --git a/src/3rdparty/libpng/png.c b/src/3rdparty/libpng/png.c index 8a77b6db5f2..6e21915c402 100644 --- a/src/3rdparty/libpng/png.c +++ b/src/3rdparty/libpng/png.c @@ -13,7 +13,7 @@ #include "pngpriv.h" /* Generate a compiler error if there is an old png.h in the search path. */ -typedef png_libpng_version_1_6_49 Your_png_h_is_not_version_1_6_49; +typedef png_libpng_version_1_6_50 Your_png_h_is_not_version_1_6_50; /* Sanity check the chunks definitions - PNG_KNOWN_CHUNKS from pngpriv.h and the * corresponding macro definitions. This causes a compile time failure if @@ -815,7 +815,7 @@ png_get_copyright(png_const_structrp png_ptr) return PNG_STRING_COPYRIGHT #else return PNG_STRING_NEWLINE \ - "libpng version 1.6.49" PNG_STRING_NEWLINE \ + "libpng version 1.6.50" PNG_STRING_NEWLINE \ "Copyright (c) 2018-2025 Cosmin Truta" PNG_STRING_NEWLINE \ "Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson" \ PNG_STRING_NEWLINE \ diff --git a/src/3rdparty/libpng/png.h b/src/3rdparty/libpng/png.h index f43e49c521a..b9985e81680 100644 --- a/src/3rdparty/libpng/png.h +++ b/src/3rdparty/libpng/png.h @@ -1,6 +1,6 @@ /* png.h - header file for PNG reference library * - * libpng version 1.6.49 + * libpng version 1.6.50 * * Copyright (c) 2018-2025 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson @@ -14,7 +14,7 @@ * libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger * libpng versions 0.97, January 1998, through 1.6.35, July 2018: * Glenn Randers-Pehrson - * libpng versions 1.6.36, December 2018, through 1.6.49, June 2025: + * libpng versions 1.6.36, December 2018, through 1.6.50, July 2025: * Cosmin Truta * See also "Contributing Authors", below. */ @@ -238,7 +238,7 @@ * ... * 1.5.30 15 10530 15.so.15.30[.0] * ... - * 1.6.49 16 10649 16.so.16.49[.0] + * 1.6.50 16 10650 16.so.16.50[.0] * * Henceforth the source version will match the shared-library major and * minor numbers; the shared-library major version number will be used for @@ -274,7 +274,7 @@ */ /* Version information for png.h - this should match the version in png.c */ -#define PNG_LIBPNG_VER_STRING "1.6.49" +#define PNG_LIBPNG_VER_STRING "1.6.50" #define PNG_HEADER_VERSION_STRING " libpng version " PNG_LIBPNG_VER_STRING "\n" /* The versions of shared library builds should stay in sync, going forward */ @@ -285,7 +285,7 @@ /* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */ #define PNG_LIBPNG_VER_MAJOR 1 #define PNG_LIBPNG_VER_MINOR 6 -#define PNG_LIBPNG_VER_RELEASE 49 +#define PNG_LIBPNG_VER_RELEASE 50 /* This should be zero for a public release, or non-zero for a * development version. @@ -316,7 +316,7 @@ * From version 1.0.1 it is: * XXYYZZ, where XX=major, YY=minor, ZZ=release */ -#define PNG_LIBPNG_VER 10649 /* 1.6.49 */ +#define PNG_LIBPNG_VER 10650 /* 1.6.50 */ /* Library configuration: these options cannot be changed after * the library has been built. @@ -426,7 +426,7 @@ extern "C" { /* This triggers a compiler error in png.c, if png.c and png.h * do not agree upon the version number. */ -typedef char* png_libpng_version_1_6_49; +typedef char* png_libpng_version_1_6_50; /* Basic control structions. Read libpng-manual.txt or libpng.3 for more info. * diff --git a/src/3rdparty/libpng/pngconf.h b/src/3rdparty/libpng/pngconf.h index e92a3b1eca4..d1081b54ddd 100644 --- a/src/3rdparty/libpng/pngconf.h +++ b/src/3rdparty/libpng/pngconf.h @@ -1,6 +1,6 @@ /* pngconf.h - machine-configurable file for libpng * - * libpng version 1.6.49 + * libpng version 1.6.50 * * Copyright (c) 2018-2025 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson diff --git a/src/3rdparty/libpng/pnglibconf.h b/src/3rdparty/libpng/pnglibconf.h index ea61c441ba6..f15fc16dade 100644 --- a/src/3rdparty/libpng/pnglibconf.h +++ b/src/3rdparty/libpng/pnglibconf.h @@ -1,6 +1,6 @@ /* pnglibconf.h - library build configuration */ -/* libpng version 1.6.49 */ +/* libpng version 1.6.50 */ /* Copyright (c) 2018-2025 Cosmin Truta */ /* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson */ diff --git a/src/3rdparty/libpng/pngpread.c b/src/3rdparty/libpng/pngpread.c index 0a3e822cf47..37aa432aeca 100644 --- a/src/3rdparty/libpng/pngpread.c +++ b/src/3rdparty/libpng/pngpread.c @@ -229,6 +229,14 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr) png_benign_error(png_ptr, "Too many IDATs found"); } + else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0) + { + /* These flags must be set consistently for all non-IDAT chunks, + * including the unknown chunks. + */ + png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT | PNG_AFTER_IDAT; + } + if (chunk_name == png_IHDR) { if (png_ptr->push_length != 13) diff --git a/src/3rdparty/libpng/pngpriv.h b/src/3rdparty/libpng/pngpriv.h index cb44a6aec8a..e3054b90aae 100644 --- a/src/3rdparty/libpng/pngpriv.h +++ b/src/3rdparty/libpng/pngpriv.h @@ -154,11 +154,7 @@ * to configure or put -DPNG_RISCV_RVV_OPT=2 in CPPFLAGS. */ -# if defined(__riscv) && defined(PNG_ALIGNED_MEMORY_SUPPORTED) -# define PNG_RISCV_RVV_OPT 1 -# else -# define PNG_RISCV_RVV_OPT 0 -# endif +# define PNG_RISCV_RVV_OPT 0 #endif #if PNG_ARM_NEON_OPT > 0 diff --git a/src/3rdparty/libpng/pngread.c b/src/3rdparty/libpng/pngread.c index a0dbf2ae208..212afb7d215 100644 --- a/src/3rdparty/libpng/pngread.c +++ b/src/3rdparty/libpng/pngread.c @@ -702,7 +702,12 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr) png_uint_32 chunk_name = png_ptr->chunk_name; if (chunk_name != png_IDAT) - png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; + { + /* These flags must be set consistently for all non-IDAT chunks, + * including the unknown chunks. + */ + png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT | PNG_AFTER_IDAT; + } if (chunk_name == png_IEND) png_handle_chunk(png_ptr, info_ptr, length); diff --git a/src/3rdparty/libpng/pngrutil.c b/src/3rdparty/libpng/pngrutil.c index 7d9a00186dc..e7c7bbe48e9 100644 --- a/src/3rdparty/libpng/pngrutil.c +++ b/src/3rdparty/libpng/pngrutil.c @@ -2412,10 +2412,6 @@ png_handle_tEXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) } #endif - /* TODO: this doesn't work and shouldn't be necessary. */ - if ((png_ptr->mode & PNG_HAVE_IDAT) != 0) - png_ptr->mode |= PNG_AFTER_IDAT; - buffer = png_read_buffer(png_ptr, length+1); if (buffer == NULL) @@ -2486,10 +2482,6 @@ png_handle_zTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) } #endif - /* TODO: should not be necessary. */ - if ((png_ptr->mode & PNG_HAVE_IDAT) != 0) - png_ptr->mode |= PNG_AFTER_IDAT; - /* Note, "length" is sufficient here; we won't be adding * a null terminator later. The limit check in png_handle_chunk should be * sufficient. @@ -2606,10 +2598,6 @@ png_handle_iTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) } #endif - /* TODO: should not be necessary. */ - if ((png_ptr->mode & PNG_HAVE_IDAT) != 0) - png_ptr->mode |= PNG_AFTER_IDAT; - buffer = png_read_buffer(png_ptr, length+1); if (buffer == NULL) diff --git a/src/3rdparty/libpng/qt_attribution.json b/src/3rdparty/libpng/qt_attribution.json index 49d0b6ca79f..9327dee564c 100644 --- a/src/3rdparty/libpng/qt_attribution.json +++ b/src/3rdparty/libpng/qt_attribution.json @@ -7,8 +7,8 @@ "Description": "libpng is the official PNG reference library.", "Homepage": "http://www.libpng.org/pub/png/libpng.html", - "Version": "1.6.49", - "DownloadLocation": "https://download.sourceforge.net/libpng/libpng-1.6.49.tar.xz", + "Version": "1.6.50", + "DownloadLocation": "https://download.sourceforge.net/libpng/libpng-1.6.50.tar.xz", "PURL": "pkg:github/pnggroup/libpng@v$<VERSION>", "CPE": "cpe:2.3:a:libpng:libpng:$<VERSION>:*:*:*:*:*:*:*", diff --git a/src/3rdparty/wayland/extensions/REUSE.toml b/src/3rdparty/wayland/extensions/REUSE.toml index 7debc4f4e09..72b4251a911 100644 --- a/src/3rdparty/wayland/extensions/REUSE.toml +++ b/src/3rdparty/wayland/extensions/REUSE.toml @@ -4,5 +4,5 @@ version = 1 path = "qt-text-input-method-unstable-v1.xml" precedence = "closest" comment = "License is in full text in file. Should it be changed?" -SPDX-FileCopyrightText = "Copyright © 2020 The Qt Company Ltd." +SPDX-FileCopyrightText = "Copyright © The Qt Company Ltd." SPDX-License-Identifier = "MIT" diff --git a/src/android/CMakeLists.txt b/src/android/CMakeLists.txt index 7c99ce7264e..12fbca624b3 100644 --- a/src/android/CMakeLists.txt +++ b/src/android/CMakeLists.txt @@ -9,6 +9,7 @@ if (ANDROID) add_subdirectory(java) add_subdirectory(templates) add_subdirectory(templates_aar) + add_subdirectory(templates_cmake) endif() qt_internal_add_java_documentation(Global) diff --git a/src/android/REUSE.toml b/src/android/REUSE.toml index 7d5a22fd2f7..04b82f125e9 100644 --- a/src/android/REUSE.toml +++ b/src/android/REUSE.toml @@ -1,15 +1,21 @@ version = 1 [[annotations]] -path = ["jar/build.gradle", "jar/settings.gradle", "templates/build.gradle"] +path = ["jar/build.gradle", "jar/settings.gradle", "templates/build.gradle", "templates_cmake/**", "templates_aar/**", "templates/**", "**.xml"] precedence = "closest" comment = "double check" -SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." +SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd." SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only" [[annotations]] path = ["java/READ-THIS-BEFORE-MANUALLY-ADDING-FILES-TO-PACKAGE.txt"] comment = "documentation" precedence = "closest" -SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." +SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd." SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only" + +[[annotations]] +path = ["**.gitignore"] +precedence = "closest" +SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." +SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR BSD-3-Clause" 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 9d7850cb517..afe4d005402 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtView.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtView.java @@ -1,6 +1,6 @@ // Copyright (C) 2024 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only -// Qt-Security score:critical reason:executing-external-code +// Qt-Security score:critical reason:execute-external-code package org.qtproject.qt.android; diff --git a/src/android/templates/build.gradle b/src/android/templates/build.gradle index 6595cb5358f..b6c4797fde7 100644 --- a/src/android/templates/build.gradle +++ b/src/android/templates/build.gradle @@ -70,8 +70,8 @@ android { abortOnError = false } - // Do not compress Qt binary resources file aaptOptions { + // Do not compress Qt binary resources file noCompress 'rcc' } diff --git a/src/android/templates_cmake/CMakeLists.txt b/src/android/templates_cmake/CMakeLists.txt new file mode 100644 index 00000000000..546a4fc50f3 --- /dev/null +++ b/src/android/templates_cmake/CMakeLists.txt @@ -0,0 +1,46 @@ +# Copyright (C) 2024 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +set(templates_files + "${CMAKE_CURRENT_SOURCE_DIR}/settings.gradle.in" + "${CMAKE_CURRENT_SOURCE_DIR}/gradle.properties.in" +) + +set(app_template_files + "${CMAKE_CURRENT_SOURCE_DIR}/app/gradle.properties.in" + "${CMAKE_CURRENT_SOURCE_DIR}/app/build.gradle.in" + "${CMAKE_CURRENT_SOURCE_DIR}/app/AndroidManifest.xml.in" +) + +set(dynamic_feature_files + "${CMAKE_CURRENT_SOURCE_DIR}/dynamic_feature/AndroidManifest.xml.in" + "${CMAKE_CURRENT_SOURCE_DIR}/dynamic_feature/build.gradle.in" +) + +add_custom_target(Qt6AndroidCMakeTemplates + SOURCES + ${templates_files} +) + +qt_path_join(destination ${QT_INSTALL_DIR} ${INSTALL_DATADIR} "src/android/templates_cmake") + +qt_copy_or_install(FILES ${templates_files} DESTINATION "${destination}") +qt_copy_or_install(FILES ${app_template_files} DESTINATION "${destination}/app") +qt_copy_or_install(FILES ${dynamic_feature_files} DESTINATION "${destination}/dynamic_feature") + +if(NOT QT_WILL_INSTALL) + qt_internal_copy_at_build_time(TARGET Qt6AndroidCMakeTemplates + FILES ${templates_files} + DESTINATION ${destination} + ) + + qt_internal_copy_at_build_time(TARGET Qt6AndroidCMakeTemplates + FILES ${app_templates_files} + DESTINATION ${destination}/app + ) + + qt_internal_copy_at_build_time(TARGET Qt6AndroidCMakeTemplates + FILES ${dynamic_feature_files} + DESTINATION ${destination}/dynamic_feature + ) +endif() diff --git a/src/android/templates_cmake/app/AndroidManifest.xml.in b/src/android/templates_cmake/app/AndroidManifest.xml.in new file mode 100644 index 00000000000..61c33cc7657 --- /dev/null +++ b/src/android/templates_cmake/app/AndroidManifest.xml.in @@ -0,0 +1,54 @@ +<?xml version="1.0"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:dist="http://schemas.android.com/apk/distribution" + package="@APP_PACKAGE_NAME@" + android:installLocation="auto" + android:versionCode="@APP_VERSION_CODE@" + android:versionName="@APP_VERSION_NAME@"> + @APP_PERMISSIONS@ + @APP_FEATURES@ + <dist:module dist:instant="true"/> + <supports-screens + android:anyDensity="true" + android:largeScreens="true" + android:normalScreens="true" + android:smallScreens="true" /> + <application + android:name="org.qtproject.qt.android.bindings.QtApplication" + android:hardwareAccelerated="true" + android:label="@APP_NAME@" + @APP_ICON@ + android:requestLegacyExternalStorage="true" + android:allowBackup="true" + android:fullBackupOnly="false"> + <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:launchMode="singleTop" + android:screenOrientation="unspecified" + android:exported="true"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + + <meta-data + android:name="android.app.lib_name" + android:value="@APP_LIB_NAME@" /> + + <meta-data + android:name="android.app.arguments" + android:value="@APP_ARGUMENTS@" /> + </activity> + + <provider + android:name="androidx.core.content.FileProvider" + android:authorities="${applicationId}.qtprovider" + android:exported="false" + android:grantUriPermissions="true"> + <meta-data + android:name="android.support.FILE_PROVIDER_PATHS" + android:resource="@xml/qtprovider_paths"/> + </provider> + </application> +</manifest> diff --git a/src/android/templates_cmake/app/build.gradle.in b/src/android/templates_cmake/app/build.gradle.in new file mode 100644 index 00000000000..917f371e46f --- /dev/null +++ b/src/android/templates_cmake/app/build.gradle.in @@ -0,0 +1,53 @@ +buildscript { + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:8.10.1' + } +} + +apply plugin: '@GRADLE_PLUGIN_TYPE@' + +dependencies { + @GRADLE_DEPENDENCIES@ +} + +android { + namespace '@PACKAGE_NAME@' + compileSdkVersion '@ANDROID_COMPILE_SDK_VERSION@' + buildToolsVersion '@ANDROID_BUILD_TOOLS_VERSION@' + ndkVersion '@ANDROID_NDK_REVISION@' + + defaultConfig { + @DEFAULT_CONFIG_VALUES@ + } + + sourceSets { + main { +@SOURCE_SETS@ + } + } + + tasks.withType(JavaCompile) { + options.incremental = true + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + lintOptions { + abortOnError false + } + + aaptOptions { + // Do not compress Qt binary resources file + noCompress 'rcc' + } + + @ANDROID_DEPLOYMENT_EXTRAS@ +} diff --git a/src/android/templates_cmake/app/gradle.properties.in b/src/android/templates_cmake/app/gradle.properties.in new file mode 100644 index 00000000000..1136551f3fa --- /dev/null +++ b/src/android/templates_cmake/app/gradle.properties.in @@ -0,0 +1 @@ +# Extend this template with the extra gradle properties applicable for Android app. diff --git a/src/android/templates_cmake/dynamic_feature/AndroidManifest.xml.in b/src/android/templates_cmake/dynamic_feature/AndroidManifest.xml.in new file mode 100644 index 00000000000..9945ec76f27 --- /dev/null +++ b/src/android/templates_cmake/dynamic_feature/AndroidManifest.xml.in @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:dist="http://schemas.android.com/apk/distribution" + split="@APP_TARGET@" + android:isFeatureSplit="true"> + <dist:module + dist:instant="true" + dist:title="@TITLE_VAR@"> + <dist:delivery> + <dist:on-demand /> + </dist:delivery> + <dist:fusing dist:include="false" /> + </dist:module> + <application android:hasCode="false"/> +</manifest> diff --git a/src/android/templates_cmake/dynamic_feature/build.gradle.in b/src/android/templates_cmake/dynamic_feature/build.gradle.in new file mode 100644 index 00000000000..917f371e46f --- /dev/null +++ b/src/android/templates_cmake/dynamic_feature/build.gradle.in @@ -0,0 +1,53 @@ +buildscript { + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:8.10.1' + } +} + +apply plugin: '@GRADLE_PLUGIN_TYPE@' + +dependencies { + @GRADLE_DEPENDENCIES@ +} + +android { + namespace '@PACKAGE_NAME@' + compileSdkVersion '@ANDROID_COMPILE_SDK_VERSION@' + buildToolsVersion '@ANDROID_BUILD_TOOLS_VERSION@' + ndkVersion '@ANDROID_NDK_REVISION@' + + defaultConfig { + @DEFAULT_CONFIG_VALUES@ + } + + sourceSets { + main { +@SOURCE_SETS@ + } + } + + tasks.withType(JavaCompile) { + options.incremental = true + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + lintOptions { + abortOnError false + } + + aaptOptions { + // Do not compress Qt binary resources file + noCompress 'rcc' + } + + @ANDROID_DEPLOYMENT_EXTRAS@ +} diff --git a/src/android/templates_cmake/gradle.properties.in b/src/android/templates_cmake/gradle.properties.in new file mode 100644 index 00000000000..b751946190a --- /dev/null +++ b/src/android/templates_cmake/gradle.properties.in @@ -0,0 +1,12 @@ +# Project-wide Gradle settings. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx2500m -XX:MaxMetaspaceSize=768m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 + +# Enable building projects in parallel +org.gradle.parallel=true + +# Allow AndroidX usage +android.useAndroidX=true diff --git a/src/android/templates_cmake/settings.gradle.in b/src/android/templates_cmake/settings.gradle.in new file mode 100644 index 00000000000..03954ae5f9f --- /dev/null +++ b/src/android/templates_cmake/settings.gradle.in @@ -0,0 +1,18 @@ +pluginManagement { + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + } +} + +rootProject.name = "@ROOT_PROJECT_NAME@" +include(":app") +@SUBPROJECTS@ diff --git a/src/assets/CMakeLists.txt b/src/assets/CMakeLists.txt index da9c0c14eea..ab07d27696e 100644 --- a/src/assets/CMakeLists.txt +++ b/src/assets/CMakeLists.txt @@ -1,6 +1,5 @@ # Copyright (C) 2024 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -add_subdirectory(icons) if (NOT INTEGRITY AND TARGET Qt6::Network AND TARGET Qt6::Concurrent) add_subdirectory(downloader) diff --git a/src/assets/icons/128x128/document-new.png b/src/assets/icons/128x128/document-new.png Binary files differdeleted file mode 100644 index 8d86a4827a7..00000000000 --- a/src/assets/icons/128x128/document-new.png +++ /dev/null diff --git a/src/assets/icons/128x128/document-open.png b/src/assets/icons/128x128/document-open.png Binary files differdeleted file mode 100644 index 2183dbbea64..00000000000 --- a/src/assets/icons/128x128/document-open.png +++ /dev/null diff --git a/src/assets/icons/128x128/document-print.png b/src/assets/icons/128x128/document-print.png Binary files differdeleted file mode 100644 index 9e7378aab2a..00000000000 --- a/src/assets/icons/128x128/document-print.png +++ /dev/null diff --git a/src/assets/icons/128x128/document-save.png b/src/assets/icons/128x128/document-save.png Binary files differdeleted file mode 100644 index e8b28406433..00000000000 --- a/src/assets/icons/128x128/document-save.png +++ /dev/null diff --git a/src/assets/icons/128x128/edit-copy.png b/src/assets/icons/128x128/edit-copy.png Binary files differdeleted file mode 100644 index 7585f4baa0c..00000000000 --- a/src/assets/icons/128x128/edit-copy.png +++ /dev/null diff --git a/src/assets/icons/128x128/edit-cut.png b/src/assets/icons/128x128/edit-cut.png Binary files differdeleted file mode 100644 index 51ede2fe37e..00000000000 --- a/src/assets/icons/128x128/edit-cut.png +++ /dev/null diff --git a/src/assets/icons/128x128/edit-delete.png b/src/assets/icons/128x128/edit-delete.png Binary files differdeleted file mode 100644 index bdf785c8285..00000000000 --- a/src/assets/icons/128x128/edit-delete.png +++ /dev/null diff --git a/src/assets/icons/128x128/edit-paste.png b/src/assets/icons/128x128/edit-paste.png Binary files differdeleted file mode 100644 index 690ffa172d9..00000000000 --- a/src/assets/icons/128x128/edit-paste.png +++ /dev/null diff --git a/src/assets/icons/128x128/edit-redo.png b/src/assets/icons/128x128/edit-redo.png Binary files differdeleted file mode 100644 index f1c97f71c25..00000000000 --- a/src/assets/icons/128x128/edit-redo.png +++ /dev/null diff --git a/src/assets/icons/128x128/edit-undo.png b/src/assets/icons/128x128/edit-undo.png Binary files differdeleted file mode 100644 index e728cbf6e03..00000000000 --- a/src/assets/icons/128x128/edit-undo.png +++ /dev/null diff --git a/src/assets/icons/128x128/format-justify-center.png b/src/assets/icons/128x128/format-justify-center.png Binary files differdeleted file mode 100644 index 44ceb2af4d5..00000000000 --- a/src/assets/icons/128x128/format-justify-center.png +++ /dev/null diff --git a/src/assets/icons/128x128/format-justify-fill.png b/src/assets/icons/128x128/format-justify-fill.png Binary files differdeleted file mode 100644 index b99a8507046..00000000000 --- a/src/assets/icons/128x128/format-justify-fill.png +++ /dev/null diff --git a/src/assets/icons/128x128/format-justify-left.png b/src/assets/icons/128x128/format-justify-left.png Binary files differdeleted file mode 100644 index 2b63887b495..00000000000 --- a/src/assets/icons/128x128/format-justify-left.png +++ /dev/null diff --git a/src/assets/icons/128x128/format-justify-right.png b/src/assets/icons/128x128/format-justify-right.png Binary files differdeleted file mode 100644 index 6c61889d595..00000000000 --- a/src/assets/icons/128x128/format-justify-right.png +++ /dev/null diff --git a/src/assets/icons/128x128/format-text-bold.png b/src/assets/icons/128x128/format-text-bold.png Binary files differdeleted file mode 100644 index 96a5ca88a22..00000000000 --- a/src/assets/icons/128x128/format-text-bold.png +++ /dev/null diff --git a/src/assets/icons/128x128/format-text-italic.png b/src/assets/icons/128x128/format-text-italic.png Binary files differdeleted file mode 100644 index 2bb71b4a4d3..00000000000 --- a/src/assets/icons/128x128/format-text-italic.png +++ /dev/null diff --git a/src/assets/icons/128x128/format-text-underline.png b/src/assets/icons/128x128/format-text-underline.png Binary files differdeleted file mode 100644 index ecf6830c929..00000000000 --- a/src/assets/icons/128x128/format-text-underline.png +++ /dev/null diff --git a/src/assets/icons/128x128@2/[email protected] b/src/assets/icons/128x128@2/[email protected] Binary files differdeleted file mode 100644 index 32776b51a96..00000000000 --- a/src/assets/icons/128x128@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/128x128@2/[email protected] b/src/assets/icons/128x128@2/[email protected] Binary files differdeleted file mode 100644 index 06e188b93b9..00000000000 --- a/src/assets/icons/128x128@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/128x128@2/[email protected] b/src/assets/icons/128x128@2/[email protected] Binary files differdeleted file mode 100644 index 644e3c149af..00000000000 --- a/src/assets/icons/128x128@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/128x128@2/[email protected] b/src/assets/icons/128x128@2/[email protected] Binary files differdeleted file mode 100644 index 16fa70493a2..00000000000 --- a/src/assets/icons/128x128@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/128x128@2/[email protected] b/src/assets/icons/128x128@2/[email protected] Binary files differdeleted file mode 100644 index b18bead117f..00000000000 --- a/src/assets/icons/128x128@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/128x128@2/[email protected] b/src/assets/icons/128x128@2/[email protected] Binary files differdeleted file mode 100644 index d9454cebf1c..00000000000 --- a/src/assets/icons/128x128@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/128x128@2/[email protected] b/src/assets/icons/128x128@2/[email protected] Binary files differdeleted file mode 100644 index 4081cdb2ca7..00000000000 --- a/src/assets/icons/128x128@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/128x128@2/[email protected] b/src/assets/icons/128x128@2/[email protected] Binary files differdeleted file mode 100644 index 3358426818d..00000000000 --- a/src/assets/icons/128x128@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/128x128@2/[email protected] b/src/assets/icons/128x128@2/[email protected] Binary files differdeleted file mode 100644 index e28b28542c6..00000000000 --- a/src/assets/icons/128x128@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/128x128@2/[email protected] b/src/assets/icons/128x128@2/[email protected] Binary files differdeleted file mode 100644 index fe10f57a398..00000000000 --- a/src/assets/icons/128x128@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/128x128@2/[email protected] b/src/assets/icons/128x128@2/[email protected] Binary files differdeleted file mode 100644 index d4ad74b0d07..00000000000 --- a/src/assets/icons/128x128@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/128x128@2/[email protected] b/src/assets/icons/128x128@2/[email protected] Binary files differdeleted file mode 100644 index bf0dd84bbb0..00000000000 --- a/src/assets/icons/128x128@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/128x128@2/[email protected] b/src/assets/icons/128x128@2/[email protected] Binary files differdeleted file mode 100644 index dde68c8514a..00000000000 --- a/src/assets/icons/128x128@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/128x128@2/[email protected] b/src/assets/icons/128x128@2/[email protected] Binary files differdeleted file mode 100644 index 8a5e7518bdc..00000000000 --- a/src/assets/icons/128x128@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/128x128@2/[email protected] b/src/assets/icons/128x128@2/[email protected] Binary files differdeleted file mode 100644 index 665d3ce37b5..00000000000 --- a/src/assets/icons/128x128@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/128x128@2/[email protected] b/src/assets/icons/128x128@2/[email protected] Binary files differdeleted file mode 100644 index 4b6846a6b98..00000000000 --- a/src/assets/icons/128x128@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/128x128@2/[email protected] b/src/assets/icons/128x128@2/[email protected] Binary files differdeleted file mode 100644 index 601f73216a3..00000000000 --- a/src/assets/icons/128x128@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/16x16/document-new.png b/src/assets/icons/16x16/document-new.png Binary files differdeleted file mode 100644 index 893e7e1aec4..00000000000 --- a/src/assets/icons/16x16/document-new.png +++ /dev/null diff --git a/src/assets/icons/16x16/document-open.png b/src/assets/icons/16x16/document-open.png Binary files differdeleted file mode 100644 index b07906f40bd..00000000000 --- a/src/assets/icons/16x16/document-open.png +++ /dev/null diff --git a/src/assets/icons/16x16/document-print.png b/src/assets/icons/16x16/document-print.png Binary files differdeleted file mode 100644 index 9341060076f..00000000000 --- a/src/assets/icons/16x16/document-print.png +++ /dev/null diff --git a/src/assets/icons/16x16/document-save.png b/src/assets/icons/16x16/document-save.png Binary files differdeleted file mode 100644 index 6238718191b..00000000000 --- a/src/assets/icons/16x16/document-save.png +++ /dev/null diff --git a/src/assets/icons/16x16/edit-copy.png b/src/assets/icons/16x16/edit-copy.png Binary files differdeleted file mode 100644 index 585f5bfc8d8..00000000000 --- a/src/assets/icons/16x16/edit-copy.png +++ /dev/null diff --git a/src/assets/icons/16x16/edit-cut.png b/src/assets/icons/16x16/edit-cut.png Binary files differdeleted file mode 100644 index 661ef1ad030..00000000000 --- a/src/assets/icons/16x16/edit-cut.png +++ /dev/null diff --git a/src/assets/icons/16x16/edit-delete.png b/src/assets/icons/16x16/edit-delete.png Binary files differdeleted file mode 100644 index 7b5998df8a4..00000000000 --- a/src/assets/icons/16x16/edit-delete.png +++ /dev/null diff --git a/src/assets/icons/16x16/edit-paste.png b/src/assets/icons/16x16/edit-paste.png Binary files differdeleted file mode 100644 index 6318a22caf3..00000000000 --- a/src/assets/icons/16x16/edit-paste.png +++ /dev/null diff --git a/src/assets/icons/16x16/edit-redo.png b/src/assets/icons/16x16/edit-redo.png Binary files differdeleted file mode 100644 index 7eb10fe899c..00000000000 --- a/src/assets/icons/16x16/edit-redo.png +++ /dev/null diff --git a/src/assets/icons/16x16/edit-undo.png b/src/assets/icons/16x16/edit-undo.png Binary files differdeleted file mode 100644 index 108712547cb..00000000000 --- a/src/assets/icons/16x16/edit-undo.png +++ /dev/null diff --git a/src/assets/icons/16x16/format-justify-center.png b/src/assets/icons/16x16/format-justify-center.png Binary files differdeleted file mode 100644 index 6b0951fa5dd..00000000000 --- a/src/assets/icons/16x16/format-justify-center.png +++ /dev/null diff --git a/src/assets/icons/16x16/format-justify-fill.png b/src/assets/icons/16x16/format-justify-fill.png Binary files differdeleted file mode 100644 index 6e1c10d7c45..00000000000 --- a/src/assets/icons/16x16/format-justify-fill.png +++ /dev/null diff --git a/src/assets/icons/16x16/format-justify-left.png b/src/assets/icons/16x16/format-justify-left.png Binary files differdeleted file mode 100644 index 9dfdc89b68a..00000000000 --- a/src/assets/icons/16x16/format-justify-left.png +++ /dev/null diff --git a/src/assets/icons/16x16/format-justify-right.png b/src/assets/icons/16x16/format-justify-right.png Binary files differdeleted file mode 100644 index 36a52081f18..00000000000 --- a/src/assets/icons/16x16/format-justify-right.png +++ /dev/null diff --git a/src/assets/icons/16x16/format-text-bold.png b/src/assets/icons/16x16/format-text-bold.png Binary files differdeleted file mode 100644 index a079317a947..00000000000 --- a/src/assets/icons/16x16/format-text-bold.png +++ /dev/null diff --git a/src/assets/icons/16x16/format-text-italic.png b/src/assets/icons/16x16/format-text-italic.png Binary files differdeleted file mode 100644 index 04202b2842f..00000000000 --- a/src/assets/icons/16x16/format-text-italic.png +++ /dev/null diff --git a/src/assets/icons/16x16/format-text-underline.png b/src/assets/icons/16x16/format-text-underline.png Binary files differdeleted file mode 100644 index a80368212d8..00000000000 --- a/src/assets/icons/16x16/format-text-underline.png +++ /dev/null diff --git a/src/assets/icons/16x16@2/[email protected] b/src/assets/icons/16x16@2/[email protected] Binary files differdeleted file mode 100644 index 482ae52024e..00000000000 --- a/src/assets/icons/16x16@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/16x16@2/[email protected] b/src/assets/icons/16x16@2/[email protected] Binary files differdeleted file mode 100644 index 9858b146f44..00000000000 --- a/src/assets/icons/16x16@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/16x16@2/[email protected] b/src/assets/icons/16x16@2/[email protected] Binary files differdeleted file mode 100644 index 1672ec58971..00000000000 --- a/src/assets/icons/16x16@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/16x16@2/[email protected] b/src/assets/icons/16x16@2/[email protected] Binary files differdeleted file mode 100644 index f04de746731..00000000000 --- a/src/assets/icons/16x16@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/16x16@2/[email protected] b/src/assets/icons/16x16@2/[email protected] Binary files differdeleted file mode 100644 index bbb34cc4c22..00000000000 --- a/src/assets/icons/16x16@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/16x16@2/[email protected] b/src/assets/icons/16x16@2/[email protected] Binary files differdeleted file mode 100644 index d89ef6c0167..00000000000 --- a/src/assets/icons/16x16@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/16x16@2/[email protected] b/src/assets/icons/16x16@2/[email protected] Binary files differdeleted file mode 100644 index 4c97ee24952..00000000000 --- a/src/assets/icons/16x16@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/16x16@2/[email protected] b/src/assets/icons/16x16@2/[email protected] Binary files differdeleted file mode 100644 index 299fa776867..00000000000 --- a/src/assets/icons/16x16@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/16x16@2/[email protected] b/src/assets/icons/16x16@2/[email protected] Binary files differdeleted file mode 100644 index 4f8849c7110..00000000000 --- a/src/assets/icons/16x16@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/16x16@2/[email protected] b/src/assets/icons/16x16@2/[email protected] Binary files differdeleted file mode 100644 index b3d366c53f6..00000000000 --- a/src/assets/icons/16x16@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/16x16@2/[email protected] b/src/assets/icons/16x16@2/[email protected] Binary files differdeleted file mode 100644 index 80c3afd9a6e..00000000000 --- a/src/assets/icons/16x16@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/16x16@2/[email protected] b/src/assets/icons/16x16@2/[email protected] Binary files differdeleted file mode 100644 index 33589ea25d0..00000000000 --- a/src/assets/icons/16x16@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/16x16@2/[email protected] b/src/assets/icons/16x16@2/[email protected] Binary files differdeleted file mode 100644 index ba028211355..00000000000 --- a/src/assets/icons/16x16@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/16x16@2/[email protected] b/src/assets/icons/16x16@2/[email protected] Binary files differdeleted file mode 100644 index 8e15d0cb44f..00000000000 --- a/src/assets/icons/16x16@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/16x16@2/[email protected] b/src/assets/icons/16x16@2/[email protected] Binary files differdeleted file mode 100644 index 754efdd9755..00000000000 --- a/src/assets/icons/16x16@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/16x16@2/[email protected] b/src/assets/icons/16x16@2/[email protected] Binary files differdeleted file mode 100644 index 6db31a4f697..00000000000 --- a/src/assets/icons/16x16@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/16x16@2/[email protected] b/src/assets/icons/16x16@2/[email protected] Binary files differdeleted file mode 100644 index 977cde9d974..00000000000 --- a/src/assets/icons/16x16@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/256x256/document-new.png b/src/assets/icons/256x256/document-new.png Binary files differdeleted file mode 100644 index 32776b51a96..00000000000 --- a/src/assets/icons/256x256/document-new.png +++ /dev/null diff --git a/src/assets/icons/256x256/document-open.png b/src/assets/icons/256x256/document-open.png Binary files differdeleted file mode 100644 index 06e188b93b9..00000000000 --- a/src/assets/icons/256x256/document-open.png +++ /dev/null diff --git a/src/assets/icons/256x256/document-print.png b/src/assets/icons/256x256/document-print.png Binary files differdeleted file mode 100644 index 644e3c149af..00000000000 --- a/src/assets/icons/256x256/document-print.png +++ /dev/null diff --git a/src/assets/icons/256x256/document-save.png b/src/assets/icons/256x256/document-save.png Binary files differdeleted file mode 100644 index 16fa70493a2..00000000000 --- a/src/assets/icons/256x256/document-save.png +++ /dev/null diff --git a/src/assets/icons/256x256/edit-copy.png b/src/assets/icons/256x256/edit-copy.png Binary files differdeleted file mode 100644 index b18bead117f..00000000000 --- a/src/assets/icons/256x256/edit-copy.png +++ /dev/null diff --git a/src/assets/icons/256x256/edit-cut.png b/src/assets/icons/256x256/edit-cut.png Binary files differdeleted file mode 100644 index d9454cebf1c..00000000000 --- a/src/assets/icons/256x256/edit-cut.png +++ /dev/null diff --git a/src/assets/icons/256x256/edit-delete.png b/src/assets/icons/256x256/edit-delete.png Binary files differdeleted file mode 100644 index 4081cdb2ca7..00000000000 --- a/src/assets/icons/256x256/edit-delete.png +++ /dev/null diff --git a/src/assets/icons/256x256/edit-paste.png b/src/assets/icons/256x256/edit-paste.png Binary files differdeleted file mode 100644 index 3358426818d..00000000000 --- a/src/assets/icons/256x256/edit-paste.png +++ /dev/null diff --git a/src/assets/icons/256x256/edit-redo.png b/src/assets/icons/256x256/edit-redo.png Binary files differdeleted file mode 100644 index e28b28542c6..00000000000 --- a/src/assets/icons/256x256/edit-redo.png +++ /dev/null diff --git a/src/assets/icons/256x256/edit-undo.png b/src/assets/icons/256x256/edit-undo.png Binary files differdeleted file mode 100644 index fe10f57a398..00000000000 --- a/src/assets/icons/256x256/edit-undo.png +++ /dev/null diff --git a/src/assets/icons/256x256/format-justify-center.png b/src/assets/icons/256x256/format-justify-center.png Binary files differdeleted file mode 100644 index d4ad74b0d07..00000000000 --- a/src/assets/icons/256x256/format-justify-center.png +++ /dev/null diff --git a/src/assets/icons/256x256/format-justify-fill.png b/src/assets/icons/256x256/format-justify-fill.png Binary files differdeleted file mode 100644 index bf0dd84bbb0..00000000000 --- a/src/assets/icons/256x256/format-justify-fill.png +++ /dev/null diff --git a/src/assets/icons/256x256/format-justify-left.png b/src/assets/icons/256x256/format-justify-left.png Binary files differdeleted file mode 100644 index dde68c8514a..00000000000 --- a/src/assets/icons/256x256/format-justify-left.png +++ /dev/null diff --git a/src/assets/icons/256x256/format-justify-right.png b/src/assets/icons/256x256/format-justify-right.png Binary files differdeleted file mode 100644 index 8a5e7518bdc..00000000000 --- a/src/assets/icons/256x256/format-justify-right.png +++ /dev/null diff --git a/src/assets/icons/256x256/format-text-bold.png b/src/assets/icons/256x256/format-text-bold.png Binary files differdeleted file mode 100644 index 665d3ce37b5..00000000000 --- a/src/assets/icons/256x256/format-text-bold.png +++ /dev/null diff --git a/src/assets/icons/256x256/format-text-italic.png b/src/assets/icons/256x256/format-text-italic.png Binary files differdeleted file mode 100644 index 4b6846a6b98..00000000000 --- a/src/assets/icons/256x256/format-text-italic.png +++ /dev/null diff --git a/src/assets/icons/256x256/format-text-underline.png b/src/assets/icons/256x256/format-text-underline.png Binary files differdeleted file mode 100644 index 601f73216a3..00000000000 --- a/src/assets/icons/256x256/format-text-underline.png +++ /dev/null diff --git a/src/assets/icons/256x256@2/[email protected] b/src/assets/icons/256x256@2/[email protected] Binary files differdeleted file mode 100644 index bfec6d0e6d1..00000000000 --- a/src/assets/icons/256x256@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/256x256@2/[email protected] b/src/assets/icons/256x256@2/[email protected] Binary files differdeleted file mode 100644 index 630a05f622c..00000000000 --- a/src/assets/icons/256x256@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/256x256@2/[email protected] b/src/assets/icons/256x256@2/[email protected] Binary files differdeleted file mode 100644 index c8611c31c49..00000000000 --- a/src/assets/icons/256x256@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/256x256@2/[email protected] b/src/assets/icons/256x256@2/[email protected] Binary files differdeleted file mode 100644 index 6f460959818..00000000000 --- a/src/assets/icons/256x256@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/256x256@2/[email protected] b/src/assets/icons/256x256@2/[email protected] Binary files differdeleted file mode 100644 index 2f350041a05..00000000000 --- a/src/assets/icons/256x256@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/256x256@2/[email protected] b/src/assets/icons/256x256@2/[email protected] Binary files differdeleted file mode 100644 index e11cf6d2347..00000000000 --- a/src/assets/icons/256x256@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/256x256@2/[email protected] b/src/assets/icons/256x256@2/[email protected] Binary files differdeleted file mode 100644 index efe6b90bf59..00000000000 --- a/src/assets/icons/256x256@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/256x256@2/[email protected] b/src/assets/icons/256x256@2/[email protected] Binary files differdeleted file mode 100644 index 32f54b39598..00000000000 --- a/src/assets/icons/256x256@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/256x256@2/[email protected] b/src/assets/icons/256x256@2/[email protected] Binary files differdeleted file mode 100644 index 1f6e366535b..00000000000 --- a/src/assets/icons/256x256@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/256x256@2/[email protected] b/src/assets/icons/256x256@2/[email protected] Binary files differdeleted file mode 100644 index 980ed370621..00000000000 --- a/src/assets/icons/256x256@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/256x256@2/[email protected] b/src/assets/icons/256x256@2/[email protected] Binary files differdeleted file mode 100644 index af7044ddee1..00000000000 --- a/src/assets/icons/256x256@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/256x256@2/[email protected] b/src/assets/icons/256x256@2/[email protected] Binary files differdeleted file mode 100644 index da14563bd68..00000000000 --- a/src/assets/icons/256x256@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/256x256@2/[email protected] b/src/assets/icons/256x256@2/[email protected] Binary files differdeleted file mode 100644 index c1025bf0102..00000000000 --- a/src/assets/icons/256x256@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/256x256@2/[email protected] b/src/assets/icons/256x256@2/[email protected] Binary files differdeleted file mode 100644 index 3a07e06e0f3..00000000000 --- a/src/assets/icons/256x256@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/256x256@2/[email protected] b/src/assets/icons/256x256@2/[email protected] Binary files differdeleted file mode 100644 index b0f4cb09958..00000000000 --- a/src/assets/icons/256x256@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/256x256@2/[email protected] b/src/assets/icons/256x256@2/[email protected] Binary files differdeleted file mode 100644 index 85f0cfc1d65..00000000000 --- a/src/assets/icons/256x256@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/256x256@2/[email protected] b/src/assets/icons/256x256@2/[email protected] Binary files differdeleted file mode 100644 index 51ee0aa7783..00000000000 --- a/src/assets/icons/256x256@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/32x32/document-new.png b/src/assets/icons/32x32/document-new.png Binary files differdeleted file mode 100644 index 482ae52024e..00000000000 --- a/src/assets/icons/32x32/document-new.png +++ /dev/null diff --git a/src/assets/icons/32x32/document-open.png b/src/assets/icons/32x32/document-open.png Binary files differdeleted file mode 100644 index 9858b146f44..00000000000 --- a/src/assets/icons/32x32/document-open.png +++ /dev/null diff --git a/src/assets/icons/32x32/document-print.png b/src/assets/icons/32x32/document-print.png Binary files differdeleted file mode 100644 index 1672ec58971..00000000000 --- a/src/assets/icons/32x32/document-print.png +++ /dev/null diff --git a/src/assets/icons/32x32/document-save.png b/src/assets/icons/32x32/document-save.png Binary files differdeleted file mode 100644 index f04de746731..00000000000 --- a/src/assets/icons/32x32/document-save.png +++ /dev/null diff --git a/src/assets/icons/32x32/edit-copy.png b/src/assets/icons/32x32/edit-copy.png Binary files differdeleted file mode 100644 index bbb34cc4c22..00000000000 --- a/src/assets/icons/32x32/edit-copy.png +++ /dev/null diff --git a/src/assets/icons/32x32/edit-cut.png b/src/assets/icons/32x32/edit-cut.png Binary files differdeleted file mode 100644 index d89ef6c0167..00000000000 --- a/src/assets/icons/32x32/edit-cut.png +++ /dev/null diff --git a/src/assets/icons/32x32/edit-delete.png b/src/assets/icons/32x32/edit-delete.png Binary files differdeleted file mode 100644 index 4c97ee24952..00000000000 --- a/src/assets/icons/32x32/edit-delete.png +++ /dev/null diff --git a/src/assets/icons/32x32/edit-paste.png b/src/assets/icons/32x32/edit-paste.png Binary files differdeleted file mode 100644 index 299fa776867..00000000000 --- a/src/assets/icons/32x32/edit-paste.png +++ /dev/null diff --git a/src/assets/icons/32x32/edit-redo.png b/src/assets/icons/32x32/edit-redo.png Binary files differdeleted file mode 100644 index 4f8849c7110..00000000000 --- a/src/assets/icons/32x32/edit-redo.png +++ /dev/null diff --git a/src/assets/icons/32x32/edit-undo.png b/src/assets/icons/32x32/edit-undo.png Binary files differdeleted file mode 100644 index b3d366c53f6..00000000000 --- a/src/assets/icons/32x32/edit-undo.png +++ /dev/null diff --git a/src/assets/icons/32x32/format-justify-center.png b/src/assets/icons/32x32/format-justify-center.png Binary files differdeleted file mode 100644 index 80c3afd9a6e..00000000000 --- a/src/assets/icons/32x32/format-justify-center.png +++ /dev/null diff --git a/src/assets/icons/32x32/format-justify-fill.png b/src/assets/icons/32x32/format-justify-fill.png Binary files differdeleted file mode 100644 index 33589ea25d0..00000000000 --- a/src/assets/icons/32x32/format-justify-fill.png +++ /dev/null diff --git a/src/assets/icons/32x32/format-justify-left.png b/src/assets/icons/32x32/format-justify-left.png Binary files differdeleted file mode 100644 index ba028211355..00000000000 --- a/src/assets/icons/32x32/format-justify-left.png +++ /dev/null diff --git a/src/assets/icons/32x32/format-justify-right.png b/src/assets/icons/32x32/format-justify-right.png Binary files differdeleted file mode 100644 index 8e15d0cb44f..00000000000 --- a/src/assets/icons/32x32/format-justify-right.png +++ /dev/null diff --git a/src/assets/icons/32x32/format-text-bold.png b/src/assets/icons/32x32/format-text-bold.png Binary files differdeleted file mode 100644 index 754efdd9755..00000000000 --- a/src/assets/icons/32x32/format-text-bold.png +++ /dev/null diff --git a/src/assets/icons/32x32/format-text-italic.png b/src/assets/icons/32x32/format-text-italic.png Binary files differdeleted file mode 100644 index 6db31a4f697..00000000000 --- a/src/assets/icons/32x32/format-text-italic.png +++ /dev/null diff --git a/src/assets/icons/32x32/format-text-underline.png b/src/assets/icons/32x32/format-text-underline.png Binary files differdeleted file mode 100644 index 977cde9d974..00000000000 --- a/src/assets/icons/32x32/format-text-underline.png +++ /dev/null diff --git a/src/assets/icons/32x32@2/[email protected] b/src/assets/icons/32x32@2/[email protected] Binary files differdeleted file mode 100644 index c9245760612..00000000000 --- a/src/assets/icons/32x32@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/32x32@2/[email protected] b/src/assets/icons/32x32@2/[email protected] Binary files differdeleted file mode 100644 index 68e75b549a0..00000000000 --- a/src/assets/icons/32x32@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/32x32@2/[email protected] b/src/assets/icons/32x32@2/[email protected] Binary files differdeleted file mode 100644 index b7843367393..00000000000 --- a/src/assets/icons/32x32@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/32x32@2/[email protected] b/src/assets/icons/32x32@2/[email protected] Binary files differdeleted file mode 100644 index f4cca4b3238..00000000000 --- a/src/assets/icons/32x32@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/32x32@2/[email protected] b/src/assets/icons/32x32@2/[email protected] Binary files differdeleted file mode 100644 index 9690d6bb041..00000000000 --- a/src/assets/icons/32x32@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/32x32@2/[email protected] b/src/assets/icons/32x32@2/[email protected] Binary files differdeleted file mode 100644 index 408b0ae19b0..00000000000 --- a/src/assets/icons/32x32@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/32x32@2/[email protected] b/src/assets/icons/32x32@2/[email protected] Binary files differdeleted file mode 100644 index 58abfc1fa53..00000000000 --- a/src/assets/icons/32x32@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/32x32@2/[email protected] b/src/assets/icons/32x32@2/[email protected] Binary files differdeleted file mode 100644 index b8c288f6c70..00000000000 --- a/src/assets/icons/32x32@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/32x32@2/[email protected] b/src/assets/icons/32x32@2/[email protected] Binary files differdeleted file mode 100644 index 89fcd33c300..00000000000 --- a/src/assets/icons/32x32@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/32x32@2/[email protected] b/src/assets/icons/32x32@2/[email protected] Binary files differdeleted file mode 100644 index 6f7ad2cb402..00000000000 --- a/src/assets/icons/32x32@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/32x32@2/[email protected] b/src/assets/icons/32x32@2/[email protected] Binary files differdeleted file mode 100644 index 9b2cc1ed160..00000000000 --- a/src/assets/icons/32x32@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/32x32@2/[email protected] b/src/assets/icons/32x32@2/[email protected] Binary files differdeleted file mode 100644 index 1212e9f7613..00000000000 --- a/src/assets/icons/32x32@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/32x32@2/[email protected] b/src/assets/icons/32x32@2/[email protected] Binary files differdeleted file mode 100644 index 8c0eca3037e..00000000000 --- a/src/assets/icons/32x32@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/32x32@2/[email protected] b/src/assets/icons/32x32@2/[email protected] Binary files differdeleted file mode 100644 index fb0ed702525..00000000000 --- a/src/assets/icons/32x32@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/32x32@2/[email protected] b/src/assets/icons/32x32@2/[email protected] Binary files differdeleted file mode 100644 index 0e67ead0b8c..00000000000 --- a/src/assets/icons/32x32@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/32x32@2/[email protected] b/src/assets/icons/32x32@2/[email protected] Binary files differdeleted file mode 100644 index f746f8956f8..00000000000 --- a/src/assets/icons/32x32@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/32x32@2/[email protected] b/src/assets/icons/32x32@2/[email protected] Binary files differdeleted file mode 100644 index 47d6fced026..00000000000 --- a/src/assets/icons/32x32@2/[email protected] +++ /dev/null diff --git a/src/assets/icons/CMakeLists.txt b/src/assets/icons/CMakeLists.txt deleted file mode 100644 index f5adb229d85..00000000000 --- a/src/assets/icons/CMakeLists.txt +++ /dev/null @@ -1,174 +0,0 @@ -# Copyright (C) 2023 The Qt Company Ltd. -# SPDX-License-Identifier: BSD-3-Clause - -qt_internal_add_module(ExampleIconsPrivate - CONFIG_MODULE_NAME example_icons - STATIC - INTERNAL_MODULE - NO_GENERATE_CPP_EXPORTS -) - -set(icons_resource_files - index.theme - 16x16/document-new.png - 16x16/document-open.png - 16x16/document-print.png - 16x16/document-save.png - 16x16/edit-copy.png - 16x16/edit-cut.png - 16x16/edit-delete.png - 16x16/edit-paste.png - 16x16/edit-redo.png - 16x16/edit-undo.png - 16x16/format-justify-center.png - 16x16/format-justify-fill.png - 16x16/format-justify-left.png - 16x16/format-justify-right.png - 16x16/format-text-bold.png - 16x16/format-text-italic.png - 16x16/format-text-underline.png - 16x16@2/[email protected] - 16x16@2/[email protected] - 16x16@2/[email protected] - 16x16@2/[email protected] - 16x16@2/[email protected] - 16x16@2/[email protected] - 16x16@2/[email protected] - 16x16@2/[email protected] - 16x16@2/[email protected] - 16x16@2/[email protected] - 16x16@2/[email protected] - 16x16@2/[email protected] - 16x16@2/[email protected] - 16x16@2/[email protected] - 16x16@2/[email protected] - 16x16@2/[email protected] - 16x16@2/[email protected] - 32x32/document-new.png - 32x32/document-open.png - 32x32/document-print.png - 32x32/document-save.png - 32x32/edit-copy.png - 32x32/edit-cut.png - 32x32/edit-delete.png - 32x32/edit-paste.png - 32x32/edit-redo.png - 32x32/edit-undo.png - 32x32/format-justify-center.png - 32x32/format-justify-fill.png - 32x32/format-justify-left.png - 32x32/format-justify-right.png - 32x32/format-text-bold.png - 32x32/format-text-italic.png - 32x32/format-text-underline.png - 32x32@2/[email protected] - 32x32@2/[email protected] - 32x32@2/[email protected] - 32x32@2/[email protected] - 32x32@2/[email protected] - 32x32@2/[email protected] - 32x32@2/[email protected] - 32x32@2/[email protected] - 32x32@2/[email protected] - 32x32@2/[email protected] - 32x32@2/[email protected] - 32x32@2/[email protected] - 32x32@2/[email protected] - 32x32@2/[email protected] - 32x32@2/[email protected] - 32x32@2/[email protected] - 32x32@2/[email protected] - 128x128/document-new.png - 128x128/document-open.png - 128x128/document-print.png - 128x128/document-save.png - 128x128/edit-copy.png - 128x128/edit-cut.png - 128x128/edit-delete.png - 128x128/edit-paste.png - 128x128/edit-redo.png - 128x128/edit-undo.png - 128x128/format-justify-center.png - 128x128/format-justify-fill.png - 128x128/format-justify-left.png - 128x128/format-justify-right.png - 128x128/format-text-bold.png - 128x128/format-text-italic.png - 128x128/format-text-underline.png - 128x128@2/[email protected] - 128x128@2/[email protected] - 128x128@2/[email protected] - 128x128@2/[email protected] - 128x128@2/[email protected] - 128x128@2/[email protected] - 128x128@2/[email protected] - 128x128@2/[email protected] - 128x128@2/[email protected] - 128x128@2/[email protected] - 128x128@2/[email protected] - 128x128@2/[email protected] - 128x128@2/[email protected] - 128x128@2/[email protected] - 128x128@2/[email protected] - 128x128@2/[email protected] - 128x128@2/[email protected] - 256x256/document-new.png - 256x256/document-open.png - 256x256/document-print.png - 256x256/document-save.png - 256x256/edit-copy.png - 256x256/edit-cut.png - 256x256/edit-delete.png - 256x256/edit-paste.png - 256x256/edit-redo.png - 256x256/edit-undo.png - 256x256/format-justify-center.png - 256x256/format-justify-fill.png - 256x256/format-justify-left.png - 256x256/format-justify-right.png - 256x256/format-text-bold.png - 256x256/format-text-italic.png - 256x256/format-text-underline.png - 256x256@2/[email protected] - 256x256@2/[email protected] - 256x256@2/[email protected] - 256x256@2/[email protected] - 256x256@2/[email protected] - 256x256@2/[email protected] - 256x256@2/[email protected] - 256x256@2/[email protected] - 256x256@2/[email protected] - 256x256@2/[email protected] - 256x256@2/[email protected] - 256x256@2/[email protected] - 256x256@2/[email protected] - 256x256@2/[email protected] - 256x256@2/[email protected] - 256x256@2/[email protected] - 256x256@2/[email protected] - scalable/document-new.svg - scalable/document-open.svg - scalable/document-print.svg - scalable/document-save.svg - scalable/edit-copy.svg - scalable/edit-cut.svg - scalable/edit-delete.svg - scalable/edit-paste.svg - scalable/edit-redo.svg - scalable/edit-undo.svg - scalable/format-justify-center.svg - scalable/format-justify-fill.svg - scalable/format-justify-left.svg - scalable/format-justify-right.svg - scalable/format-text-bold.svg - scalable/format-text-italic.svg - scalable/format-text-underline.svg -) - -qt_internal_add_resource(ExampleIconsPrivate "example_icons" - PREFIX - "/qt-project.org/icons/example_icons" - FILES - ${icons_resource_files} -) - diff --git a/src/assets/icons/README b/src/assets/icons/README deleted file mode 100644 index 26d94e9ff13..00000000000 --- a/src/assets/icons/README +++ /dev/null @@ -1,29 +0,0 @@ -Copyright (C) 2023 The Qt Company Ltd. -SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -Setting up a project for using Example icon library - -1. Add ExampleIconsPrivate component to your project CMakeList.txt file - ... - find_package(Qt6 - REQUIRED COMPONENTS Core Gui Widgets ExampleIconsPrivate - ) - - target_link_libraries(imageviewer PRIVATE - Qt6::Core - Qt6::Gui - Qt6::Widgets - Qt6::ExampleIconsPrivate - ) - ... - -2. Load the theme - ... - QIcon::setThemeSearchPaths(QIcon::themeSearchPaths() << u":/qt-project.org/icons"_s); - QIcon::setFallbackThemeName(u"example_icons"_s); - ... - -3. Use the icons - ... - const QIcon openIcon = QIcon::fromTheme("document-open"); - ... diff --git a/src/assets/icons/index.theme b/src/assets/icons/index.theme deleted file mode 100644 index e389719e01c..00000000000 --- a/src/assets/icons/index.theme +++ /dev/null @@ -1,46 +0,0 @@ -[Icon Theme] -Name=example_icons - -Directories=16x16,16x16@2,32x32,32x32@2,128x128,128x128@2,256x256,256x256@2,scalable - -[16x16] -Size=16 -Type=Fixed - -[16x16@2] -Size=16 -Scale=2 -Type=Fixed - -[32x32] -Size=32 -Type=Fixed - -[32x32@2] -Size=32 -Scale=2 -Type=Fixed - -[128x128] -Size=128 -Type=Fixed - -[128x128@2] -Size=128 -Scale=2 -Type=Fixed - -[256x256] -Size=256 -Type=Fixed - -[256x256@2] -Size=256 -Scale=2 -Type=Fixed - -[scalable] -Size=512 -Type=Scalable -MinSize=16 -MaxSize=512 diff --git a/src/assets/icons/scalable/document-new.svg b/src/assets/icons/scalable/document-new.svg deleted file mode 100644 index b926a7b0e11..00000000000 --- a/src/assets/icons/scalable/document-new.svg +++ /dev/null @@ -1 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?><svg id="Outlined_icons" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path id="iconDesktopApp_New" d="m15,13c0,.28-.22.5-.5.5h-2v2c0,.28-.22.5-.5.5s-.5-.22-.5-.5v-2h-2c-.28,0-.5-.22-.5-.5s.22-.5.5-.5h2v-2c0-.28.22-.5.5-.5s.5.22.5.5v2h2c.28,0,.5.22.5.5Zm-12,2h5v1H3c-1.1,0-2-.9-2-2V2C1,.9,1.9,0,3,0h7c1.14,1.14,2.93,2.93,4,4v5h-1v-4h-2c-1.1,0-2-.9-2-2V1H3c-.55,0-1,.45-1,1v12c0,.55.45,1,1,1ZM10,1.41v1.59c0,.55.45,1,1,1h1.59l-.82-.82-1.76-1.76Z"/></svg>
\ No newline at end of file diff --git a/src/assets/icons/scalable/document-open.svg b/src/assets/icons/scalable/document-open.svg deleted file mode 100644 index 778c1b7c6e9..00000000000 --- a/src/assets/icons/scalable/document-open.svg +++ /dev/null @@ -1 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?><svg id="Outlined_icons" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path id="iconDesktopApp_Open" d="m14.5,5h-1.5v-1c0-1.1-.9-2-2-2h-5L4,0h-2C.9,0,0,.9,0,2v12c0,1.1.9,2,2,2h9s0,0,0,0c.12,0,.25-.01.36-.03.98-.16,1.94-.94,2.24-1.87l2.29-7.19c.33-1.05-.29-1.91-1.39-1.91ZM1,14V2c0-.55.45-1,1-1h1.59l1.71,1.71c.19.19.44.29.71.29h5c.55,0,1,.45,1,1v1h-5.5c-1.1,0-2.27.86-2.61,1.91l-2.29,7.19c-.09.28-.11.54-.07.78-.32-.17-.54-.49-.54-.87Zm13.94-7.4l-2.29,7.19c-.2.63-.99,1.21-1.65,1.21H3c-.2,0-.36-.05-.43-.15-.07-.1-.07-.26-.01-.45l2.29-7.19c.2-.63.99-1.21,1.65-1.21h8c.2,0,.36.05.43.15.07.1.07.26.01.45Z"/></svg>
\ No newline at end of file diff --git a/src/assets/icons/scalable/document-print.svg b/src/assets/icons/scalable/document-print.svg deleted file mode 100644 index fb8436af81a..00000000000 --- a/src/assets/icons/scalable/document-print.svg +++ /dev/null @@ -1 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?><svg id="Outlined_icons" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path id="iconDesktopApp_Print" d="m14,4h-2v-2c0-1.1-.9-2-2-2h-4c-1.1,0-2,.9-2,2v2h-2c-1.1,0-2,.9-2,2v4c0,1.1.9,2,2,2h2v2c0,1.1.9,2,2,2h4c1.1,0,2-.9,2-2v-2h2c1.1,0,2-.9,2-2v-4c0-1.1-.9-2-2-2ZM5,2c0-.55.45-1,1-1h4c.55,0,1,.45,1,1v2h-6v-2Zm5,13h-4c-.55,0-1-.45-1-1v-5h6v5c0,.55-.45,1-1,1Zm5-5c0,.55-.45,1-1,1h-2v-2h.5c.28,0,.5-.22.5-.5s-.22-.5-.5-.5h-.5s-8,0-8,0h0s-.5,0-.5,0c-.28,0-.5.22-.5.5s.22.5.5.5h.5v2h-2c-.55,0-1-.45-1-1v-4c0-.55.45-1,1-1h12c.55,0,1,.45,1,1v4Zm-5,1.5c0,.28-.22.5-.5.5h-3c-.28,0-.5-.22-.5-.5s.22-.5.5-.5h3c.28,0,.5.22.5.5Zm0,2c0,.28-.22.5-.5.5h-3c-.28,0-.5-.22-.5-.5s.22-.5.5-.5h3c.28,0,.5.22.5.5Z"/></svg>
\ No newline at end of file diff --git a/src/assets/icons/scalable/document-save.svg b/src/assets/icons/scalable/document-save.svg deleted file mode 100644 index 03675f4dab0..00000000000 --- a/src/assets/icons/scalable/document-save.svg +++ /dev/null @@ -1 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?><svg id="Outlined_icons" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path id="iconDesktopApp_Save" d="m16,11h0V2.29c0-1.26-1.02-2.29-2.29-2.29H2.29C1.02,0,0,1.02,0,2.29v8.71h0v1h0v1.71c0,1.26,1.02,2.29,2.29,2.29h11.43c1.26,0,2.29-1.02,2.29-2.29v-1.71h0v-1ZM5.71,1h5.29v4.5c0,.28-.22.5-.5.5h-5c-.28,0-.5-.22-.5-.5V1h.71ZM1,2.29c0-.71.58-1.29,1.29-1.29h1.71v4.5c0,.83.67,1.5,1.5,1.5h5c.83,0,1.5-.67,1.5-1.5V1h1.71c.71,0,1.29.58,1.29,1.29v8.71H1V2.29Zm14,11.43c0,.71-.58,1.29-1.29,1.29H2.29c-.71,0-1.29-.58-1.29-1.29v-1.71h14v1.71Z"/></svg>
\ No newline at end of file diff --git a/src/assets/icons/scalable/edit-copy.svg b/src/assets/icons/scalable/edit-copy.svg deleted file mode 100644 index db53ff11624..00000000000 --- a/src/assets/icons/scalable/edit-copy.svg +++ /dev/null @@ -1 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?><svg id="Outlined_icons" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path id="iconDesktopApp_Copy" d="m12,0h-5c-1.1,0-2,.9-2,2h1c0-.55.45-1,1-1h4v2c0,1.1.9,2,2,2h2v6c0,.55-.45,1-1,1h-2v1h2c1.1,0,2-.9,2-2v-7c-1.07-1.07-2.86-2.86-4-4Zm1,4c-.55,0-1-.45-1-1v-1.59l1.29,1.29,1.29,1.29h-1.59Zm-6-1H2c-1.1,0-2,.9-2,2v9c0,1.1.9,2,2,2h7c1.1,0,2-.9,2-2v-7c-1.07-1.07-2.86-2.86-4-4Zm3,6v5c0,.55-.45,1-1,1H2c-.55,0-1-.45-1-1V5c0-.55.45-1,1-1h4v2c0,1.1.9,2,2,2h2v1Zm-2-2c-.55,0-1-.45-1-1v-1.59l1.29,1.29,1.29,1.29h-1.59Z"/></svg>
\ No newline at end of file diff --git a/src/assets/icons/scalable/edit-cut.svg b/src/assets/icons/scalable/edit-cut.svg deleted file mode 100644 index 7f75d0b829d..00000000000 --- a/src/assets/icons/scalable/edit-cut.svg +++ /dev/null @@ -1 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?><svg id="Outlined_icons" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path id="iconDesktopApp_Cut" d="m15.22,12.05l-7.39-3.55,7.39-3.55c.25-.12.35-.42.23-.67-.12-.25-.42-.35-.67-.23l-8.12,3.9-2.48-1.19c1.07-.46,1.81-1.52,1.81-2.75,0-1.66-1.34-3-3-3S0,2.34,0,4c0,1.28.81,2.36,1.93,2.8.1.05.22.1.35.15l3.23,1.55-3.23,1.55c-.1.05-.18.09-.26.13-1.18.41-2.02,1.51-2.02,2.82,0,1.66,1.34,3,3,3s3-1.34,3-3c0-1.24-.75-2.29-1.81-2.75l2.48-1.19,8.12,3.9c.07.03.14.05.22.05.19,0,.37-.1.45-.28.12-.25.01-.55-.23-.67ZM3,2c1.1,0,2,.9,2,2s-.9,2-2,2-2-.9-2-2,.9-2,2-2Zm2,11c0,1.1-.9,2-2,2s-2-.9-2-2,.9-2,2-2,2,.9,2,2Z"/></svg>
\ No newline at end of file diff --git a/src/assets/icons/scalable/edit-delete.svg b/src/assets/icons/scalable/edit-delete.svg deleted file mode 100644 index 15d1a9c7fd6..00000000000 --- a/src/assets/icons/scalable/edit-delete.svg +++ /dev/null @@ -1 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?><svg id="Outlined_icons" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path id="iconDesktopApp_Delete" d="m8,0C3.58,0,0,3.58,0,8s3.58,8,8,8,8-3.58,8-8S12.42,0,8,0Zm0,15c-3.86,0-7-3.14-7-7S4.14,1,8,1s7,3.14,7,7-3.14,7-7,7Zm2.83-9.12l-2.12,2.12,2.12,2.12c.2.2.2.51,0,.71-.1.1-.23.15-.35.15s-.26-.05-.35-.15l-2.12-2.12-2.12,2.12c-.1.1-.23.15-.35.15s-.26-.05-.35-.15c-.2-.2-.2-.51,0-.71l2.12-2.12-2.12-2.12c-.2-.2-.2-.51,0-.71s.51-.2.71,0l2.12,2.12,2.12-2.12c.2-.2.51-.2.71,0s.2.51,0,.71Z"/></svg>
\ No newline at end of file diff --git a/src/assets/icons/scalable/edit-paste.svg b/src/assets/icons/scalable/edit-paste.svg deleted file mode 100644 index 57e94d917d2..00000000000 --- a/src/assets/icons/scalable/edit-paste.svg +++ /dev/null @@ -1 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?><svg id="Outlined_icons" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path id="iconDesktopApp_Paste" d="m14.09,6.09c-.71-.74-1.44-1.5-2.09-2.09h-3.78c-1.23,0-2.22.9-2.22,2v8c0,1.1.99,2,2.22,2h5.56c1.23,0,2.22-.9,2.22-2v-6c-.52-.52-1.21-1.21-1.91-1.91Zm-2.09-.68l1.38,1.38c.41.43.8.83,1.18,1.21h-1.56c-.55,0-1-.45-1-1v-1.59Zm3,5.59v3c0,.55-.55,1-1.22,1h-5.56c-.67,0-1.22-.45-1.22-1V6c0-.55.55-1,1.22-1h2.78v2c0,1.1.9,2,2,2h2v2Zm-6.5,0h5c.28,0,.5.22.5.5s-.22.5-.5.5h-5c-.28,0-.5-.22-.5-.5s.22-.5.5-.5ZM5.5,3h1c.83,0,1.5-.67,1.5-1.5v-.5h2c.55,0,1,.45,1,1v1h1v-1C12,.9,11.1,0,10,0h-2s-4,0-4,0h0s-2,0-2,0C.9,0,0,.9,0,2v10c0,1.1.9,2,2,2h3v-1h-3c-.55,0-1-.45-1-1V2c0-.55.45-1,1-1h2v.5c0,.83.67,1.5,1.5,1.5Zm1.5-1.5c0,.28-.22.5-.5.5h-1c-.28,0-.5-.22-.5-.5v-.5h2v.5Zm7,12c0,.28-.22.5-.5.5h-5c-.28,0-.5-.22-.5-.5s.22-.5.5-.5h5c.28,0,.5.22.5.5Z"/></svg>
\ No newline at end of file diff --git a/src/assets/icons/scalable/edit-redo.svg b/src/assets/icons/scalable/edit-redo.svg deleted file mode 100644 index 92d60e1dd8c..00000000000 --- a/src/assets/icons/scalable/edit-redo.svg +++ /dev/null @@ -1 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?><svg id="Outlined_icons" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path id="iconDesktopApp_Redo" d="m15.85,4.68l-3.54-3.54c-.2-.2-.51-.2-.71,0s-.2.51,0,.71l2.68,2.68H2.5c-1.38,0-2.5,1.12-2.5,2.5v4c0,1.38,1.12,2.5,2.5,2.5h7c.28,0,.5-.22.5-.5s-.22-.5-.5-.5H2.5c-.83,0-1.5-.67-1.5-1.5v-4c0-.83.67-1.5,1.5-1.5h11.79l-2.68,2.68c-.2.2-.2.51,0,.71.1.1.23.15.35.15s.26-.05.35-.15l3.54-3.54c.2-.2.2-.51,0-.71Z"/></svg>
\ No newline at end of file diff --git a/src/assets/icons/scalable/edit-undo.svg b/src/assets/icons/scalable/edit-undo.svg deleted file mode 100644 index 91731bb86fa..00000000000 --- a/src/assets/icons/scalable/edit-undo.svg +++ /dev/null @@ -1 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?><svg id="Outlined_icons" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path id="iconDesktopApp_Undo" d="m13.5,4.54H1.71l2.68-2.68c.2-.2.2-.51,0-.71s-.51-.2-.71,0L.15,4.68c-.2.2-.2.51,0,.71l3.54,3.54c.1.1.23.15.35.15s.26-.05.35-.15c.2-.2.2-.51,0-.71l-2.68-2.68h11.79c.83,0,1.5.67,1.5,1.5v4c0,.83-.67,1.5-1.5,1.5h-7c-.28,0-.5.22-.5.5s.22.5.5.5h7c1.38,0,2.5-1.12,2.5-2.5v-4c0-1.38-1.12-2.5-2.5-2.5Z"/></svg>
\ No newline at end of file diff --git a/src/assets/icons/scalable/format-justify-center.svg b/src/assets/icons/scalable/format-justify-center.svg deleted file mode 100644 index 9822c95f2fa..00000000000 --- a/src/assets/icons/scalable/format-justify-center.svg +++ /dev/null @@ -1 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?><svg id="Outlined_icons" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path id="iconTextEditor_alignCenter" d="m15.5,8H.5c-.28,0-.5-.22-.5-.5h0c0-.28.22-.5.5-.5h15c.28,0,.5.22.5.5h0c0,.28-.22.5-.5.5Zm-2,3.5h0c0-.28-.22-.5-.5-.5H3c-.28,0-.5.22-.5.5h0c0,.28.22.5.5.5h10c.28,0,.5-.22.5-.5Zm2.5,4h0c0-.28-.22-.5-.5-.5H.5c-.28,0-.5.22-.5.5h0c0,.28.22.5.5.5h15c.28,0,.5-.22.5-.5Zm-2.5-12h0c0-.28-.22-.5-.5-.5H3c-.28,0-.5.22-.5.5h0c0,.28.22.5.5.5h10c.28,0,.5-.22.5-.5Z"/></svg>
\ No newline at end of file diff --git a/src/assets/icons/scalable/format-justify-fill.svg b/src/assets/icons/scalable/format-justify-fill.svg deleted file mode 100644 index 2fa7ddfa40d..00000000000 --- a/src/assets/icons/scalable/format-justify-fill.svg +++ /dev/null @@ -1 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?><svg id="Outlined_icons" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path id="iconTextEditor_alignJustify" d="m15.5,8H.5c-.28,0-.5-.22-.5-.5h0c0-.28.22-.5.5-.5h15c.28,0,.5.22.5.5h0c0,.28-.22.5-.5.5Zm.5,3.5h0c0-.28-.22-.5-.5-.5H.5c-.28,0-.5.22-.5.5h0c0,.28.22.5.5.5h15c.28,0,.5-.22.5-.5Zm0,4h0c0-.28-.22-.5-.5-.5H.5c-.28,0-.5.22-.5.5h0c0,.28.22.5.5.5h15c.28,0,.5-.22.5-.5Zm0-12h0c0-.28-.22-.5-.5-.5H.5c-.28,0-.5.22-.5.5h0c0,.28.22.5.5.5h15c.28,0,.5-.22.5-.5Z"/></svg>
\ No newline at end of file diff --git a/src/assets/icons/scalable/format-justify-left.svg b/src/assets/icons/scalable/format-justify-left.svg deleted file mode 100644 index 99d666428d9..00000000000 --- a/src/assets/icons/scalable/format-justify-left.svg +++ /dev/null @@ -1 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?><svg id="Outlined_icons" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path id="iconTextEditor_alignLeft" d="m15.5,8H.5c-.28,0-.5-.22-.5-.5h0c0-.28.22-.5.5-.5h15c.28,0,.5.22.5.5h0c0,.28-.22.5-.5.5Zm-4.5,3.5h0c0-.28-.22-.5-.5-.5H.5c-.28,0-.5.22-.5.5h0c0,.28.22.5.5.5h10c.28,0,.5-.22.5-.5Zm5,4h0c0-.28-.22-.5-.5-.5H.5c-.28,0-.5.22-.5.5h0c0,.28.22.5.5.5h15c.28,0,.5-.22.5-.5ZM11,3.5h0c0-.28-.22-.5-.5-.5H.5c-.28,0-.5.22-.5.5h0c0,.28.22.5.5.5h10c.28,0,.5-.22.5-.5Z"/></svg>
\ No newline at end of file diff --git a/src/assets/icons/scalable/format-justify-right.svg b/src/assets/icons/scalable/format-justify-right.svg deleted file mode 100644 index 7041f5e3f88..00000000000 --- a/src/assets/icons/scalable/format-justify-right.svg +++ /dev/null @@ -1 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?><svg id="Outlined_icons" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path id="iconTextEditor_alignRight" d="m15.5,8H.5c-.28,0-.5-.22-.5-.5h0c0-.28.22-.5.5-.5h15c.28,0,.5.22.5.5h0c0,.28-.22.5-.5.5Zm.5,3.5h0c0-.28-.22-.5-.5-.5H5.5c-.28,0-.5.22-.5.5h0c0,.28.22.5.5.5h10c.28,0,.5-.22.5-.5Zm0,4h0c0-.28-.22-.5-.5-.5H.5c-.28,0-.5.22-.5.5h0c0,.28.22.5.5.5h15c.28,0,.5-.22.5-.5Zm0-12h0c0-.28-.22-.5-.5-.5H5.5c-.28,0-.5.22-.5.5h0c0,.28.22.5.5.5h10c.28,0,.5-.22.5-.5Z"/></svg>
\ No newline at end of file diff --git a/src/assets/icons/scalable/format-text-bold.svg b/src/assets/icons/scalable/format-text-bold.svg deleted file mode 100644 index c0f43e0a692..00000000000 --- a/src/assets/icons/scalable/format-text-bold.svg +++ /dev/null @@ -1 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?><svg id="Outlined_icons" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path id="iconTextEditor_Bold" d="m12.06,7.75c.65-.36,1.13-.81,1.44-1.35.3-.55.46-1.29.46-2.24,0-1.45-.4-2.5-1.21-3.16-.81-.66-2.03-.99-3.67-.99H3v16h6.26c3.39,0,5.09-1.51,5.09-4.53,0-1.88-.76-3.12-2.29-3.71ZM5.59,2.24h3.34c1.59,0,2.38.74,2.38,2.22,0,1.57-.76,2.36-2.29,2.36h-3.43V2.24Zm5.45,10.98c-.43.36-1.07.54-1.93.54h-3.53v-4.74h3.48c.75,0,1.37.17,1.87.53.5.35.75.96.75,1.83s-.21,1.49-.64,1.85Z"/></svg>
\ No newline at end of file diff --git a/src/assets/icons/scalable/format-text-italic.svg b/src/assets/icons/scalable/format-text-italic.svg deleted file mode 100644 index 43df7ca54dc..00000000000 --- a/src/assets/icons/scalable/format-text-italic.svg +++ /dev/null @@ -1 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?><svg id="Outlined_icons" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><polygon id="iconTextEditor_Italic" points="6.63 0 6.18 2.01 8.18 2.01 5.45 13.99 3.45 13.99 3 16 9.56 16 10.01 13.99 8.01 13.99 10.74 2.01 12.74 2.01 13.19 0 6.63 0"/></svg>
\ No newline at end of file diff --git a/src/assets/icons/scalable/format-text-underline.svg b/src/assets/icons/scalable/format-text-underline.svg deleted file mode 100644 index 62778fc579e..00000000000 --- a/src/assets/icons/scalable/format-text-underline.svg +++ /dev/null @@ -1 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?><svg id="Outlined_icons" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path id="iconTextEditor_Underline" d="m3.38,11.88c-.92-.75-1.38-1.94-1.38-3.57V0h2.44v8.35c0,1.79,1.02,2.69,3.06,2.69s3.06-.9,3.06-2.69V0h2.44v8.31c0,1.63-.46,2.82-1.39,3.57-.92.75-2.3,1.12-4.13,1.12s-3.2-.37-4.11-1.12Zm10.12,3.12H1.5c-.28,0-.5.22-.5.5s.22.5.5.5h12c.28,0,.5-.22.5-.5s-.22-.5-.5-.5Z"/></svg>
\ No newline at end of file diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt index 4d83bbf794e..249b9b8c1ee 100644 --- a/src/corelib/CMakeLists.txt +++ b/src/corelib/CMakeLists.txt @@ -16,7 +16,11 @@ qt_internal_extend_sbom(WrapZLIB::WrapZLIB if(ANDROID) set(corelib_extra_cmake_files - "${CMAKE_CURRENT_SOURCE_DIR}/${QT_CMAKE_EXPORT_NAMESPACE}AndroidMacros.cmake") + "${CMAKE_CURRENT_SOURCE_DIR}/${QT_CMAKE_EXPORT_NAMESPACE}AndroidMacros.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/${QT_CMAKE_EXPORT_NAMESPACE}AndroidDynamicFeatureHelpers.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/${QT_CMAKE_EXPORT_NAMESPACE}AndroidGradleHelpers.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/${QT_CMAKE_EXPORT_NAMESPACE}AndroidPermissionHelpers.cmake" + ) endif() if(WASM) set(corelib_extra_cmake_files diff --git a/src/corelib/Qt6AndroidDynamicFeatureHelpers.cmake b/src/corelib/Qt6AndroidDynamicFeatureHelpers.cmake new file mode 100644 index 00000000000..e8a81bde1d7 --- /dev/null +++ b/src/corelib/Qt6AndroidDynamicFeatureHelpers.cmake @@ -0,0 +1,152 @@ +# Copyright (C) 2025 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause +# Collects the dynamic features for the target + +function(_qt_internal_android_add_dynamic_feature_deployment target) + get_target_property(dynamic_features ${target} _qt_android_dynamic_features) + if(NOT dynamic_features) + return() + endif() + + foreach(dynamic_feature IN LISTS dynamic_features) + get_target_property(is_imported ${dynamic_feature} IMPORTED) + if(is_imported) + message(FATAL_ERROR "Imported target ${dynamic_feature} can not be a" + " 'DYNAMIC_FEATURE'.") + endif() + + get_target_property(type ${dynamic_feature} TYPE) + if(NOT type STREQUAL "SHARED_LIBRARY") + message(FATAL_ERROR "Cannot make ${dynamic_feature} 'DYNAMIC_FEATURE'." + " The target must be the 'SHARED_LIBRARY'.") + endif() + + get_target_property(android_type ${dynamic_feature} _qt_android_target_type) + if(NOT android_type STREQUAL "" AND NOT android_type MATCHES "-NOTFOUND$" + AND NOT android_type STREQUAL "DYNAMIC_FEATURE") + message(FATAL_ERROR "Cannot make ${dynamic_feature} 'DYNAMIC_FEATURE'," + " it's already '${android_type}'. The target must be the plain 'SHARED_LIBRARY'.") + endif() + + # Mark the target as DYNAMIC_FEATURE, since we used it in this role once. + set_target_properties(${dynamic_feature} PROPERTIES _qt_android_target_type DYNAMIC_FEATURE) + _qt_internal_set_android_dynamic_feature_gradle_defaults(${dynamic_feature}) + + _qt_internal_android_get_dynamic_feature_deployment_dir(dynamic_feature_deployment_dir + ${target} ${dynamic_feature}) + _qt_internal_android_generate_target_build_gradle(${dynamic_feature} + DEPLOYMENT_DIR "${dynamic_feature_deployment_dir}") + _qt_internal_android_generate_dynamic_feature_manifest(${target} ${dynamic_feature}) + _qt_internal_android_copy_dynamic_feature(${target} ${dynamic_feature}) + endforeach() +endfunction() + +# Sets the default values of the gradle properties for the Android dynamic feature target. +function(_qt_internal_set_android_dynamic_feature_gradle_defaults target) + _qt_internal_android_java_dir(android_java_dir) + + # TODO: make androidx.core:core versionc configurable. + # Currently, it is hardcoded to 1.16.0. + set(implementation_dependencies "project(':app')" "'androidx.core:core:1.16.0'") + + set_target_properties(${target} PROPERTIES + _qt_android_gradle_java_source_dirs "src;java" + _qt_android_gradle_aidl_source_dirs "src;aidl" + _qt_android_gradle_res_source_dirs "res" + _qt_android_gradle_resources_source_dirs "resources" + _qt_android_gradle_renderscript_source_dirs "src" + _qt_android_gradle_assets_source_dirs "assets" + _qt_android_gradle_jniLibs_source_dirs "libs" + _qt_android_manifest "AndroidManifest.xml" + _qt_android_gradle_implementation_dependencies "${implementation_dependencies}" + ) +endfunction() + +# Copies the dynamic feature library to the respective gradle build tree. +function(_qt_internal_android_copy_dynamic_feature target dynamic_feature) + if(NOT TARGET ${dynamic_feature}) + message(FATAL_ERROR "${dynamic_feature} is not a target.") + endif() + + _qt_internal_android_get_dynamic_feature_deployment_dir(dynamic_feature_deployment_dir + ${target} ${dynamic_feature}) + + set(dynamic_feature_libs_dir "${dynamic_feature_deployment_dir}/libs/${CMAKE_ANDROID_ARCH_ABI}") + get_target_property(output_name ${dynamic_feature} OUTPUT_NAME) + if(NOT output_name) + get_target_property(suffix "${dynamic_feature}" SUFFIX) + set(output_name "lib${dynamic_feature}${suffix}") + endif() + set(output_file_path "${dynamic_feature_libs_dir}/${output_name}") + _qt_internal_copy_file_if_different_command(copy_command + "$<TARGET_FILE:${dynamic_feature}>" + "${output_file_path}" + ) + add_custom_command(OUTPUT ${output_file_path} + COMMAND ${copy_command} + DEPENDS ${dynamic_feature} + COMMENT "Copying ${dynamic_feature} dynamic feature to ${target} deployment directory" + ) + add_custom_target(${target}_deploy_dynamic_features DEPENDS "${output_file_path}") +endfunction() + +# Generates the feature name strings and copy them to the respective deployment directory. +function(_qt_internal_android_generate_dynamic_feature_names target) + get_target_property(dynamic_features ${target} _qt_android_dynamic_features) + if(NOT dynamic_features) + return() + endif() + + # Collect the titles + string(JOIN "\n" content + "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + "<resources>" + ) + foreach(feature IN LISTS dynamic_features) + string(APPEND content "\n <string name=\"${feature}_title\">${feature}</string>") + endforeach() + string(APPEND content "\n</resources>") + + _qt_internal_android_get_target_deployment_dir(deployment_dir ${target}) + # TODO: androiddeployqt wipes the android build directory. Generate feature_names.xml target + # build dir and copy after androiddeployqt run. We should skip feature_names.xml copying when + # androiddeployqt is not involved into the deployment process anymore. + # + # set(output_file "${deployment_dir}/res/values/feature_names.xml") + set(output_file "$<TARGET_PROPERTY:${target},BINARY_DIR>/res/values/feature_names.xml") + _qt_internal_configure_file(GENERATE OUTPUT "${output_file}" CONTENT "${content}") + set(output_file_in_deployment_dir "${deployment_dir}/res/values/feature_names.xml") + add_custom_command(OUTPUT "${output_file_in_deployment_dir}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${output_file}" + "${output_file_in_deployment_dir}" + DEPENDS "${output_file}" ${target}_android_deploy_aux + VERBATIM + ) + add_custom_target(${target}_copy_feature_names + DEPENDS + "${output_file_in_deployment_dir}" + ) +endfunction() + +# Returns the dynamic feature deployment directory in the target build tree. +function(_qt_internal_android_get_dynamic_feature_deployment_dir out_var target dynamic_feature) + _qt_internal_android_get_target_android_build_dir(android_build_dir ${target}) + set(${out_var} "${android_build_dir}/${dynamic_feature}" PARENT_SCOPE) +endfunction() + +# Generates the AndroidManifest.xml file for the dynamic_feature. +function(_qt_internal_android_generate_dynamic_feature_manifest target dynamic_feature) + set(android_manifest_filename AndroidManifest.xml) + _qt_internal_android_get_dynamic_feature_deployment_dir(dynamic_feature_deployment_dir ${target} + ${dynamic_feature}) + + _qt_internal_android_get_template_path(template_file ${target} + "dynamic_feature/${android_manifest_filename}") + + set(APP_TARGET "${target}") + set(TITLE_VAR "@string/${dynamic_feature}_title") + + set(output_file "${dynamic_feature_deployment_dir}/AndroidManifest.xml") + _qt_internal_configure_file(CONFIGURE OUTPUT "${output_file}" INPUT "${template_file}") +endfunction() diff --git a/src/corelib/Qt6AndroidGradleHelpers.cmake b/src/corelib/Qt6AndroidGradleHelpers.cmake new file mode 100644 index 00000000000..09184c93b69 --- /dev/null +++ b/src/corelib/Qt6AndroidGradleHelpers.cmake @@ -0,0 +1,631 @@ +# Copyright (C) 2024 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +# Returns the path to the template file from either user defined template directory, or +# Qt default template directory. +function(_qt_internal_android_get_template_path out_var target template_name) + if(template_name STREQUAL "") + message(FATAL_ERROR "Template name is empty." + " This is the Qt issue, please report a bug at https://bugreports.qt.io.") + endif() + + _qt_internal_android_template_dir(template_directory) + get_filename_component(template_directory "${template_directory}" ABSOLUTE) + + # The paths are ordered according to their priority, from highest to lowest. + set(possible_paths + "${template_directory}/${template_name}.in" + ) + + get_target_property(android_target_type ${target} _qt_android_target_type) + if(android_target_type STREQUAL "APPLICATION") + _qt_internal_android_get_package_source_dir(user_template_directory ${target}) + get_filename_component(user_template_directory "${user_template_directory}" ABSOLUTE) + + # Add user template with the higher priority + list(PREPEND possible_paths "${user_template_directory}/${template_name}.in") + endif() + + set(template_path "") + foreach(possible_path IN LISTS possible_paths) + if(EXISTS "${possible_path}") + set(template_path "${possible_path}") + break() + endif() + endforeach() + + if(template_path STREQUAL "") + message(FATAL_ERROR "'${template_name}' is not found." + " This is the Qt issue, please report a bug at https://bugreports.qt.io.") + endif() + + set(${out_var} "${template_path}" PARENT_SCOPE) +endfunction() + +# Generates the settings.gradle file for the target. Writes the result to the target android build +# directory. +function(_qt_internal_android_generate_bundle_settings_gradle target) + set(settings_gradle_filename "settings.gradle") + _qt_internal_android_get_target_android_build_dir(android_build_dir ${target}) + set(settings_gradle_file "${android_build_dir}/${settings_gradle_filename}") + + # Skip generating the file if it's already provided by user. + get_target_property(deployment_files ${target} _qt_android_deployment_files) + if("${settings_gradle_file}" IN_LIST deployment_files) + return() + endif() + + _qt_internal_android_get_template_path(template_file ${target} "${settings_gradle_filename}") + + set(android_app_name "$<TARGET_PROPERTY:${target},QT_ANDROID_APP_NAME>") + string(JOIN "" ROOT_PROJECT_NAME + "$<IF:$<BOOL:${android_app_name}>," + "${android_app_name}," + "${target}" + ">" + ) + + set(target_dynamic_features "$<TARGET_PROPERTY:${target},_qt_android_dynamic_features>") + set(include_prefix "include(\":") + set(include_suffix "\")") + set(include_glue "${include_suffix}\n${include_prefix}") + string(JOIN "" SUBPROJECTS + "$<$<BOOL:${target_dynamic_features}>:" + "${include_prefix}" + "$<JOIN:${target_dynamic_features},${include_glue}>" + "${include_suffix}" + ">" + ) + + _qt_internal_configure_file(GENERATE OUTPUT ${settings_gradle_file} + INPUT "${template_file}") + set_property(TARGET ${target} APPEND PROPERTY _qt_android_deployment_files + "${settings_gradle_file}") +endfunction() + +# Generates the source sets for the target. +function(_qt_internal_android_get_gradle_source_sets out_var target) + set(known_types java aidl res resources renderscript assets jniLibs) + set(source_set "") + set(indent " ") + foreach(type IN LISTS known_types) + set(source_dirs + "$<GENEX_EVAL:$<TARGET_PROPERTY:${target},_qt_android_gradle_${type}_source_dirs>>") + string(JOIN "" source_set + "${source_set}" + "$<$<BOOL:${source_dirs}>:" + "${indent}${type}.srcDirs = ['$<JOIN:${source_dirs},'$<COMMA> '>']\n" + ">" + ) + endforeach() + + set(manifest + "$<TARGET_PROPERTY:${target},_qt_android_manifest>") + string(JOIN "" source_set + "${source_set}" + "$<$<BOOL:${manifest}>:" + "${indent}manifest.srcFile '${manifest}'\n" + ">" + ) + set(${out_var} "${source_set}" PARENT_SCOPE) +endfunction() + +# Generates the gradle dependency list for the target. +function(_qt_internal_android_get_gradle_dependencies out_var target) + # Use dependencies from file tree by default + set(known_dependencies + "implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])") + foreach(dep_type implementation api) + string(JOIN "\n " dep_prefix + "\n //noinspection GradleDependency" + "${dep_type} " + ) + set(dep_postfix "") + set(dep_property "$<GENEX_EVAL:$<TARGET_PROPERTY:${target},_qt_android_gradle_${dep_type}_dependencies>>") + string(JOIN "" known_dependencies + "${known_dependencies}" + "$<$<BOOL:${dep_property}>:" + "${dep_prefix}$<JOIN:${dep_property},${dep_postfix}${dep_prefix}>${dep_postfix}" + ">" + ) + endforeach() + set(${out_var} "${known_dependencies}" PARENT_SCOPE) +endfunction() + +# Sets the default values of the gradle properties for the Android executable target. +function(_qt_internal_set_android_application_gradle_defaults target) + _qt_internal_android_java_dir(android_java_dir) + + set(target_dynamic_features "$<TARGET_PROPERTY:${target},_qt_android_dynamic_features>") + string(JOIN "" implementation_dependencies + "$<$<BOOL:${target_dynamic_features}>:'com.google.android.play:feature-delivery:2.1.0'>" + ) + # TODO: make androidx.core:core version configurable. + # Currently, it is hardcoded to 1.16.0. + list(APPEND implementation_dependencies "'androidx.core:core:1.16.0'") + + set_target_properties(${target} PROPERTIES + _qt_android_gradle_java_source_dirs "${android_java_dir}/src;src;java" + _qt_android_gradle_aidl_source_dirs "${android_java_dir}/src;src;aidl" + _qt_android_gradle_res_source_dirs "${android_java_dir}/res;res" + _qt_android_gradle_resources_source_dirs "resources" + _qt_android_gradle_renderscript_source_dirs "src" + _qt_android_gradle_assets_source_dirs "assets" + _qt_android_gradle_jniLibs_source_dirs "libs" + _qt_android_manifest "AndroidManifest.xml" + _qt_android_gradle_implementation_dependencies "${implementation_dependencies}" + ) +endfunction() + +# Generates the build.gradle file for the target. Writes the result to the target app deployment +# directory. +function(_qt_internal_android_generate_target_build_gradle target) + cmake_parse_arguments(PARSE_ARGV 1 arg "" "DEPLOYMENT_DIR" "") + + if(NOT arg_DEPLOYMENT_DIR) + message(FATAL_ERROR "DEPLOYMENT_DIR is not specified.") + endif() + + set(build_gradle_filename "build.gradle") + set(out_file "${arg_DEPLOYMENT_DIR}/${build_gradle_filename}") + + # Skip generating the file if it's already provided by user. + get_target_property(deployment_files ${target} _qt_android_deployment_files) + if("${out_file}" IN_LIST deployment_files) + return() + endif() + + # TODO: The current build.gradle.in templates hardcodes couple values that needs to be + # configurable in the future. For example the buildscript dependencies, or the use of + # androidx.core:core:1.13.1 and the dependency for all user applications. + + _qt_internal_android_get_gradle_property(PACKAGE_NAME ${target} + QT_ANDROID_PACKAGE_NAME "org.qtproject.example.$<MAKE_C_IDENTIFIER:${target}>") + + _qt_internal_android_get_target_sdk_build_tools_revision(ANDROID_BUILD_TOOLS_VERSION + ${target}) + + _qt_internal_detect_latest_android_platform(ANDROID_COMPILE_SDK_VERSION) + if(NOT ANDROID_COMPILE_SDK_VERSION) + message(FATAL_ERROR "Unable to detect the android platform in ${ANDROID_SDK_ROOT}. " + "Please check your Android SDK installation.") + endif() + + _qt_internal_android_get_gradle_source_sets(SOURCE_SETS ${target}) + _qt_internal_android_get_gradle_dependencies(GRADLE_DEPENDENCIES ${target}) + + _qt_internal_android_get_gradle_property(min_sdk_version ${target} + QT_ANDROID_MIN_SDK_VERSION "28") + + _qt_internal_android_get_gradle_property(target_sdk_version ${target} + QT_ANDROID_TARGET_SDK_VERSION "34") + + set(target_abis "$<TARGET_PROPERTY:${target},_qt_android_abis>") + set(target_abi_list "$<JOIN:${target_abis};${CMAKE_ANDROID_ARCH_ABI},'$<COMMA> '>") + + string(JOIN "\n " DEFAULT_CONFIG_VALUES + "resConfig 'en'" + "minSdkVersion ${min_sdk_version}" + "targetSdkVersion ${target_sdk_version}" + "ndk.abiFilters = ['${target_abi_list}']" + ) + + set(target_dynamic_features "$<TARGET_PROPERTY:${target},_qt_android_dynamic_features>") + set(include_prefix "\":") + set(include_suffix "\"") + set(include_glue "${include_suffix}$<COMMA>${include_prefix}") + string(APPEND ANDROID_DEPLOYMENT_EXTRAS + "$<$<BOOL:${target_dynamic_features}>:dynamicFeatures = [" + "${include_prefix}" + "$<JOIN:${target_dynamic_features},${include_glue}>" + "${include_suffix}]" + ">" + ) + + get_target_property(android_target_type ${target} _qt_android_target_type) + if(android_target_type STREQUAL "APPLICATION") + set(GRADLE_PLUGIN_TYPE "com.android.application") + set(template_subdir "app") + elseif(android_target_type STREQUAL "DYNAMIC_FEATURE") + set(GRADLE_PLUGIN_TYPE "com.android.dynamic-feature") + set(template_subdir "dynamic_feature") + else() + message(FATAL_ERROR "Unsupported target type for android bundle deployment ${target}") + endif() + + _qt_internal_android_get_template_path(template_file ${target} + "${template_subdir}/${build_gradle_filename}") + _qt_internal_configure_file(GENERATE + OUTPUT "${out_file}" + INPUT "${template_file}" + ) + set_property(TARGET ${target} APPEND PROPERTY _qt_android_deployment_files "${out_file}") +endfunction() + +# Prepares the artifacts for the gradle build of the target. +function(_qt_internal_android_prepare_gradle_build target) + _qt_internal_android_get_target_android_build_dir(android_build_dir ${target}) + _qt_internal_android_get_target_deployment_dir(deployment_dir ${target}) + + _qt_internal_android_copy_gradle_files(${target} "${android_build_dir}") + _qt_internal_android_copy_target_package_sources(${target}) + + _qt_internal_android_generate_bundle_gradle_properties(${target}) + _qt_internal_android_generate_bundle_settings_gradle(${target}) + _qt_internal_android_generate_bundle_local_properties(${target}) + _qt_internal_android_generate_target_build_gradle(${target} DEPLOYMENT_DIR "${deployment_dir}") + _qt_internal_android_generate_target_gradle_properties(${target} + DEPLOYMENT_DIR "${deployment_dir}") + _qt_internal_android_generate_target_android_manifest(${target} + DEPLOYMENT_DIR "${deployment_dir}") + + + _qt_internal_android_add_gradle_build(${target} apk) + _qt_internal_android_add_gradle_build(${target} aab) + + # Make global apk, aab, and aar targets depend on the respective targets. + _qt_internal_android_add_global_package_dependencies(${target}) + _qt_internal_create_global_apk_all_target_if_needed() +endfunction() + +# Adds the modern gradle build targets. +# These targets use the settings.gradle based build directory structure. +function(_qt_internal_android_add_gradle_build target type) + _qt_internal_android_get_deployment_type_option(android_deployment_type_option + "assembleRelease" "assembleDebug") + + _qt_internal_android_gradlew_name(gradlew_file_name) + _qt_internal_android_get_target_android_build_dir(android_build_dir ${target}) + set(gradlew "${android_build_dir}/${gradlew_file_name}") + + set(extra_args "") + if(type STREQUAL "aab") + set(extra_args "bundle") + endif() + + set(package_file_path "${android_build_dir}/${target}.${type}") + + _qt_internal_android_package_path(package_build_dir ${target} ${type}) + _qt_internal_android_get_deployment_type_option(deployment_type_suffix + "release" "debug") + set(package_build_file_path + "${package_build_dir}/${deployment_type_suffix}/app-${deployment_type_suffix}.${type}") + + set(extra_deps "") + if(TARGET ${target}_copy_feature_names) + list(APPEND extra_deps ${target}_copy_feature_names) + endif() + + if(TARGET ${target}_deploy_dynamic_features) + list(APPEND extra_deps ${target}_deploy_dynamic_features) + endif() + + set(gradle_scripts "$<TARGET_PROPERTY:${target},_qt_android_deployment_files>") + add_custom_command(OUTPUT "${package_file_path}" + BYPRODUCTS "${package_build_file_path}" + COMMAND + "${gradlew}" ${android_deployment_type_option} ${extra_args} + COMMAND + ${CMAKE_COMMAND} -E copy_if_different + "${package_build_file_path}" "${package_file_path}" + DEPENDS + ${target} + ${gradle_scripts} + ${target}_copy_gradle_files + ${target}_android_deploy_aux + ${extra_deps} + WORKING_DIRECTORY + "${android_build_dir}" + VERBATIM + ) + + add_custom_target(${target}_make_${type} DEPENDS "${package_file_path}") +endfunction() + +# Returns the path to the android executable package either apk or aab. +function(_qt_internal_android_package_path out_var target type) + set(supported_package_types apk aab) + if(NOT type IN_LIST supported_package_types) + message(FATAL_ERROR "Invalid package type, supported types: ${supported_package_types}") + endif() + + # aab packages are located in the bundle directory + if(type STREQUAL "aab") + set(type "bundle") + endif() + + _qt_internal_android_get_target_deployment_dir(deployment_dir ${target}) + + set(${out_var} "${deployment_dir}/build/outputs/${type}" PARENT_SCOPE) +endfunction() + +# Returns the path to the gradle build directory. +function(_qt_internal_android_gradle_template_dir out_var) + if(PROJECT_NAME STREQUAL "QtBase" OR QT_SUPERBUILD) + set(${out_var} "${QtBase_SOURCE_DIR}/src/3rdparty/gradle" PARENT_SCOPE) + else() + set(${out_var} "${QT6_INSTALL_PREFIX}/${QT6_INSTALL_DATA}/src/3rdparty/gradle" PARENT_SCOPE) + endif() +endfunction() + +# Returns the path to the android java dir. +function(_qt_internal_android_java_dir out_var) + if(PROJECT_NAME STREQUAL "QtBase" OR QT_SUPERBUILD) + set(${out_var} "${QtBase_SOURCE_DIR}/src/android/java" PARENT_SCOPE) + else() + set(${out_var} "${QT6_INSTALL_PREFIX}/${QT6_INSTALL_DATA}/src/android/java" PARENT_SCOPE) + endif() +endfunction() + +# Returns the platform-spefic name of the gradlew script. +function(_qt_internal_android_gradlew_name out_var) + if(CMAKE_HOST_WIN32) + set(gradlew_file_name "gradlew.bat") + else() + set(gradlew_file_name "gradlew") + endif() + + set(${out_var} "${gradlew_file_name}" PARENT_SCOPE) +endfunction() + +# Return the path to the gradlew script. +function(_qt_internal_android_gradlew_path out_var target) + _qt_internal_android_get_target_android_build_dir(android_build_dir ${target}) + set(${out_var} "${android_build_dir}/${gradlew_file_name}" PARENT_SCOPE) +endfunction() + +# Returns the generator expression for the gradle_property value. Defaults to the default_value +# argument. +function(_qt_internal_android_get_gradle_property out_var target target_property default_value) + set(target_property_genex "$<GENEX_EVAL:$<TARGET_PROPERTY:${target},${target_property}>>") + string(JOIN "" result + "$<IF:$<BOOL:${target_property_genex}>," + "${target_property_genex}," + "${default_value}" + ">" + ) + set(${out_var} "${result}" PARENT_SCOPE) +endfunction() + +# Generates gradle.properties for the specific target. Usually contains the +# target build type(executable, dynamic feature, library). +function(_qt_internal_android_generate_target_gradle_properties target) + cmake_parse_arguments(PARSE_ARGV 1 arg "" "DEPLOYMENT_DIR" "") + + if(NOT arg_DEPLOYMENT_DIR) + message(FATAL_ERROR "DEPLOYMENT_DIR is not specified.") + endif() + + set(gradle_properties_file_name "gradle.properties") + set(out_file "${arg_DEPLOYMENT_DIR}/${gradle_properties_file_name}") + # Skip generating the file if it's already provided by user. + get_target_property(deployment_files ${target} _qt_android_deployment_files) + if("${out_file}" IN_LIST deployment_files) + return() + endif() + + _qt_internal_android_get_template_path(template_file ${target} + "app/${gradle_properties_file_name}") + _qt_internal_configure_file(CONFIGURE + OUTPUT "${out_file}" + INPUT "${template_file}" + ) + set_property(TARGET ${target} APPEND PROPERTY _qt_android_deployment_files "${out_file}") +endfunction() + +# Constucts generator expression that returns either target property or the default value +function(_qt_internal_android_get_manifest_property out_var target property default) + set(target_property "$<TARGET_PROPERTY:${target},${property}>") + string(JOIN "" out_genex + "$<IF:$<BOOL:${target_property}>," + "${target_property}," + "${default}" + ">" + ) + + set(${out_var} "${out_genex}" PARENT_SCOPE) +endfunction() + +# Generates the target AndroidManifest.xml +function(_qt_internal_android_generate_target_android_manifest target) + cmake_parse_arguments(PARSE_ARGV 1 arg "" "DEPLOYMENT_DIR" "") + + if(NOT arg_DEPLOYMENT_DIR) + message(FATAL_ERROR "DEPLOYMENT_DIR is not specified.") + endif() + + set(android_manifest_filename "AndroidManifest.xml") + set(out_file "${arg_DEPLOYMENT_DIR}/${android_manifest_filename}") + + # Skip generating the file if it's already provided by user. + get_target_property(deployment_files ${target} _qt_android_deployment_files) + if("${out_file}" IN_LIST deployment_files) + return() + endif() + + _qt_internal_android_get_template_path(template_file ${target} + "app/${android_manifest_filename}") + set(temporary_file "${out_file}.tmp") + + # The file cannot be generated at cmake configure time, because androiddeployqt + # will override it at build time. We use this trick with temporary file to override + # it after the aux run of androiddeployqt. + add_custom_command(OUTPUT "${out_file}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${temporary_file}" + "${out_file}" + DEPENDS + "${template_file}" + "${temporary_file}" + ${target}_android_deploy_aux + ) + + _qt_internal_android_get_manifest_property(APP_PACKAGE_NAME ${target} + QT_ANDROID_PACKAGE_NAME "org.qtproject.example.$<MAKE_C_IDENTIFIER:${target}>") + _qt_internal_android_get_manifest_property(APP_NAME ${target} + QT_ANDROID_APP_NAME "${target}") + _qt_internal_android_get_manifest_property(APP_VERSION_CODE ${target} + QT_ANDROID_VERSION_CODE "1") + _qt_internal_android_get_manifest_property(APP_VERSION_NAME ${target} + QT_ANDROID_VERSION_NAME "1") + _qt_internal_android_get_manifest_property(APP_LIB_NAME ${target} OUTPUT_NAME "${target}") + + # For application icon we substitute the whole attribute definition, but not only value + # otherwise it leads to the Manifest processing issue. + set(target_property "$<TARGET_PROPERTY:${target},QT_ANDROID_APP_ICON>") + string(JOIN "" APP_ICON + "$<$<BOOL:${target_property}>:" + "android:icon=\"${target_property}\"" + ">" + ) + + file(READ "${template_file}" manifest_content) + string(REPLACE ">" "$<ANGLE-R>" manifest_content "${manifest_content}") + string(REPLACE ";" "$<SEMICOLON>" manifest_content "${manifest_content}") + string(REPLACE "," "$<COMMA>" manifest_content "${manifest_content}") + + _qt_internal_android_convert_permissions(APP_PERMISSIONS ${target} XML) + + set(feature_prefix "\n <uses-feature android:name=\"") + set(feature_suffix " \" android:required=\"false\" /$<ANGLE-R>") + set(feature_property "$<TARGET_PROPERTY:${target},QT_ANDROID_FEATURES>") + string(JOIN "" APP_FEATURES + "$<$<BOOL:${feature_property}>:" + "${feature_prefix}" + "$<JOIN:${feature_property},${feature_suffix},${feature_prefix}>" + "${feature_suffix}" + ">" + ) + + set(APP_ARGUMENTS "${QT_ANDROID_APPLICATION_ARGUMENTS}") + + _qt_internal_configure_file(GENERATE OUTPUT "${temporary_file}" + CONTENT "${manifest_content}") + + set_property(TARGET ${target} APPEND PROPERTY + _qt_android_deployment_files "${out_file}" "${temporary_file}") +endfunction() + +# Generates the top-level gradle.properties in the android-build directory +# The file contains the information about the versions of the android build +# tools, the list of supported ABIs. +function(_qt_internal_android_generate_bundle_gradle_properties target) + set(EXTRA_PROPERTIES "") + + set(gradle_properties_file_name "gradle.properties") + _qt_internal_android_get_target_android_build_dir(android_build_dir ${target}) + set(out_file "${android_build_dir}/${gradle_properties_file_name}") + + # Skip generating the file if it's already provided by user. + get_target_property(deployment_files ${target} _qt_android_deployment_files) + if("${out_file}" IN_LIST deployment_files) + return() + endif() + + _qt_internal_android_get_template_path(template_file ${target} "${gradle_properties_file_name}") + _qt_internal_configure_file(CONFIGURE + OUTPUT "${out_file}" + INPUT "${template_file}" + ) + set_property(TARGET ${target} APPEND PROPERTY _qt_android_deployment_files "${out_file}") +endfunction() + +# Generates the local.properties for gradle builds. Contains the path to the +# Android SDK root. +function(_qt_internal_android_generate_bundle_local_properties target) + _qt_internal_android_get_target_android_build_dir(android_build_dir ${target}) + set(out_file "${android_build_dir}/local.properties") + + # Skip generating the file if it's already provided by user. + get_target_property(deployment_files ${target} _qt_android_deployment_files) + if("${out_file}" IN_LIST deployment_files) + return() + endif() + + file(TO_CMAKE_PATH "${ANDROID_SDK_ROOT}" ANDROID_SDK_ROOT_NATIVE) + _qt_internal_configure_file(CONFIGURE OUTPUT "${out_file}" + CONTENT "sdk.dir=${ANDROID_SDK_ROOT_NATIVE}\n") +endfunction() + +# Copies the customized Android package sources to the Android build directory +function(_qt_internal_android_copy_target_package_sources target) + _qt_internal_android_get_package_source_dir(package_source_dir ${target}) + + if(NOT package_source_dir) + return() + endif() + get_filename_component(package_source_dir "${package_source_dir}" ABSOLUTE) + + # Collect deployment files from use-defined package source directory + file(GLOB_RECURSE package_files + LIST_DIRECTORIES false + RELATIVE "${package_source_dir}" + "${package_source_dir}/*" + ) + + # Do not copy files that we treat as CMake templates, having '.in' extention. + # + # TODO: If it ever will be an issue we may exclude only templates that are + # known by our build system. + list(FILTER package_files EXCLUDE REGEX ".+\\.in$") + + _qt_internal_android_get_target_android_build_dir(android_build_dir ${target}) + list(TRANSFORM package_files PREPEND "${android_build_dir}/" OUTPUT_VARIABLE out_package_files) + list(TRANSFORM package_files PREPEND "${package_source_dir}/" OUTPUT_VARIABLE in_package_files) + + if(in_package_files) + # TODO: Add cmake < 3.26 support + if(CMAKE_VERSION VERSION_LESS 3.26) + message(FATAL_ERROR "The use of QT_ANDROID_PACKAGE_SOURCE_DIR property with + the QT_USE_ANDROID_MODERN_BUNDLE option enabled requires CMake version >= 3.26.") + endif() + set(copy_commands COMMAND "${CMAKE_COMMAND}" -E copy_directory_if_different + "${package_source_dir}" "${android_build_dir}") + else() + # We actually have nothing to deploy. + return() + endif() + + add_custom_command(OUTPUT ${out_package_files} + ${copy_commands} + DEPENDS + ${in_package_files} + VERBATIM + ) + + set_target_properties(${target} PROPERTIES _qt_android_deployment_files "${out_package_files}") +endfunction() + +# Copies gradle scripts to a build directory. +function(_qt_internal_android_copy_gradle_files target output_directory) + _qt_internal_android_gradlew_name(gradlew_file_name) + _qt_internal_android_gradle_template_dir(gradle_template_dir) + + set(gradlew_file_src "${gradle_template_dir}/${gradlew_file_name}") + set(gradlew_file_dst "${output_directory}/${gradlew_file_name}") + + add_custom_command(OUTPUT "${gradlew_file_dst}" + COMMAND + ${CMAKE_COMMAND} -E copy_if_different "${gradlew_file_src}" "${gradlew_file_dst}" + DEPENDS "${gradlew_file_src}" + COMMENT "Copying gradlew script for ${target}" + VERBATIM + ) + + # TODO: make a more precise directory copying + set(gradle_dir_src "${gradle_template_dir}/gradle") + set(gradle_dir_dst "${output_directory}/gradle") + add_custom_command(OUTPUT "${gradle_dir_dst}" + COMMAND + ${CMAKE_COMMAND} -E copy_directory "${gradle_dir_src}" "${gradle_dir_dst}" + DEPENDS "${gradle_dir_src}" + COMMENT "Copying gradle support files for ${target}" + VERBATIM + ) + + add_custom_target(${target}_copy_gradle_files + DEPENDS + "${gradlew_file_dst}" + "${gradle_dir_dst}" + ) +endfunction() diff --git a/src/corelib/Qt6AndroidMacros.cmake b/src/corelib/Qt6AndroidMacros.cmake index aa0e5bfed24..ed97a42c83f 100644 --- a/src/corelib/Qt6AndroidMacros.cmake +++ b/src/corelib/Qt6AndroidMacros.cmake @@ -120,6 +120,29 @@ function(_qt_internal_generate_android_permissions_json out_result target) set(${out_result} "${result}" PARENT_SCOPE) endfunction() +# Add the specific dynamic library as the dynamic feature for the Android application target. +function(qt6_add_android_dynamic_features target) + cmake_parse_arguments(PARSE_ARGV 1 arg "" "" "FEATURE_TARGETS") + if(NOT QT_USE_ANDROID_MODERN_BUNDLE) + message(FATAL_ERROR "qt6_add_android_dynamic_features is only supported with" + " 'QT_USE_ANDROID_MODERN_BUNDLE' enabled.") + endif() + if(NOT TARGET ${target}) + message(FATAL_ERROR "${target} is not a target. Cannot add the dynamic features.") + endif() + get_target_property(android_type ${target} _qt_android_target_type) + if(NOT android_type STREQUAL "APPLICATION") + message(FATAL_ERROR "${target} is not an android executable target." + " Cannot add the dynamic features.") + endif() + if(arg_FEATURE_TARGETS) + set_property(TARGET ${target} + APPEND PROPERTY _qt_android_dynamic_features ${arg_FEATURE_TARGETS}) + else() + message(WARNING "No dynamic features provided.") + endif() +endfunction() + # Generate the deployment settings json file for a cmake target. function(qt6_android_generate_deployment_settings target) # Information extracted from mkspecs/features/android/android_deployment_settings.prf @@ -324,8 +347,9 @@ function(qt6_android_generate_deployment_settings target) __qt_internal_collect_plugin_library_files_v2("${target}" "${plugin_targets}" plugin_targets) string(APPEND file_contents " \"android-deploy-plugins\":\"${plugin_targets}\",\n") - _qt_internal_generate_android_permissions_json(permissions_json_array "${target}") - string(APPEND file_contents " \"permissions\": ${permissions_json_array},\n") + + _qt_internal_android_convert_permissions(permissions_genex ${target} JSON) + string(APPEND file_contents " \"permissions\": ${permissions_genex},\n") # App binary string(APPEND file_contents @@ -415,44 +439,6 @@ if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS) endfunction() endif() -function(_qt_internal_add_android_permission target) - if(NOT TARGET ${target}) - message(FATAL_ERROR "Empty or invalid target for adding Android permission: (${target})") - endif() - - cmake_parse_arguments(arg "" "NAME" "ATTRIBUTES" ${ARGN}) - - if(NOT arg_NAME) - message(FATAL_ERROR "NAME for adding Android permission cannot be empty (${target})") - endif() - - set(permission_entry "${arg_NAME}") - - if(arg_ATTRIBUTES) - # Permission with additional attributes - list(LENGTH arg_ATTRIBUTES attributes_len) - math(EXPR attributes_modulus "${attributes_len} % 2") - if(NOT (attributes_len GREATER 1 AND attributes_modulus EQUAL 0)) - message(FATAL_ERROR "Android permission: ${arg_NAME} attributes: ${arg_ATTRIBUTES} must" - " be name-value pairs (for example: minSdkVersion 30)") - endif() - # Combine name-value pairs - set(index 0) - set(attributes "") - while(index LESS attributes_len) - list(GET arg_ATTRIBUTES ${index} name) - math(EXPR index "${index} + 1") - list(GET arg_ATTRIBUTES ${index} value) - string(APPEND attributes "android:${name}=\'${value}\' ") - math(EXPR index "${index} + 1") - endwhile() - set(permission_entry "${permission_entry}\;${attributes}") - endif() - - # Append the permission to the target's property - set_property(TARGET ${target} APPEND PROPERTY QT_ANDROID_PERMISSIONS "${permission_entry}") -endfunction() - function(qt6_add_android_permission target) _qt_internal_add_android_permission(${ARGV}) endfunction() @@ -519,18 +505,6 @@ function(qt6_android_add_apk_target target) ">" ) - # Make global apk and aab targets depend on the current apk target. - if(TARGET aab) - add_dependencies(aab ${target}_make_aab) - endif() - if(TARGET aar) - add_dependencies(aar ${target}_make_aar) - endif() - if(TARGET apk) - add_dependencies(apk ${target}_make_apk) - _qt_internal_create_global_apk_all_target_if_needed() - endif() - _qt_internal_android_get_deployment_tool(deployment_tool) # No need to use genex for the BINARY_DIR since it's read-only. @@ -719,6 +693,10 @@ function(qt6_android_add_apk_target target) ) add_dependencies(${target}_make_aab ${target}_prepare_apk_dir) + # Make global apk, aab, and aar targets depend on the respective targets. + _qt_internal_android_add_global_package_dependencies(${target}) + _qt_internal_create_global_apk_all_target_if_needed() + if(QT_IS_ANDROID_MULTI_ABI_EXTERNAL_PROJECT) # When building per-ABI external projects we only need to copy ABI-specific libraries and # resources to the "main" ABI android build folder. @@ -1661,13 +1639,26 @@ endfunction() # module and is executed implicitly when configuring user projects. function(_qt_internal_android_executable_finalizer target) set_property(TARGET ${target} PROPERTY _qt_android_executable_finalizer_called TRUE) + set_property(TARGET ${target} PROPERTY _qt_android_in_finalizer "EXECUTABLE") _qt_internal_expose_android_package_source_dir_to_ide(${target}) _qt_internal_configure_android_multiabi_target("${target}") qt6_android_generate_deployment_settings("${target}") - qt6_android_add_apk_target("${target}") + if(QT_USE_ANDROID_MODERN_BUNDLE) + _qt_internal_android_generate_dynamic_feature_names("${target}") + _qt_internal_android_add_dynamic_feature_deployment("${target}") + + _qt_internal_android_prepare_gradle_build("${target}") + _qt_internal_android_add_aux_deployment("${target}") + + _qt_internal_collect_apk_dependencies_defer() + _qt_internal_collect_apk_imported_dependencies_defer("${target}") + else() + qt6_android_add_apk_target("${target}") + endif() _qt_internal_android_create_runner_wrapper("${target}") + set_property(TARGET ${target} PROPERTY _qt_android_in_finalizer "") endfunction() # Helper to add the android executable finalizer. @@ -1737,8 +1728,9 @@ function(_qt_internal_android_app_runner_arguments target out_runner_path out_ar set(${out_runner_path} "${runner_dir}/qt-android-runner.py" PARENT_SCOPE) _qt_internal_android_get_target_android_build_dir(android_build_dir ${target}) + _qt_internal_android_get_platform_tools_path(platform_tools) set(${out_arguments} - "--adb" "${ANDROID_SDK_ROOT}/platform-tools/adb" + "--adb" "${platform_tools}/adb" "--build-path" "${android_build_dir}" "--apk" "${android_build_dir}/${target}.apk" PARENT_SCOPE @@ -1754,8 +1746,13 @@ function(_qt_internal_android_get_target_android_build_dir out_build_dir target) endif() endfunction() +function(_qt_internal_android_get_target_deployment_dir out_deploy_dir target) + _qt_internal_android_get_target_android_build_dir(build_dir ${target}) + set(${out_deploy_dir} "${build_dir}/app" PARENT_SCOPE) +endfunction() + function(_qt_internal_expose_android_package_source_dir_to_ide target) - get_target_property(android_package_source_dir ${target} QT_ANDROID_PACKAGE_SOURCE_DIR) + _qt_internal_android_get_package_source_dir(android_package_source_dir ${target}) if(android_package_source_dir) get_target_property(target_source_dir ${target} SOURCE_DIR) if(NOT IS_ABSOLUTE "${android_package_source_dir}") @@ -1778,6 +1775,71 @@ function(_qt_internal_expose_android_package_source_dir_to_ide target) endif() endfunction() +function(_qt_internal_android_add_aux_deployment target) + cmake_parse_arguments(arg "" "OUTPUT_TARGET_NAME;DEPLOYMENT_DIRECTORY" "EXTRA_ARGS" ${ARGN}) + _qt_internal_validate_all_args_are_parsed(arg) + + string(JOIN "" deployment_file + "$<GENEX_EVAL:" + "$<TARGET_PROPERTY:${target},QT_ANDROID_DEPLOYMENT_SETTINGS_FILE>" + ">" + ) + + _qt_internal_android_get_deployment_tool(deployment_tool) + if(arg_DEPLOYMENT_DIRECTORY) + set(deployment_dir "${arg_DEPLOYMENT_DIRECTORY}") + else() + _qt_internal_android_get_target_deployment_dir(deployment_dir ${target}) + endif() + + cmake_policy(PUSH) + if(POLICY CMP0116) + # Without explicitly setting this policy to NEW, we get a warning + # even though we ensure there's actually no problem here. + # See https://gitlab.kitware.com/cmake/cmake/-/issues/21959 + cmake_policy(SET CMP0116 NEW) + set(relative_to_dir ${CMAKE_CURRENT_BINARY_DIR}) + else() + set(relative_to_dir ${CMAKE_BINARY_DIR}) + endif() + + set(target_file_copy_relative_path + "libs/${CMAKE_ANDROID_ARCH_ABI}/$<TARGET_FILE_NAME:${target}>") + _qt_internal_copy_file_if_different_command(copy_command + "$<TARGET_FILE:${target}>" + "${deployment_dir}/${target_file_copy_relative_path}" + ) + + _qt_internal_android_get_use_terminal_for_deployment(uses_terminal) + + # TODO: We use androiddeployqt to collect target depdenencies and produce the lib.xml file + # which autoloads the collected libraries. Should be done using GRE and transitive properties + # in the future. + set(libs_xml "${deployment_dir}/res/values/libs.xml") + add_custom_command(OUTPUT "${libs_xml}" + COMMAND ${copy_command} + COMMAND "${deployment_tool}" + --input "${deployment_file}" + --output "${deployment_dir}" + --builddir "${relative_to_dir}" + --aux-mode + ${arg_EXTRA_ARGS} + #TODO: Support signing + COMMENT "Deploying Android artifacts for ${target}" + DEPENDS "${target}" "${deployment_file}" + VERBATIM + ${uses_terminal} + ) + + if(NOT arg_OUTPUT_TARGET_NAME) + set(arg_OUTPUT_TARGET_NAME ${target}_android_deploy_aux) + endif() + + add_custom_target(${arg_OUTPUT_TARGET_NAME} DEPENDS "${libs_xml}") + + cmake_policy(POP) +endfunction() + # Enables the terminal usage for the add_custom_command calls when verbose deployment is enabled. function(_qt_internal_android_get_use_terminal_for_deployment out_var) if(QT_ENABLE_VERBOSE_DEPLOYMENT) @@ -1822,6 +1884,45 @@ function(_qt_internal_android_get_deployment_type_option out_var release_flag de endif() endfunction() +# Returns the path to the android template directory, that are used by CMake +# deployment procedures. +function(_qt_internal_android_template_dir out_var) + if(PROJECT_NAME STREQUAL "QtBase" OR QT_SUPERBUILD) + set(${out_var} "${QtBase_SOURCE_DIR}/src/android/templates_cmake" PARENT_SCOPE) + else() + set(${out_var} + "${QT6_INSTALL_PREFIX}/${QT6_INSTALL_DATA}/src/android/templates_cmake" PARENT_SCOPE) + endif() +endfunction() + +# Return the path to the target template directory if it's set for the target. +# Then this path is stored in the target QT_ANDROID_PACKAGE_SOURCE_DIR property +# and can only be effectively read in android finalizers. +function(_qt_internal_android_get_package_source_dir out_var target) + get_target_property(in_finalizer ${target} _qt_android_in_finalizer) + if(NOT in_finalizer) + message(FATAL_ERROR "The '_qt_internal_android_get_package_source_dir' function is" + " called outside the Android finalizer." + " This is the Qt issue, please report a bug at https://bugreports.qt.io.") + endif() + get_target_property(package_src_dir ${target} QT_ANDROID_PACKAGE_SOURCE_DIR) + if(NOT package_src_dir) + set(package_src_dir "") + endif() + set(${out_var} "${package_src_dir}" PARENT_SCOPE) +endfunction() + +# Add target_make_<apk|aab> as the depednecy for the respective global apk/aab +# target. +function(_qt_internal_android_add_global_package_dependencies target) + foreach(type apk aab aar) + # Make global apk and aab targets depend on the current apk target. + if(TARGET ${type} AND TARGET ${target}_make_${type}) + add_dependencies(${type} ${target}_make_${type}) + endif() + endforeach() +endfunction() + function(_qt_internal_android_get_target_abis out_abis target) get_target_property(target_abis ${target} QT_ANDROID_ABIS) if(target_abis) @@ -1840,5 +1941,10 @@ function(_qt_internal_android_get_target_abis out_abis target) set(${out_abis} "${android_abis}" PARENT_SCOPE) endfunction() +# Returns the path to the Android platform-tools(adb is located there). +function(_qt_internal_android_get_platform_tools_path out_var) + set(${out_var} "${ANDROID_SDK_ROOT}/platform-tools" PARENT_SCOPE) +endfunction() + set(QT_INTERNAL_ANDROID_TARGET_BUILD_DIR_SUPPORT ON CACHE INTERNAL "Indicates that Qt supports per-target Android build directories") diff --git a/src/corelib/Qt6AndroidPermissionHelpers.cmake b/src/corelib/Qt6AndroidPermissionHelpers.cmake new file mode 100644 index 00000000000..7f851e14667 --- /dev/null +++ b/src/corelib/Qt6AndroidPermissionHelpers.cmake @@ -0,0 +1,126 @@ +# Copyright (C) 2025 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +# Generates the generator expression that converts the 'target' +# QT_ANDROID_PERMISSIONS property to the specific 'type'. +# +# It's expected that each element in QT_ANDROID_PERMISSIONS list has specific +# format: +# <name>\;<permission>\\\;<extra1>\;<value>\\\;<extra2>\;<value> +# +# Synopsis +# _qt_internal_android_convert_permissions(out_var target <JSON|XML>) +# +# Arguments +# +# `out_var` +# The name of the variable where the resulting generator expression is +# stored. +# +# `target` +# The name of the target. +# +# `JSON` +# Generate JSON array known by androiddeployqt. +# +# `XML` +# Generate XML content compatible with AndroidManifest.xml. +function(_qt_internal_android_convert_permissions out_var target type) + set(permissions_property "$<TARGET_PROPERTY:${target},QT_ANDROID_PERMISSIONS>") + set(permissions_genex "$<$<BOOL:${permissions_property}>:") + if(type STREQUAL "JSON") + set(pref "{ \"") + set(post "\" }") + set(indent "\n ") + string(APPEND permissions_genex + "[${indent}$<JOIN:" + "$<JOIN:" + "${pref}$<JOIN:" + "${permissions_property}," + "${post}$<COMMA>${indent}${pref}" + ">${post}," + "\": \"" + ">," + "\"$<COMMA> \"" + ">\n ]" + ) + elseif(type STREQUAL "XML") + set(pref "<uses-permission\n android:") + set(post "' /$<ANGLE-R>\n") + string(APPEND permissions_genex + "$<JOIN:" + "$<JOIN:" + "${pref}$<JOIN:" + "${permissions_property}," + "${post}${pref}" + ">${post}\n," + "='" + ">," + "' android:" + ">" + ) + else() + message(FATAL_ERROR "Invalid type ${type}. Supported types: JSON, XML") + endif() + string(APPEND permissions_genex ">") + + set(${out_var} "${permissions_genex}" PARENT_SCOPE) +endfunction() + +# Add the specific Android permission to the target. The permission is stored +# in the QT_ANDROID_PERMISSIONS property(the property is not a public API) +# and has the following format: +# <name>\;<permission>\\\;<extra1>\;<value>\\\;<extra2>\;<value> +# +# Synopsis +# _qt_internal_add_android_permission(target NAME <permission> +# ATTRIBUTES <extra1> <value1> +# [<extra2> <value2>]... +# ) +# +# Arguments +# +# `target` +# The Android target. +# +# `NAME` +# The permission name. E.g. 'android.permission.CAMERA'. +# +# `ATTRIBUTES` +# Extra permission attribute key-value pairs. +# See https://developer.android.com/guide/topics/manifest/uses-permission-element +# for details. +function(_qt_internal_add_android_permission target) + if(NOT TARGET ${target}) + message(FATAL_ERROR "Empty or invalid target for adding Android permission: (${target})") + endif() + + cmake_parse_arguments(arg "" "NAME" "ATTRIBUTES" ${ARGN}) + + if(NOT arg_NAME) + message(FATAL_ERROR "NAME for adding Android permission cannot be empty (${target})") + endif() + + set(permission_entry "name\;${arg_NAME}") + if(arg_ATTRIBUTES) + # Permission with additional attributes + list(LENGTH arg_ATTRIBUTES attributes_len) + math(EXPR attributes_modulus "${attributes_len} % 2") + if(NOT (attributes_len GREATER 1 AND attributes_modulus EQUAL 0)) + message(FATAL_ERROR "Android permission: ${arg_NAME} attributes: ${arg_ATTRIBUTES}" + " must be name-value pairs (for example: minSdkVersion 30)") + endif() + # Combine name-value pairs + set(index 0) + while(index LESS attributes_len) + list(GET arg_ATTRIBUTES ${index} name) + math(EXPR index "${index} + 1") + list(GET arg_ATTRIBUTES ${index} value) + string(APPEND permission_entry "\\\;${name}\;${value}") + math(EXPR index "${index} + 1") + endwhile() + endif() + + # Append the permission to the target's property + set_property(TARGET ${target} APPEND PROPERTY QT_ANDROID_PERMISSIONS "${permission_entry}") +endfunction() diff --git a/src/corelib/Qt6CoreConfigExtras.cmake.in b/src/corelib/Qt6CoreConfigExtras.cmake.in index 15405197a61..8a88d558fa8 100644 --- a/src/corelib/Qt6CoreConfigExtras.cmake.in +++ b/src/corelib/Qt6CoreConfigExtras.cmake.in @@ -30,6 +30,10 @@ _qt_internal_setup_deploy_support() if(ANDROID_PLATFORM) include("${CMAKE_CURRENT_LIST_DIR}/@[email protected]") + include("${CMAKE_CURRENT_LIST_DIR}/@[email protected]") + include("${CMAKE_CURRENT_LIST_DIR}/@[email protected]") + include("${CMAKE_CURRENT_LIST_DIR}/@[email protected]") + _qt_internal_create_global_android_targets() _qt_internal_collect_default_android_abis() if(__qt_Core_targets_file_included) diff --git a/src/corelib/Qt6CoreMacros.cmake b/src/corelib/Qt6CoreMacros.cmake index 3f5f9180805..5bc85ae7f7a 100644 --- a/src/corelib/Qt6CoreMacros.cmake +++ b/src/corelib/Qt6CoreMacros.cmake @@ -683,6 +683,9 @@ function(_qt_internal_create_executable target) ) qt6_android_apply_arch_suffix("${target}") + if(QT_USE_ANDROID_MODERN_BUNDLE) + _qt_internal_set_android_application_gradle_defaults(${target}) + endif() else() cmake_policy(PUSH) __qt_internal_set_cmp0156() @@ -3799,7 +3802,7 @@ function(qt6_generate_deploy_app_script) qt6_generate_deploy_script(${generate_args} CONTENT " qt6_deploy_runtime_dependencies( - EXECUTABLE $<TARGET_FILE_NAME:${arg_TARGET}>.app + EXECUTABLE \"$<TARGET_FILE_NAME:${arg_TARGET}>.app\" ${common_deploy_args}) ") @@ -3807,7 +3810,7 @@ ${common_deploy_args}) qt6_generate_deploy_script(${generate_args} CONTENT " qt6_deploy_runtime_dependencies( - EXECUTABLE $<TARGET_FILE:${arg_TARGET}> + EXECUTABLE \"$<TARGET_FILE:${arg_TARGET}>\" GENERATE_QT_CONF ${common_deploy_args}) ") @@ -3817,7 +3820,7 @@ ${common_deploy_args}) qt6_generate_deploy_script(${generate_args} CONTENT " qt6_deploy_runtime_dependencies( - EXECUTABLE $<TARGET_FILE:${arg_TARGET}> + EXECUTABLE \"$<TARGET_FILE:${arg_TARGET}>\" GENERATE_QT_CONF ${common_deploy_args}) ") diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp index d74894e1e42..4388122b7b9 100644 --- a/src/corelib/animation/qabstractanimation.cpp +++ b/src/corelib/animation/qabstractanimation.cpp @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default /*! \class QAbstractAnimation diff --git a/src/corelib/animation/qabstractanimation.h b/src/corelib/animation/qabstractanimation.h index 69a30556a3a..b4b43e64a1d 100644 --- a/src/corelib/animation/qabstractanimation.h +++ b/src/corelib/animation/qabstractanimation.h @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #ifndef QABSTRACTANIMATION_H #define QABSTRACTANIMATION_H diff --git a/src/corelib/animation/qabstractanimation_p.h b/src/corelib/animation/qabstractanimation_p.h index d6c245f36f0..51c635f1bed 100644 --- a/src/corelib/animation/qabstractanimation_p.h +++ b/src/corelib/animation/qabstractanimation_p.h @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #ifndef QABSTRACTANIMATION_P_H #define QABSTRACTANIMATION_P_H diff --git a/src/corelib/animation/qanimationgroup.cpp b/src/corelib/animation/qanimationgroup.cpp index d2572a7462b..ae96069e86f 100644 --- a/src/corelib/animation/qanimationgroup.cpp +++ b/src/corelib/animation/qanimationgroup.cpp @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default /*! \class QAnimationGroup diff --git a/src/corelib/animation/qanimationgroup.h b/src/corelib/animation/qanimationgroup.h index 412e2d442ea..07d24ae1f73 100644 --- a/src/corelib/animation/qanimationgroup.h +++ b/src/corelib/animation/qanimationgroup.h @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #ifndef QANIMATIONGROUP_H #define QANIMATIONGROUP_H diff --git a/src/corelib/animation/qanimationgroup_p.h b/src/corelib/animation/qanimationgroup_p.h index 334f780968a..a09bc6ebcc6 100644 --- a/src/corelib/animation/qanimationgroup_p.h +++ b/src/corelib/animation/qanimationgroup_p.h @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #ifndef QANIMATIONGROUP_P_H #define QANIMATIONGROUP_P_H diff --git a/src/corelib/animation/qparallelanimationgroup.cpp b/src/corelib/animation/qparallelanimationgroup.cpp index 86e9417b595..0b43a73434f 100644 --- a/src/corelib/animation/qparallelanimationgroup.cpp +++ b/src/corelib/animation/qparallelanimationgroup.cpp @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default /*! \class QParallelAnimationGroup diff --git a/src/corelib/animation/qparallelanimationgroup.h b/src/corelib/animation/qparallelanimationgroup.h index 77bc6eabac7..9442f4f7355 100644 --- a/src/corelib/animation/qparallelanimationgroup.h +++ b/src/corelib/animation/qparallelanimationgroup.h @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #ifndef QPARALLELANIMATIONGROUP_H #define QPARALLELANIMATIONGROUP_H diff --git a/src/corelib/animation/qparallelanimationgroup_p.h b/src/corelib/animation/qparallelanimationgroup_p.h index 62c53d36097..482b9555c7d 100644 --- a/src/corelib/animation/qparallelanimationgroup_p.h +++ b/src/corelib/animation/qparallelanimationgroup_p.h @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #ifndef QPARALLELANIMATIONGROUP_P_H #define QPARALLELANIMATIONGROUP_P_H diff --git a/src/corelib/animation/qpauseanimation.cpp b/src/corelib/animation/qpauseanimation.cpp index 344b21946e3..74e22e2f053 100644 --- a/src/corelib/animation/qpauseanimation.cpp +++ b/src/corelib/animation/qpauseanimation.cpp @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default /*! \class QPauseAnimation diff --git a/src/corelib/animation/qpauseanimation.h b/src/corelib/animation/qpauseanimation.h index f661459f835..bf7863a171c 100644 --- a/src/corelib/animation/qpauseanimation.h +++ b/src/corelib/animation/qpauseanimation.h @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #ifndef QPAUSEANIMATION_H #define QPAUSEANIMATION_H diff --git a/src/corelib/animation/qpropertyanimation.cpp b/src/corelib/animation/qpropertyanimation.cpp index 04f048af753..b4c6b6ff8a6 100644 --- a/src/corelib/animation/qpropertyanimation.cpp +++ b/src/corelib/animation/qpropertyanimation.cpp @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default /*! \class QPropertyAnimation diff --git a/src/corelib/animation/qpropertyanimation.h b/src/corelib/animation/qpropertyanimation.h index 038c202b8f3..590a6ddaf15 100644 --- a/src/corelib/animation/qpropertyanimation.h +++ b/src/corelib/animation/qpropertyanimation.h @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #ifndef QPROPERTYANIMATION_H #define QPROPERTYANIMATION_H diff --git a/src/corelib/animation/qpropertyanimation_p.h b/src/corelib/animation/qpropertyanimation_p.h index ef5534cd9c3..c1918ae1bf8 100644 --- a/src/corelib/animation/qpropertyanimation_p.h +++ b/src/corelib/animation/qpropertyanimation_p.h @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #ifndef QPROPERTYANIMATION_P_H #define QPROPERTYANIMATION_P_H diff --git a/src/corelib/animation/qsequentialanimationgroup.cpp b/src/corelib/animation/qsequentialanimationgroup.cpp index 260481dbef5..d11249ca7ed 100644 --- a/src/corelib/animation/qsequentialanimationgroup.cpp +++ b/src/corelib/animation/qsequentialanimationgroup.cpp @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default /*! \class QSequentialAnimationGroup diff --git a/src/corelib/animation/qsequentialanimationgroup.h b/src/corelib/animation/qsequentialanimationgroup.h index 6786078170d..b7f9c1b17a1 100644 --- a/src/corelib/animation/qsequentialanimationgroup.h +++ b/src/corelib/animation/qsequentialanimationgroup.h @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #ifndef QSEQUENTIALANIMATIONGROUP_H #define QSEQUENTIALANIMATIONGROUP_H diff --git a/src/corelib/animation/qsequentialanimationgroup_p.h b/src/corelib/animation/qsequentialanimationgroup_p.h index cbdf204d0a6..131902b5aa5 100644 --- a/src/corelib/animation/qsequentialanimationgroup_p.h +++ b/src/corelib/animation/qsequentialanimationgroup_p.h @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #ifndef QSEQUENTIALANIMATIONGROUP_P_H #define QSEQUENTIALANIMATIONGROUP_P_H diff --git a/src/corelib/animation/qvariantanimation.cpp b/src/corelib/animation/qvariantanimation.cpp index be5c09519e9..bd12d5dae95 100644 --- a/src/corelib/animation/qvariantanimation.cpp +++ b/src/corelib/animation/qvariantanimation.cpp @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #include "qvariantanimation.h" #include "qvariantanimation_p.h" diff --git a/src/corelib/animation/qvariantanimation.h b/src/corelib/animation/qvariantanimation.h index 4bdb9713578..172ee0d6090 100644 --- a/src/corelib/animation/qvariantanimation.h +++ b/src/corelib/animation/qvariantanimation.h @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #ifndef QVARIANTANIMATION_H #define QVARIANTANIMATION_H diff --git a/src/corelib/animation/qvariantanimation_p.h b/src/corelib/animation/qvariantanimation_p.h index 0ac238a882b..5fdd9666dba 100644 --- a/src/corelib/animation/qvariantanimation_p.h +++ b/src/corelib/animation/qvariantanimation_p.h @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #ifndef QVARIANTANIMATION_P_H #define QVARIANTANIMATION_P_H diff --git a/src/corelib/configure.cmake b/src/corelib/configure.cmake index 909041cf44b..096dce9e84e 100644 --- a/src/corelib/configure.cmake +++ b/src/corelib/configure.cmake @@ -591,6 +591,7 @@ qt_config_compile_test(cpp_winrt runtimeobject CODE "// Including winrt/base.h causes an error in some configurations (Windows 10 SDK + c++20) +# include <guiddef.h> // required by clang-cl: https://github.com/microsoft/cppwinrt/issues/1179 # include <winrt/base.h> int main(void) diff --git a/src/corelib/doc/REUSE.toml b/src/corelib/doc/REUSE.toml index 254251a0b6b..969cc0d9938 100644 --- a/src/corelib/doc/REUSE.toml +++ b/src/corelib/doc/REUSE.toml @@ -3,23 +3,23 @@ version = 1 [[annotations]] path = ["snippets/**"] precedence = "closest" -SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." +SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd." SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR BSD-3-Clause" [[annotations]] path = ["**qdocinc", "**/images/**"] precedence = "closest" -SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." +SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd." SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only" [[annotations]] path = ["src/corelib/doc/qtcore.qdocconf"] precedence = "closest" -SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." +SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd." SPDX-License-Identifier = "BSD-3-Clause" [[annotations]] path = ["src/corelib/doc/include/QtCoreDoc"] precedence = "closest" -SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." +SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd." SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only" diff --git a/src/corelib/doc/snippets/CMakeLists.txt b/src/corelib/doc/snippets/CMakeLists.txt index 937433f2e21..78cd4f6b001 100644 --- a/src/corelib/doc/snippets/CMakeLists.txt +++ b/src/corelib/doc/snippets/CMakeLists.txt @@ -39,6 +39,7 @@ qt_internal_extend_target(corelib_snippets CONDITION QT_FEATURE_widgets hellotrmain.cpp fileinfo/main.cpp pointer/pointer.cpp + qsignalmapper/buttonwidget.cpp qsortfilterproxymodel-details/main.cpp qstring/main.cpp qtcast/qtcast.cpp @@ -53,6 +54,8 @@ qt_internal_extend_target(corelib_snippets CONDITION QT_FEATURE_gui qdebug/qdebugsnippet.cpp ) +set_target_properties(corelib_snippets PROPERTIES COMPILE_OPTIONS "-w") + if ("${CMAKE_CXX_COMPILE_FEATURES}" MATCHES "cxx_std_23") set_property(TARGET corelib_snippets PROPERTY CXX_STANDARD 23) endif() diff --git a/src/corelib/doc/snippets/code/doc_src_containers.cpp b/src/corelib/doc/snippets/code/doc_src_containers.cpp index b5684624929..167437c0151 100644 --- a/src/corelib/doc/snippets/code/doc_src_containers.cpp +++ b/src/corelib/doc/snippets/code/doc_src_containers.cpp @@ -3,6 +3,8 @@ #undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses +#include <QtCore> + //! [0] class Employee { @@ -18,225 +20,225 @@ private: }; //! [0] -//! [range_for] -QList<QString> list = {"A", "B", "C", "D"}; -for (const auto &item : list) { - ... -} -//! [range_for] - -//! [range_for_as_const] -QList<QString> list = {"A", "B", "C", "D"}; -for (const auto &item : std::as_const(list)) { - ... -} -//! [range_for_as_const] - -//! [index] -QList<QString> list = {"A", "B", "C", "D"}; -for (qsizetype i = 0; i < list.size(); ++i) { - const auto &item = list.at(i); - ... -} -//! [index] - -//! [1] -QList<QString> list = {"A", "B", "C", "D"}; - -QListIterator<QString> i(list); -while (i.hasNext()) - QString s = i.next(); -//! [1] - - -//! [2] -QListIterator<QString> i(list); -i.toBack(); -while (i.hasPrevious()) - QString s = i.previous(); -//! [2] - - -//! [3] -QMutableListIterator<int> i(list); -while (i.hasNext()) { - if (i.next() % 2 != 0) - i.remove(); -} -//! [3] - - -//! [4] -QMutableListIterator<int> i(list); -i.toBack(); -while (i.hasPrevious()) { - if (i.previous() % 2 != 0) - i.remove(); -} -//! [4] - - -//! [5] -QMutableListIterator<int> i(list); -while (i.hasNext()) { - if (i.next() > 128) - i.setValue(128); -} -//! [5] - - -//! [6] -QMutableListIterator<int> i(list); -while (i.hasNext()) - i.next() *= 2; -//! [6] - - -//! [7] -QMap<QString, QString> map = { - {"Paris", "France"}, - {"Guatemala City", "Guatemala"}, - {"Mexico City", "Mexico"}, - {"Moscow", "Russia"} -}; -... - -QMutableMapIterator<QString, QString> i(map); -while (i.hasNext()) { - if (i.next().key().endsWith("City")) - i.remove(); -} -//! [7] - - -//! [8] -QMap<int, QWidget *> map; -QHash<int, QWidget *> hash; - -QMapIterator<int, QWidget *> i(map); -while (i.hasNext()) { - i.next(); - hash.insert(i.key(), i.value()); -} -//! [8] - - -//! [9] -QMutableMapIterator<int, QWidget *> i(map); -while (i.findNext(widget)) - i.remove(); -//! [9] +void examles() +{ + { + //! [range_for] + QList<QString> list = {"A", "B", "C", "D"}; + for (const auto &item : list) { + //... + } + //! [range_for] + } + { + //! [range_for_as_const] + QList<QString> list = {"A", "B", "C", "D"}; + for (const auto &item : std::as_const(list)) { + //... + } + //! [range_for_as_const] + } -//! [10] -QList<QString> list = {"A", "B", "C", "D"}; + { + //! [index] + QList<QString> list = {"A", "B", "C", "D"}; + for (qsizetype i = 0; i < list.size(); ++i) { + const auto &item = list.at(i); + //... + } + //! [index] + } -for (auto i = list.begin(), end = list.end(); i != end; ++i) - *i = (*i).toLower(); -//! [10] + { + //! [1] + QList<QString> list = {"A", "B", "C", "D"}; + QListIterator<QString> i(list); + while (i.hasNext()) + QString s = i.next(); + //! [1] + } -//! [11] -QList<QString> list = {"A", "B", "C", "D"}; + { + QList<QString> list = {"A", "B", "C", "D"}; -for (auto i = list.rbegin(), rend = list.rend(); i != rend; ++i) - *i = i->toLower(); -//! [11] + //! [2] + QListIterator<QString> i(list); + i.toBack(); + while (i.hasPrevious()) + QString s = i.previous(); + //! [2] + } + { + QList<int> list = {1, 2, 3, 4}; + { + //! [3] + QMutableListIterator<int> i(list); + while (i.hasNext()) { + if (i.next() % 2 != 0) + i.remove(); + } + //! [3] + } + + { + //! [4] + QMutableListIterator<int> i(list); + i.toBack(); + while (i.hasPrevious()) { + if (i.previous() % 2 != 0) + i.remove(); + } + //! [4] + } + + { + //! [5] + QMutableListIterator<int> i(list); + while (i.hasNext()) { + if (i.next() > 128) + i.setValue(128); + } + //! [5] + } + + { + //! [6] + QMutableListIterator<int> i(list); + while (i.hasNext()) + i.next() *= 2; + //! [6] + } + } -//! [12] -for (auto i = list.cbegin(), end = list.cend(); i != end; ++i) - qDebug() << *i; -//! [12] + { + //! [7] + QMap<QString, QString> map = { + {"Paris", "France"}, + {"Guatemala City", "Guatemala"}, + {"Mexico City", "Mexico"}, + {"Moscow", "Russia"} + }; + //... + + QMutableMapIterator<QString, QString> i(map); + while (i.hasNext()) { + if (i.next().key().endsWith("City")) + i.remove(); + } + //! [7] + } + { + //! [10] + QList<QString> list = {"A", "B", "C", "D"}; -//! [13] -QMap<int, int> map; -... -for (auto i = map.cbegin(), end = map.cend(); i != end; ++i) - qDebug() << i.key() << ':' << i.value(); -//! [13] + for (auto i = list.begin(), end = list.end(); i != end; ++i) + *i = (*i).toLower(); + //! [10] + } + { + //! [11] + QList<QString> list = {"A", "B", "C", "D"}; -//! [14] -// RIGHT -const QList<int> sizes = splitter->sizes(); -for (auto i = sizes.begin(), end = sizes.end(); i != end; ++i) - ... + for (auto i = list.rbegin(), rend = list.rend(); i != rend; ++i) + *i = i->toLower(); + //! [11] -// WRONG -for (auto i = splitter->sizes().begin(); - i != splitter->sizes().end(); ++i) - ... -//! [14] + //! [12] + for (auto i = list.cbegin(), end = list.cend(); i != end; ++i) + qDebug() << *i; + //! [12] -//! [15] -QList<QString> values; -... -QString str; -foreach (str, values) - qDebug() << str; -//! [15] + //! [13] + QMap<int, int> map; + //... + for (auto i = map.cbegin(), end = map.cend(); i != end; ++i) + qDebug() << i.key() << ':' << i.value(); + //! [13] + } -//! [16] -QList<QString> values; -... -QListIterator<QString> i(values); -while (i.hasNext()) { - QString s = i.next(); - qDebug() << s; -} -//! [16] + { + //! [15] + QList<QString> values; + //... + QString str; + foreach (str, values) + qDebug() << str; + //! [15] + } + { + //! [16] + QList<QString> values; + //... + QListIterator<QString> i(values); + while (i.hasNext()) { + QString s = i.next(); + qDebug() << s; + } + //! [16] + } -//! [17] -QList<QString> values; -... -foreach (const QString &str, values) - qDebug() << str; -//! [17] + { + //! [17] + QList<QString> values; + //... + foreach (const QString &str, values) + qDebug() << str; + //! [17] + } + { + //! [18] + QList<QString> values; + //... + foreach (const QString &str, values) { + if (str.isEmpty()) + break; + qDebug() << str; + } + //! [18] + } -//! [18] -QList<QString> values; -... -foreach (const QString &str, values) { - if (str.isEmpty()) - break; - qDebug() << str; -} -//! [18] + { + //! [19] + QMap<QString, int> map; + //... + foreach (const QString &str, map.keys()) + qDebug() << str << ':' << map.value(str); + //! [19] + } + { + //! [20] + QMultiMap<QString, int> map; + //... + foreach (const QString &str, map.uniqueKeys()) { + foreach (int i, map.values(str)) + qDebug() << str << ':' << i; + } + //! [20] + } -//! [19] -QMap<QString, int> map; -... -foreach (const QString &str, map.keys()) - qDebug() << str << ':' << map.value(str); -//! [19] + { + #if 0 + //! [22] + CONFIG += no_keywords + //! [22] -//! [20] -QMultiMap<QString, int> map; -... -foreach (const QString &str, map.uniqueKeys()) { - foreach (int i, map.values(str)) - qDebug() << str << ':' << i; + //! [cmake_no_keywords] + target_compile_definitions(my_app PRIVATE QT_NO_KEYWORDS) + //! [cmake_no_keywords] + #endif + } } -//! [20] - - -//! [22] -CONFIG += no_keywords -//! [22] - - -//! [cmake_no_keywords] -target_compile_definitions(my_app PRIVATE QT_NO_KEYWORDS) -//! [cmake_no_keywords] - //! [23] QString onlyLetters(const QString &in) @@ -250,61 +252,111 @@ QString onlyLetters(const QString &in) } //! [23] -//! [24] -QList<int> a, b; -a.resize(100000); // make a big list filled with 0. - -QList<int>::iterator i = a.begin(); -// WRONG way of using the iterator i: -b = a; -/* - Now we should be careful with iterator i since it will point to shared data - If we do *i = 4 then we would change the shared instance (both vectors) - The behavior differs from STL containers. Avoid doing such things in Qt. -*/ - -a[0] = 5; -/* - Container a is now detached from the shared data, - and even though i was an iterator from the container a, it now works as an iterator in b. - Here the situation is that (*i) == 0. -*/ - -b.clear(); // Now the iterator i is completely invalid. - -int j = *i; // Undefined behavior! -/* - The data from b (which i pointed to) is gone. - This would be well-defined with STL containers (and (*i) == 5), - but with QList this is likely to crash. -*/ -//! [24] - -//! [25] -QList<int> list = {1, 2, 3, 4, 4, 5}; -QSet<int> set(list.cbegin(), list.cend()); -/* - Will generate a QSet containing 1, 2, 3, 4, 5. -*/ -//! [25] - -//! [26] -QList<int> list = {2, 3, 1}; - -std::sort(list.begin(), list.end()); -/* - Sort the list, now contains { 1, 2, 3 } -*/ - -std::reverse(list.begin(), list.end()); -/* - Reverse the list, now contains { 3, 2, 1 } -*/ - -int even_elements = - std::count_if(list.begin(), list.end(), [](int element) { return (element % 2 == 0); }); -/* - Count how many elements that are even numbers, 1 -*/ - -//! [26] +void wrap() +{ + //! [24] + QList<int> a, b; + a.resize(100000); // make a big list filled with 0. + + QList<int>::iterator i = a.begin(); + // WRONG way of using the iterator i: + b = a; + /* + Now we should be careful with iterator i since it will point to shared data + If we do *i = 4 then we would change the shared instance (both vectors) + The behavior differs from STL containers. Avoid doing such things in Qt. + */ + + a[0] = 5; + /* + Container a is now detached from the shared data, + and even though i was an iterator from the container a, it now works as an iterator in b. + Here the situation is that (*i) == 0. + */ + + b.clear(); // Now the iterator i is completely invalid. + + int j = *i; // Undefined behavior! + /* + The data from b (which i pointed to) is gone. + This would be well-defined with STL containers (and (*i) == 5), + but with QList this is likely to crash. + */ + //! [24] + + { + //! [25] + QList<int> list = {1, 2, 3, 4, 4, 5}; + QSet<int> set(list.cbegin(), list.cend()); + /* + Will generate a QSet containing 1, 2, 3, 4, 5. + */ + //! [25] + } + + //! [26] + QList<int> list = {2, 3, 1}; + + std::sort(list.begin(), list.end()); + /* + Sort the list, now contains { 1, 2, 3 } + */ + + std::reverse(list.begin(), list.end()); + /* + Reverse the list, now contains { 3, 2, 1 } + */ + + int even_elements = + std::count_if(list.begin(), list.end(), [](int element) { return (element % 2 == 0); }); + /* + Count how many elements that are even numbers, 1 + */ + //! [26] +} + +#if __has_include(<QWidget>) + +#include <QWidget> +#include <QSplitter> + +void examples_with_widgets() +{ + { + //! [8] + QMap<int, QWidget *> map; + QHash<int, QWidget *> hash; + + QMapIterator<int, QWidget *> i(map); + while (i.hasNext()) { + i.next(); + hash.insert(i.key(), i.value()); + } + //! [8] + } + + { + QMap<int, QWidget *> map; + QWidget* widget; + //! [9] + QMutableMapIterator<int, QWidget *> i(map); + while (i.findNext(widget)) + i.remove(); + //! [9] + } + + QSplitter* splitter; + + //! [14] + // RIGHT + const QList<int> sizes = splitter->sizes(); + for (auto i = sizes.begin(), end = sizes.end(); i != end; ++i) + {/*...*/} + + // WRONG + for (auto i = splitter->sizes().begin(); + i != splitter->sizes().end(); ++i) + {/*...*/} + //! [14] +} +#endif diff --git a/src/corelib/doc/snippets/code/doc_src_groups.cpp b/src/corelib/doc/snippets/code/doc_src_groups.cpp index a0901904db0..2d7c2f96056 100644 --- a/src/corelib/doc/snippets/code/doc_src_groups.cpp +++ b/src/corelib/doc/snippets/code/doc_src_groups.cpp @@ -1,6 +1,15 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +#include <QPen> +#include <QPainter> + +class QPenPrivate { +public: + int ref = 1; + Qt::PenStyle style; +}; + //! [0] void QPen::setStyle(Qt::PenStyle style) { @@ -11,19 +20,21 @@ void QPen::setStyle(Qt::PenStyle style) void QPen::detach() { if (d->ref != 1) { - ... // perform a deep copy + //... // perform a deep copy } } //! [0] +void example() +{ + //! [1] + QPixmap p1, p2; + p1.load("image.bmp"); + p2 = p1; // p1 and p2 share data -//! [1] -QPixmap p1, p2; -p1.load("image.bmp"); -p2 = p1; // p1 and p2 share data - -QPainter paint; -paint.begin(&p2); // cuts p2 loose from p1 -paint.drawText(0,50, "Hi"); -paint.end(); -//! [1] + QPainter paint; + paint.begin(&p2); // cuts p2 loose from p1 + paint.drawText(0,50, "Hi"); + paint.end(); + //! [1] +} diff --git a/src/corelib/doc/snippets/code/doc_src_objecttrees.cpp b/src/corelib/doc/snippets/code/doc_src_objecttrees.cpp index b7c71ccb6b0..8b55ad9b157 100644 --- a/src/corelib/doc/snippets/code/doc_src_objecttrees.cpp +++ b/src/corelib/doc/snippets/code/doc_src_objecttrees.cpp @@ -1,23 +1,31 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -//![0] +#include <QPushButton> + +//![open] int main() { - QWidget window; - QPushButton quit("Quit", &window); - ... -} -//![0] +//![open] + { + //![example1] + QWidget window; + QPushButton quit("Quit", &window); + //... + //![example1] + } -//![1] -int main() -{ - QPushButton quit("Quit"); - QWidget window; + { + //![example2] + QPushButton quit("Quit"); + QWidget window; + + quit.setParent(&window); + //... + //![example2] + } - quit.setParent(&window); - ... +//![close] } -//![1] +//![close] diff --git a/src/corelib/doc/snippets/code/doc_src_properties.cpp b/src/corelib/doc/snippets/code/doc_src_properties.cpp index 190a8437101..eafa7acda3b 100644 --- a/src/corelib/doc/snippets/code/doc_src_properties.cpp +++ b/src/corelib/doc/snippets/code/doc_src_properties.cpp @@ -1,6 +1,7 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +#ifdef QPROPERTY_MACRO //! [0] Q_PROPERTY(type name (READ getFunction [WRITE setFunction] | @@ -25,33 +26,40 @@ Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled) Q_PROPERTY(QCursor cursor READ cursor WRITE setCursor RESET unsetCursor) //! [1] - //! [2] Q_PROPERTY(QDate date READ getDate WRITE setDate) //! [2] +#endif +#if __has_include(<QPushButton>) +#include <QPushButton> +void button_example() +{ + //! [3] + QPushButton *button = new QPushButton; + QObject *object = button; -//! [3] -QPushButton *button = new QPushButton; -QObject *object = button; - -button->setDown(true); -object->setProperty("down", true); -//! [3] - - -//! [4] -QObject *object = ... -const QMetaObject *metaobject = object->metaObject(); -int count = metaobject->propertyCount(); -for (int i=0; i<count; ++i) { - QMetaProperty metaproperty = metaobject->property(i); - const char *name = metaproperty.name(); - QVariant value = object->property(name); - ... + button->setDown(true); + object->setProperty("down", true); + //! [3] } -//! [4] +#endif +#include <QMetaProperty> +void qobject_example() +{ + //! [4] + QObject *object = new QObject; + const QMetaObject *metaobject = object->metaObject(); + int count = metaobject->propertyCount(); + for (int i=0; i<count; ++i) { + QMetaProperty metaproperty = metaobject->property(i); + const char *name = metaproperty.name(); + QVariant value = object->property(name); + //... + } + //! [4] +} //! [5] class MyClass : public QObject @@ -85,16 +93,17 @@ private: }; //! [5] +void example(){ + //! [6] + MyClass *myinstance = new MyClass; + QObject *object = myinstance; -//! [6] -MyClass *myinstance = new MyClass; -QObject *object = myinstance; - -myinstance->setPriority(MyClass::VeryHigh); -object->setProperty("priority", "VeryHigh"); -//! [6] - + myinstance->setPriority(MyClass::VeryHigh); + object->setProperty("priority", "VeryHigh"); + //! [6] +} +#ifdef QPROPERTY_MACRO //! [7] Q_CLASSINFO("DefaultProperty", "content") //! [7] @@ -103,7 +112,7 @@ Q_CLASSINFO("DefaultProperty", "content") Q_PROPERTY(QColor color MEMBER m_color NOTIFY colorChanged) Q_PROPERTY(qreal spacing MEMBER m_spacing NOTIFY spacingChanged) Q_PROPERTY(QString text MEMBER m_text NOTIFY textChanged) - ... + //... signals: void colorChanged(); void spacingChanged(); @@ -114,4 +123,4 @@ private: qreal m_spacing; QString m_text; //! [8] - +#endif diff --git a/src/corelib/doc/snippets/code/doc_src_qalgorithms.cpp b/src/corelib/doc/snippets/code/doc_src_qalgorithms.cpp index f2b94a74165..9155345508a 100644 --- a/src/corelib/doc/snippets/code/doc_src_qalgorithms.cpp +++ b/src/corelib/doc/snippets/code/doc_src_qalgorithms.cpp @@ -1,11 +1,17 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -//! [1] -QList<Employee *> list; -list.append(new Employee("Blackpool", "Stephen")); -list.append(new Employee("Twist", "Oliver")); +#include <QList> +#include <QColor> -qDeleteAll(list.begin(), list.end()); -list.clear(); -//! [1] +void example() +{ + //! [1] + QList<QColor *> list; + list.append(new QColor(Qt::blue)); + list.append(new QColor(Qt::yellow)); + + qDeleteAll(list.begin(), list.end()); + list.clear(); + //! [1] +} diff --git a/src/corelib/doc/snippets/code/doc_src_qcache.cpp b/src/corelib/doc/snippets/code/doc_src_qcache.cpp index a15a8027600..3157981f3fa 100644 --- a/src/corelib/doc/snippets/code/doc_src_qcache.cpp +++ b/src/corelib/doc/snippets/code/doc_src_qcache.cpp @@ -1,20 +1,34 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -//! [0] -QCache<int, Employee> cache; -//! [0] +#include <QCache> +struct Employee { + void setId(int id); + int id() const { return 0; } + void setName(const QString &name); +}; -//! [1] -Employee *employee = new Employee; -employee->setId(37); -employee->setName("Richard Schmit"); -... -cache.insert(employee->id(), employee); -//! [1] +struct MyDataStructure { }; +void example() +{ + //! [0] + QCache<int, Employee> cache; + //! [0] -//! [2] -QCache<int, MyDataStructure> cache(5000); -//! [2] + + //! [1] + Employee *employee = new Employee; + employee->setId(37); + employee->setName("Richard Schmit"); + //... + cache.insert(employee->id(), employee); + //! [1] + + { + //! [2] + QCache<int, MyDataStructure> cache(5000); + //! [2] + } +} diff --git a/src/corelib/doc/snippets/code/doc_src_qiterator.cpp b/src/corelib/doc/snippets/code/doc_src_qiterator.cpp index 0d921b87e67..209e98af522 100644 --- a/src/corelib/doc/snippets/code/doc_src_qiterator.cpp +++ b/src/corelib/doc/snippets/code/doc_src_qiterator.cpp @@ -1,278 +1,349 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -//! [0] -QList<float> list; -... -QListIterator<float> i(list); -while (i.hasNext()) - float f = i.next(); -//! [0] - - -//! [1] -QListIterator<float> i(list); -i.toBack(); -while (i.hasPrevious()) - float f = i.previous(); -//! [1] - -//! [6] -QSet<QString> set; -... -QSetIterator<QString> i(set); -while (i.hasNext()) - float f = i.next(); -//! [6] - -//! [8] -QList<float> list; -... -QMutableListIterator<float> i(list); -while (i.hasNext()) - float f = i.next(); -//! [8] - - -//! [9] -QMutableListIterator<float> i(list); -i.toBack(); -while (i.hasPrevious()) - float f = i.previous(); -//! [9] - - -//! [10] -QMutableListIterator<int> i(list); -while (i.hasNext()) { - int val = i.next(); - if (val < 0) { - i.setValue(-val); - } else if (val == 0) { - i.remove(); +#include <QList> +#include <QSet> + +void example() +{ + { + //! [0] + QList<float> list; + //... + QListIterator<float> i(list); + while (i.hasNext()) + float f = i.next(); + //! [0] } -} -//! [10] - -//! [17] -QSet<float> set; -... -QMutableSetIterator<float> i(set); -while (i.hasNext()) - float f = i.next(); -//! [17] -//! [19] -QMutableListIterator<int> i(list); -while (i.hasNext()) { - int val = i.next(); - if (val < -32768 || val > 32767) - i.remove(); -} -//! [19] - -//! [22] -QMutableSetIterator<int> i(set); -while (i.hasNext()) { - int val = i.next(); - if (val < -32768 || val > 32767) - i.remove(); -} -//! [22] - - -//! [23] -QMutableListIterator<double> i(list); -while (i.hasNext()) { - double val = i.next(); - i.setValue(std::sqrt(val)); -} -//! [23] - -//! [26] -QMap<int, QWidget *> map; -... -QMapIterator<int, QWidget *> i(map); -while (i.hasNext()) { - i.next(); - qDebug() << i.key() << ": " << i.value(); -} -//! [26] - - -//! [27] -QMapIterator<int, QWidget *> i(map); -i.toBack(); -while (i.hasPrevious()) { - i.previous(); - qDebug() << i.key() << ": " << i.value(); -} -//! [27] - - -//! [28] -QMapIterator<int, QWidget *> i(map); -while (i.findNext(widget)) { - qDebug() << "Found widget " << widget << " under key " - << i.key(); -} -//! [28] - -//! [26multi] -QMultiMap<int, QWidget *> multimap; -... -QMultiMapIterator<int, QWidget *> i(multimap); -while (i.hasNext()) { - i.next(); - qDebug() << i.key() << ": " << i.value(); -} -//! [26multi] + QList<float> list; + { + //! [1] + QListIterator<float> i(list); + i.toBack(); + while (i.hasPrevious()) + float f = i.previous(); + //! [1] + } -//! [27multi] -QMultiMapIterator<int, QWidget *> i(multimap); -i.toBack(); -while (i.hasPrevious()) { - i.previous(); - qDebug() << i.key() << ": " << i.value(); -} -//! [27multi] + { + //! [6] + QSet<QString> set; + //... + QSetIterator<QString> i(set); + while (i.hasNext()) + QString f = i.next(); + //! [6] + } + { + //! [8] + QList<float> list; + //... + QMutableListIterator<float> i(list); + while (i.hasNext()) + float f = i.next(); + //! [8] + } -//! [28multi] -QMultiMapIterator<int, QWidget *> i(multimap); -while (i.findNext(widget)) { - qDebug() << "Found widget " << widget << " under key " - << i.key(); -} -//! [28multi] + { + //! [9] + QMutableListIterator<float> i(list); + i.toBack(); + while (i.hasPrevious()) + float f = i.previous(); + //! [9] + } + { + QList<int> list = {1, 2, 3, 4, 5}; + //! [10] + QMutableListIterator<int> i(list); + while (i.hasNext()) { + int val = i.next(); + if (val < 0) { + i.setValue(-val); + } else if (val == 0) { + i.remove(); + } + } + //! [10] + } -//! [29] -QHash<int, QWidget *> hash; -... -QHashIterator<int, QWidget *> i(hash); -while (i.hasNext()) { - i.next(); - qDebug() << i.key() << ": " << i.value(); -} -//! [29] + { + //! [17] + QSet<float> set; + //... + QMutableSetIterator<float> i(set); + while (i.hasNext()) + float f = i.next(); + //! [17] + } + { + QList<int> list = {1, 2, 3, 4, 5}; + //! [19] + QMutableListIterator<int> i(list); + while (i.hasNext()) { + int val = i.next(); + if (val < -32768 || val > 32767) + i.remove(); + } + //! [19] + } -//! [31] -QHashIterator<int, QWidget *> i(hash); -while (i.findNext(widget)) { - qDebug() << "Found widget " << widget << " under key " - << i.key(); -} -//! [31] + { + QSet<int> set; + //! [22] + QMutableSetIterator<int> i(set); + while (i.hasNext()) { + int val = i.next(); + if (val < -32768 || val > 32767) + i.remove(); + } + //! [22] + } + { + QList<double> list; + //! [23] + QMutableListIterator<double> i(list); + while (i.hasNext()) { + double val = i.next(); + i.setValue(std::sqrt(val)); + } + //! [23] + } -//! [32] -QMap<int, QWidget *> map; -... -QMutableMapIterator<int, QWidget *> i(map); -while (i.hasNext()) { - i.next(); - qDebug() << i.key() << ": " << i.value(); + { + //! [25] + QList<int> list; + //... + QListIterator<int> i(list); + while (i.hasNext()) + int val = i.next(); + //! [25] + } } -//! [32] - -//! [33] -QMutableMapIterator<int, QWidget *> i(map); -i.toBack(); -while (i.hasPrevious()) { - i.previous(); - qDebug() << i.key() << ": " << i.value(); -} -//! [33] +#if __has_include(<QWidget>) +#include <QWidget> +void example_widgets() +{ + QMap<int, QWidget *> map; + { + //! [26] + QMap<int, QWidget *> map; + //... + QMapIterator<int, QWidget *> i(map); + while (i.hasNext()) { + i.next(); + qDebug() << i.key() << ": " << i.value(); + } + //! [26] + } + { + //! [27] + QMapIterator<int, QWidget *> i(map); + i.toBack(); + while (i.hasPrevious()) { + i.previous(); + qDebug() << i.key() << ": " << i.value(); + } + //! [27] + } -//! [34] -QMutableMapIterator<int, QWidget *> i(map); -while (i.findNext(widget)) { - qDebug() << "Found widget " << widget << " under key " - << i.key(); -} -//! [34] + QWidget *widget; + { + //! [28] + QMapIterator<int, QWidget *> i(map); + while (i.findNext(widget)) { + qDebug() << "Found widget " << widget << " under key " + << i.key(); + } + //! [28] + } + { + //! [26multi] + QMultiMap<int, QWidget *> multimap; + //... + QMultiMapIterator<int, QWidget *> i(multimap); + while (i.hasNext()) { + i.next(); + qDebug() << i.key() << ": " << i.value(); + } + //! [26multi] + } -//! [35] -QMutableMapIterator<QString, QString> i(map); -while (i.hasNext()) { - i.next(); - if (i.key() == i.value()) - i.remove(); -} -//! [35] + QMultiMap<int, QWidget *> multimap; + { + //! [27multi] + QMultiMapIterator<int, QWidget *> i(multimap); + i.toBack(); + while (i.hasPrevious()) { + i.previous(); + qDebug() << i.key() << ": " << i.value(); + } + //! [27multi] + } + { + //! [28multi] + QMultiMapIterator<int, QWidget *> i(multimap); + while (i.findNext(widget)) { + qDebug() << "Found widget " << widget << " under key " + << i.key(); + } + //! [28multi] + } -//! [32multi] -QMultiMap<int, QWidget *> multimap; -... -QMutableMultiMapIterator<int, QWidget *> i(multimap); -while (i.hasNext()) { - i.next(); - qDebug() << i.key() << ": " << i.value(); -} -//! [32multi] + { + //! [29] + QHash<int, QWidget *> hash; + //... + QHashIterator<int, QWidget *> i(hash); + while (i.hasNext()) { + i.next(); + qDebug() << i.key() << ": " << i.value(); + } + //! [29] + } + QHash<int, QWidget *> hash; + { + //! [31] + QHashIterator<int, QWidget *> i(hash); + while (i.findNext(widget)) { + qDebug() << "Found widget " << widget << " under key " + << i.key(); + } + //! [31] + } -//! [33multi] -QMutableMultiMapIterator<int, QWidget *> i(multimap); -i.toBack(); -while (i.hasPrevious()) { - i.previous(); - qDebug() << i.key() << ": " << i.value(); -} -//! [33multi] + { + //! [32] + QMap<int, QWidget *> map; + //... + QMutableMapIterator<int, QWidget *> i(map); + while (i.hasNext()) { + i.next(); + qDebug() << i.key() << ": " << i.value(); + } + //! [32] + } + { + //! [33] + QMutableMapIterator<int, QWidget *> i(map); + i.toBack(); + while (i.hasPrevious()) { + i.previous(); + qDebug() << i.key() << ": " << i.value(); + } + //! [33] + } -//! [34multi] -QMutableMultiMapIterator<int, QWidget *> i(multimap); -while (i.findNext(widget)) { - qDebug() << "Found widget " << widget << " under key " - << i.key(); -} -//! [34multi] + { + //! [34] + QMutableMapIterator<int, QWidget *> i(map); + while (i.findNext(widget)) { + qDebug() << "Found widget " << widget << " under key " + << i.key(); + } + //! [34] + } + { + QMap<QString, QString> map; + //! [35] + QMutableMapIterator<QString, QString> i(map); + while (i.hasNext()) { + i.next(); + if (i.key() == i.value()) + i.remove(); + } + //! [35] + } -//! [35multi] -QMutableMultiMapIterator<QString, QString> i(multimap); -while (i.hasNext()) { - i.next(); - if (i.key() == i.value()) - i.remove(); -} -//! [35multi] + { + //! [32multi] + QMultiMap<int, QWidget *> multimap; + //... + QMutableMultiMapIterator<int, QWidget *> i(multimap); + while (i.hasNext()) { + i.next(); + qDebug() << i.key() << ": " << i.value(); + } + //! [32multi] + } + { + //! [33multi] + QMutableMultiMapIterator<int, QWidget *> i(multimap); + i.toBack(); + while (i.hasPrevious()) { + i.previous(); + qDebug() << i.key() << ": " << i.value(); + } + //! [33multi] + } -//! [36] -QHash<int, QWidget *> hash; -... -QMutableHashIterator<QString, QWidget *> i(hash); -while (i.hasNext()) { - i.next(); - qDebug() << i.key() << ": " << i.value(); -} -//! [36] + { + //! [34multi] + QMutableMultiMapIterator<int, QWidget *> i(multimap); + while (i.findNext(widget)) { + qDebug() << "Found widget " << widget << " under key " + << i.key(); + } + //! [34multi] + } + { + QMultiMap<QString, QString> multimap; + //! [35multi] + QMutableMultiMapIterator<QString, QString> i(multimap); + while (i.hasNext()) { + i.next(); + if (i.key() == i.value()) + i.remove(); + } + //! [35multi] + } -//! [38] -QMutableHashIterator<int, QWidget *> i(hash); -while (i.findNext(widget)) { - qDebug() << "Found widget " << widget << " under key " - << i.key(); -} -//! [38] + { + //! [36] + QHash<int, QWidget *> hash; + //... + QMutableHashIterator<int, QWidget *> i(hash); + while (i.hasNext()) { + i.next(); + qDebug() << i.key() << ": " << i.value(); + } + //! [36] + } + { + //! [38] + QMutableHashIterator<int, QWidget *> i(hash); + while (i.findNext(widget)) { + qDebug() << "Found widget " << widget << " under key " + << i.key(); + } + //! [38] + } -//! [39] -QMutableHashIterator<QString, QString> i(hash); -while (i.hasNext()) { - i.next(); - if (i.key() == i.value()) - i.remove(); + { + QHash<QString, QString> hash; + //! [39] + QMutableHashIterator<QString, QString> i(hash); + while (i.hasNext()) { + i.next(); + if (i.key() == i.value()) + i.remove(); + } + //! [39] + } } -//! [39] +#endif diff --git a/src/corelib/doc/snippets/code/doc_src_qnamespace.cpp b/src/corelib/doc/snippets/code/doc_src_qnamespace.cpp index 10845855840..d753874f0dd 100644 --- a/src/corelib/doc/snippets/code/doc_src_qnamespace.cpp +++ b/src/corelib/doc/snippets/code/doc_src_qnamespace.cpp @@ -1,6 +1,8 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +#include <QEvent> + //! [1] enum CustomEventPriority { diff --git a/src/corelib/doc/snippets/code/doc_src_qplugin.cpp b/src/corelib/doc/snippets/code/doc_src_qplugin.cpp index 3bca27b9661..4382d13838a 100644 --- a/src/corelib/doc/snippets/code/doc_src_qplugin.cpp +++ b/src/corelib/doc/snippets/code/doc_src_qplugin.cpp @@ -1,10 +1,12 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +#include <QtPlugin> + //! [0] namespace Foo { - struct MyInterface { ... }; + struct MyInterface { /*...*/ }; } Q_DECLARE_INTERFACE(Foo::MyInterface, "org.examples.MyInterface") diff --git a/src/corelib/doc/snippets/code/doc_src_qset.cpp b/src/corelib/doc/snippets/code/doc_src_qset.cpp index 98a6f336f5a..8342e1d6f98 100644 --- a/src/corelib/doc/snippets/code/doc_src_qset.cpp +++ b/src/corelib/doc/snippets/code/doc_src_qset.cpp @@ -1,107 +1,134 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -//! [0] -QSet<QString> set; -//! [0] +#include <QtCore> +#include <iostream> +using namespace std; +void snippets_0_3() +{ + //! [0] + QSet<QString> set; + //! [0] -//! [1] -set.insert("one"); -set.insert("three"); -set.insert("seven"); -//! [1] + //! [1] + set.insert("one"); + set.insert("three"); + set.insert("seven"); + //! [1] -//! [2] -set << "twelve" << "fifteen" << "nineteen"; -//! [2] + //! [2] + set << "twelve" << "fifteen" << "nineteen"; + //! [2] -//! [3] -if (!set.contains("ninety-nine")) - ... -//! [3] - -//! [4] -QSetIterator<QWidget *> i(set); -while (i.hasNext()) { - QWidget *w = i.next(); - qDebug() << w; + //! [3] + if (!set.contains("ninety-nine")) + {/*...*/} + //! [3] } -//! [4] - -//! [5] -for (auto i = set.cbegin(), end = set.cend(); i != end; ++i) - qDebug() << *i; -//! [5] +#if __has_include(<QWidget>) +#include <QWidget> -//! [6] -QSet<QString> set; -... -for (const auto &value : set) - qDebug() << value; -//! [6] +void example_widgets() +{ + QSet<QWidget *> set; + //! [4] + QSetIterator<QWidget *> i(set); + while (i.hasNext()) { + QWidget *w = i.next(); + qDebug() << w; + } + //! [4] +} +#endif + +void snippets_5_12() +{ + QSet<QString> set; + + //! [5] + for (auto i = set.cbegin(), end = set.cend(); i != end; ++i) + qDebug() << *i; + //! [5] + + { + //! [6] + QSet<QString> set; + //... + for (const auto &value : set) + qDebug() << value; + //! [6] + } + { + QString values[3]; + //! [7] + QSet<QString> set; + set.reserve(20000); + for (int i = 0; i < 20000; ++i) + set.insert(values[i]); + //! [7] + } -//! [7] -QSet<QString> set; -set.reserve(20000); -for (int i = 0; i < 20000; ++i) - set.insert(values[i]); -//! [7] + { + //! [8] + QSet<QString> set = {"January", "February", /*...*/ "December"}; + // i is a QSet<QString>::iterator + for (auto i = set.begin(), end = set.end(); i != end; ++i) + qDebug() << *i; + //! [8] + } -//! [8] -QSet<QString> set = {"January", "February", ... "December"} + { + //! [9] + QSet<QString> set = {"January", "February", /*...*/ "December"}; + + auto i = set.begin(); + while (i != set.end()) { + if ((*i).startsWith('J')) { + i = set.erase(i); + } else { + ++i; + } + } + //! [9] + } -// i is a QSet<QString>::iterator -for (auto i = set.begin(), end = set.end(); i != end; ++i) - qDebug() << *i; -//! [8] + { + //! [10] + QSet<QString> set; + //... + const auto predicate = [](const QString &s) { return s.compare("Jeanette", Qt::CaseInsensitive) == 0; }; + QSet<QString>::iterator it = std::find_if(set.begin(), set.end(), predicate); + if (it != set.end()) + cout << "Found Jeanette" << endl; + //! [10] + } + { + //! [11] + QSet<QString> set = {"January", "February", /*...*/ "December"}; -//! [9] -QSet<QString> set = {"January", "February", ... "December"}; + // i is QSet<QString>::const_iterator + for (auto i = set.cbegin(), end = set.cend(); i != end; ++i) + qDebug() << *i; + //! [11] + } -auto i = set.begin(); -while (i != set.end()) { - if ((*i).startsWith('J')) { - i = set.erase(i); - } else { - ++i; + { + //! [12] + QSet<QString> set; + //... + const auto predicate = [](const QString &s) { return s.compare("Jeanette", Qt::CaseInsensitive) == 0; }; + QSet<QString>::const_iterator it = std::find_if(set.cbegin(), set.cend(), predicate); + if (it != set.constEnd()) + cout << "Found Jeanette" << endl; + //! [12] } } -//! [9] - - -//! [10] -QSet<QString> set; -... -const auto predicate = [](const QString &s) { return s.compare("Jeanette", Qt::CaseInsensitive) == 0; }; -QSet<QString>::iterator it = std::find_if(set.begin(), set.end(), predicate); -if (it != set.end()) - cout << "Found Jeanette" << endl; -//! [10] - - -//! [11] -QSet<QString> set = {"January", "February", ... "December"}; - -// i is QSet<QString>::const_iterator -for (auto i = set.cbegin(), end = set.cend(); i != end; ++i) - qDebug() << *i; -//! [11] - - -//! [12] -QSet<QString> set; -... -const auto predicate = [](const QString &s) { return s.compare("Jeanette", Qt::CaseInsensitive) == 0; }; -QSet<QString>::const_iterator it = std::find_if(set.cbegin(), set.cend(), predicate); -if (it != set.constEnd()) - cout << "Found Jeanette" << endl; -//! [12] diff --git a/src/corelib/doc/snippets/code/doc_src_qvarlengtharray.cpp b/src/corelib/doc/snippets/code/doc_src_qvarlengtharray.cpp index 080874fc77d..4d2ccc82c2e 100644 --- a/src/corelib/doc/snippets/code/doc_src_qvarlengtharray.cpp +++ b/src/corelib/doc/snippets/code/doc_src_qvarlengtharray.cpp @@ -1,21 +1,24 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +#include <QVarLengthArray> + +#if 0 //! [0] -int myfunc(int n) +int myfunc_wrong(int n) { int table[n + 1]; // WRONG - ... + //... return table[n]; } //! [0] - +#endif //! [1] -int myfunc(int n) +int myfunc_correct(int n) { int *table = new int[n + 1]; - ... + //... int ret = table[n]; delete[] table; return ret; @@ -24,18 +27,21 @@ int myfunc(int n) //! [2] -int myfunc(int n) +int myfunc_q(int n) { QVarLengthArray<int, 1024> array(n + 1); - ... + //... return array[n]; } //! [2] -//! [3] -QVarLengthArray<int> array(10); -int *data = array.data(); -for (int i = 0; i < 10; ++i) - data[i] = 2 * i; -//! [3] +void example() +{ + //! [3] + QVarLengthArray<int> array(10); + int *data = array.data(); + for (int i = 0; i < 10; ++i) + data[i] = 2 * i; + //! [3] +} diff --git a/src/corelib/doc/snippets/code/doc_src_resources.cpp b/src/corelib/doc/snippets/code/doc_src_resources.cpp index 04ecf810ec1..9a244b9239d 100644 --- a/src/corelib/doc/snippets/code/doc_src_resources.cpp +++ b/src/corelib/doc/snippets/code/doc_src_resources.cpp @@ -1,10 +1,25 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -//! [4] -QResource::registerResource("/path/to/myresource.rcc"); -//! [4] +#include <QResource> +#include <QFile> +void wrap() +{ + //! [4] + QResource::registerResource("/path/to/myresource.rcc"); + //! [4] +} + +class BaseClass { + public: + BaseClass() {} +}; + +class MyClass : BaseClass { + public: + MyClass(); +}; //! [5] MyClass::MyClass() : BaseClass() @@ -12,6 +27,6 @@ MyClass::MyClass() : BaseClass() Q_INIT_RESOURCE(resources); QFile file(":/myfile.dat"); - ... + //... } //! [5] diff --git a/src/corelib/doc/snippets/eventfilters/CMakeLists.txt b/src/corelib/doc/snippets/eventfilters/CMakeLists.txt index ea381e425a5..7da83cbdf6e 100644 --- a/src/corelib/doc/snippets/eventfilters/CMakeLists.txt +++ b/src/corelib/doc/snippets/eventfilters/CMakeLists.txt @@ -1,17 +1,19 @@ -add_library(snippets_eventfilters OBJECT) +add_library(corelib_snippets_eventfilters OBJECT) -target_link_libraries(snippets_eventfilters PRIVATE +set_target_properties(corelib_snippets_eventfilters PROPERTIES COMPILE_OPTIONS "-w") + +target_link_libraries(corelib_snippets_eventfilters PRIVATE Qt::Core ) -qt_internal_extend_target(snippets_eventfilters CONDITION QT_FEATURE_widgets +qt_internal_extend_target(corelib_snippets_eventfilters CONDITION QT_FEATURE_widgets LIBRARIES Qt::Widgets SOURCE main.cpp ) -qt_internal_extend_target(snippets_eventfilters CONDITION QT_FEATURE_gui +qt_internal_extend_target(corelib_snippets_eventfilters CONDITION QT_FEATURE_gui LIBRARIES Qt::Gui SOURCES diff --git a/src/corelib/doc/snippets/qmetaobject-invokable/CMakeLists.txt b/src/corelib/doc/snippets/qmetaobject-invokable/CMakeLists.txt index 76bb79951a3..972bf43d9b1 100644 --- a/src/corelib/doc/snippets/qmetaobject-invokable/CMakeLists.txt +++ b/src/corelib/doc/snippets/qmetaobject-invokable/CMakeLists.txt @@ -2,13 +2,15 @@ if(NOT QT_FEATURE_widgets) return() endif() -add_library(snippets_qmetaobject-invokable OBJECT) +add_library(corelib_snippets_qmetaobject-invokable OBJECT) -target_link_libraries(snippets_qmetaobject-invokable PRIVATE +set_target_properties(corelib_snippets_qmetaobject-invokable PROPERTIES COMPILE_OPTIONS "-w") + +target_link_libraries(corelib_snippets_qmetaobject-invokable PRIVATE Qt::Core ) -qt_internal_extend_target(snippets_qmetaobject-invokable CONDITION QT_FEATURE_widgets +qt_internal_extend_target(corelib_snippets_qmetaobject-invokable CONDITION QT_FEATURE_widgets LIBRARIES Qt::Widgets SOURCES diff --git a/src/corelib/doc/snippets/qmetaobject-revision/CMakeLists.txt b/src/corelib/doc/snippets/qmetaobject-revision/CMakeLists.txt index 0cadf9380b1..369b2e15315 100644 --- a/src/corelib/doc/snippets/qmetaobject-revision/CMakeLists.txt +++ b/src/corelib/doc/snippets/qmetaobject-revision/CMakeLists.txt @@ -2,13 +2,15 @@ if(NOT QT_FEATURE_widgets) return() endif() -add_library(snippets_qmetaobject-revision OBJECT) +add_library(corelib_snippets_qmetaobject-revision OBJECT) -target_link_libraries(snippets_qmetaobject-revision PRIVATE +set_target_properties(corelib_snippets_qmetaobject-revision PROPERTIES COMPILE_OPTIONS "-w") + +target_link_libraries(corelib_snippets_qmetaobject-revision PRIVATE Qt::Core ) -qt_internal_extend_target(snippets_qmetaobject-revision CONDITION QT_FEATURE_widgets +qt_internal_extend_target(corelib_snippets_qmetaobject-revision CONDITION QT_FEATURE_widgets LIBRARIES Qt::Widgets SOURCES diff --git a/src/corelib/doc/snippets/qprocess/CMakeLists.txt b/src/corelib/doc/snippets/qprocess/CMakeLists.txt index 07b66d0b36b..d00e051ed9b 100644 --- a/src/corelib/doc/snippets/qprocess/CMakeLists.txt +++ b/src/corelib/doc/snippets/qprocess/CMakeLists.txt @@ -1,8 +1,12 @@ -add_library(snippets_qprocess OBJECT +set(CMAKE_UNITY_BUILD OFF) + +add_library(corelib_snippets_qprocess OBJECT qprocess-createprocessargumentsmodifier.cpp qprocess-simpleexecution.cpp ) -target_link_libraries(snippets_qprocess PRIVATE +set_target_properties(corelib_snippets_qprocess PROPERTIES COMPILE_OPTIONS "-w") + +target_link_libraries(corelib_snippets_qprocess PRIVATE Qt::Core ) diff --git a/src/corelib/doc/snippets/qsignalmapper/CMakeLists.txt b/src/corelib/doc/snippets/qsignalmapper/CMakeLists.txt deleted file mode 100644 index 086ddbf9c5e..00000000000 --- a/src/corelib/doc/snippets/qsignalmapper/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -if(NOT TARGET Qt::Widgets) - return() -endif() - -add_library(snippets_qsignalmapper OBJECT - buttonwidget.cpp -) - -add_compile_definitions(EXAMPLE_ONE) - -target_link_libraries(snippets_qsignalmapper PRIVATE - Qt::Core -) - -qt_internal_extend_target(snippets_qsignalmapper CONDITION QT_FEATURE_widgets - LIBRARIES - Qt::Widgets -) diff --git a/src/corelib/doc/snippets/qsignalmapper/buttonwidget.cpp b/src/corelib/doc/snippets/qsignalmapper/buttonwidget.cpp index 1f9e53f1385..cdbf83a977d 100644 --- a/src/corelib/doc/snippets/qsignalmapper/buttonwidget.cpp +++ b/src/corelib/doc/snippets/qsignalmapper/buttonwidget.cpp @@ -5,39 +5,40 @@ #include <QtWidgets> -#ifdef EXAMPLE_ONE -//! [0] -ButtonWidget::ButtonWidget(const QStringList &texts, QWidget *parent) - : QWidget(parent) -{ - signalMapper = new QSignalMapper(this); + //! [OpenCtor] + ButtonWidget::ButtonWidget(const QStringList &texts, QWidget *parent) + : QWidget(parent) + { + //! [OpenCtor] + { + //![OldNotation] + signalMapper = new QSignalMapper(this); - QGridLayout *gridLayout = new QGridLayout(this); - for (int i = 0; i < texts.size(); ++i) { - QPushButton *button = new QPushButton(texts[i]); - connect(button, &QPushButton::clicked, signalMapper, qOverload<>(&QSignalMapper::map)); -//! [0] //! [1] - signalMapper->setMapping(button, texts[i]); - gridLayout->addWidget(button, i / 3, i % 3); + QGridLayout *gridLayout = new QGridLayout(this); + for (int i = 0; i < texts.size(); ++i) { + QPushButton *button = new QPushButton(texts[i]); + connect(button, &QPushButton::clicked, signalMapper, qOverload<>(&QSignalMapper::map)); + signalMapper->setMapping(button, texts[i]); + gridLayout->addWidget(button, i / 3, i % 3); + } + + connect(signalMapper, &QSignalMapper::mappedString, + this, &ButtonWidget::clicked); + //![OldNotation] + } + + { + //![ModernNotation] + QGridLayout *gridLayout = new QGridLayout(this); + for (int i = 0; i < texts.size(); ++i) { + QString text = texts[i]; + QPushButton *button = new QPushButton(text); + connect(button, &QPushButton::clicked, [this, text] { clicked(text); }); + gridLayout->addWidget(button, i / 3, i % 3); + } + //![ModernNotation] } - connect(signalMapper, &QSignalMapper::mappedString, -//! [1] //! [2] - this, &ButtonWidget::clicked); -} -//! [2] -#else -//! [3] -ButtonWidget::ButtonWidget(const QStringList &texts, QWidget *parent) - : QWidget(parent) -{ - QGridLayout *gridLayout = new QGridLayout(this); - for (int i = 0; i < texts.size(); ++i) { - QString text = texts[i]; - QPushButton *button = new QPushButton(text); - connect(button, &QPushButton::clicked, [this, text] { clicked(text); }); - gridLayout->addWidget(button, i / 3, i % 3); + //! [CloseBrackets] } -} -//! [3] -#endif + //! [CloseBrackets] diff --git a/src/corelib/doc/snippets/qsignalmapper/buttonwidget.h b/src/corelib/doc/snippets/qsignalmapper/buttonwidget.h index 537c21c9141..cd75628dc2b 100644 --- a/src/corelib/doc/snippets/qsignalmapper/buttonwidget.h +++ b/src/corelib/doc/snippets/qsignalmapper/buttonwidget.h @@ -4,10 +4,8 @@ #ifndef BUTTONWIDGET_H #define BUTTONWIDGET_H -#include <QWidget> +#include <QtWidgets> -class QSignalMapper; -class QString; //! [0] class ButtonWidget : public QWidget diff --git a/src/corelib/doc/src/cmake/qt_add_resources.qdoc b/src/corelib/doc/src/cmake/qt_add_resources.qdoc index 570272c6097..445e37e000a 100644 --- a/src/corelib/doc/src/cmake/qt_add_resources.qdoc +++ b/src/corelib/doc/src/cmake/qt_add_resources.qdoc @@ -111,5 +111,9 @@ resources linked into the final target. This especially affects static builds. There, the same resource name in different static libraries conflict in the consuming target. +In contrast to \l{qmake}'s \c{RESOURCES}, \c qt_add_resources does not +attempt to compile any QML or JavaScript files using \l{qmlcachegen}. Use +\l{qt_add_qml_module} for this. + \sa {qt6_add_big_resources}{qt_add_big_resources()} */ diff --git a/src/corelib/doc/src/objectmodel/objecttrees.qdoc b/src/corelib/doc/src/objectmodel/objecttrees.qdoc index 8939a534d40..25245fd5de8 100644 --- a/src/corelib/doc/src/objectmodel/objecttrees.qdoc +++ b/src/corelib/doc/src/objectmodel/objecttrees.qdoc @@ -59,7 +59,9 @@ behavior applies. Normally, the order of destruction still doesn't present a problem. Consider the following snippet: - \snippet code/doc_src_objecttrees.cpp 0 + \snippet code/doc_src_objecttrees.cpp open + \snippet code/doc_src_objecttrees.cpp example1 + \snippet code/doc_src_objecttrees.cpp close The parent, \c window, and the child, \c quit, are both \l {QObject} {QObjects} because QPushButton inherits QWidget, and QWidget inherits @@ -73,7 +75,9 @@ But now consider what happens if we swap the order of construction, as shown in this second snippet: - \snippet code/doc_src_objecttrees.cpp 1 + \snippet code/doc_src_objecttrees.cpp open + \snippet code/doc_src_objecttrees.cpp example2 + \snippet code/doc_src_objecttrees.cpp close In this case, the order of destruction causes a problem. The parent's destructor is called first because it was created last. It then calls diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index 1ecec63aed4..d1fc672564f 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -1,6 +1,7 @@ // Copyright (C) 2021 The Qt Company Ltd. // Copyright (C) 2021 Intel Corporation. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:critical reason:execute-external-code #include "qdir.h" #include "qstringlist.h" diff --git a/src/corelib/global/qnumeric.cpp b/src/corelib/global/qnumeric.cpp index 16b2b7ca408..8b153bcdb84 100644 --- a/src/corelib/global/qnumeric.cpp +++ b/src/corelib/global/qnumeric.cpp @@ -1,5 +1,6 @@ // Copyright (C) 2019 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:critical reason:data-parser #include "qnumeric.h" #include "qnumeric_p.h" diff --git a/src/corelib/global/qnumeric.h b/src/corelib/global/qnumeric.h index 2c7110c97a6..bc2bbf9e53e 100644 --- a/src/corelib/global/qnumeric.h +++ b/src/corelib/global/qnumeric.h @@ -1,6 +1,7 @@ // Copyright (C) 2021 The Qt Company Ltd. // Copyright (C) 2025 Klarälvdalens Datakonsult AB, a KDAB Group company, [email protected], author Giuseppe D'Angelo <[email protected]> // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:critical reason:data-parser #ifndef QNUMERIC_H #define QNUMERIC_H diff --git a/src/corelib/global/qrandom.cpp b/src/corelib/global/qrandom.cpp index fd742898f81..dab903f51fb 100644 --- a/src/corelib/global/qrandom.cpp +++ b/src/corelib/global/qrandom.cpp @@ -1,6 +1,7 @@ // Copyright (C) 2021 Intel Corporation. // Copyright (C) 2021 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:critical reason:cryptography // for rand_s #define _CRT_RAND_S diff --git a/src/corelib/global/qrandom.h b/src/corelib/global/qrandom.h index 5ac864e79ef..30599413d75 100644 --- a/src/corelib/global/qrandom.h +++ b/src/corelib/global/qrandom.h @@ -1,5 +1,6 @@ // Copyright (C) 2020 Intel Corporation. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:critical reason:cryptography #ifndef QRANDOM_H #define QRANDOM_H diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp index c645e57bdb6..8c22483fbfe 100644 --- a/src/corelib/io/qfile.cpp +++ b/src/corelib/io/qfile.cpp @@ -1,6 +1,7 @@ // Copyright (C) 2020 The Qt Company Ltd. // Copyright (C) 2017 Intel Corporation. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #include "qplatformdefs.h" #include "qdebug.h" diff --git a/src/corelib/io/qfile.h b/src/corelib/io/qfile.h index c115a6aee98..11546d87d9c 100644 --- a/src/corelib/io/qfile.h +++ b/src/corelib/io/qfile.h @@ -1,6 +1,7 @@ // Copyright (C) 2020 The Qt Company Ltd. // Copyright (C) 2016 Intel Corporation. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #ifndef QFILE_H #define QFILE_H diff --git a/src/corelib/io/qfile_p.h b/src/corelib/io/qfile_p.h index 126da28b0f9..a50fe575f8e 100644 --- a/src/corelib/io/qfile_p.h +++ b/src/corelib/io/qfile_p.h @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #ifndef QFILE_P_H #define QFILE_P_H diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp index 6f995fe082e..5a0be1d895e 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -893,6 +893,12 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM { Q_CHECK_FILE_NAME(entry, false); + // Detection of WasDeletedAttribute is imperfect: in general, if we can + // successfully stat() or access() a file, it hasn't been deleted (though + // there are exceptions, like /proc/XXX/fd/ entries on Linux). So we have + // to restore this flag in case we fail to stat() anything. + auto hadBeenDeleted = data.entryFlags & QFileSystemMetaData::WasDeletedAttribute; + #if defined(Q_OS_DARWIN) if (what & (QFileSystemMetaData::BundleType | QFileSystemMetaData::CaseSensitive)) { if (!data.hasFlags(QFileSystemMetaData::DirectoryType)) @@ -1103,6 +1109,11 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM if (entryErrno != 0) { what &= ~QFileSystemMetaData::LinkType; // don't clear link: could be broken symlink data.clearFlags(what); + + // see comment at the top + data.entryFlags |= hadBeenDeleted; + data.knownFlagsMask |= hadBeenDeleted; + return false; } return true; diff --git a/src/corelib/io/qfilesystemwatcher.cpp b/src/corelib/io/qfilesystemwatcher.cpp index 064be4c2112..cd72f21acdf 100644 --- a/src/corelib/io/qfilesystemwatcher.cpp +++ b/src/corelib/io/qfilesystemwatcher.cpp @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #include "qfilesystemwatcher.h" #include "qfilesystemwatcher_p.h" diff --git a/src/corelib/io/qfilesystemwatcher.h b/src/corelib/io/qfilesystemwatcher.h index 668bc143b20..9523945435e 100644 --- a/src/corelib/io/qfilesystemwatcher.h +++ b/src/corelib/io/qfilesystemwatcher.h @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #ifndef QFILESYSTEMWATCHER_H #define QFILESYSTEMWATCHER_H diff --git a/src/corelib/io/qfilesystemwatcher_fsevents.mm b/src/corelib/io/qfilesystemwatcher_fsevents.mm index 0d9b84890ae..0f49d43bc02 100644 --- a/src/corelib/io/qfilesystemwatcher_fsevents.mm +++ b/src/corelib/io/qfilesystemwatcher_fsevents.mm @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #include <qplatformdefs.h> diff --git a/src/corelib/io/qfilesystemwatcher_fsevents_p.h b/src/corelib/io/qfilesystemwatcher_fsevents_p.h index d6ce176a30f..2fc95a99931 100644 --- a/src/corelib/io/qfilesystemwatcher_fsevents_p.h +++ b/src/corelib/io/qfilesystemwatcher_fsevents_p.h @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #ifndef QFILESYSTEMWATCHER_FSEVENTS_P_H #define QFILESYSTEMWATCHER_FSEVENTS_P_H diff --git a/src/corelib/io/qfilesystemwatcher_inotify.cpp b/src/corelib/io/qfilesystemwatcher_inotify.cpp index e60f6881109..4971b41c102 100644 --- a/src/corelib/io/qfilesystemwatcher_inotify.cpp +++ b/src/corelib/io/qfilesystemwatcher_inotify.cpp @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #include "qfilesystemwatcher.h" #include "qfilesystemwatcher_inotify_p.h" diff --git a/src/corelib/io/qfilesystemwatcher_inotify_p.h b/src/corelib/io/qfilesystemwatcher_inotify_p.h index 05f87df14c1..705fe71725a 100644 --- a/src/corelib/io/qfilesystemwatcher_inotify_p.h +++ b/src/corelib/io/qfilesystemwatcher_inotify_p.h @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #ifndef QFILESYSTEMWATCHER_INOTIFY_P_H #define QFILESYSTEMWATCHER_INOTIFY_P_H diff --git a/src/corelib/io/qfilesystemwatcher_kqueue.cpp b/src/corelib/io/qfilesystemwatcher_kqueue.cpp index 7a9be337bf8..bc331c9dd2a 100644 --- a/src/corelib/io/qfilesystemwatcher_kqueue.cpp +++ b/src/corelib/io/qfilesystemwatcher_kqueue.cpp @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #include <qplatformdefs.h> diff --git a/src/corelib/io/qfilesystemwatcher_kqueue_p.h b/src/corelib/io/qfilesystemwatcher_kqueue_p.h index 05844d5be95..a460da6882e 100644 --- a/src/corelib/io/qfilesystemwatcher_kqueue_p.h +++ b/src/corelib/io/qfilesystemwatcher_kqueue_p.h @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #ifndef QFILESYSTEMWATCHER_KQUEUE_P_H #define QFILESYSTEMWATCHER_KQUEUE_P_H diff --git a/src/corelib/io/qfilesystemwatcher_p.h b/src/corelib/io/qfilesystemwatcher_p.h index c34e3e2408f..79cf7443e37 100644 --- a/src/corelib/io/qfilesystemwatcher_p.h +++ b/src/corelib/io/qfilesystemwatcher_p.h @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #ifndef QFILESYSTEMWATCHER_P_H #define QFILESYSTEMWATCHER_P_H diff --git a/src/corelib/io/qfilesystemwatcher_polling.cpp b/src/corelib/io/qfilesystemwatcher_polling.cpp index 5ec13a77f6c..ea374141563 100644 --- a/src/corelib/io/qfilesystemwatcher_polling.cpp +++ b/src/corelib/io/qfilesystemwatcher_polling.cpp @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #include "qfilesystemwatcher_polling_p.h" diff --git a/src/corelib/io/qfilesystemwatcher_polling_p.h b/src/corelib/io/qfilesystemwatcher_polling_p.h index 80d7b7d1526..2ace2947be4 100644 --- a/src/corelib/io/qfilesystemwatcher_polling_p.h +++ b/src/corelib/io/qfilesystemwatcher_polling_p.h @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #ifndef QFILESYSTEMWATCHER_POLLING_P_H #define QFILESYSTEMWATCHER_POLLING_P_H diff --git a/src/corelib/io/qfilesystemwatcher_win.cpp b/src/corelib/io/qfilesystemwatcher_win.cpp index 5418265ba2c..3a2cb02c3d7 100644 --- a/src/corelib/io/qfilesystemwatcher_win.cpp +++ b/src/corelib/io/qfilesystemwatcher_win.cpp @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #include "qfilesystemwatcher.h" #include "qfilesystemwatcher_win_p.h" diff --git a/src/corelib/io/qfilesystemwatcher_win_p.h b/src/corelib/io/qfilesystemwatcher_win_p.h index f6c6fd6c923..0687080b0ed 100644 --- a/src/corelib/io/qfilesystemwatcher_win_p.h +++ b/src/corelib/io/qfilesystemwatcher_win_p.h @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #ifndef QFILESYSTEMWATCHER_WIN_P_H #define QFILESYSTEMWATCHER_WIN_P_H diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp index 585a07158ea..9c1bb45dd2d 100644 --- a/src/corelib/io/qiodevice.cpp +++ b/src/corelib/io/qiodevice.cpp @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:critical reason:network-protocol //#define QIODEVICE_DEBUG @@ -1308,8 +1309,11 @@ QByteArray QIODevice::readAll() The newline character ('\\n') is included in the buffer. If a newline is not encountered before maxSize - 1 bytes are read, a - newline will not be inserted into the buffer. On windows newline - characters are replaced with '\\n'. + newline will not be inserted into the buffer. + + \note Newline translation(e.g., converting \r to \n) is performed + only when the device is opened for reading with QIODevice::Text + flag. Note that on sequential devices, data may not be immediately available, which may result in a partial line being returned. By calling the diff --git a/src/corelib/io/qiodevice.h b/src/corelib/io/qiodevice.h index 6bf7149e9af..263214ff012 100644 --- a/src/corelib/io/qiodevice.h +++ b/src/corelib/io/qiodevice.h @@ -1,5 +1,6 @@ // Copyright (C) 2020 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:header-decls-only #ifndef QIODEVICE_H #define QIODEVICE_H diff --git a/src/corelib/io/qiodevice_p.h b/src/corelib/io/qiodevice_p.h index 151548fb04e..6a1a91e1dea 100644 --- a/src/corelib/io/qiodevice_p.h +++ b/src/corelib/io/qiodevice_p.h @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:critical reason:network-protocol #ifndef QIODEVICE_P_H #define QIODEVICE_P_H diff --git a/src/corelib/io/qsavefile.cpp b/src/corelib/io/qsavefile.cpp index 91f168f20f6..a7d101dc124 100644 --- a/src/corelib/io/qsavefile.cpp +++ b/src/corelib/io/qsavefile.cpp @@ -1,5 +1,6 @@ // Copyright (C) 2012 David Faure <[email protected]> // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:critical reason:guaranteed-behavior #include "qsavefile.h" diff --git a/src/corelib/io/qsavefile.h b/src/corelib/io/qsavefile.h index bf0a91bae74..5e8cffe7c38 100644 --- a/src/corelib/io/qsavefile.h +++ b/src/corelib/io/qsavefile.h @@ -1,5 +1,6 @@ // Copyright (C) 2012 David Faure <[email protected]> // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:header-decls-only #ifndef QSAVEFILE_H #define QSAVEFILE_H diff --git a/src/corelib/io/qsavefile_p.h b/src/corelib/io/qsavefile_p.h index 50ecdad2daf..e1dcc0abe23 100644 --- a/src/corelib/io/qsavefile_p.h +++ b/src/corelib/io/qsavefile_p.h @@ -1,5 +1,6 @@ // Copyright (C) 2013 David Faure <[email protected]> // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:header-decls-only #ifndef QSAVEFILE_P_H #define QSAVEFILE_P_H diff --git a/src/corelib/io/qstorageinfo.cpp b/src/corelib/io/qstorageinfo.cpp index 6f55397eed9..aa7c67e8596 100644 --- a/src/corelib/io/qstorageinfo.cpp +++ b/src/corelib/io/qstorageinfo.cpp @@ -1,6 +1,7 @@ // Copyright (C) 2022 The Qt Company Ltd. // Copyright (C) 2015 Ivan Komissarov <[email protected]> // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #include "qstorageinfo.h" #include "qstorageinfo_p.h" @@ -12,6 +13,7 @@ QT_BEGIN_NAMESPACE Q_LOGGING_CATEGORY(lcStorageInfo, "qt.core.qstorageinfo", QtWarningMsg) QT_IMPL_METATYPE_EXTERN(QStorageInfo) +QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QStorageInfoPrivate) /*! \class QStorageInfo @@ -96,6 +98,17 @@ QStorageInfo::QStorageInfo(const QStorageInfo &other) = default; /*! + \since 6.10 + \fn QStorageInfo::QStorageInfo(QStorageInfo &&other) + + Move-constructs a new QStorageInfo from \a other. + + The moved-from object \a other is placed in a partially-formed state, in + which the only valid operations are destruction and assignment of a new + value. +*/ + +/*! Destroys the QStorageInfo object and frees its resources. */ QStorageInfo::~QStorageInfo() @@ -110,7 +123,9 @@ QStorageInfo &QStorageInfo::operator=(const QStorageInfo &other) /*! \fn QStorageInfo &QStorageInfo::operator=(QStorageInfo &&other) - Assigns \a other to this QStorageInfo instance. + Move-assigns \a other to this QStorageInfo instance. + + The moved-from object \a other is placed in a valid, but unspecified state. */ /*! diff --git a/src/corelib/io/qstorageinfo.h b/src/corelib/io/qstorageinfo.h index 2d7c60ec915..846cfaf4f41 100644 --- a/src/corelib/io/qstorageinfo.h +++ b/src/corelib/io/qstorageinfo.h @@ -1,5 +1,6 @@ // Copyright (C) 2014 Ivan Komissarov <[email protected]> // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #ifndef QSTORAGEINFO_H #define QSTORAGEINFO_H @@ -17,6 +18,7 @@ QT_BEGIN_NAMESPACE class QDebug; class QStorageInfoPrivate; +QT_DECLARE_QESDP_SPECIALIZATION_DTOR(QStorageInfoPrivate) class Q_CORE_EXPORT QStorageInfo { public: @@ -24,6 +26,7 @@ public: explicit QStorageInfo(const QString &path); explicit QStorageInfo(const QDir &dir); QStorageInfo(const QStorageInfo &other); + QStorageInfo(QStorageInfo &&) noexcept = default; ~QStorageInfo(); QStorageInfo &operator=(const QStorageInfo &other); diff --git a/src/corelib/io/qstorageinfo_linux.cpp b/src/corelib/io/qstorageinfo_linux.cpp index 00331a57127..f706650c637 100644 --- a/src/corelib/io/qstorageinfo_linux.cpp +++ b/src/corelib/io/qstorageinfo_linux.cpp @@ -3,6 +3,7 @@ // Copyright (C) 2016 Intel Corporation. // Copyright (C) 2023 Ahmad Samir <[email protected]> // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #include "qstorageinfo_linux_p.h" diff --git a/src/corelib/io/qstorageinfo_linux_p.h b/src/corelib/io/qstorageinfo_linux_p.h index 8f92b9e9783..26a60dcbc13 100644 --- a/src/corelib/io/qstorageinfo_linux_p.h +++ b/src/corelib/io/qstorageinfo_linux_p.h @@ -3,6 +3,7 @@ // Copyright (C) 2016 Intel Corporation. // Copyright (C) 2023 Ahmad Samir <[email protected]> // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #ifndef QSTORAGEINFO_LINUX_P_H #define QSTORAGEINFO_LINUX_P_H diff --git a/src/corelib/io/qstorageinfo_mac.cpp b/src/corelib/io/qstorageinfo_mac.cpp index c6c0f501dab..acfa21d8146 100644 --- a/src/corelib/io/qstorageinfo_mac.cpp +++ b/src/corelib/io/qstorageinfo_mac.cpp @@ -1,5 +1,6 @@ // Copyright (C) 2014 Ivan Komissarov <[email protected]> // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #include "qstorageinfo_p.h" diff --git a/src/corelib/io/qstorageinfo_p.h b/src/corelib/io/qstorageinfo_p.h index a917763fe36..0e3f81151e7 100644 --- a/src/corelib/io/qstorageinfo_p.h +++ b/src/corelib/io/qstorageinfo_p.h @@ -1,5 +1,6 @@ // Copyright (C) 2014 Ivan Komissarov <[email protected]> // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #ifndef QSTORAGEINFO_P_H #define QSTORAGEINFO_P_H diff --git a/src/corelib/io/qstorageinfo_stub.cpp b/src/corelib/io/qstorageinfo_stub.cpp index f2f7d2eb656..805b66b893c 100644 --- a/src/corelib/io/qstorageinfo_stub.cpp +++ b/src/corelib/io/qstorageinfo_stub.cpp @@ -1,5 +1,6 @@ // Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #include "qstorageinfo_p.h" diff --git a/src/corelib/io/qstorageinfo_unix.cpp b/src/corelib/io/qstorageinfo_unix.cpp index 40580e3be17..34ba7b9682b 100644 --- a/src/corelib/io/qstorageinfo_unix.cpp +++ b/src/corelib/io/qstorageinfo_unix.cpp @@ -2,6 +2,7 @@ // Copyright (C) 2014 Ivan Komissarov <[email protected]> // Copyright (C) 2016 Intel Corporation. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #include "qstorageinfo_p.h" diff --git a/src/corelib/io/qstorageinfo_win.cpp b/src/corelib/io/qstorageinfo_win.cpp index 3582612508c..cbaf01848e2 100644 --- a/src/corelib/io/qstorageinfo_win.cpp +++ b/src/corelib/io/qstorageinfo_win.cpp @@ -1,5 +1,6 @@ // Copyright (C) 2014 Ivan Komissarov <[email protected]> // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #include "qstorageinfo_p.h" diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp index c1f01267949..038db4d857e 100644 --- a/src/corelib/io/qtemporaryfile.cpp +++ b/src/corelib/io/qtemporaryfile.cpp @@ -1,6 +1,7 @@ // Copyright (C) 2016 The Qt Company Ltd. // Copyright (C) 2017 Intel Corporation. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:critical reason:data-parser #include "qtemporaryfile.h" @@ -881,6 +882,11 @@ void QTemporaryFile::setFileTemplate(const QString &name) be used for a similar purpose too, particularly if the destination file is not temporary. + \note Calling rename() does not disable autoRemove. If you want the renamed + file to persist, you must call setAutoRemove and set it to \c false after + calling rename(). Otherwise, the file will be deleted when the QTemporaryFile + object is destroyed. + \sa QSaveFile, QSaveFile::commit(), QFile::rename() */ bool QTemporaryFile::rename(const QString &newName) diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index 565ce04c6ce..a4fbf69da8b 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -3660,17 +3660,29 @@ QList<QUrl> QUrl::fromStringList(const QStringList &urls, ParsingMode mode) */ size_t qHash(const QUrl &url, size_t seed) noexcept { + QtPrivate::QHashCombineWithSeed hasher(seed); + + // non-commutative, we must hash the port first if (!url.d) - return qHash(-1, seed); // the hash of an unset port (-1) - - return qHash(url.d->scheme) ^ - qHash(url.d->userName) ^ - qHash(url.d->password) ^ - qHash(url.d->host) ^ - qHash(url.d->port, seed) ^ - qHash(url.d->path) ^ - qHash(url.d->query) ^ - qHash(url.d->fragment); + return hasher(0, -1); + size_t state = hasher(0, url.d->port); + + if (url.d->hasScheme()) + state = hasher(state, url.d->scheme); + if (url.d->hasUserInfo()) { + // see presentSections(), appendUserName(), etc. + state = hasher(state, url.d->userName); + state = hasher(state, url.d->password); + } + if (url.d->hasHost() || url.d->isLocalFile()) // for XDG compatibility + state = hasher(state, url.d->host); + if (url.d->hasPath()) + state = hasher(state, url.d->path); + if (url.d->hasQuery()) + state = hasher(state, url.d->query); + if (url.d->hasFragment()) + state = hasher(state, url.d->fragment); + return state; } static QUrl adjustFtpPath(QUrl url) diff --git a/src/corelib/ipc/qsharedmemory.cpp b/src/corelib/ipc/qsharedmemory.cpp index a2f6e42579e..7345753ce5b 100644 --- a/src/corelib/ipc/qsharedmemory.cpp +++ b/src/corelib/ipc/qsharedmemory.cpp @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #include "qsharedmemory.h" #include "qsharedmemory_p.h" diff --git a/src/corelib/ipc/qsharedmemory.h b/src/corelib/ipc/qsharedmemory.h index ab448b15c16..eec7d82160c 100644 --- a/src/corelib/ipc/qsharedmemory.h +++ b/src/corelib/ipc/qsharedmemory.h @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #ifndef QSHAREDMEMORY_H #define QSHAREDMEMORY_H diff --git a/src/corelib/ipc/qsharedmemory_p.h b/src/corelib/ipc/qsharedmemory_p.h index 82cce8919ac..df0a6963598 100644 --- a/src/corelib/ipc/qsharedmemory_p.h +++ b/src/corelib/ipc/qsharedmemory_p.h @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #ifndef QSHAREDMEMORY_P_H #define QSHAREDMEMORY_P_H diff --git a/src/corelib/ipc/qsharedmemory_posix.cpp b/src/corelib/ipc/qsharedmemory_posix.cpp index 582c6628e19..fa215c3b538 100644 --- a/src/corelib/ipc/qsharedmemory_posix.cpp +++ b/src/corelib/ipc/qsharedmemory_posix.cpp @@ -2,6 +2,7 @@ // Copyright (C) 2016 The Qt Company Ltd. // Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, [email protected], author Tobias Koenig <[email protected]> // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #include "qsharedmemory.h" #include "qsharedmemory_p.h" diff --git a/src/corelib/ipc/qsharedmemory_systemv.cpp b/src/corelib/ipc/qsharedmemory_systemv.cpp index dc9de11091d..1777236bacc 100644 --- a/src/corelib/ipc/qsharedmemory_systemv.cpp +++ b/src/corelib/ipc/qsharedmemory_systemv.cpp @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #include "qsharedmemory.h" #include "qsharedmemory_p.h" diff --git a/src/corelib/ipc/qsharedmemory_win.cpp b/src/corelib/ipc/qsharedmemory_win.cpp index 472f34f9a18..b46d0da0c8c 100644 --- a/src/corelib/ipc/qsharedmemory_win.cpp +++ b/src/corelib/ipc/qsharedmemory_win.cpp @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #include "qsharedmemory.h" #include "qsharedmemory_p.h" diff --git a/src/corelib/ipc/qsystemsemaphore.cpp b/src/corelib/ipc/qsystemsemaphore.cpp index 24f4789f975..67e8c4bf757 100644 --- a/src/corelib/ipc/qsystemsemaphore.cpp +++ b/src/corelib/ipc/qsystemsemaphore.cpp @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #include "qsystemsemaphore.h" #include "qsystemsemaphore_p.h" diff --git a/src/corelib/ipc/qsystemsemaphore.h b/src/corelib/ipc/qsystemsemaphore.h index 0981a7eecee..2d80955b85c 100644 --- a/src/corelib/ipc/qsystemsemaphore.h +++ b/src/corelib/ipc/qsystemsemaphore.h @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #ifndef QSYSTEMSEMAPHORE_H #define QSYSTEMSEMAPHORE_H diff --git a/src/corelib/ipc/qsystemsemaphore_p.h b/src/corelib/ipc/qsystemsemaphore_p.h index 788c4fb7844..5b4630a20a8 100644 --- a/src/corelib/ipc/qsystemsemaphore_p.h +++ b/src/corelib/ipc/qsystemsemaphore_p.h @@ -1,6 +1,7 @@ // Copyright (C) 2016 The Qt Company Ltd. // Copyright (C) 2022 Intel Corporation. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #ifndef QSYSTEMSEMAPHORE_P_H #define QSYSTEMSEMAPHORE_P_H diff --git a/src/corelib/ipc/qsystemsemaphore_posix.cpp b/src/corelib/ipc/qsystemsemaphore_posix.cpp index 7df9593513c..89a75048b4c 100644 --- a/src/corelib/ipc/qsystemsemaphore_posix.cpp +++ b/src/corelib/ipc/qsystemsemaphore_posix.cpp @@ -3,6 +3,7 @@ // Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, [email protected], author Tobias Koenig <[email protected]> // Copyright (C) 2022 Intel Corporation. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #include "qsystemsemaphore.h" #include "qsystemsemaphore_p.h" diff --git a/src/corelib/ipc/qsystemsemaphore_systemv.cpp b/src/corelib/ipc/qsystemsemaphore_systemv.cpp index e5d231d1d42..54e62c615cf 100644 --- a/src/corelib/ipc/qsystemsemaphore_systemv.cpp +++ b/src/corelib/ipc/qsystemsemaphore_systemv.cpp @@ -1,6 +1,7 @@ // Copyright (C) 2016 The Qt Company Ltd. // Copyright (C) 2022 Intel Corporation. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #include "qsystemsemaphore.h" #include "qsystemsemaphore_p.h" diff --git a/src/corelib/ipc/qsystemsemaphore_win.cpp b/src/corelib/ipc/qsystemsemaphore_win.cpp index f42fecf71f6..a157dec0dd2 100644 --- a/src/corelib/ipc/qsystemsemaphore_win.cpp +++ b/src/corelib/ipc/qsystemsemaphore_win.cpp @@ -1,5 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #include "qsystemsemaphore.h" #include "qsystemsemaphore_p.h" diff --git a/src/corelib/ipc/qtipccommon.cpp b/src/corelib/ipc/qtipccommon.cpp index 355f6fbc602..e56046497c5 100644 --- a/src/corelib/ipc/qtipccommon.cpp +++ b/src/corelib/ipc/qtipccommon.cpp @@ -1,5 +1,6 @@ // Copyright (C) 2022 Intel Corporation. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #include "qtipccommon.h" #include "qtipccommon_p.h" diff --git a/src/corelib/ipc/qtipccommon.h b/src/corelib/ipc/qtipccommon.h index 658a426914f..375100f9837 100644 --- a/src/corelib/ipc/qtipccommon.h +++ b/src/corelib/ipc/qtipccommon.h @@ -1,5 +1,6 @@ // Copyright (C) 2022 Intel Corporation. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #ifndef QTIPCCOMMON_H #define QTIPCCOMMON_H diff --git a/src/corelib/ipc/qtipccommon_p.h b/src/corelib/ipc/qtipccommon_p.h index 8836cd64421..dc8619299fc 100644 --- a/src/corelib/ipc/qtipccommon_p.h +++ b/src/corelib/ipc/qtipccommon_p.h @@ -1,5 +1,6 @@ // Copyright (C) 2022 Intel Corporation. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Qt-Security score:significant reason:default #ifndef QTIPCCOMMON_P_H #define QTIPCCOMMON_P_H diff --git a/src/corelib/itemmodels/qrangemodel_impl.h b/src/corelib/itemmodels/qrangemodel_impl.h index 849d6084b80..38378fdcc64 100644 --- a/src/corelib/itemmodels/qrangemodel_impl.h +++ b/src/corelib/itemmodels/qrangemodel_impl.h @@ -952,7 +952,7 @@ public: if constexpr (multi_role::int_key) return std::as_const(value).find(Qt::ItemDataRole(role)); else - return std::as_const(value).find(roleNames().value(role)); + return std::as_const(value).find(itemModel().roleNames().value(role)); }(); if (it != value.cend()) { result = QRangeModelDetails::value(it); @@ -981,13 +981,20 @@ public: if constexpr (std::is_convertible_v<value_type, decltype(result)>) { result = value; } else { + const auto roleNames = [this]() -> QHash<int, QByteArray> { + Q_UNUSED(this); + if constexpr (!multi_role::int_key) + return itemModel().roleNames(); + else + return {}; + }(); for (auto it = std::cbegin(value); it != std::cend(value); ++it) { - int role = [this, key = QRangeModelDetails::key(it)]() { - Q_UNUSED(this); + const int role = [&roleNames, key = QRangeModelDetails::key(it)]() { + Q_UNUSED(roleNames); if constexpr (multi_role::int_key) return int(key); else - return roleNames().key(key.toUtf8(), -1); + return roleNames.key(key.toUtf8(), -1); }(); if (role != -1) @@ -999,7 +1006,7 @@ public: tried = true; using meta_type = QRangeModelDetails::wrapped_t<value_type>; const QMetaObject &mo = meta_type::staticMetaObject; - for (auto &&[role, roleName] : roleNames().asKeyValueRange()) { + for (auto &&[role, roleName] : itemModel().roleNames().asKeyValueRange()) { QVariant data; if constexpr (std::is_base_of_v<QObject, meta_type>) { if (value) @@ -1064,19 +1071,26 @@ public: Qt::ItemDataRole roleToSet = Qt::ItemDataRole(role); // If there is an entry for EditRole, overwrite that; otherwise, // set the entry for DisplayRole. + const auto roleNames = [this]() -> QHash<int, QByteArray> { + Q_UNUSED(this); + if constexpr (!multi_role::int_key) + return itemModel().roleNames(); + else + return {}; + }(); if (role == Qt::EditRole) { if constexpr (multi_role::int_key) { if (target.find(roleToSet) == target.end()) roleToSet = Qt::DisplayRole; } else { - if (target.find(roleNames().value(roleToSet)) == target.end()) + if (target.find(roleNames.value(roleToSet)) == target.end()) roleToSet = Qt::DisplayRole; } } if constexpr (multi_role::int_key) return write(target[roleToSet], data); else - return write(target[roleNames().value(roleToSet)], data); + return write(target[roleNames.value(roleToSet)], data); } else if (role == Qt::DisplayRole || role == Qt::EditRole) { return write(target, data); } @@ -1108,7 +1122,9 @@ public: if constexpr (multi_role()) { using key_type = typename value_type::key_type; tried = true; - const auto roleName = [map = roleNames()](int role) { return map.value(role); }; + const auto roleName = [map = itemModel().roleNames()](int role) { + return map.value(role); + }; // transactional: only update target if all values from data // can be stored. Storing never fails with int-keys. @@ -1148,8 +1164,9 @@ public: else // can't copy - targetCopy is now a pointer return &origin; }(target); + const auto roleNames = itemModel().roleNames(); for (auto &&[role, value] : data.asKeyValueRange()) { - const QByteArray roleName = roleNames().value(role); + const QByteArray roleName = roleNames.value(role); bool written = false; if constexpr (std::is_base_of_v<QObject, meta_type>) { if (targetCopy) @@ -1547,7 +1564,7 @@ protected: QMetaProperty roleProperty(int role) const { const QMetaObject *mo = &ItemType::staticMetaObject; - const QByteArray roleName = roleNames().value(role); + const QByteArray roleName = itemModel().roleNames().value(role); if (const int index = mo->indexOfProperty(roleName.data()); index >= 0) return mo->property(index); return {}; diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index a19e39685f1..1b711ba16bd 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -2189,7 +2189,7 @@ bool QCoreApplication::installTranslator(QTranslator *translationFile) QCoreApplicationPrivate *d = self->d_func(); { - QMutexLocker locker(&d->translateMutex); + QWriteLocker locker(&d->translateMutex); d->translators.prepend(translationFile); } @@ -2221,7 +2221,7 @@ bool QCoreApplication::removeTranslator(QTranslator *translationFile) if (!QCoreApplicationPrivate::checkInstance("removeTranslator")) return false; QCoreApplicationPrivate *d = self->d_func(); - QMutexLocker locker(&d->translateMutex); + QWriteLocker locker(&d->translateMutex); if (d->translators.removeAll(translationFile)) { #ifndef QT_NO_QOBJECT locker.unlock(); @@ -2306,7 +2306,7 @@ QString QCoreApplication::translate(const char *context, const char *sourceText, if (self) { QCoreApplicationPrivate *d = self->d_func(); - QMutexLocker locker(&d->translateMutex); + QReadLocker locker(&d->translateMutex); if (!d->translators.isEmpty()) { QList<QTranslator*>::ConstIterator it; QTranslator *translationFile; @@ -2332,23 +2332,13 @@ QString qtTrId(const char *id, int n) return QCoreApplication::translate(nullptr, id, nullptr, n); } -/*! - \internal - Returns a locked mutex handle if \a translator is registered in QCoreApplication, - and might be therefore queried for translations from other threads. - Returns an unlocked/dummy QMutexLocker otherwise. - */ -std::unique_lock<QMutex> QCoreApplicationPrivate::mutexLockerForTranslator(QTranslator *translator) +bool QCoreApplicationPrivate::isTranslatorInstalled(QTranslator *translator) { if (!QCoreApplication::self) - return std::unique_lock<QMutex>(); - + return false; QCoreApplicationPrivate *d = QCoreApplication::self->d_func(); - std::unique_lock<QMutex> locker(d->translateMutex); - if (!d->translators.contains(translator)) - locker.unlock(); - - return locker; + QReadLocker locker(&d->translateMutex); + return d->translators.contains(translator); } #else @@ -2562,8 +2552,9 @@ static QStringList winCmdArgs() Otherwise, the arguments() are constructed from the return value of \l{https://docs.microsoft.com/en-us/windows/win32/api/processenv/nf-processenv-getcommandlinea}{GetCommandLine()}. - As a result of this, the string given by arguments().at(0) might not be - the program name on Windows, depending on how the application was started. + As a result of this, the string given by arguments().at(0) + might not be the exact program used to start the application + on Windows. \sa applicationFilePath(), QCommandLineParser */ diff --git a/src/corelib/kernel/qcoreapplication_p.h b/src/corelib/kernel/qcoreapplication_p.h index 4cb6254e98d..0027b1ad57f 100644 --- a/src/corelib/kernel/qcoreapplication_p.h +++ b/src/corelib/kernel/qcoreapplication_p.h @@ -30,12 +30,10 @@ #include "private/qcore_mac_p.h" #endif -#ifndef QT_NO_TRANSLATION -#include <mutex> -#endif - QT_BEGIN_NAMESPACE +typedef QList<QTranslator*> QTranslatorList; + class QAbstractEventDispatcher; #ifndef QT_NO_QOBJECT @@ -149,9 +147,9 @@ public: static bool is_app_closing; #endif #ifndef QT_NO_TRANSLATION - QList<QTranslator*> translators; - QMutex translateMutex; - static std::unique_lock<QMutex> mutexLockerForTranslator(QTranslator *translator); + QTranslatorList translators; + QReadWriteLock translateMutex; + static bool isTranslatorInstalled(QTranslator *translator); #endif static bool setuidAllowed; diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 2356611a5cf..de5f27f9619 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -3149,6 +3149,20 @@ bool QMetaMethod::invokeOnGadget(void *gadget, representation. The scope() function returns the class scope this enumerator was declared in. + To use QMetaEnum functionality, register the enumerator within the meta-object + system using the Q_ENUM macro. + + \code + enum AppleType { + Big, + Small + }; + Q_ENUM(AppleType) + + QMetaEnum metaEnum = QMetaEnum::fromType<ModelApple::AppleType>(); + qDebug() << metaEnum.valueToKey(ModelApple::Big); + \endcode + \sa QMetaObject, QMetaMethod, QMetaProperty */ diff --git a/src/corelib/kernel/qmetaobjectbuilder.cpp b/src/corelib/kernel/qmetaobjectbuilder.cpp index 60bcdedba13..445009ea000 100644 --- a/src/corelib/kernel/qmetaobjectbuilder.cpp +++ b/src/corelib/kernel/qmetaobjectbuilder.cpp @@ -2080,6 +2080,17 @@ bool QMetaPropertyBuilder::isBindable() const else return false; } +/*! + Returns \c true if the property is required. + The default is \c false. + */ +bool QMetaPropertyBuilder::isRequired() const +{ + if (auto d = d_func()) + return d->flag(Required); + else + return false; +} /*! Sets this property to readable if \a value is true. @@ -2236,6 +2247,15 @@ void QMetaPropertyBuilder::setBindable(bool value) } /*! + Sets the\c REQUIRED flag on this property to \a value + */ +void QMetaPropertyBuilder::setRequired(bool value) +{ + if (auto d = d_func()) + d->setFlag(Required, value); +} + +/*! Returns the revision of this property. \sa setRevision() diff --git a/src/corelib/kernel/qmetaobjectbuilder_p.h b/src/corelib/kernel/qmetaobjectbuilder_p.h index cf64e51c30c..36cd08d908c 100644 --- a/src/corelib/kernel/qmetaobjectbuilder_p.h +++ b/src/corelib/kernel/qmetaobjectbuilder_p.h @@ -216,6 +216,7 @@ public: bool isFinal() const; bool isAlias() const; bool isBindable() const; + bool isRequired() const; void setReadable(bool value); void setWritable(bool value); @@ -230,6 +231,7 @@ public: void setFinal(bool value); void setAlias(bool value); void setBindable(bool value); + void setRequired(bool value); int revision() const; void setRevision(int revision); diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp index 1242a40f185..45c947004f5 100644 --- a/src/corelib/kernel/qmetatype.cpp +++ b/src/corelib/kernel/qmetatype.cpp @@ -981,12 +981,6 @@ void QMetaType::unregisterMetaType(QMetaType type) than the QMetaType \a rhs, otherwise returns \c false. */ -/*! \internal */ -bool QMetaTypeModuleHelper::convert(const void *, int, void *, int) const -{ - return false; -} - static constexpr auto createStaticTypeToIdMap() { #define QT_ADD_STATIC_METATYPE(MetaTypeName, MetaTypeId, RealName) \ @@ -1049,8 +1043,8 @@ static bool qIntegerConversionFromFPHelper(From from, To *to) return true; } -// NOLINTNEXTLINE(cppcoreguidelines-virtual-class-destructor): this is not a base class -static constexpr struct : QMetaTypeModuleHelper +namespace { +struct QCoreVariantHelper : QMetaTypeModuleHelper { template<typename T, typename LiteralWrapper = std::conditional_t<std::is_same_v<T, QString>, QLatin1StringView, const char *>> @@ -1060,7 +1054,8 @@ static constexpr struct : QMetaTypeModuleHelper return !(str.isEmpty() || str == LiteralWrapper("0") || str == LiteralWrapper("false")); } - const QtPrivate::QMetaTypeInterface *interfaceForType(int type) const override { + static const QtPrivate::QMetaTypeInterface *interfaceForType(int type) + { switch (type) { QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(QT_METATYPE_CONVERT_ID_TO_TYPE) QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(QT_METATYPE_CONVERT_ID_TO_TYPE) @@ -1072,11 +1067,14 @@ static constexpr struct : QMetaTypeModuleHelper } } -#ifndef QT_BOOTSTRAPPED - bool convert(const void *from, int fromTypeId, void *to, int toTypeId) const override + static bool convert(const void *from, int fromTypeId, void *to, int toTypeId) { Q_ASSERT(fromTypeId != toTypeId); +#ifdef QT_BOOTSTRAPPED + Q_UNUSED(from); + Q_UNUSED(to); +#else // canConvert calls with two nullptr bool onlyCheck = (from == nullptr && to == nullptr); @@ -1747,26 +1745,28 @@ QT_WARNING_DISABLE_CLANG("-Wtautological-compare") QT_WARNING_POP } +#endif // !QT_BOOTSTRAPPED return false; } -#endif // !QT_BOOTSTRAPPED -} metatypeHelper = {}; +}; +} // unnamed namespace -Q_CONSTINIT Q_CORE_EXPORT const QMetaTypeModuleHelper *qMetaTypeGuiHelper = nullptr; -Q_CONSTINIT Q_CORE_EXPORT const QMetaTypeModuleHelper *qMetaTypeWidgetsHelper = nullptr; +Q_CONSTINIT Q_CORE_EXPORT QMetaTypeModuleHelper qMetaTypeGuiHelper = {}; +Q_CONSTINIT Q_CORE_EXPORT QMetaTypeModuleHelper qMetaTypeWidgetsHelper = {}; -static const QMetaTypeModuleHelper *qModuleHelperForType(int type) +#ifndef QT_BOOTSTRAPPED +static bool tryConvertBuiltinTypes(const void *from, int fromTypeId, void *to, int toTypeId) { + int type = qMax(fromTypeId, toTypeId); if (type <= QMetaType::LastCoreType) - return &metatypeHelper; + return QCoreVariantHelper::convert(from, fromTypeId, to, toTypeId); if (type >= QMetaType::FirstGuiType && type <= QMetaType::LastGuiType) - return qMetaTypeGuiHelper; + return qMetaTypeGuiHelper.convert(from, fromTypeId, to, toTypeId); else if (type >= QMetaType::FirstWidgetsType && type <= QMetaType::LastWidgetsType) - return qMetaTypeWidgetsHelper; - return nullptr; + return qMetaTypeWidgetsHelper.convert(from, fromTypeId, to, toTypeId); + return false; } -#ifndef QT_BOOTSTRAPPED template<typename T, typename Key> class QMetaTypeFunctionRegistry { @@ -2471,10 +2471,8 @@ bool QMetaType::convert(QMetaType fromType, const void *from, QMetaType toType, int fromTypeId = fromType.id(); int toTypeId = toType.id(); - if (auto moduleHelper = qModuleHelperForType(qMax(fromTypeId, toTypeId))) { - if (moduleHelper->convert(from, fromTypeId, to, toTypeId)) - return true; - } + if (tryConvertBuiltinTypes(from, fromTypeId, to, toTypeId)) + return true; const auto f = customTypesConversionRegistry()->function({fromTypeId, toTypeId}); if (f) return (*f)(from, to); @@ -2676,10 +2674,9 @@ bool QMetaType::canConvert(QMetaType fromType, QMetaType toType) if (fromTypeId == toTypeId) return true; - if (auto moduleHelper = qModuleHelperForType(qMax(fromTypeId, toTypeId))) { - if (moduleHelper->convert(nullptr, fromTypeId, nullptr, toTypeId)) - return true; - } + if (tryConvertBuiltinTypes(nullptr, fromTypeId, nullptr, toTypeId)) + return true; + const ConverterFunction * const f = customTypesConversionRegistry()->function(std::make_pair(fromTypeId, toTypeId)); if (f) @@ -2879,8 +2876,12 @@ void QMetaType::registerNormalizedTypedef(const NS(QByteArray) & normalizedTypeN static const QtPrivate::QMetaTypeInterface *interfaceForStaticType(int typeId) { Q_ASSERT(typeId < QMetaType::User); - if (auto moduleHelper = qModuleHelperForType(typeId)) - return moduleHelper->interfaceForType(typeId); + if (typeId <= QMetaType::LastCoreType) + return QCoreVariantHelper::interfaceForType(typeId); + if (typeId >= QMetaType::FirstGuiType && typeId <= QMetaType::LastGuiType) + return qMetaTypeGuiHelper.interfaceForType(typeId); + if (typeId >= QMetaType::FirstWidgetsType && typeId <= QMetaType::LastWidgetsType) + return qMetaTypeWidgetsHelper.interfaceForType(typeId); return nullptr; } @@ -2909,40 +2910,18 @@ bool QMetaType::isRegistered(int type) return interfaceForTypeNoWarning(type) != nullptr; } -namespace { -enum NormalizeTypeMode { - DontNormalizeType, - TryNormalizeType -}; -} -template <NormalizeTypeMode tryNormalizedType> static inline -const QtPrivate::QMetaTypeInterface *qMetaTypeTypeImpl(QByteArrayView name) +static const QtPrivate::QMetaTypeInterface *findMetaTypeByName(QByteArrayView name) { - if (name.isEmpty()) - return nullptr; - + Q_PRE(!name.isEmpty()); int type = qMetaTypeStaticType(name); if (type != QMetaType::UnknownType) { return interfaceForStaticType(type); #ifndef QT_BOOTSTRAPPED - } else { - QReadLocker locker(&customTypeRegistry()->lock); + } else if (customTypeRegistry.exists()) { + QReadLocker locker(&customTypeRegistry->lock); auto it = customTypeRegistry->aliases.constFind(name); if (it != customTypeRegistry->aliases.constEnd()) return it.value().data(); - -#ifndef QT_NO_QOBJECT - if (tryNormalizedType) { - const char *typeName = name.constData(); - const NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName); - type = qMetaTypeStaticType(normalizedTypeName); - if (type == QMetaType::UnknownType) { - return customTypeRegistry->aliases.value(normalizedTypeName).data(); - } else { - return interfaceForStaticType(type); - } - } -#endif #endif } return nullptr; @@ -2969,7 +2948,9 @@ const QtPrivate::QMetaTypeInterface *qMetaTypeTypeImpl(QByteArrayView name) */ int qMetaTypeTypeInternal(QByteArrayView name) { - const QtPrivate::QMetaTypeInterface *iface = qMetaTypeTypeImpl<DontNormalizeType>(name); + const QtPrivate::QMetaTypeInterface *iface = nullptr; + if (!name.isEmpty()) + iface = findMetaTypeByName(name); return iface ? iface->typeId.loadRelaxed() : QMetaType::UnknownType; } @@ -3138,7 +3119,20 @@ QMetaType QMetaType::underlyingType() const */ QMetaType QMetaType::fromName(QByteArrayView typeName) { - return QMetaType(qMetaTypeTypeImpl<TryNormalizeType>(typeName)); + if (typeName.isEmpty()) + return QMetaType(); + + const QtPrivate::QMetaTypeInterface *iface = findMetaTypeByName(typeName); + if (iface) + return QMetaType(iface); + +#if !defined(QT_NO_QOBJECT) + const NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName.constData()); + if (normalizedTypeName != typeName) + iface = findMetaTypeByName(normalizedTypeName); +#endif + + return QMetaType(iface); } /*! diff --git a/src/corelib/kernel/qmetatype_p.h b/src/corelib/kernel/qmetatype_p.h index c05bce5fc8f..b39e1de0be2 100644 --- a/src/corelib/kernel/qmetatype_p.h +++ b/src/corelib/kernel/qmetatype_p.h @@ -40,25 +40,29 @@ QT_BEGIN_NAMESPACE assign_and_return \ } -class Q_CORE_EXPORT QMetaTypeModuleHelper +struct QMetaTypeModuleHelper { - Q_DISABLE_COPY_MOVE(QMetaTypeModuleHelper) -protected: - QMetaTypeModuleHelper() = default; - ~QMetaTypeModuleHelper() = default; -public: - Q_WEAK_OVERLOAD // prevent it from entering the ABI and rendering constexpr useless static constexpr auto makePair(int from, int to) -> quint64 { return (quint64(from) << 32) + quint64(to); } - virtual const QtPrivate::QMetaTypeInterface *interfaceForType(int) const = 0; - virtual bool convert(const void *, int, void *, int) const; + static const QtPrivate::QMetaTypeInterface *interfaceForType_dummy(int) + { + return nullptr; + } + + static bool convert_dummy(const void *, int, void *, int) + { + return false; + } + + decltype(&interfaceForType_dummy) interfaceForType = &interfaceForType_dummy; + decltype(&convert_dummy) convert = &convert_dummy; }; -extern Q_CORE_EXPORT const QMetaTypeModuleHelper *qMetaTypeGuiHelper; -extern Q_CORE_EXPORT const QMetaTypeModuleHelper *qMetaTypeWidgetsHelper; +extern Q_CORE_EXPORT QMetaTypeModuleHelper qMetaTypeGuiHelper; +extern Q_CORE_EXPORT QMetaTypeModuleHelper qMetaTypeWidgetsHelper; namespace QtMetaTypePrivate { template<typename T> diff --git a/src/corelib/kernel/qproperty.cpp b/src/corelib/kernel/qproperty.cpp index 384253265be..7368af2df6e 100644 --- a/src/corelib/kernel/qproperty.cpp +++ b/src/corelib/kernel/qproperty.cpp @@ -1385,6 +1385,7 @@ QString QPropertyBindingError::description() const /*! \fn template <typename T> template <typename Functor> QPropertyBinding<T> QProperty<T>::setBinding(Functor f) \overload + \since 6.0 Associates the value of this property with the provided functor \a f and returns the previously associated binding. The property's value is set to the @@ -1442,6 +1443,7 @@ QString QPropertyBindingError::description() const /*! \fn template <typename T> template <typename Functor> QPropertyChangeHandler<T, Functor> QProperty<T>::subscribe(Functor f) + \since 6.0 Subscribes the given functor \a f as a callback that is called immediately and whenever the value of the property changes in the future. On each value @@ -1459,6 +1461,7 @@ QString QPropertyBindingError::description() const /*! \fn template <typename T> template <typename Functor> QPropertyNotifier QProperty<T>::addNotifier(Functor f) + \since 6.2 Subscribes the given functor \a f as a callback that is called whenever the value of the property changes. @@ -1948,6 +1951,7 @@ QString QPropertyBindingError::description() const \brief The QPropertyNotifier class controls the lifecycle of change callback installed on a QProperty. \ingroup tools + \since 6.2 QPropertyNotifier is created when registering a callback on a QProperty to listen to changes to the property's value, using QProperty::addNotifier. As diff --git a/src/corelib/kernel/qsignalmapper.cpp b/src/corelib/kernel/qsignalmapper.cpp index 65d766db4a9..96e909d1be7 100644 --- a/src/corelib/kernel/qsignalmapper.cpp +++ b/src/corelib/kernel/qsignalmapper.cpp @@ -74,9 +74,9 @@ public: The only function that we need to implement is the constructor: - \snippet qsignalmapper/buttonwidget.cpp 0 - \snippet qsignalmapper/buttonwidget.cpp 1 - \snippet qsignalmapper/buttonwidget.cpp 2 + \snippet qsignalmapper/buttonwidget.cpp OpenCtor + \snippet qsignalmapper/buttonwidget.cpp OldNotation + \snippet qsignalmapper/buttonwidget.cpp CloseBrackets A list of texts is passed to the constructor. A signal mapper is constructed and for each text in the list a QPushButton is @@ -92,7 +92,9 @@ public: slots. The example above can be rewritten simpler without QSignalMapper by connecting to a lambda function. - \snippet qsignalmapper/buttonwidget.cpp 3 + \snippet qsignalmapper/buttonwidget.cpp OpenCtor + \snippet qsignalmapper/buttonwidget.cpp ModernNotation + \snippet qsignalmapper/buttonwidget.cpp CloseBrackets \sa QObject, QButtonGroup, QActionGroup */ diff --git a/src/corelib/kernel/qtranslator.cpp b/src/corelib/kernel/qtranslator.cpp index 47483dc6470..c8348aba16a 100644 --- a/src/corelib/kernel/qtranslator.cpp +++ b/src/corelib/kernel/qtranslator.cpp @@ -39,6 +39,8 @@ #include <vector> #include <memory> +#include <QtCore/qmutex.h> + QT_BEGIN_NAMESPACE Q_STATIC_LOGGING_CATEGORY(lcTranslator, "qt.core.qtranslator") @@ -259,6 +261,8 @@ class QTranslatorPrivate : public QObjectPrivate public: enum { Contexts = 0x2f, Hashes = 0x42, Messages = 0x69, NumerusRules = 0x88, Dependencies = 0x96, Language = 0xa7 }; + mutable QMutex lock; + QTranslatorPrivate() : #if defined(QT_USE_MMAP) used_mmap(0), @@ -463,12 +467,7 @@ bool QTranslator::load(const QString & filename, const QString & directory, const QString & suffix) { Q_D(QTranslator); - - std::unique_lock locker = QCoreApplicationPrivate::mutexLockerForTranslator(this); - if (locker.owns_lock()) - QCoreApplication::postEvent(QCoreApplication::instance(), - new QEvent(QEvent::LanguageChange)); - + QMutexLocker locker(&d->lock); d->clear(); QString prefix; @@ -744,12 +743,7 @@ bool QTranslator::load(const QLocale & locale, const QString & suffix) { Q_D(QTranslator); - - std::unique_lock locker = QCoreApplicationPrivate::mutexLockerForTranslator(this); - if (locker.owns_lock()) - QCoreApplication::postEvent(QCoreApplication::instance(), - new QEvent(QEvent::LanguageChange)); - + QMutexLocker locker(&d->lock); d->clear(); return d->load_translation(locale, filename, prefix, directory, suffix); } @@ -769,12 +763,7 @@ bool QTranslator::load(const QLocale & locale, bool QTranslator::load(const uchar *data, int len, const QString &directory) { Q_D(QTranslator); - - std::unique_lock locker = QCoreApplicationPrivate::mutexLockerForTranslator(this); - if (locker.owns_lock()) - QCoreApplication::postEvent(QCoreApplication::instance(), - new QEvent(QEvent::LanguageChange)); - + QMutexLocker locker(&d->lock); d->clear(); if (!data || len < MagicLength || memcmp(data, magic, MagicLength)) @@ -1048,6 +1037,7 @@ searchDependencies: void QTranslatorPrivate::clear() { + Q_Q(QTranslator); if (unmapPointer && unmapLength) { #if defined(QT_USE_MMAP) if (used_mmap) { @@ -1075,9 +1065,15 @@ void QTranslatorPrivate::clear() language.clear(); filePath.clear(); + + if (QCoreApplicationPrivate::isTranslatorInstalled(q)) + QCoreApplication::postEvent(QCoreApplication::instance(), + new QEvent(QEvent::LanguageChange)); } /*! + \threadsafe + Returns the translation for the key (\a context, \a sourceText, \a disambiguation). If none is found, also tries (\a context, \a sourceText, ""). If that still fails, returns a null string. @@ -1099,7 +1095,14 @@ QString QTranslator::translate(const char *context, const char *sourceText, cons int n) const { Q_D(const QTranslator); - return d->do_translate(context, sourceText, disambiguation, n); + + // Return early to avoid a deadlock in case translate() is called + // from a code path triggered by QTranslator::load() + if (!d->lock.tryLock()) + return QString(); + QString result = d->do_translate(context, sourceText, disambiguation, n); + d->lock.unlock(); + return result; } /*! diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index 31f5869c9d9..e9d3ffb9ae3 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -332,7 +332,16 @@ public: inline void swap(QVariant &other) noexcept { std::swap(d, other.d); } int userType() const { return typeId(); } - int typeId() const { return metaType().id(); } + int typeId() const + { + // QVariant types are always registered (see fromMetaType()) + const QtPrivate::QMetaTypeInterface *mt = metaType().iface(); + if (!mt) + return 0; + int id = mt->typeId.loadRelaxed(); + // Q_ASSUME(id > 0); + return id; + } const char *typeName() const; QMetaType metaType() const; diff --git a/src/corelib/platform/windows/qt_winrtbase_p.h b/src/corelib/platform/windows/qt_winrtbase_p.h index fb7366f93de..79c2bdf6b1c 100644 --- a/src/corelib/platform/windows/qt_winrtbase_p.h +++ b/src/corelib/platform/windows/qt_winrtbase_p.h @@ -18,6 +18,7 @@ #include <QtCore/qglobal.h> #if QT_CONFIG(cpp_winrt) +# include <guiddef.h> // required by clang-cl: https://github.com/microsoft/cppwinrt/issues/1179 # include <winrt/base.h> # include <QtCore/private/qfactorycacheregistration_p.h> // Workaround for Windows SDK bug. diff --git a/src/corelib/serialization/qcborarray.cpp b/src/corelib/serialization/qcborarray.cpp index e00b7a4571f..9a566b999b4 100644 --- a/src/corelib/serialization/qcborarray.cpp +++ b/src/corelib/serialization/qcborarray.cpp @@ -98,6 +98,17 @@ QCborArray::QCborArray(const QCborArray &other) noexcept } /*! + \fn QCborArray::QCborArray(QCborArray &&other) + \since 6.10 + + Move-constructor. + + The moved-from object \a other is placed in the default-constructed state. + + \sa QCborArray::QCborArray() +*/ + +/*! \fn QCborArray::QCborArray(std::initializer_list<QCborValue> args) Initializes this QCborArray from the C++ brace-enclosed list found in \a @@ -126,6 +137,15 @@ QCborArray &QCborArray::operator=(const QCborArray &other) noexcept } /*! + \fn QCborArray &QCborArray::operator=(QCborArray &&other) + \since 6.10 + + Move-assignment operator. + + The moved-from object \a other is placed in a valid, but unspecified state. +*/ + +/*! \fn void QCborArray::swap(QCborArray &other) \memberswap{array} */ diff --git a/src/corelib/serialization/qcborarray.h b/src/corelib/serialization/qcborarray.h index dd24e5604c0..208d5bcc9a1 100644 --- a/src/corelib/serialization/qcborarray.h +++ b/src/corelib/serialization/qcborarray.h @@ -204,7 +204,9 @@ public: QCborArray() noexcept; QCborArray(const QCborArray &other) noexcept; + QCborArray(QCborArray &&other) noexcept = default; QCborArray &operator=(const QCborArray &other) noexcept; + QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QCborArray) QCborArray(std::initializer_list<QCborValue> args) : QCborArray() { diff --git a/src/corelib/serialization/qcborcommon.h b/src/corelib/serialization/qcborcommon.h index b9f7a66ae2f..5183a90937f 100644 --- a/src/corelib/serialization/qcborcommon.h +++ b/src/corelib/serialization/qcborcommon.h @@ -7,6 +7,7 @@ #include <QtCore/qobjectdefs.h> #include <QtCore/qmetatype.h> +#include <QtCore/qshareddata.h> #if 0 #pragma qt_class(QtCborCommon) @@ -22,6 +23,9 @@ QT_BEGIN_NAMESPACE class QDebug; +class QCborContainerPrivate; +QT_DECLARE_QESDP_SPECIALIZATION_DTOR(QCborContainerPrivate) // defined in qcborvalue.cpp + enum class QCborSimpleType : quint8 { False = 20, True = 21, diff --git a/src/corelib/serialization/qcbormap.cpp b/src/corelib/serialization/qcbormap.cpp index 6166775c8ce..e6075dcfc36 100644 --- a/src/corelib/serialization/qcbormap.cpp +++ b/src/corelib/serialization/qcbormap.cpp @@ -276,6 +276,17 @@ QCborMap::QCborMap(const QCborMap &other) noexcept } /*! + \fn QCborMap::QCborMap(QCborMap &&other) + \since 6.10 + + Move-constructor. + + The moved-from object \a other is placed in the default-constructed state. + + \sa QCborMap::QCborMap() +*/ + +/*! \fn QCborMap::QCborMap(std::initializer_list<value_type> args) Constructs a QCborMap with items from a brace-initialization list found in @@ -309,6 +320,15 @@ QCborMap &QCborMap::operator=(const QCborMap &other) noexcept } /*! + \fn QCborMap &QCborMap::operator=(QCborMap &&other) + \since 6.10 + + Move-assignment operator. + + The moved-from object \a other is placed in a valid, but unspecified state. +*/ + +/*! \fn void QCborMap::swap(QCborMap &other) \memberswap{map} */ diff --git a/src/corelib/serialization/qcbormap.h b/src/corelib/serialization/qcbormap.h index 039c436c76b..e2945621451 100644 --- a/src/corelib/serialization/qcbormap.h +++ b/src/corelib/serialization/qcbormap.h @@ -239,7 +239,9 @@ public: QCborMap() noexcept; QCborMap(const QCborMap &other) noexcept; + QCborMap(QCborMap &&other) noexcept = default; QCborMap &operator=(const QCborMap &other) noexcept; + QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QCborMap) QCborMap(std::initializer_list<value_type> args) : QCborMap() { diff --git a/src/corelib/serialization/qcborvalue.cpp b/src/corelib/serialization/qcborvalue.cpp index fabed2f06e1..5b7ec705079 100644 --- a/src/corelib/serialization/qcborvalue.cpp +++ b/src/corelib/serialization/qcborvalue.cpp @@ -28,6 +28,8 @@ QT_BEGIN_NAMESPACE +QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QCborContainerPrivate) + // Worst case memory allocation for a corrupt stream: 256 MB for 32-bit, 1 GB for 64-bit static constexpr quint64 MaxAcceptableMemoryUse = (sizeof(void*) == 4 ? 256 : 1024) * 1024 * 1024; diff --git a/src/corelib/thread/qatomicwait.cpp b/src/corelib/thread/qatomicwait.cpp index 3d70333ca7b..25ca771643b 100644 --- a/src/corelib/thread/qatomicwait.cpp +++ b/src/corelib/thread/qatomicwait.cpp @@ -4,6 +4,7 @@ #include "qatomicwait_p.h" #include <qendian.h> +#include "qfutex_p.h" #include "qwaitcondition_p.h" #include <array> @@ -96,8 +97,21 @@ struct QAtomicWaitLocks }; } // unnamed namespace +static inline void checkFutexUse() +{ +#if !defined(QATOMICWAIT_USE_FALLBACK) + if (QtFutex::futexAvailable()) { + // This will disable the code and data on systems where futexes are + // always available (currently: FreeBSD, Linux, Windows). + qFatal("Implementation should have used futex!"); + } +#endif +} + static QAtomicWaitLocks &atomicLocks() noexcept { + checkFutexUse(); + static QAtomicWaitLocks global {}; return global; } diff --git a/src/corelib/thread/qmutex.cpp b/src/corelib/thread/qmutex.cpp index bd3b269c0b7..832d87332b0 100644 --- a/src/corelib/thread/qmutex.cpp +++ b/src/corelib/thread/qmutex.cpp @@ -120,8 +120,8 @@ void QBasicMutex::destroyInternal(void *ptr) Locks the mutex. If another thread has locked the mutex then this call will block until that thread has unlocked it. - Calling this function multiple times on the same mutex from the - same thread will cause a \e dead-lock. + If the mutex was already locked by the current thread, this call will + never return, causing a \e dead-lock. \sa unlock() */ @@ -140,9 +140,6 @@ void QBasicMutex::destroyInternal(void *ptr) If the lock was obtained, the mutex must be unlocked with unlock() before another thread can successfully lock it. - Calling this function multiple times on the same mutex from the - same thread will cause a \e dead-lock. - \sa lock(), unlock() */ @@ -157,9 +154,6 @@ void QBasicMutex::destroyInternal(void *ptr) If the lock was obtained, the mutex must be unlocked with unlock() before another thread can successfully lock it. - Calling this function multiple times on the same mutex from the - same thread will cause a \e dead-lock. - \sa lock(), unlock() */ @@ -172,9 +166,6 @@ void QBasicMutex::destroyInternal(void *ptr) If the lock was obtained, the mutex must be unlocked with unlock() before another thread can successfully lock it. - Calling this function multiple times on the same mutex from the - same thread will cause a \e dead-lock. - \sa lock(), unlock() */ @@ -202,9 +193,6 @@ void QBasicMutex::destroyInternal(void *ptr) If the lock was obtained, the mutex must be unlocked with unlock() before another thread can successfully lock it. - Calling this function multiple times on the same mutex from the - same thread will cause a \e dead-lock. - \sa lock(), unlock() */ @@ -222,9 +210,6 @@ void QBasicMutex::destroyInternal(void *ptr) If the lock was obtained, the mutex must be unlocked with unlock() before another thread can successfully lock it. - Calling this function multiple times on the same mutex from the - same thread will cause a \e dead-lock. - \sa lock(), unlock() */ diff --git a/src/corelib/time/qdatetime.cpp b/src/corelib/time/qdatetime.cpp index 42011993243..43b16cd0f4f 100644 --- a/src/corelib/time/qdatetime.cpp +++ b/src/corelib/time/qdatetime.cpp @@ -405,13 +405,16 @@ static int fromOffsetString(QStringView offsetString, bool *valid) noexcept \section2 Range of Valid Dates - Dates are stored internally as a Julian Day number, an integer count of - every day in a contiguous range, with 24 November 4714 BCE in the Gregorian - calendar being Julian Day 0 (1 January 4713 BCE in the Julian calendar). - As well as being an efficient and accurate way of storing an absolute date, - it is suitable for converting a date into other calendar systems such as - Hebrew, Islamic or Chinese. The Julian Day number can be obtained using - QDate::toJulianDay() and can be set using QDate::fromJulianDay(). + Dates are stored internally as a modified Julian Day number, an integer + count of every day in a contiguous range, with 24 November 4714 BCE in the + Gregorian calendar being Julian Day 0 (1 January 4713 BCE in the Julian + calendar). As well as being an efficient and accurate way of storing an + absolute date, it is suitable for converting a date into other calendar + systems such as Hebrew, Islamic or Chinese. For the purposes of QDate, + Julian Days are delimited at midnight and, for those of QDateTime, in the + zone used by the datetime. (This departs from the formal definition, which + delimits Julian Days at UTC noon.) The Julian Day number can be obtained + using QDate::toJulianDay() and can be set using QDate::fromJulianDay(). The range of Julian Day numbers that QDate can represent is, for technical reasons, limited to between -784350574879 and 784354017364, which means from diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp index 37d6dea35f9..54bd971cb36 100644 --- a/src/corelib/tools/qarraydata.cpp +++ b/src/corelib/tools/qarraydata.cpp @@ -181,13 +181,12 @@ allocateHelper(qsizetype objectSize, qsizetype alignment, qsizetype capacity, return {}; void *data = nullptr; - QArrayData *header = static_cast<QArrayData *>(::malloc(size_t(allocSize))); - if (Q_LIKELY(header)) { - header->ref_.storeRelaxed(1); - header->flags = {}; + void *mem = ::malloc(size_t(allocSize)); + QArrayData *header = nullptr; + if (Q_LIKELY(mem)) { + header = new (mem) QArrayData{1, {}, capacity}; // find where offset should point to so that data() is aligned to alignment bytes data = QTypedArrayData<void>::dataStart(header, alignment); - header->alloc = capacity; } return { data, header }; @@ -245,8 +244,12 @@ QArrayData::reallocateUnaligned(QArrayData *data, void *dataPointer, Q_ASSERT(offset > 0); Q_ASSERT(offset <= allocSize); // equals when all free space is at the beginning - QArrayData *header = static_cast<QArrayData *>(::realloc(data, size_t(allocSize))); - if (header) { + const bool hadData = data; + void *mem = ::realloc(data, size_t(allocSize)); + QArrayData *header = static_cast<QArrayData *>(mem); + if (mem) { + if (!hadData) + header = new (mem) QArrayData{0, {}, {}}; header->alloc = capacity; dataPointer = reinterpret_cast<char *>(header) + offset; } else { diff --git a/src/corelib/tools/qatomicscopedvaluerollback.h b/src/corelib/tools/qatomicscopedvaluerollback.h index 8f653acba5e..929a2e2d466 100644 --- a/src/corelib/tools/qatomicscopedvaluerollback.h +++ b/src/corelib/tools/qatomicscopedvaluerollback.h @@ -11,6 +11,7 @@ #include <QtCore/qtconfigmacros.h> #include <atomic> +#include <type_traits> QT_BEGIN_NAMESPACE @@ -122,6 +123,33 @@ template <typename T> QAtomicScopedValueRollback(QBasicAtomicPointer<T> &, std::memory_order) -> QAtomicScopedValueRollback<T*>; +template <typename T, typename V, + std::enable_if_t<std::is_convertible_v<V, T>, bool> = true> +QAtomicScopedValueRollback(std::atomic<T>&, V) + -> QAtomicScopedValueRollback<T>; +template <typename T, typename V, + std::enable_if_t<std::is_convertible_v<V, T>, bool> = true> +QAtomicScopedValueRollback(std::atomic<T>&, V, std::memory_order) + -> QAtomicScopedValueRollback<T>; + +template <typename T, typename V, + std::enable_if_t<std::is_convertible_v<V, T>, bool> = true> +QAtomicScopedValueRollback(QBasicAtomicInteger<T>&, V) + -> QAtomicScopedValueRollback<T>; +template <typename T, typename V, + std::enable_if_t<std::is_convertible_v<V, T>, bool> = true> +QAtomicScopedValueRollback(QBasicAtomicInteger<T>&, V, std::memory_order) + -> QAtomicScopedValueRollback<T>; + +template <typename T, typename V, + std::enable_if_t<std::is_convertible_v<V, T*>, bool> = true> +QAtomicScopedValueRollback(QBasicAtomicPointer<T>&, V) + -> QAtomicScopedValueRollback<T*>; +template <typename T, typename V, + std::enable_if_t<std::is_convertible_v<V, T*>, bool> = true> +QAtomicScopedValueRollback(QBasicAtomicPointer<T>&, V, std::memory_order) + -> QAtomicScopedValueRollback<T*>; + QT_END_NAMESPACE #endif // QATOMICASCOPEDVALUEROLLBACK_H diff --git a/src/corelib/tools/qfreelist_p.h b/src/corelib/tools/qfreelist_p.h index 5c12332aa4a..ecefd1f55df 100644 --- a/src/corelib/tools/qfreelist_p.h +++ b/src/corelib/tools/qfreelist_p.h @@ -199,27 +199,27 @@ inline typename QFreeList<T, ConstantsType>::ReferenceType QFreeList<T, Constant template <typename T, typename ConstantsType> inline int QFreeList<T, ConstantsType>::next() { - int id, newid, at; - ElementType *v; + int newid; + int id = _next.loadAcquire(); do { - id = _next.loadAcquire(); - - at = id & ConstantsType::IndexMask; + int at = id & ConstantsType::IndexMask; const int block = blockfor(at); - v = _v[block].loadAcquire(); + ElementType *v = _v[block].loadAcquire(); if (!v) { - v = allocate((id & ConstantsType::IndexMask) - at, ConstantsType::Sizes[block]); - if (!_v[block].testAndSetRelease(nullptr, v)) { + ElementType* const alloced = allocate((id & ConstantsType::IndexMask) - at, + ConstantsType::Sizes[block]); + if (_v[block].testAndSetRelease(nullptr, alloced, v)) { + v = alloced; + } else { // race with another thread lost - delete[] v; - v = _v[block].loadAcquire(); + delete[] alloced; Q_ASSERT(v != nullptr); } } newid = v[at].next.loadRelaxed() | (id & ~ConstantsType::IndexMask); - } while (!_next.testAndSetRelease(id, newid)); + } while (!_next.testAndSetOrdered(id, newid, id)); // qDebug("QFreeList::next(): returning %d (_next now %d, serial %d)", // id & ConstantsType::IndexMask, // newid & ConstantsType::IndexMask, @@ -232,7 +232,7 @@ inline void QFreeList<T, ConstantsType>::release(int id) { int at = id & ConstantsType::IndexMask; const int block = blockfor(at); - ElementType *v = _v[block].loadRelaxed(); + ElementType *v = _v[block].loadAcquire(); int x, newid; do { diff --git a/src/corelib/tools/qhashfunctions.h b/src/corelib/tools/qhashfunctions.h index cbe217db11e..3e44f5f3442 100644 --- a/src/corelib/tools/qhashfunctions.h +++ b/src/corelib/tools/qhashfunctions.h @@ -298,19 +298,32 @@ bool qHashEquals(const T1 &a, const T2 &b) } namespace QtPrivate { -template <typename Mixer> struct QHashCombiner : private Mixer +template <typename Mixer> struct QHashCombinerWithSeed : private Mixer { - using result_type = typename Mixer::result_type ; + using result_type = typename Mixer::result_type; + size_t seed; + constexpr QHashCombinerWithSeed(result_type s) noexcept : seed(s) {} + + template <typename T> + constexpr result_type operator()(result_type result, const T &t) const + noexcept(noexcept(qHash(t, seed))) + { + return Mixer::operator()(result, qHash(t, seed)); + } +}; #if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) || defined(QT_BOOTSTRAPPED) - // Qt 6.x didn't use to pass the seed; bootstrap has no seed +// Earlier Qt 6.x versions of qHashMulti() failed to pass the seed as the seed +// argument of qHash(), so this class exists for compatibility with user and +// inline code that relies on the old behavior. For Qt 7, we'll replace with +// the above version, except for the bootstrapped tools (which have no seed). +template <typename Mixer> struct QHashCombiner : private Mixer +{ + using result_type = typename Mixer::result_type; + static constexpr size_t seed = 0; constexpr QHashCombiner(result_type) noexcept {} Q_DECL_DEPRECATED_X("pass the seed argument") constexpr QHashCombiner() noexcept {} -#else - size_t seed; - constexpr QHashCombiner(result_type s) : seed(s) noexcept {} -#endif template <typename T> constexpr result_type operator()(result_type result, const T &t) const @@ -319,6 +332,9 @@ template <typename Mixer> struct QHashCombiner : private Mixer return Mixer::operator()(result, qHash(t, seed)); } }; +#else +template <typename Mixer> using QHashCombiner = QHashCombinerWithSeed<Mixer>; +#endif struct QHashCombineMixer { @@ -330,6 +346,7 @@ struct QHashCombineMixer } }; using QHashCombine = QHashCombiner<QHashCombineMixer>; +using QHashCombineWithSeed = QHashCombinerWithSeed<QHashCombineMixer>; struct QHashCombineCommutativeMixer : std::plus<size_t> { @@ -341,6 +358,7 @@ struct QHashCombineCommutativeMixer : std::plus<size_t> typedef size_t result_type; }; using QHashCombineCommutative = QHashCombiner<QHashCombineCommutativeMixer>; +using QHashCombineCommutativeWithSeed = QHashCombinerWithSeed<QHashCombineCommutativeMixer>; template <typename... T> using QHashMultiReturnType = decltype( diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h index a9d334e28f3..e0c0110b794 100644 --- a/src/corelib/tools/qsharedpointer_impl.h +++ b/src/corelib/tools/qsharedpointer_impl.h @@ -592,7 +592,10 @@ class QWeakPointer { typedef QtSharedPointer::ExternalRefCountData Data; template <typename X> - using IfCompatible = typename std::enable_if<std::is_convertible<X*, T*>::value, bool>::type; + using IfCompatible = std::enable_if_t<std::conjunction_v< + std::negation<std::is_same<T, X>>, // don't make accidental copy/move SMFs + std::is_convertible<X*, T*> + >, bool>; template <typename X> using IfVirtualBase = typename std::enable_if<qxp::is_virtual_base_of_v<T, X>, bool>::type; @@ -768,6 +771,11 @@ private: { return *this = QWeakPointer<T>(ptr, true); } #ifndef QT_NO_QOBJECT + Q_NODISCARD_CTOR + QWeakPointer(T *ptr, bool) + : d{ptr ? Data::getAndRef(ptr) : nullptr}, value{ptr} + { } + template <class X, IfCompatible<X> = true> Q_NODISCARD_CTOR inline QWeakPointer(X *ptr, bool) : d(ptr ? Data::getAndRef(ptr) : nullptr), value(ptr) diff --git a/src/gui/compat/removed_api.cpp b/src/gui/compat/removed_api.cpp index 6a39d8b8615..33549a06504 100644 --- a/src/gui/compat/removed_api.cpp +++ b/src/gui/compat/removed_api.cpp @@ -88,3 +88,16 @@ void QWindowSystemInterface::handleContextMenuEvent(QWindow *window, bool mouseT // order sections alphabetically #endif // QT_GUI_REMOVED_SINCE(6, 8) + +#if QT_GUI_REMOVED_SINCE(6, 11) + +#include "qpainter.h" // inlined API + +#include "qquaternion.h" // inlined API + + +// #include "qotherheader.h" +// // implement removed functions from qotherheader.h +// order sections alphabetically + +#endif // QT_GUI_REMOVED_SINCE(6, 11) diff --git a/src/gui/kernel/qguivariant.cpp b/src/gui/kernel/qguivariant.cpp index c6462dfed7b..6da0c4d387b 100644 --- a/src/gui/kernel/qguivariant.cpp +++ b/src/gui/kernel/qguivariant.cpp @@ -52,14 +52,13 @@ QT_BEGIN_NAMESPACE namespace { - -// NOLINTNEXTLINE(cppcoreguidelines-virtual-class-destructor): this is not a base class struct QVariantGuiHelper : QMetaTypeModuleHelper { #define QT_IMPL_METATYPEINTERFACE_GUI_TYPES(MetaTypeName, MetaTypeId, RealName) \ QT_METATYPE_INTERFACE_INIT(RealName), - const QtPrivate::QMetaTypeInterface *interfaceForType(int type) const override { + static const QtPrivate::QMetaTypeInterface *interfaceForType(int type) + { switch (type) { QT_FOR_EACH_STATIC_GUI_CLASS(QT_METATYPE_CONVERT_ID_TO_TYPE) default: return nullptr; @@ -67,7 +66,7 @@ struct QVariantGuiHelper : QMetaTypeModuleHelper } #undef QT_IMPL_METATYPEINTERFACE_GUI_TYPES - bool convert(const void *from, int fromTypeId, void *to, int toTypeId) const override + static bool convert(const void *from, int fromTypeId, void *to, int toTypeId) { Q_ASSERT(fromTypeId != toTypeId); @@ -133,14 +132,14 @@ struct QVariantGuiHelper : QMetaTypeModuleHelper return false; } }; - -static constexpr QVariantGuiHelper qVariantGuiHelper; - } // namespace used to hide QVariant handler void qRegisterGuiVariant() { - qMetaTypeGuiHelper = &qVariantGuiHelper; + qMetaTypeGuiHelper = QMetaTypeModuleHelper{ + &QVariantGuiHelper::interfaceForType, + &QVariantGuiHelper::convert, + }; } Q_CONSTRUCTOR_FUNCTION(qRegisterGuiVariant) diff --git a/src/gui/kernel/qscreen.cpp b/src/gui/kernel/qscreen.cpp index afe6de35305..caf4cb7fe5b 100644 --- a/src/gui/kernel/qscreen.cpp +++ b/src/gui/kernel/qscreen.cpp @@ -34,6 +34,12 @@ QT_BEGIN_NAMESPACE \note Both physical and logical DPI are expressed in device-independent dots. Multiply by QScreen::devicePixelRatio() to get device-dependent density. + To obtain a QScreen object, use QGuiApplication::primaryScreen() for the + primary screen, or QGuiApplication::screens() to get a list of all screens. + + \sa QGuiApplication::primaryScreen() + \sa QGuiApplication::screens() + \inmodule QtGui */ diff --git a/src/gui/kernel/qtestsupport_gui.cpp b/src/gui/kernel/qtestsupport_gui.cpp index ca62798ddfd..dfcea928fd8 100644 --- a/src/gui/kernel/qtestsupport_gui.cpp +++ b/src/gui/kernel/qtestsupport_gui.cpp @@ -24,8 +24,19 @@ QT_BEGIN_NAMESPACE /*! \since 5.0 + \overload - Returns \c true, if \a window is active within \a timeout milliseconds. Otherwise returns \c false. + The \a timeout is in milliseconds. +*/ +bool QTest::qWaitForWindowActive(QWindow *window, int timeout) +{ + return qWaitForWindowActive(window, QDeadlineTimer{timeout, Qt::TimerType::PreciseTimer}); +} + +/*! + \since 6.10 + + Returns \c true, if \a window is active within \a timeout. Otherwise returns \c false. The method is useful in tests that call QWindow::show() and rely on the window actually being active (i.e. being visible and having focus) before proceeding. @@ -38,7 +49,7 @@ QT_BEGIN_NAMESPACE \sa qWaitForWindowExposed(), qWaitForWindowFocused(), QWindow::isActive() */ -Q_GUI_EXPORT bool QTest::qWaitForWindowActive(QWindow *window, int timeout) +bool QTest::qWaitForWindowActive(QWindow *window, QDeadlineTimer timeout) { if (Q_UNLIKELY(!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))) { qWarning() << "qWaitForWindowActive was called on a platform that doesn't support window" @@ -52,6 +63,17 @@ Q_GUI_EXPORT bool QTest::qWaitForWindowActive(QWindow *window, int timeout) } /*! + \since 6.10 + \overload + + This function uses the default timeout of 5 seconds. +*/ +bool QTest::qWaitForWindowActive(QWindow *window) +{ + return qWaitForWindowActive(window, Internal::defaultTryTimeout); +} + +/*! \since 6.7 Returns \c true, if \a window is the focus window within \a timeout. Otherwise returns \c false. @@ -73,9 +95,31 @@ Q_GUI_EXPORT bool QTest::qWaitForWindowFocused(QWindow *window, QDeadlineTimer t } /*! + \since 6.10 + \overload + + This function uses the default timeout of 5 seconds. +*/ +bool QTest::qWaitForWindowFocused(QWindow *window) +{ + return qWaitForWindowFocused(window, Internal::defaultTryTimeout); +} + +/*! \since 5.0 + \overload + + The \a timeout is in milliseconds. +*/ +bool QTest::qWaitForWindowExposed(QWindow *window, int timeout) +{ + return qWaitForWindowExposed(window, std::chrono::milliseconds(timeout)); +} - Returns \c true, if \a window is exposed within \a timeout milliseconds. Otherwise returns \c false. +/*! + \since 6.10 + + Returns \c true, if \a window is exposed within \a timeout. Otherwise returns \c false. The method is useful in tests that call QWindow::show() and rely on the window actually being being visible before proceeding. @@ -86,11 +130,22 @@ Q_GUI_EXPORT bool QTest::qWaitForWindowFocused(QWindow *window, QDeadlineTimer t \sa qWaitForWindowActive(), QWindow::isExposed() */ -Q_GUI_EXPORT bool QTest::qWaitForWindowExposed(QWindow *window, int timeout) +bool QTest::qWaitForWindowExposed(QWindow *window, QDeadlineTimer timeout) { return QTest::qWaitFor([&]() { return window->isExposed(); }, timeout); } +/*! + \since 6.10 + \overload + + This function uses the default timeout of 5 seconds. +*/ +bool QTest::qWaitForWindowExposed(QWindow *window) +{ + return qWaitForWindowExposed(window, Internal::defaultTryTimeout); +} + namespace QTest { QTouchEventSequence::~QTouchEventSequence() diff --git a/src/gui/kernel/qtestsupport_gui.h b/src/gui/kernel/qtestsupport_gui.h index 951d9df1c7c..39278c2f034 100644 --- a/src/gui/kernel/qtestsupport_gui.h +++ b/src/gui/kernel/qtestsupport_gui.h @@ -23,12 +23,16 @@ Q_GUI_EXPORT bool qt_handleTouchEventv2(QWindow *w, const QPointingDevice *devic namespace QTest { -[[nodiscard]] Q_GUI_EXPORT bool qWaitForWindowActive(QWindow *window, - int timeout = static_cast<int>(Internal::defaultTryTimeout.count())); -[[nodiscard]] Q_GUI_EXPORT bool qWaitForWindowFocused(QWindow *window, - QDeadlineTimer timeout = Internal::defaultTryTimeout); -[[nodiscard]] Q_GUI_EXPORT bool qWaitForWindowExposed(QWindow *window, - int timeout = static_cast<int>(Internal::defaultTryTimeout.count())); +[[nodiscard]] Q_GUI_EXPORT bool qWaitForWindowActive(QWindow *window, int timeout); +[[nodiscard]] Q_GUI_EXPORT bool qWaitForWindowActive(QWindow *window, QDeadlineTimer timeout); +[[nodiscard]] Q_GUI_EXPORT bool qWaitForWindowActive(QWindow *window); + +[[nodiscard]] Q_GUI_EXPORT bool qWaitForWindowFocused(QWindow *window, QDeadlineTimer timeout); +[[nodiscard]] Q_GUI_EXPORT bool qWaitForWindowFocused(QWindow *window); + +[[nodiscard]] Q_GUI_EXPORT bool qWaitForWindowExposed(QWindow *window, int timeout); +[[nodiscard]] Q_GUI_EXPORT bool qWaitForWindowExposed(QWindow *window, QDeadlineTimer timeout); +[[nodiscard]] Q_GUI_EXPORT bool qWaitForWindowExposed(QWindow *window); Q_GUI_EXPORT QPointingDevice * createTouchDevice(QInputDevice::DeviceType devType = QInputDevice::DeviceType::TouchScreen, QInputDevice::Capabilities caps = QInputDevice::Capability::Position); diff --git a/src/gui/math3d/qquaternion.cpp b/src/gui/math3d/qquaternion.cpp index b4dccfc42fe..99061fb7163 100644 --- a/src/gui/math3d/qquaternion.cpp +++ b/src/gui/math3d/qquaternion.cpp @@ -336,6 +336,9 @@ QVector3D QQuaternion::rotatedVector(const QVector3D &vector) const Extracts a 3D axis \a axis and a rotating angle \a angle (in degrees) that corresponds to this quaternion. + Both \a axis and \a angle must be valid, non-\nullptr pointers, + otherwise the behavior is undefined. + \sa fromAxisAndAngle() */ @@ -366,6 +369,9 @@ QQuaternion QQuaternion::fromAxisAndAngle(const QVector3D &axis, float angle) Extracts a 3D axis (\a x, \a y, \a z) and a rotating angle \a angle (in degrees) that corresponds to this quaternion. + All of \a x, \a y, \a z, and \a angle must be valid, non-\nullptr pointers, + otherwise the behavior is undefined. + \sa fromAxisAndAngle() */ void QQuaternion::getAxisAndAngle(float *x, float *y, float *z, float *angle) const @@ -447,6 +453,9 @@ QQuaternion QQuaternion::fromAxisAndAngle Calculates \a roll, \a pitch, and \a yaw Euler angles (in degrees) that corresponds to this quaternion. + All of \a pitch, \a yaw, and \a roll must be valid, non-\nullptr pointers, + otherwise the behavior is undefined. + \sa fromEulerAngles() */ void QQuaternion::getEulerAngles(float *pitch, float *yaw, float *roll) const @@ -548,7 +557,7 @@ QQuaternion QQuaternion::fromEulerAngles(float pitch, float yaw, float roll) \note If this quaternion is not normalized, the resulting rotation matrix will contain scaling information. - \sa fromRotationMatrix(), getAxes() + \sa fromRotationMatrix(), toAxes() */ QMatrix3x3 QQuaternion::toRotationMatrix() const { @@ -631,23 +640,71 @@ QQuaternion QQuaternion::fromRotationMatrix(const QMatrix3x3 &rot3x3) #ifndef QT_NO_VECTOR3D /*! - \since 5.5 + \since 6.11 + \class QQuaternion::Axes + \ingroup painting-3D + \inmodule QtGui - Returns the 3 orthonormal axes (\a xAxis, \a yAxis, \a zAxis) defining the quaternion. + A struct containing the three orthonormal axes that define a + \l{QQuaternion}{quaternion}. - \sa fromAxes(), toRotationMatrix() + + \sa QQuaternion::toAxes(), QQuaternion::fromAxes(Axes) */ -void QQuaternion::getAxes(QVector3D *xAxis, QVector3D *yAxis, QVector3D *zAxis) const -{ - Q_ASSERT(xAxis && yAxis && zAxis); +/*! + \variable QQuaternion::Axes::x + + The x orthonormal axis that, together with \l{y} and \l{z}, defines a + quaternion. +*/ + +/*! + \variable QQuaternion::Axes::y + + The y orthonormal axis that, together with \l{x} and \l{z}, defines a + quaternion. +*/ + +/*! + \variable QQuaternion::Axes::z + + The z orthonormal axis that, together with \l{x} and \l{y}, defines a + quaternion. +*/ + +/*! + \since 6.11 + + Returns the three orthonormal axes that define this quaternion. + + \sa QQuaternion::Axes, fromAxes(QQuaternion::Axes), toRotationMatrix() +*/ +auto QQuaternion::toAxes() const -> Axes +{ const QMatrix3x3 rot3x3(toRotationMatrix()); - *xAxis = QVector3D(rot3x3(0, 0), rot3x3(1, 0), rot3x3(2, 0)); - *yAxis = QVector3D(rot3x3(0, 1), rot3x3(1, 1), rot3x3(2, 1)); - *zAxis = QVector3D(rot3x3(0, 2), rot3x3(1, 2), rot3x3(2, 2)); + return { {rot3x3(0, 0), rot3x3(1, 0), rot3x3(2, 0)}, + {rot3x3(0, 1), rot3x3(1, 1), rot3x3(2, 1)}, + {rot3x3(0, 2), rot3x3(1, 2), rot3x3(2, 2)} }; } + +/*! + \fn void QQuaternion::getAxes(QVector3D *xAxis, QVector3D *yAxis, QVector3D *zAxis) const + \since 5.5 + + \obsolete + Use toAxes() instead. + + Returns the 3 orthonormal axes (\a xAxis, \a yAxis, \a zAxis) defining the quaternion. + + All of \a xAxis, \a yAxis, and \a zAxis must be valid, non-\nullptr pointers, + otherwise the behavior is undefined. + + \sa fromAxes(), toRotationMatrix() +*/ + /*! \since 5.5 @@ -655,7 +712,7 @@ void QQuaternion::getAxes(QVector3D *xAxis, QVector3D *yAxis, QVector3D *zAxis) \note The axes are assumed to be orthonormal. - \sa getAxes(), fromRotationMatrix() + \sa toAxes(), fromRotationMatrix() */ QQuaternion QQuaternion::fromAxes(const QVector3D &xAxis, const QVector3D &yAxis, const QVector3D &zAxis) { @@ -674,6 +731,17 @@ QQuaternion QQuaternion::fromAxes(const QVector3D &xAxis, const QVector3D &yAxis } /*! + \since 6.11 + \overload + + \sa toAxes(), fromRotationMatrix() +*/ +QQuaternion QQuaternion::fromAxes(Axes axes) // clazy:exclude=function-args-by-ref +{ + return fromAxes(axes.x, axes.y, axes.z); +} + +/*! \since 5.5 Constructs the quaternion using specified forward direction \a direction diff --git a/src/gui/math3d/qquaternion.h b/src/gui/math3d/qquaternion.h index 0ea844ae41f..ffc95a852ce 100644 --- a/src/gui/math3d/qquaternion.h +++ b/src/gui/math3d/qquaternion.h @@ -118,7 +118,14 @@ QT_WARNING_POP QT7_ONLY(Q_GUI_EXPORT) static QQuaternion fromRotationMatrix(const QMatrix3x3 &rot3x3); #ifndef QT_NO_VECTOR3D - QT7_ONLY(Q_GUI_EXPORT) void getAxes(QVector3D *xAxis, QVector3D *yAxis, QVector3D *zAxis) const; + struct Axes + { + QVector3D x, y, z; + }; + QT7_ONLY(Q_GUI_EXPORT) Axes toAxes() const; + QT7_ONLY(Q_GUI_EXPORT) static QQuaternion fromAxes(Axes axes); // clazy:exclude=function-args-by-ref + QT_GUI_INLINE_SINCE(6, 11) + void getAxes(QVector3D *xAxis, QVector3D *yAxis, QVector3D *zAxis) const; QT7_ONLY(Q_GUI_EXPORT) static QQuaternion fromAxes(const QVector3D &xAxis, const QVector3D &yAxis, const QVector3D &zAxis); @@ -330,6 +337,19 @@ QQuaternion QQuaternion::fromEulerAngles(const QVector3D &angles) return QQuaternion::fromEulerAngles(angles.x(), angles.y(), angles.z()); } +#if QT_GUI_INLINE_IMPL_SINCE(6, 11) +void QQuaternion::getAxes(QVector3D *xAxis, QVector3D *yAxis, QVector3D *zAxis) const +{ + Q_PRE(xAxis); + Q_PRE(yAxis); + Q_PRE(zAxis); + const Axes axes = toAxes(); + *xAxis = axes.x; + *yAxis = axes.y; + *zAxis = axes.z; +} +#endif // QT_GUI_INLINE_IMPL_SINCE(6, 11) + #endif // QT_NO_VECTOR3D constexpr void QQuaternion::setVector(float aX, float aY, float aZ) noexcept diff --git a/src/gui/painting/qbackingstoredefaultcompositor.cpp b/src/gui/painting/qbackingstoredefaultcompositor.cpp index c1452ca7688..41ab7c97f8c 100644 --- a/src/gui/painting/qbackingstoredefaultcompositor.cpp +++ b/src/gui/painting/qbackingstoredefaultcompositor.cpp @@ -460,11 +460,20 @@ QPlatformBackingStore::FlushResult QBackingStoreDefaultCompositor::flush(QPlatfo const QRegion ®ion, const QPoint &offset, QPlatformTextureList *textures, - bool translucentBackground) + bool translucentBackground, + qreal sourceTransformFactor) { if (!rhi) return QPlatformBackingStore::FlushFailed; + // Note, the sourceTransformFactor is different from the sourceDevicePixelRatio, + // as the former may reflect the fact that the region and offset is pre-transformed, + // in which case we don't need to do a full transform here based on the source DPR. + // In the default case where no explicit source transform has been passed, we fall + // back to the source device pixel ratio. + if (!sourceTransformFactor) + sourceTransformFactor = sourceDevicePixelRatio; + Q_ASSERT(textures); // may be empty if there are no render-to-texture widgets at all, but null it cannot be if (!m_rhi) { @@ -508,7 +517,7 @@ QPlatformBackingStore::FlushResult QBackingStoreDefaultCompositor::flush(QPlatfo const QImage::Format format = QImage::toImageFormat(graphicsBuffer->format()); const QSize size = graphicsBuffer->size(); QImage wrapperImage(graphicsBuffer->data(), size.width(), size.height(), graphicsBuffer->bytesPerLine(), format); - toTexture(wrapperImage, rhi, resourceUpdates, scaledRegion(region, sourceDevicePixelRatio, offset), &flags); + toTexture(wrapperImage, rhi, resourceUpdates, scaledRegion(region, sourceTransformFactor, offset), &flags); gotTextureFromGraphicsBuffer = true; graphicsBuffer->unlock(); if (graphicsBuffer->origin() == QPlatformGraphicsBuffer::OriginBottomLeft) @@ -516,7 +525,7 @@ QPlatformBackingStore::FlushResult QBackingStoreDefaultCompositor::flush(QPlatfo } } if (!gotTextureFromGraphicsBuffer) - toTexture(backingStore, rhi, resourceUpdates, scaledRegion(region, sourceDevicePixelRatio, offset), &flags); + toTexture(backingStore, rhi, resourceUpdates, scaledRegion(region, sourceTransformFactor, offset), &flags); ensureResources(resourceUpdates, swapchain->renderPassDescriptor()); @@ -549,7 +558,7 @@ QPlatformBackingStore::FlushResult QBackingStoreDefaultCompositor::flush(QPlatfo // The backingstore is for the entire tlw. In case of native children, offset tells the position // relative to the tlw. The window rect is scaled by the source device pixel ratio to get // the source rect. - const QPoint sourceWindowOffset = scaledOffset(offset, sourceDevicePixelRatio); + const QPoint sourceWindowOffset = scaledOffset(offset, sourceTransformFactor); const QRect srcRect = toBottomLeftRect(sourceWindowRect.translated(sourceWindowOffset), m_texture->pixelSize().height()); const QMatrix3x3 source = sourceTransform(srcRect, m_texture->pixelSize(), origin); QMatrix4x4 target; // identity diff --git a/src/gui/painting/qbackingstoredefaultcompositor_p.h b/src/gui/painting/qbackingstoredefaultcompositor_p.h index c5a8ffd328e..cdc9d098099 100644 --- a/src/gui/painting/qbackingstoredefaultcompositor_p.h +++ b/src/gui/painting/qbackingstoredefaultcompositor_p.h @@ -41,7 +41,8 @@ public: const QRegion ®ion, const QPoint &offset, QPlatformTextureList *textures, - bool translucentBackground); + bool translucentBackground, + qreal sourceTransformFactor); private: enum UpdateUniformOption { diff --git a/src/gui/painting/qdrawhelper_avx2.cpp b/src/gui/painting/qdrawhelper_avx2.cpp index 8bc49f42ab5..72853be6e97 100644 --- a/src/gui/painting/qdrawhelper_avx2.cpp +++ b/src/gui/painting/qdrawhelper_avx2.cpp @@ -35,9 +35,7 @@ BYTE_MUL_AVX2(__m256i &pixelVector, __m256i alphaChannel, __m256i colorMask, __m pixelVectorAG = _mm256_add_epi16(pixelVectorAG, half); pixelVectorRB = _mm256_srli_epi16(pixelVectorRB, 8); - pixelVectorAG = _mm256_andnot_si256(colorMask, pixelVectorAG); - - pixelVector = _mm256_or_si256(pixelVectorAG, pixelVectorRB); + pixelVector = _mm256_blendv_epi8(pixelVectorAG, pixelVectorRB, colorMask); } inline static void Q_DECL_VECTORCALL @@ -55,9 +53,7 @@ BYTE_MUL_RGB64_AVX2(__m256i &pixelVector, __m256i alphaChannel, __m256i colorMas pixelVectorAG = _mm256_add_epi32(pixelVectorAG, half); pixelVectorRB = _mm256_srli_epi32(pixelVectorRB, 16); - pixelVectorAG = _mm256_andnot_si256(colorMask, pixelVectorAG); - - pixelVector = _mm256_or_si256(pixelVectorAG, pixelVectorRB); + pixelVector = _mm256_blendv_epi8(pixelVectorAG, pixelVectorRB, colorMask); } // See INTERPOLATE_PIXEL_255_SSE2 for details. @@ -78,10 +74,9 @@ INTERPOLATE_PIXEL_255_AVX2(__m256i srcVector, __m256i &dstVector, __m256i alphaC finalRB = _mm256_add_epi16(finalRB, _mm256_srli_epi16(finalRB, 8)); finalAG = _mm256_add_epi16(finalAG, half); finalRB = _mm256_add_epi16(finalRB, half); - finalAG = _mm256_andnot_si256(colorMask, finalAG); finalRB = _mm256_srli_epi16(finalRB, 8); - dstVector = _mm256_or_si256(finalAG, finalRB); + dstVector = _mm256_blendv_epi8(finalAG, finalRB, colorMask); } inline static void Q_DECL_VECTORCALL @@ -101,10 +96,8 @@ INTERPOLATE_PIXEL_RGB64_AVX2(__m256i srcVector, __m256i &dstVector, __m256i alph finalRB = _mm256_add_epi32(finalRB, _mm256_srli_epi32(finalRB, 16)); finalAG = _mm256_add_epi32(finalAG, half); finalRB = _mm256_add_epi32(finalRB, half); - finalAG = _mm256_andnot_si256(colorMask, finalAG); finalRB = _mm256_srli_epi32(finalRB, 16); - - dstVector = _mm256_or_si256(finalAG, finalRB); + dstVector = _mm256_blendv_epi8(finalAG, finalRB, colorMask); } // See BLEND_SOURCE_OVER_ARGB32_SSE2 for details. diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 5013e96f740..344bb8f1bef 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -41,6 +41,8 @@ #include <private/qrawfont_p.h> #include <private/qfont_p.h> +#include <QtCore/private/qtclasshelper_p.h> + QT_BEGIN_NAMESPACE using namespace Qt::StringLiterals; @@ -3652,6 +3654,8 @@ void QPainter::setPen(const QColor &color) } /*! + \fn void QPainter::setPen(const QPen &pen) + Sets the painter's pen to be the given \a pen. The \a pen defines how to draw lines and outlines, and it also @@ -3660,7 +3664,13 @@ void QPainter::setPen(const QColor &color) \sa pen(), {QPainter#Settings}{Settings} */ -void QPainter::setPen(const QPen &pen) +/*! + \fn void QPainter::setPen(QPen &&pen) + \since 6.11 + \overload +*/ + +void QPainter::doSetPen(const QPen &pen, QPen *rvalue) { #ifdef QT_DEBUG_DRAW @@ -3677,7 +3687,7 @@ void QPainter::setPen(const QPen &pen) if (d->state->pen == pen) return; - d->state->pen = pen; + q_choose_assign(d->state->pen, pen, rvalue); if (d->extended) { d->checkEmulation(); @@ -3733,6 +3743,8 @@ const QPen &QPainter::pen() const /*! + \fn void QPainter::setBrush(const QBrush &brush) + Sets the painter's brush to the given \a brush. The painter's brush defines how shapes are filled. @@ -3740,7 +3752,13 @@ const QPen &QPainter::pen() const \sa brush(), {QPainter#Settings}{Settings} */ -void QPainter::setBrush(const QBrush &brush) +/*! + \fn void QPainter::setBrush(QBrush &&brush) + \since 6.11 + \overload +*/ + +void QPainter::doSetBrush(const QBrush &brush, QBrush *rvalue) { #ifdef QT_DEBUG_DRAW if constexpr (qt_show_painter_debug_output) @@ -3756,13 +3774,13 @@ void QPainter::setBrush(const QBrush &brush) return; if (d->extended) { - d->state->brush = brush; + q_choose_assign(d->state->brush, brush, rvalue); d->checkEmulation(); d->extended->brushChanged(); return; } - d->state->brush = brush; + q_choose_assign(d->state->brush, brush, rvalue); d->state->dirtyFlags |= QPaintEngine::DirtyBrush; } diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h index 3c09b632364..83bde3b8cad 100644 --- a/src/gui/painting/qpainter.h +++ b/src/gui/painting/qpainter.h @@ -150,11 +150,15 @@ public: QFontInfo fontInfo() const; void setPen(const QColor &color); + QT_GUI_INLINE_SINCE(6, 11) void setPen(const QPen &pen); + void setPen(QPen &&pen) { doSetPen(pen, &pen); } void setPen(Qt::PenStyle style); const QPen &pen() const; + QT_GUI_INLINE_SINCE(6, 11) void setBrush(const QBrush &brush); + void setBrush(QBrush &&brush) { doSetBrush(brush, &brush); } void setBrush(Qt::BrushStyle style); void setBrush(QColor color); void setBrush(Qt::GlobalColor color) { setBrush(QColor(color)); } @@ -419,6 +423,9 @@ public: private: Q_DISABLE_COPY(QPainter) + void doSetPen(const QPen &lvalue, QPen *rvalue); + void doSetBrush(const QBrush &lvalue, QBrush *rvalue); + std::unique_ptr<QPainterPrivate> d_ptr; friend class QWidget; @@ -700,6 +707,21 @@ inline void QPainter::fillRect(const QRectF &r, QGradient::Preset p) fillRect(r, QGradient(p)); } +#if QT_GUI_INLINE_IMPL_SINCE(6, 11) + +void QPainter::setPen(const QPen &p) +{ + doSetPen(p, nullptr); +} + +void QPainter::setBrush(const QBrush &b) +{ + doSetBrush(b, nullptr); +} + +#endif // QT_GUI_INLINE_IMPL_SINCE(6, 11) + + inline void QPainter::setBrushOrigin(int x, int y) { setBrushOrigin(QPoint(x, y)); diff --git a/src/gui/painting/qplatformbackingstore.cpp b/src/gui/painting/qplatformbackingstore.cpp index 21e89d67fd2..2acc5ef7c52 100644 --- a/src/gui/painting/qplatformbackingstore.cpp +++ b/src/gui/painting/qplatformbackingstore.cpp @@ -213,14 +213,15 @@ QPlatformBackingStore::FlushResult QPlatformBackingStore::rhiFlush(QWindow *wind const QRegion ®ion, const QPoint &offset, QPlatformTextureList *textures, - bool translucentBackground) + bool translucentBackground, + qreal sourceTransformFactor) { auto &surfaceSupport = d_ptr->surfaceSupport[window->surfaceType()]; return surfaceSupport.compositor.flush(this, surfaceSupport.rhiSupport.rhi(), surfaceSupport.rhiSupport.swapChainForWindow(window), window, sourceDevicePixelRatio, region, offset, textures, - translucentBackground); + translucentBackground, sourceTransformFactor); } /*! diff --git a/src/gui/painting/qplatformbackingstore.h b/src/gui/painting/qplatformbackingstore.h index a6cb43b4e66..86035b98bea 100644 --- a/src/gui/painting/qplatformbackingstore.h +++ b/src/gui/painting/qplatformbackingstore.h @@ -151,7 +151,8 @@ public: const QRegion ®ion, const QPoint &offset, QPlatformTextureList *textures, - bool translucentBackground); + bool translucentBackground, + qreal sourceTransformFactor = 0); virtual QImage toImage() const; diff --git a/src/gui/painting/qrhibackingstore.cpp b/src/gui/painting/qrhibackingstore.cpp index d59cc2d83c5..3d9932e5ee2 100644 --- a/src/gui/painting/qrhibackingstore.cpp +++ b/src/gui/painting/qrhibackingstore.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qrhibackingstore_p.h" +#include "qpa/qplatformwindow.h" #include <private/qimage_p.h> QT_BEGIN_NAMESPACE @@ -43,10 +44,22 @@ void QRhiBackingStore::flush(QWindow *flushedWindow, const QRegion ®ion, cons createRhi(flushedWindow, rhiConfig); } + // The backing store operates on behalf of its window(), even if we're + // flushing a child window, so pull the source DPR from the window(). + const qreal sourceDevicePixelRatio = window()->devicePixelRatio(); + + // QBackingStore::flush will convert the region and offset from device independent + // pixels to native pixels before calling QPlatformBackingStore::flush, which means + // we can't pass on the window's DPR as the sourceTransformFactor, as that will include + // the Qt scale factor, which has already been applied. Instead we ask the platform + // window, which only reflect the remaining scale factor from the OS. + const qreal sourceTransformFactor = flushedWindow->handle()->devicePixelRatio(); + static QPlatformTextureList emptyTextureList; bool translucentBackground = m_image.hasAlphaChannel(); - rhiFlush(flushedWindow, flushedWindow->devicePixelRatio(), - region, offset, &emptyTextureList, translucentBackground); + rhiFlush(flushedWindow, sourceDevicePixelRatio, + region, offset, &emptyTextureList, translucentBackground, + sourceTransformFactor); } QImage::Format QRhiBackingStore::format() const diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp index 66f1cf2a985..148d40b8361 100644 --- a/src/gui/painting/qtransform.cpp +++ b/src/gui/painting/qtransform.cpp @@ -784,7 +784,7 @@ bool QTransform::operator==(const QTransform &o) const */ size_t qHash(const QTransform &key, size_t seed) noexcept { - QtPrivate::QHashCombine hash(seed); + QtPrivate::QHashCombineWithSeed hash(seed); seed = hash(seed, key.m11()); seed = hash(seed, key.m12()); seed = hash(seed, key.m21()); diff --git a/src/gui/painting/shaders/REUSE.toml b/src/gui/painting/shaders/REUSE.toml index ee4e083dc8f..938a9764b6b 100644 --- a/src/gui/painting/shaders/REUSE.toml +++ b/src/gui/painting/shaders/REUSE.toml @@ -3,5 +3,5 @@ version = 1 [[annotations]] path = ["*"] precedence = "closest" -SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." +SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd." SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only" diff --git a/src/gui/rhi/qrhi.cpp b/src/gui/rhi/qrhi.cpp index b9312f6b304..7a3d4974e53 100644 --- a/src/gui/rhi/qrhi.cpp +++ b/src/gui/rhi/qrhi.cpp @@ -6543,7 +6543,7 @@ bool operator!=(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBind size_t qHash(const QRhiShaderResourceBinding &b, size_t seed) noexcept { const QRhiShaderResourceBinding::Data *d = QRhiImplementation::shaderResourceBindingData(b); - QtPrivate::QHashCombine hash(seed); + QtPrivate::QHashCombineWithSeed hash(seed); seed = hash(seed, d->binding); seed = hash(seed, d->stage); seed = hash(seed, d->type); diff --git a/src/gui/rhi/qshader.cpp b/src/gui/rhi/qshader.cpp index 5e967c62e40..1234d01b6ec 100644 --- a/src/gui/rhi/qshader.cpp +++ b/src/gui/rhi/qshader.cpp @@ -812,7 +812,7 @@ bool operator==(const QShader &lhs, const QShader &rhs) noexcept size_t qHash(const QShader &s, size_t seed) noexcept { if (s.d) { - QtPrivate::QHashCombine hash(seed); + QtPrivate::QHashCombineWithSeed hash(seed); seed = hash(seed, s.stage()); if (!s.d->shaders.isEmpty()) { seed = hash(seed, s.d->shaders.firstKey()); diff --git a/src/gui/text/qfontdatabase_p.h b/src/gui/text/qfontdatabase_p.h index 4cd6996aab8..27fb34aecdd 100644 --- a/src/gui/text/qfontdatabase_p.h +++ b/src/gui/text/qfontdatabase_p.h @@ -51,7 +51,7 @@ inline bool operator!=(const QtFontFallbacksCacheKey &lhs, const QtFontFallbacks inline size_t qHash(const QtFontFallbacksCacheKey &key, size_t seed = 0) noexcept { - QtPrivate::QHashCombine hash(seed); + QtPrivate::QHashCombineWithSeed hash(seed); seed = hash(seed, key.family); seed = hash(seed, int(key.style)); seed = hash(seed, int(key.styleHint)); diff --git a/src/gui/util/qgridlayoutengine.cpp b/src/gui/util/qgridlayoutengine.cpp index e8a6b56ae20..32fee3bcdf7 100644 --- a/src/gui/util/qgridlayoutengine.cpp +++ b/src/gui/util/qgridlayoutengine.cpp @@ -471,6 +471,7 @@ void QGridLayoutRowData::dump(int indent) const qDebug("%*s Multi-cell entry <%d, %d> (stretch %d)", indent, "", it.key().first, it.key().second, it.value().q_stretch); it.value().q_box.dump(indent + 2); + ++it; } } #endif diff --git a/src/network/android/REUSE.toml b/src/network/android/REUSE.toml index e46bfebe93c..8c759f3eee7 100644 --- a/src/network/android/REUSE.toml +++ b/src/network/android/REUSE.toml @@ -4,5 +4,5 @@ version = 1 path = ["jar/build.gradle", "jar/settings.gradle"] precedence = "closest" comment = "double check" -SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." +SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd." SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only" diff --git a/src/network/socket/qnativesocketengine.cpp b/src/network/socket/qnativesocketengine.cpp index 4c8b3ebf3f8..ca5fb50f086 100644 --- a/src/network/socket/qnativesocketengine.cpp +++ b/src/network/socket/qnativesocketengine.cpp @@ -429,11 +429,14 @@ bool QNativeSocketEngine::initialize(QAbstractSocket::SocketType socketType, QAb if (socketType == QAbstractSocket::UdpSocket) { // Set the broadcasting flag if it's a UDP socket. - if (!setOption(BroadcastSocketOption, 1)) { - d->setError(QAbstractSocket::UnsupportedSocketOperationError, - QNativeSocketEnginePrivate::BroadcastingInitFailedErrorString); - close(); - return false; + // IPv6 does not support broadcast — only set option for IPv4 + if (protocol == QAbstractSocket::IPv4Protocol) { + if (!setOption(BroadcastSocketOption, 1)) { + d->setError(QAbstractSocket::UnsupportedSocketOperationError, + QNativeSocketEnginePrivate::BroadcastingInitFailedErrorString); + close(); + return false; + } } // Set some extra flags that are interesting to us, but accept failure diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index 6949eec9560..b78d2829704 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -822,6 +822,12 @@ qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const recvResult = getsockopt(socketDescriptor, SOL_SOCKET, SO_NREAD, &value, &valuelen); if (recvResult != -1) recvResult = value; +#elif defined(Q_OS_VXWORKS) + // VxWorks: use ioctl(FIONREAD) to query the number of bytes available + int available = 0; + int ioctlResult = ::ioctl(socketDescriptor, FIONREAD, &available); + if (ioctlResult != -1) + recvResult = available; #else // We need to grow the buffer to fit the entire datagram. // We start at 1500 bytes (the MTU for Ethernet V2), which should catch diff --git a/src/opengl/qopenglcompositorbackingstore.cpp b/src/opengl/qopenglcompositorbackingstore.cpp index 20c86fb8adc..95dd1a562a6 100644 --- a/src/opengl/qopenglcompositorbackingstore.cpp +++ b/src/opengl/qopenglcompositorbackingstore.cpp @@ -163,7 +163,8 @@ QPlatformBackingStore::FlushResult QOpenGLCompositorBackingStore::rhiFlush(QWind const QRegion ®ion, const QPoint &offset, QPlatformTextureList *textures, - bool translucentBackground) + bool translucentBackground, + qreal sourceTransformFactor) { // QOpenGLWidget/QQuickWidget content provided as textures. The raster content goes on top. @@ -171,6 +172,7 @@ QPlatformBackingStore::FlushResult QOpenGLCompositorBackingStore::rhiFlush(QWind Q_UNUSED(offset); Q_UNUSED(translucentBackground); Q_UNUSED(sourceDevicePixelRatio); + Q_UNUSED(sourceTransformFactor); m_rhi = rhi(window); Q_ASSERT(m_rhi); diff --git a/src/opengl/qopenglcompositorbackingstore_p.h b/src/opengl/qopenglcompositorbackingstore_p.h index 4512e2d589e..b50629000cf 100644 --- a/src/opengl/qopenglcompositorbackingstore_p.h +++ b/src/opengl/qopenglcompositorbackingstore_p.h @@ -48,7 +48,8 @@ public: const QRegion ®ion, const QPoint &offset, QPlatformTextureList *textures, - bool translucentBackground) override; + bool translucentBackground, + qreal sourceTransformFactor = 0) override; const QPlatformTextureList *textures() const { return m_textures; } diff --git a/src/plugins/REUSE.toml b/src/plugins/REUSE.toml index d017617236d..d58822731c1 100644 --- a/src/plugins/REUSE.toml +++ b/src/plugins/REUSE.toml @@ -6,19 +6,19 @@ path = ["**.json", "**.png", "**.svg", "**.xml", "platforms/ios/module.modulemap", "tracing/metadata_template.txt"] precedence = "closest" -SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." +SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd." SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only" [[annotations]] path = ["platforms/wasm/**"] precedence = "closest" -SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." +SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd." SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR GPL-3.0-only" [[annotations]] path = ["**.qmake.conf", "networkinformation/android/jar/build.gradle", "networkinformation/android/jar/settings.gradle"] precedence = "closest" -SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." +SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd." SPDX-License-Identifier = "BSD-3-Clause" diff --git a/src/plugins/imageformats/ico/qicohandler.cpp b/src/plugins/imageformats/ico/qicohandler.cpp index b5113578dd2..03677107d7d 100644 --- a/src/plugins/imageformats/ico/qicohandler.cpp +++ b/src/plugins/imageformats/ico/qicohandler.cpp @@ -518,7 +518,7 @@ QImage ICOReader::iconAt(int index) } } } - img.setText(QLatin1String(icoOrigDepthKey), QString::number(iconEntry.wBitCount)); + img.setText(QLatin1String(icoOrigDepthKey), QString::number(icoAttrib.nbits)); } } } diff --git a/src/plugins/platforminputcontexts/ibus/REUSE.toml b/src/plugins/platforminputcontexts/ibus/REUSE.toml index a16b04598f2..6423551b15d 100644 --- a/src/plugins/platforminputcontexts/ibus/REUSE.toml +++ b/src/plugins/platforminputcontexts/ibus/REUSE.toml @@ -4,5 +4,5 @@ version = 1 path = ["qibusinputcontextproxy.cpp", "qibusinputcontextproxy.h", "qibusproxy.cpp", "qibusproxy.h", "qibusproxyportal.cpp", "qibusproxyportal.h"] precedence = "override" -SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." +SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd." SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only" diff --git a/src/plugins/platforms/CMakeLists.txt b/src/plugins/platforms/CMakeLists.txt index f30c27c24be..498a0772bc9 100644 --- a/src/plugins/platforms/CMakeLists.txt +++ b/src/plugins/platforms/CMakeLists.txt @@ -4,10 +4,10 @@ if(ANDROID) add_subdirectory(android) endif() -if(NOT ANDROID AND NOT WASM) +if(NOT WASM) add_subdirectory(minimal) endif() -if(QT_FEATURE_freetype AND NOT ANDROID AND NOT WASM) +if(QT_FEATURE_freetype AND NOT WASM) add_subdirectory(offscreen) endif() if(QT_FEATURE_xcb) diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.h b/src/plugins/platforms/cocoa/qcocoabackingstore.h index 71b6015a54d..79aed15a1d0 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.h +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.h @@ -44,7 +44,8 @@ public: const QRegion ®ion, const QPoint &offset, QPlatformTextureList *textures, - bool translucentBackground) override; + bool translucentBackground, + qreal sourceTransformFactor) override; QImage toImage() const override; QPlatformGraphicsBuffer *graphicsBuffer() const override; diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm index 78d23b01dea..186aeaac44d 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm @@ -457,7 +457,8 @@ QPlatformBackingStore::FlushResult QCALayerBackingStore::rhiFlush(QWindow *windo const QRegion ®ion, const QPoint &offset, QPlatformTextureList *textures, - bool translucentBackground) + bool translucentBackground, + qreal sourceTransformFactor) { if (!m_buffers.back()) { qCWarning(lcQpaBackingStore) << "Flush requested with no back buffer. Ignoring."; @@ -466,7 +467,8 @@ QPlatformBackingStore::FlushResult QCALayerBackingStore::rhiFlush(QWindow *windo finalizeBackBuffer(); - return QPlatformBackingStore::rhiFlush(window, sourceDevicePixelRatio, region, offset, textures, translucentBackground); + return QPlatformBackingStore::rhiFlush(window, sourceDevicePixelRatio, + region, offset, textures, translucentBackground, sourceTransformFactor); } QImage QCALayerBackingStore::toImage() const diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.h b/src/plugins/platforms/cocoa/qcocoaglcontext.h index 36546879ae4..13139dd399d 100644 --- a/src/plugins/platforms/cocoa/qcocoaglcontext.h +++ b/src/plugins/platforms/cocoa/qcocoaglcontext.h @@ -43,6 +43,8 @@ public: QFunctionPointer getProcAddress(const char *procName) override; + bool isSoftwareContext() const; + private: static NSOpenGLPixelFormat *pixelFormatForSurfaceFormat(const QSurfaceFormat &format); @@ -54,6 +56,7 @@ private: QSurfaceFormat m_format; QVarLengthArray<QMacNotificationObserver, 3> m_updateObservers; QAtomicInt m_needsUpdate = false; + bool m_isSoftwareContext = false; #ifndef QT_NO_DEBUG_STREAM friend QDebug operator<<(QDebug debug, const QCocoaGLContext *screen); diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm index bfac716b633..2f0f513dfc1 100644 --- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm +++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm @@ -289,6 +289,9 @@ void QCocoaGLContext::updateSurfaceFormat() else m_format.setSwapBehavior(QSurfaceFormat::SingleBuffer); + m_isSoftwareContext = (pixelFormatAttribute(NSOpenGLPFARendererID) + & kCGLRendererIDMatchingMask) == kCGLRendererGenericFloatID; + // ------------------- Query the context ------------------- auto glContextParameter = [&](NSOpenGLContextParameter parameter) { @@ -512,6 +515,11 @@ bool QCocoaGLContext::isSharing() const return m_shareContext != nil; } +bool QCocoaGLContext::isSoftwareContext() const +{ + return m_isSoftwareContext; +} + NSOpenGLContext *QCocoaGLContext::nativeContext() const { return m_context; diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 8c6dcfd4f60..4c5975af34a 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -232,6 +232,24 @@ bool QCocoaIntegration::hasCapability(QPlatformIntegration::Capability cap) cons // layer-backed. return false; case OpenGL: + if (QOperatingSystemVersion::current() > QOperatingSystemVersion::MacOSSonoma) { + // Tahoe has issues with software-backed GL, crashing in common operations + static bool isSoftwareContext = []{ + QOpenGLContext context; + context.create(); + auto *cocoaContext = static_cast<QCocoaGLContext*>(context.handle()); + if (cocoaContext->isSoftwareContext()) { + qWarning() << "Detected software OpenGL backend," + << "which is known to be broken on" + << qUtf8Printable(QSysInfo::prettyProductName()); + return true; + } else { + return false; + } + }(); + return !isSoftwareContext; + } + Q_FALLTHROUGH(); case BufferQueueingOpenGL: #endif case ThreadedPixmaps: diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp index 9f19e649f85..59265daa127 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp @@ -10,6 +10,7 @@ #include <private/qeglfskmsintegration_p.h> #include <QtCore/QLoggingCategory> +#include <QtCore/qtimer.h> #include <QtCore/private/qcore_unix_p.h> #define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) diff --git a/src/plugins/platforms/ios/qiosapplicationdelegate.mm b/src/plugins/platforms/ios/qiosapplicationdelegate.mm index 088d48fc9ff..990409f2d17 100644 --- a/src/plugins/platforms/ios/qiosapplicationdelegate.mm +++ b/src/plugins/platforms/ios/qiosapplicationdelegate.mm @@ -16,19 +16,28 @@ #include <QtCore/QtCore> @interface QIOSWindowSceneDelegate : NSObject<UIWindowSceneDelegate> +@property (nullable, nonatomic, strong) UIWindow *window; @end @implementation QIOSApplicationDelegate - (UISceneConfiguration *)application:(UIApplication *)application - configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession + configurationForConnectingSceneSession:(UISceneSession *)session options:(UISceneConnectionOptions *)options { - qCDebug(lcQpaWindowScene) << "Configuring scene for" << connectingSceneSession - << "with options" << options; + qCDebug(lcQpaWindowScene) << "Configuring scene for" << session << "with options" << options; + + auto *sceneConfig = session.configuration; + + if ([sceneConfig.role hasPrefix:@"CPTemplateApplication"]) { + qCDebug(lcQpaWindowScene) << "Not touching CarPlay scene with role" << sceneConfig.role + << "and existing delegate class" << sceneConfig.delegateClass; + // FIXME: Consider ignoring any scene with an existing sceneClass, delegateClass, or + // storyboard. But for visionOS the default delegate is SwiftUI.AppSceneDelegate. + } else { + sceneConfig.delegateClass = QIOSWindowSceneDelegate.class; + } - auto *sceneConfig = connectingSceneSession.configuration; - sceneConfig.delegateClass = QIOSWindowSceneDelegate.class; return sceneConfig; } @@ -40,27 +49,53 @@ { qCDebug(lcQpaWindowScene) << "Connecting" << scene << "to" << session; - Q_ASSERT([scene isKindOfClass:UIWindowScene.class]); + // Handle URL contexts, even if we return early + const auto handleUrlContexts = qScopeGuard([&]{ + if (connectionOptions.URLContexts.count > 0) + [self scene:scene openURLContexts:connectionOptions.URLContexts]; + }); + +#if defined(Q_OS_VISIONOS) + // CPImmersiveScene is a UIWindowScene, most likely so it can handle its internal + // CPSceneLayerEventWindow and UITextEffectsWindow, but we don't want a QUIWindow + // for these scenes, so bail out early. + if ([scene.session.role isEqualToString:@"CPSceneSessionRoleImmersiveSpaceApplication"]) { + qCDebug(lcQpaWindowScene) << "Skipping UIWindow creation for immersive scene"; + return; + } +#endif + + if (![scene isKindOfClass:UIWindowScene.class]) { + qCWarning(lcQpaWindowScene) << "Unexpectedly encountered non-window scene"; + return; + } + UIWindowScene *windowScene = static_cast<UIWindowScene*>(scene); QUIWindow *window = [[QUIWindow alloc] initWithWindowScene:windowScene]; + window.rootViewController = [[[QIOSViewController alloc] initWithWindow:window] autorelease]; - QIOSScreen *screen = [&]{ - for (auto *screen : qGuiApp->screens()) { - auto *platformScreen = static_cast<QIOSScreen*>(screen->handle()); -#if !defined(Q_OS_VISIONOS) - if (platformScreen->uiScreen() == windowScene.screen) -#endif - return platformScreen; - } - Q_UNREACHABLE(); - }(); + self.window = [window autorelease]; +} - window.rootViewController = [[[QIOSViewController alloc] - initWithWindow:window andScreen:screen] autorelease]; +- (void)windowScene:(UIWindowScene *)windowScene + didUpdateCoordinateSpace:(id<UICoordinateSpace>)previousCoordinateSpace + interfaceOrientation:(UIInterfaceOrientation)previousInterfaceOrientation + traitCollection:(UITraitCollection *)previousTraitCollection +{ + qCDebug(lcQpaWindowScene) << "Scene" << windowScene << "did update properties"; + if (!self.window) + return; - if (connectionOptions.URLContexts.count > 0) - [self scene:scene openURLContexts:connectionOptions.URLContexts]; + Q_ASSERT([self.window isKindOfClass:QUIWindow.class]); + auto *viewController = static_cast<QIOSViewController*>(self.window.rootViewController); + [viewController updatePlatformScreen]; +} + +- (void)sceneDidDisconnect:(UIScene *)scene +{ + qCDebug(lcQpaWindowScene) << "Disconnecting" << scene; + self.window = nil; } - (void)scene:(UIScene *)scene openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts diff --git a/src/plugins/platforms/ios/qiosglobal.mm b/src/plugins/platforms/ios/qiosglobal.mm index 9ab490b2970..89a343061ee 100644 --- a/src/plugins/platforms/ios/qiosglobal.mm +++ b/src/plugins/platforms/ios/qiosglobal.mm @@ -13,7 +13,7 @@ QT_BEGIN_NAMESPACE Q_LOGGING_CATEGORY(lcQpaApplication, "qt.qpa.application"); -Q_LOGGING_CATEGORY(lcQpaInputMethods, "qt.qpa.input.methods"); +Q_LOGGING_CATEGORY(lcQpaInputMethods, "qt.qpa.input.methods", QtCriticalMsg); Q_LOGGING_CATEGORY(lcQpaWindow, "qt.qpa.window"); Q_LOGGING_CATEGORY(lcQpaWindowScene, "qt.qpa.window.scene"); diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm index 5716ad041e0..8544c497d43 100644 --- a/src/plugins/platforms/ios/qiosinputcontext.mm +++ b/src/plugins/platforms/ios/qiosinputcontext.mm @@ -371,7 +371,8 @@ void QIOSInputContext::updateKeyboardState(NSNotification *notification) // with input-accessory-views. The reason for using frameEnd here (the future state), // instead of the current state reflected in frameBegin, is that QInputMethod::isVisible() // is documented to reflect the future state in the case of animated transitions. - m_keyboardState.keyboardVisible = CGRectIntersectsRect(frameEnd, [UIScreen mainScreen].bounds); + m_keyboardState.keyboardVisible = !CGRectIsEmpty(UIScreen.mainScreen.bounds) && + !CGRectIsEmpty(frameEnd) && CGRectIntersectsRect(frameEnd, UIScreen.mainScreen.bounds); // Used for auto-scroller, and will be used for animation-signal in the future m_keyboardState.keyboardEndRect = frameEnd; @@ -639,8 +640,10 @@ void QIOSInputContext::update(Qt::InputMethodQueries updatedProperties) // focus object. We try to detect code paths that fail this assertion and smooth // over the situation by doing a manual update of the focus object. if (qApp->focusObject() != m_imeState.focusObject && updatedProperties != Qt::ImQueryAll) { - qWarning() << "stale focus object" << static_cast<void *>(m_imeState.focusObject) - << ", doing manual update"; + qCWarning(lcQpaInputMethods).verbosity(0) << "Updating input context" << updatedProperties + << "with last reported focus object" << m_imeState.focusObject + << "but qGuiApp reports" << qApp->focusObject() + << "which means someone failed to call QPlatformInputContext::setFocusObject()"; setFocusObject(qApp->focusObject()); return; } diff --git a/src/plugins/platforms/ios/qiosviewcontroller.h b/src/plugins/platforms/ios/qiosviewcontroller.h index 1f8da41ba4f..b5ce88d6a33 100644 --- a/src/plugins/platforms/ios/qiosviewcontroller.h +++ b/src/plugins/platforms/ios/qiosviewcontroller.h @@ -12,10 +12,12 @@ QT_END_NAMESPACE @interface QIOSViewController : UIViewController -- (instancetype)initWithWindow:(UIWindow*)window andScreen:(QT_PREPEND_NAMESPACE(QIOSScreen) *)screen; -- (void)updateProperties; +- (instancetype)initWithWindow:(UIWindow*)window; +- (void)updateStatusBarProperties; - (NSArray*)keyCommands; - (void)handleShortcut:(UIKeyCommand*)keyCommand; +- (void)updatePlatformScreen; + #ifndef Q_OS_TVOS // UIViewController diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm index 36ce785e031..169f8ae1754 100644 --- a/src/plugins/platforms/ios/qiosviewcontroller.mm +++ b/src/plugins/platforms/ios/qiosviewcontroller.mm @@ -231,11 +231,12 @@ @synthesize preferredStatusBarStyle; #endif -- (instancetype)initWithWindow:(UIWindow*)window andScreen:(QT_PREPEND_NAMESPACE(QIOSScreen) *)screen +- (instancetype)initWithWindow:(UIWindow*)window { if (self = [self init]) { self.window = window; - self.platformScreen = screen; + self.platformScreen = nil; + [self updatePlatformScreen]; self.changingOrientation = NO; #ifndef Q_OS_TVOS @@ -246,7 +247,7 @@ #endif m_focusWindowChangeConnection = QObject::connect(qApp, &QGuiApplication::focusWindowChanged, [self]() { - [self updateProperties]; + [self updateStatusBarProperties]; }); QIOSApplicationState *applicationState = &QIOSIntegration::instance()->applicationState; @@ -314,6 +315,54 @@ // ------------------------------------------------------------------------- +- (void)updatePlatformScreen +{ + auto *windowScene = self.window.windowScene; + + QIOSScreen *newPlatformScreen = [&]{ + for (auto *screen : qGuiApp->screens()) { + auto *platformScreen = static_cast<QIOSScreen*>(screen->handle()); +#if !defined(Q_OS_VISIONOS) + if (platformScreen->uiScreen() == windowScene.screen) +#endif + return platformScreen; + } + Q_UNREACHABLE(); + }(); + + if (newPlatformScreen != self.platformScreen) { + QIOSScreen *oldPlatformScreen = self.platformScreen; + self.platformScreen = newPlatformScreen; + + qCDebug(lcQpaWindow) << "View controller" << self << "moved from" + << oldPlatformScreen << "to" << newPlatformScreen; + + QScreen *newScreen = newPlatformScreen ? newPlatformScreen->screen() : nullptr; + + const bool isPrimaryScene = !qt_apple_sharedApplication().supportsMultipleScenes + && windowScene.session.role == UIWindowSceneSessionRoleApplication; + + if (isPrimaryScene) { + // When we only have a single application-role scene we treat the + // active screen as the primary one, so that windows shown on the + // primary screen end up in our view controller. + QWindowSystemInterface::handlePrimaryScreenChanged(newPlatformScreen); + } + + for (auto *window : qGuiApp->topLevelWindows()) { + // Move window to new screen if it was on the old screen, + // or if we're setting up the primary scene, in which case + // we want to adopt all existing windows to this screen. + if ((window->screen()->handle() == oldPlatformScreen) + || (isPrimaryScene && !oldPlatformScreen)) { + QWindowSystemInterface::handleWindowScreenChanged(window, newScreen); + } + } + } +} + +// ------------------------------------------------------------------------- + - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)orientation duration:(NSTimeInterval)duration { self.changingOrientation = YES; @@ -390,7 +439,7 @@ // ------------------------------------------------------------------------- -- (void)updateProperties +- (void)updateStatusBarProperties { if (!isQtApplication()) return; diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm index 3e2b6b0102a..af1fbb0abaf 100644 --- a/src/plugins/platforms/ios/qioswindow.mm +++ b/src/plugins/platforms/ios/qioswindow.mm @@ -243,7 +243,7 @@ void QIOSWindow::setWindowState(Qt::WindowStates state) qt_window_private(window())->windowState = state; if (window()->isTopLevel() && window()->isVisible() && window()->isActive()) - [m_view.qtViewController updateProperties]; + [m_view.qtViewController updateStatusBarProperties]; if (state & Qt::WindowMinimized) { applyGeometry(QRect()); diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm index 9b17eef07b0..86b6ce07518 100644 --- a/src/plugins/platforms/ios/quiview.mm +++ b/src/plugins/platforms/ios/quiview.mm @@ -786,6 +786,9 @@ inline ulong getTimeStamp(UIEvent *event) #if QT_CONFIG(tabletevent) - (void)handleHover:(UIHoverGestureRecognizer *)recognizer { + if (!self.platformWindow) + return; + ulong timeStamp = [[NSProcessInfo processInfo] systemUptime] * 1000; CGFloat zOffset = 0; diff --git a/src/plugins/platforms/wayland/qwaylandcursor.cpp b/src/plugins/platforms/wayland/qwaylandcursor.cpp index 4967f9d46f4..a9cff626224 100644 --- a/src/plugins/platforms/wayland/qwaylandcursor.cpp +++ b/src/plugins/platforms/wayland/qwaylandcursor.cpp @@ -331,7 +331,7 @@ void QWaylandCursor::changeCursor(QCursor *cursor, QWindow *window) device->setCursor(cursor, bitmapBuffer, qCeil(waylandWindow->devicePixelRatio())); } - mDisplay->flushRequests(); + wl_display_flush(mDisplay->wl_display()); } } diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 38b3bdadd35..a407cde2a7c 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -1156,9 +1156,13 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, case QtWindows::MoveEvent: platformWindow->handleMoved(); return true; - case QtWindows::ResizeEvent: + case QtWindows::ResizeEvent: { + QWindow *window = platformWindow->window(); platformWindow->handleResized(static_cast<int>(wParam), lParam); + if (window->flags().testFlags(Qt::ExpandedClientAreaHint)) + platformWindow->updateCustomTitlebar(); return true; + } case QtWindows::QuerySizeHints: platformWindow->getSizeHints(reinterpret_cast<MINMAXINFO *>(lParam)); return true;// maybe available on some SDKs revisit WM_NCCALCSIZE @@ -1174,8 +1178,12 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, return platformWindow->handleNonClientActivate(result); case QtWindows::GeometryChangingEvent: return platformWindow->handleGeometryChanging(&msg); - case QtWindows::ExposeEvent: + case QtWindows::ExposeEvent: { + QWindow *window = platformWindow->window(); + if (window->flags().testFlags(Qt::ExpandedClientAreaHint)) + platformWindow->updateCustomTitlebar(); return platformWindow->handleWmPaint(hwnd, message, wParam, lParam, result); + } case QtWindows::NonClientMouseEvent: if (!platformWindow->frameStrutEventsEnabled()) break; @@ -1219,6 +1227,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, case QtWindows::FocusInEvent: // see QWindowsWindow::requestActivateWindow(). if (platformWindow->window()->flags() & Qt::WindowDoesNotAcceptFocus) return false; + [[fallthrough]]; case QtWindows::FocusOutEvent: handleFocusEvent(et, platformWindow); return true; diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index 25c15861ba1..0f66193f47d 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -262,6 +262,11 @@ bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) co return true; #ifndef QT_NO_OPENGL case OpenGL: +#if !QT_CONFIG(run_opengl_tests) + // Workaround for build configs on WoA that don't have OpenGL installed + // FIXME: Detect at runtime + return false; +#endif return true; case ThreadedOpenGL: if (const QWindowsStaticOpenGLContext *glContext = QWindowsIntegration::staticOpenGLContext()) diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 81a3f1d37b7..731673b61db 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -284,40 +284,6 @@ static inline RECT RECTfromQRect(const QRect &rect) return result; } -static LRESULT WINAPI WndProcTitleBar(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - HWND parentHwnd = reinterpret_cast<HWND>(GetWindowLongPtr(hwnd, GWL_HWNDPARENT)); - QWindowsWindow* platformWindow = QWindowsContext::instance()->findPlatformWindow(parentHwnd); - - switch (message) { - case WM_SHOWWINDOW: - ShowWindow(hwnd,SW_HIDE); - if ((BOOL)wParam == TRUE) - platformWindow->transitionAnimatedCustomTitleBar(); - return 0; - case WM_SIZE: { - if (platformWindow) - platformWindow->updateCustomTitlebar(); - break; - } - case WM_NCHITTEST: - return HTTRANSPARENT; - case WM_TIMER: - ShowWindow(hwnd, SW_SHOWNOACTIVATE); - platformWindow->updateCustomTitlebar(); - break; - case WM_PAINT: - { - PAINTSTRUCT ps; - BeginPaint(hwnd, &ps); - EndPaint(hwnd, &ps); - return 0; - } - } - return DefWindowProc(hwnd, message, wParam, lParam); -} - - #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug d, const RECT &r) { @@ -917,7 +883,7 @@ QWindowsWindowData const auto appinst = reinterpret_cast<HINSTANCE>(GetModuleHandle(nullptr)); const QString windowClassName = QWindowsContext::instance()->registerWindowClass(w); - const QString windowTitlebarName = QWindowsContext::instance()->registerWindowClass(QStringLiteral("_q_titlebar"), WndProcTitleBar, CS_VREDRAW|CS_HREDRAW, nullptr, false); + const QString windowTitlebarName = QWindowsContext::instance()->registerWindowClass(QStringLiteral("_q_titlebar"), DefWindowProc, CS_VREDRAW|CS_HREDRAW, nullptr, false); const QScreen *screen{}; const QRect rect = QPlatformWindow::initialGeometry(w, data.geometry, @@ -970,15 +936,13 @@ QWindowsWindowData context->frameWidth, context->frameHeight, parentHandle, nullptr, appinst, nullptr); - if (w->flags().testFlags(Qt::ExpandedClientAreaHint)) { - const UINT dpi = ::GetDpiForWindow(result.hwnd); - const int titleBarHeight = getTitleBarHeight_sys(dpi); - result.hwndTitlebar = CreateWindowEx(WS_EX_LAYERED | WS_EX_TRANSPARENT, - classTitleBarNameUtf16, classTitleBarNameUtf16, - WS_POPUP, 0, 0, - context->frameWidth, titleBarHeight, - result.hwnd, nullptr, appinst, nullptr); - } + const UINT dpi = ::GetDpiForWindow(result.hwnd); + const int titleBarHeight = getTitleBarHeight_sys(dpi); + result.hwndTitlebar = CreateWindowEx(WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_NOACTIVATE, + classTitleBarNameUtf16, classTitleBarNameUtf16, + 0, 0, 0, + context->frameWidth, titleBarHeight, + nullptr, nullptr, appinst, nullptr); qCDebug(lcQpaWindow).nospace() << "CreateWindowEx: returns " << w << ' ' << result.hwnd << " obtained geometry: " @@ -1056,6 +1020,9 @@ void WindowCreationData::initialize(const QWindow *w, HWND hwnd, bool frameChang if (flags & Qt::ExpandedClientAreaHint) { // Gives us the rounded corners looks and the frame shadow MARGINS margins = { -1, -1, -1, -1 }; DwmExtendFrameIntoClientArea(hwnd, &margins); + } else { + MARGINS margins = { 0, 0, 0, 0 }; + DwmExtendFrameIntoClientArea(hwnd, &margins); } } else { // child. SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, swpFlags); @@ -1191,19 +1158,26 @@ QMargins QWindowsGeometryHint::frame(const QWindow *w, const QRect &geometry, bool QWindowsGeometryHint::handleCalculateSize(const QWindow *window, const QMargins &customMargins, const MSG &msg, LRESULT *result) { + // Prevent adding any border for frameless window + if (msg.wParam && window->flags() & Qt::FramelessWindowHint) { + *result = 0; + return true; + } + const QWindowsWindow *platformWindow = QWindowsWindow::windowsWindowOf(window); + // In case the platformwindow was not yet created, use the initial windowflags provided by the user. + const bool clientAreaExpanded = platformWindow != nullptr ? platformWindow->isClientAreaExpanded() : window->flags() & Qt::ExpandedClientAreaHint; // Return 0 to remove the window's border - const bool clientAreaExpanded = window->flags() & Qt::ExpandedClientAreaHint; if (msg.wParam && clientAreaExpanded) { // Prevent content from being cutoff by border for maximized, but not fullscreened windows. - if (IsZoomed(msg.hwnd) && window->visibility() != QWindow::FullScreen) { - auto *ncp = reinterpret_cast<NCCALCSIZE_PARAMS *>(msg.lParam); - RECT *clientArea = &ncp->rgrc[0]; - const int border = getResizeBorderThickness(QWindowsWindow::windowsWindowOf(window)->savedDpi()); + const bool maximized = IsZoomed(msg.hwnd) && window->visibility() != QWindow::FullScreen; + auto *ncp = reinterpret_cast<NCCALCSIZE_PARAMS *>(msg.lParam); + RECT *clientArea = &ncp->rgrc[0]; + const int border = getResizeBorderThickness(96); + if (maximized) clientArea->top += border; - clientArea->bottom -= border; - clientArea->left += border; - clientArea->right -= border; - } + clientArea->bottom -= border; + clientArea->left += border; + clientArea->right -= border; *result = 0; return true; } @@ -1623,6 +1597,12 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data) #endif { QWindowsContext::instance()->addWindow(m_data.hwnd, this); + + if (aWindow->flags().testFlags(Qt::ExpandedClientAreaHint)) { + SetParent(m_data.hwndTitlebar, m_data.hwnd); + ShowWindow(m_data.hwndTitlebar, SW_SHOW); + } + const Qt::WindowType type = aWindow->type(); if (type == Qt::Desktop) return; // No further handling for Qt::Desktop @@ -1847,21 +1827,6 @@ QWindow *QWindowsWindow::topLevelOf(QWindow *w) return w; } -// Checks whether the Window is tiled with Aero snap -bool QWindowsWindow::isWindowArranged(HWND hwnd) -{ - typedef BOOL(WINAPI* PIsWindowArranged)(HWND); - static PIsWindowArranged pIsWindowArranged = nullptr; - static bool resolved = false; - if (!resolved) { - resolved = true; - pIsWindowArranged = (PIsWindowArranged)QSystemLibrary::resolve(QLatin1String("user32.dll"), "IsWindowArranged"); - } - if (pIsWindowArranged == nullptr) - return false; - return pIsWindowArranged(hwnd); -} - QWindowsWindowData QWindowsWindowData::create(const QWindow *w, const QWindowsWindowData ¶meters, @@ -1903,13 +1868,6 @@ void QWindowsWindow::setVisible(bool visible) fireExpose(QRegion()); } } - if (m_data.hwndTitlebar) { - if (visible) { - SetWindowPos(m_data.hwndTitlebar, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); - } else { - ShowWindow(m_data.hwndTitlebar, SW_HIDE); - } - } } bool QWindowsWindow::isVisible() const @@ -2050,10 +2008,6 @@ void QWindowsWindow::show_sys() const setFlag(WithinMaximize); // QTBUG-8361 ShowWindow(m_data.hwnd, sm); - if (m_data.flags.testFlag(Qt::ExpandedClientAreaHint)) { - ShowWindow(m_data.hwndTitlebar, sm); - SetActiveWindow(m_data.hwnd); - } clearFlag(WithinMaximize); @@ -2245,7 +2199,7 @@ QRect QWindowsWindow::normalGeometry() const QMargins QWindowsWindow::safeAreaMargins() const { if (m_data.flags.testFlags(Qt::ExpandedClientAreaHint)) { - const int titleBarHeight = getTitleBarHeight_sys(savedDpi()); + const int titleBarHeight = getTitleBarHeight_sys(96); return QMargins(0, titleBarHeight, 0, 0); } @@ -2457,15 +2411,9 @@ void QWindowsWindow::handleGeometryChange() clearFlag(SynchronousGeometryChangeEvent); qCDebug(lcQpaEvents) << __FUNCTION__ << this << window() << m_data.geometry; - if (m_data.hwndTitlebar) { - bool arranged = QWindowsWindow::isWindowArranged(m_data.hwnd); - if (arranged || (m_windowWasArranged && !arranged)) - transitionAnimatedCustomTitleBar(); - + if (m_data.flags & Qt::ExpandedClientAreaHint) { const int titleBarHeight = getTitleBarHeight_sys(savedDpi()); - MoveWindow(m_data.hwndTitlebar, m_data.geometry.x(), m_data.geometry.y(), - m_data.geometry.width(), titleBarHeight, true); - m_windowWasArranged = arranged; + MoveWindow(m_data.hwndTitlebar, 0, 0, m_data.geometry.width(), titleBarHeight, true); } } @@ -2627,6 +2575,16 @@ QWindowsWindowData QWindowsWindow::setWindowFlags_sys(Qt::WindowFlags wt, creationData.applyWindowFlags(m_data.hwnd); creationData.initialize(window(), m_data.hwnd, true, m_opacity); + if (creationData.flags.testFlag(Qt::ExpandedClientAreaHint)) { + SetParent(m_data.hwndTitlebar, m_data.hwnd); + ShowWindow(m_data.hwndTitlebar, SW_SHOW); + } else { + if (IsWindowVisible(m_data.hwndTitlebar)) { + SetParent(m_data.hwndTitlebar, HWND_MESSAGE); + ShowWindow(m_data.hwndTitlebar, SW_HIDE); + } + } + QWindowsWindowData result = m_data; result.flags = creationData.flags; result.embedded = creationData.embedded; @@ -2645,7 +2603,7 @@ void QWindowsWindow::handleWindowStateChange(Qt::WindowStates state) handleHidden(); QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents); // Tell QQuickWindow to stop rendering now. } else { - transitionAnimatedCustomTitleBar(); + updateCustomTitlebar(); if (state & Qt::WindowMaximized) { WINDOWPLACEMENT windowPlacement{}; windowPlacement.length = sizeof(WINDOWPLACEMENT); @@ -2743,20 +2701,6 @@ void QWindowsWindow::correctWindowPlacement(WINDOWPLACEMENT &windowPlacement) } } -void QWindowsWindow::transitionAnimatedCustomTitleBar() -{ - if (!m_data.hwndTitlebar) - return; - const QWinRegistryKey registry(HKEY_CURRENT_USER, LR"(Control Panel\Desktop\WindowMetrics)"); - if (registry.isValid() && registry.value(LR"(MinAnimate)") == 1) { - ShowWindow(m_data.hwndTitlebar, SW_HIDE); - SetTimer(m_data.hwndTitlebar, 1, 200, nullptr); - } else { - ShowWindow(m_data.hwndTitlebar, SW_SHOWNOACTIVATE); - updateCustomTitlebar(); - } -} - void QWindowsWindow::updateRestoreGeometry() { m_data.restoreGeometry = normalFrameGeometry(m_data.hwnd); @@ -3078,7 +3022,8 @@ void QWindowsWindow::calculateFullFrameMargins() const auto systemMargins = testFlag(DisableNonClientScaling) ? QWindowsGeometryHint::frameOnPrimaryScreen(window(), m_data.hwnd) : frameMargins_sys(); - const QMargins actualMargins = systemMargins + customMargins(); + const int extendedClientAreaBorder = window()->flags().testFlag(Qt::ExpandedClientAreaHint) ? qRound(QHighDpiScaling::factor(window())) * 2 : 0; + const QMargins actualMargins = systemMargins + customMargins() - extendedClientAreaBorder; const int yDiff = (windowRect.bottom - windowRect.top) - (clientRect.bottom - clientRect.top); const bool typicalFrame = (actualMargins.left() == actualMargins.right()) @@ -3517,19 +3462,6 @@ bool QWindowsWindow::handleNonClientActivate(LRESULT *result) const return false; } -static void _q_drawCustomTitleBarButton(QPainter& p, const QRectF& r) -{ - QPainterPath path(QPointF(r.x(), r.y())); - QRectF rightCorner(r.x() + r.width() - 2.0, r.y() + 4.0, 2, 2); - QRectF leftCorner(r.x(), r.y() + 4, 2, 2); - path.lineTo(r.x() + r.width() - 5.0f, r.y()); - path.arcTo(rightCorner, 90, -90); - path.lineTo(r.x() + r.width(), r.y() + r.height() - 1); - path.lineTo(r.x(), r.y() + r.height() - 1); - path.closeSubpath(); - p.drawPath(path); -} - void QWindowsWindow::updateCustomTitlebar() { HWND hwnd = m_data.hwndTitlebar; @@ -3545,7 +3477,7 @@ void QWindowsWindow::updateCustomTitlebar() POINT localPos; GetCursorPos(&localPos); - MapWindowPoints(HWND_DESKTOP, hwnd, &localPos, 1); + MapWindowPoints(HWND_DESKTOP, m_data.hwnd, &localPos, 1); const bool isDarkmode = QWindowsIntegration::instance()->darkModeHandling().testFlags(QWindowsApplication::DarkModeWindowFrames) && qApp->styleHints()->colorScheme() == Qt::ColorScheme::Dark; @@ -3567,25 +3499,9 @@ void QWindowsWindow::updateCustomTitlebar() p.setPen(Qt::NoPen); if (!wnd->flags().testFlags(Qt::NoTitleBarBackgroundHint)) { QRect titleRect; - titleRect.setX(2); titleRect.setWidth(windowWidth); titleRect.setHeight(titleBarHeight); - - if (isWindows11orAbove) { - QPainterPath path(QPointF(titleRect.x() + 4.0f, titleRect.y())); - QRectF rightCorner(titleRect.x() + titleRect.width() - 4.0, titleRect.y() + 4.0, 2, 2); - QRectF leftCorner(titleRect.x(), titleRect.y() + 4, 2, 2); - path.lineTo(titleRect.x() + titleRect.width() - 7.0f, titleRect.y()); - path.arcTo(rightCorner, 90, -90); - path.lineTo(titleRect.x() + titleRect.width() - 2.0, titleRect.y() + titleRect.height() - 1); - path.lineTo(titleRect.x(), titleRect.y() + titleRect.height() - 1); - path.lineTo(titleRect.x(), titleRect.y() + 4.0f); - path.arcTo(leftCorner, -90, -90); - path.closeSubpath(); - p.drawPath(path); - } else { - p.drawRect(titleRect); - } + p.drawRect(titleRect); } if (wnd->flags().testFlags(Qt::WindowTitleHint | Qt::CustomizeWindowHint) || !wnd->flags().testFlag(Qt::CustomizeWindowHint)) { @@ -3631,15 +3547,12 @@ void QWindowsWindow::updateCustomTitlebar() QRectF rect; rect.setY(1); rect.setX(windowWidth - titleButtonWidth * buttons); - rect.setWidth(titleButtonWidth - 1); + rect.setWidth(titleButtonWidth); rect.setHeight(titleBarHeight); if (localPos.x > (windowWidth - buttons * titleButtonWidth) && localPos.x < (windowWidth - (buttons - 1) * titleButtonWidth) && localPos.y > rect.y() && localPos.y < rect.y() + rect.height()) { - if (isWindows11orAbove && buttons == 1) - _q_drawCustomTitleBarButton(p, rect); - else - p.drawRect(rect); + p.drawRect(rect); const QPen closeButtonHoveredPen = QPen(QColor(0xFF, 0xFF, 0xFD, 0xFF)); p.setPen(closeButtonHoveredPen); } else { @@ -3655,15 +3568,12 @@ void QWindowsWindow::updateCustomTitlebar() QRectF rect; rect.setY(1); rect.setX(windowWidth - titleButtonWidth * buttons); - rect.setWidth(titleButtonWidth - 1); + rect.setWidth(titleButtonWidth); rect.setHeight(titleBarHeight); if (localPos.x > (windowWidth - buttons * titleButtonWidth) && localPos.x < (windowWidth - (buttons - 1) * titleButtonWidth) && localPos.y > rect.y() && localPos.y < rect.y() + rect.height()) { - if (isWindows11orAbove && buttons == 1) - _q_drawCustomTitleBarButton(p, rect); - else - p.drawRect(rect); + p.drawRect(rect); } p.setPen(textPen); p.drawText(rect,QStringLiteral("\uE922"), QTextOption(Qt::AlignVCenter | Qt::AlignHCenter)); @@ -3676,15 +3586,12 @@ void QWindowsWindow::updateCustomTitlebar() QRectF rect; rect.setY(1); rect.setX(windowWidth - titleButtonWidth * buttons); - rect.setWidth(titleButtonWidth - 1); + rect.setWidth(titleButtonWidth); rect.setHeight(titleBarHeight); if (localPos.x > (windowWidth - buttons * titleButtonWidth) && localPos.x < (windowWidth - (buttons - 1) * titleButtonWidth) && localPos.y > rect.y() && localPos.y < rect.y() + rect.height()) { - if (isWindows11orAbove && buttons == 1) - _q_drawCustomTitleBarButton(p, rect); - else - p.drawRect(rect); + p.drawRect(rect); } p.setPen(textPen); p.drawText(rect,QStringLiteral("\uE921"), QTextOption(Qt::AlignVCenter | Qt::AlignHCenter)); @@ -3702,7 +3609,7 @@ void QWindowsWindow::updateCustomTitlebar() BLENDFUNCTION blend = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA}; - POINT ptLocation = { windowRect.left, windowRect.top }; + POINT ptLocation = { 0, 0 }; SIZE szWnd = { windowWidth, titleBarHeight }; POINT ptSrc = { 0, 0 }; UpdateLayeredWindow(hwnd, hdc, &ptLocation, &szWnd, memdc, &ptSrc, 0, &blend, ULW_ALPHA); diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index b67bd2850b3..a0e150aeb01 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -307,7 +307,6 @@ public: static QWindow *topLevelOf(QWindow *w); static inline void *userDataOf(HWND hwnd); static inline void setUserDataOf(HWND hwnd, void *ud); - static bool isWindowArranged(HWND hwnd); static bool hasNoNativeFrame(HWND hwnd, Qt::WindowFlags flags); static bool setWindowLayered(HWND hwnd, Qt::WindowFlags flags, bool hasAlpha, qreal opacity); @@ -359,12 +358,10 @@ public: int savedDpi() const { return m_savedDpi; } qreal dpiRelativeScale(const UINT dpi) const; - bool isFrameless() const { return m_data.flags.testFlag(Qt::FramelessWindowHint); } + bool isClientAreaExpanded() const { return m_data.flags.testFlag(Qt::ExpandedClientAreaHint); } void requestUpdate() override; - void transitionAnimatedCustomTitleBar(); - private: inline void show_sys() const; inline QWindowsWindowData setWindowFlags_sys(Qt::WindowFlags wt, unsigned flags = 0) const; diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp index 8353fac6a92..fda47944d9d 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp +++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp @@ -870,7 +870,8 @@ QPlatformBackingStore::FlushResult QXcbBackingStore::rhiFlush(QWindow *window, const QRegion ®ion, const QPoint &offset, QPlatformTextureList *textures, - bool translucentBackground) + bool translucentBackground, + qreal sourceTransformFactor) { if (!m_image || m_image->size().isEmpty()) return FlushFailed; @@ -878,7 +879,7 @@ QPlatformBackingStore::FlushResult QXcbBackingStore::rhiFlush(QWindow *window, m_image->flushScrolledRegion(true); auto result = QPlatformBackingStore::rhiFlush(window, sourceDevicePixelRatio, region, offset, - textures, translucentBackground); + textures, translucentBackground, sourceTransformFactor); if (result != FlushSuccess) return result; QXcbWindow *platformWindow = static_cast<QXcbWindow *>(window->handle()); diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.h b/src/plugins/platforms/xcb/qxcbbackingstore.h index 674640780eb..5cda9e1ab79 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.h +++ b/src/plugins/platforms/xcb/qxcbbackingstore.h @@ -27,7 +27,8 @@ public: const QRegion ®ion, const QPoint &offset, QPlatformTextureList *textures, - bool translucentBackground) override; + bool translucentBackground, + qreal sourceTransformFactor) override; QImage toImage() const override; QPlatformGraphicsBuffer *graphicsBuffer() const override; diff --git a/src/plugins/styles/modernwindows/qwindows11style.cpp b/src/plugins/styles/modernwindows/qwindows11style.cpp index 3f40dea5eb9..62269a21de1 100644 --- a/src/plugins/styles/modernwindows/qwindows11style.cpp +++ b/src/plugins/styles/modernwindows/qwindows11style.cpp @@ -183,30 +183,24 @@ void QWindows11Style::drawComplexControl(ComplexControl control, const QStyleOpt QObject *styleObject = option->styleObject; // Can be widget or qquickitem QRectF thumbRect = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget); - auto center = thumbRect.center(); const qreal outerRadius = qMin(8.0, (slider->orientation == Qt::Horizontal ? thumbRect.height() / 2.0 : thumbRect.width() / 2.0) - 1); - - thumbRect.setWidth(outerRadius); - thumbRect.setHeight(outerRadius); - thumbRect.moveCenter(center); - QPointF cursorPos = widget ? widget->mapFromGlobal(QCursor::pos()) : QPointF(); - bool isInsideHandle = thumbRect.contains(cursorPos); + bool isInsideHandle = option->activeSubControls == SC_SliderHandle; bool oldIsInsideHandle = styleObject->property("_q_insidehandle").toBool(); - int oldState = styleObject->property("_q_stylestate").toInt(); - int oldActiveControls = styleObject->property("_q_stylecontrols").toInt(); + State oldState = State(styleObject->property("_q_stylestate").toInt()); + SubControls oldActiveControls = SubControls(styleObject->property("_q_stylecontrols").toInt()); QRectF oldRect = styleObject->property("_q_stylerect").toRect(); styleObject->setProperty("_q_insidehandle", isInsideHandle); - styleObject->setProperty("_q_stylestate", int(option->state)); + styleObject->setProperty("_q_stylestate", int(state)); styleObject->setProperty("_q_stylecontrols", int(option->activeSubControls)); styleObject->setProperty("_q_stylerect", option->rect); if (option->styleObject->property("_q_end_radius").isNull()) option->styleObject->setProperty("_q_end_radius", outerRadius * 0.43); bool doTransition = (((state & State_Sunken) != (oldState & State_Sunken) - || ((oldIsInsideHandle) != (isInsideHandle)) - || oldActiveControls != int(option->activeSubControls)) + || (oldIsInsideHandle != isInsideHandle) + || (oldActiveControls != option->activeSubControls)) && state & State_Enabled); if (oldRect != option->rect) { @@ -242,11 +236,11 @@ void QWindows11Style::drawComplexControl(ComplexControl control, const QStyleOpt QCachedPainter cp(painter, QLatin1StringView("win11_spinbox") % HexString<uint8_t>(colorSchemeIndex), sb, sb->rect.size()); if (cp.needsPainting()) { - const auto frameRect = option->rect.marginsRemoved(QMargins(1, 1, 1, 1)); + const auto frameRect = QRectF(option->rect).marginsRemoved(QMarginsF(1.5, 1.5, 1.5, 1.5)); drawRoundedRect(cp.painter(), frameRect, Qt::NoPen, option->palette.brush(QPalette::Base)); if (sb->frame && (sub & SC_SpinBoxFrame)) - drawLineEditFrame(cp.painter(), option); + drawLineEditFrame(cp.painter(), frameRect, option); const bool isMouseOver = state & State_MouseOver; const bool hasFocus = state & State_HasFocus; @@ -374,31 +368,29 @@ void QWindows11Style::drawComplexControl(ComplexControl control, const QStyleOpt } } if (sub & SC_SliderHandle) { - if (const auto *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) { - const QRectF rect = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget); - const QPointF center = rect.center(); + const QRectF rect = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget); + const QPointF center = rect.center(); - const QNumberStyleAnimation* animation = qobject_cast<QNumberStyleAnimation*>(d->animation(option->styleObject)); + const QNumberStyleAnimation* animation = qobject_cast<QNumberStyleAnimation*>(d->animation(option->styleObject)); - if (animation != nullptr) - option->styleObject->setProperty("_q_inner_radius", animation->currentValue()); - else - option->styleObject->setProperty("_q_inner_radius", option->styleObject->property("_q_end_radius")); - - const qreal outerRadius = qMin(8.0,(slider->orientation == Qt::Horizontal ? rect.height() / 2.0 : rect.width() / 2.0) - 1); - const float innerRadius = option->styleObject->property("_q_inner_radius").toFloat(); - painter->setRenderHint(QPainter::Antialiasing, true); - painter->setPen(Qt::NoPen); - painter->setBrush(WINUI3Colors[colorSchemeIndex][controlFillSolid]); - painter->drawEllipse(center, outerRadius, outerRadius); - painter->setBrush(option->palette.accent()); - painter->drawEllipse(center, innerRadius, innerRadius); - - painter->setPen(WINUI3Colors[colorSchemeIndex][controlStrokeSecondary]); - painter->setBrush(Qt::NoBrush); - painter->drawEllipse(center, outerRadius + 0.5, outerRadius + 0.5); - painter->drawEllipse(center, innerRadius + 0.5, innerRadius + 0.5); - } + float innerRadius = 0; + if (animation != nullptr) + innerRadius = animation->currentValue(); + else + innerRadius = option->styleObject->property("_q_end_radius").toFloat(); + option->styleObject->setProperty("_q_inner_radius", innerRadius); + const qreal outerRadius = qMin(8.0,(slider->orientation == Qt::Horizontal ? rect.height() / 2.0 : rect.width() / 2.0) - 1); + + painter->setPen(Qt::NoPen); + painter->setBrush(winUI3Color(controlFillSolid)); + painter->drawEllipse(center, outerRadius, outerRadius); + painter->setBrush(option->palette.accent()); + painter->drawEllipse(center, innerRadius, innerRadius); + + painter->setPen(winUI3Color(controlStrokeSecondary)); + painter->setBrush(Qt::NoBrush); + painter->drawEllipse(center, outerRadius + 0.5, outerRadius + 0.5); + painter->drawEllipse(center, innerRadius + 0.5, innerRadius + 0.5); } if (slider->state & State_HasFocus) { QStyleOptionFocusRect fropt; @@ -412,11 +404,11 @@ void QWindows11Style::drawComplexControl(ComplexControl control, const QStyleOpt #if QT_CONFIG(combobox) case CC_ComboBox: if (const QStyleOptionComboBox *combobox = qstyleoption_cast<const QStyleOptionComboBox *>(option)) { - const auto frameRect = option->rect.marginsRemoved(QMargins(1, 1, 1, 1)); + const auto frameRect = QRectF(option->rect).marginsRemoved(QMarginsF(1.5, 1.5, 1.5, 1.5)); drawRoundedRect(painter, frameRect, Qt::NoPen, option->palette.brush(QPalette::Base)); if (combobox->frame) - drawLineEditFrame(painter, option); + drawLineEditFrame(painter, frameRect, option); const bool isMouseOver = state & State_MouseOver; const bool hasFocus = state & State_HasFocus; @@ -668,7 +660,7 @@ void QWindows11Style::drawPrimitive(PrimitiveElement element, const QStyleOption t->setStartValue(styleObject->property("_q_inner_radius").toFloat()); t->setEndValue(7.0f); if (option->state & State_Sunken) - t->setEndValue(2.0f); + t->setEndValue(4.0f); else if (option->state & State_MouseOver && !(option->state & State_On)) t->setEndValue(7.0f); else if (option->state & State_MouseOver && (option->state & State_On)) @@ -709,27 +701,19 @@ void QWindows11Style::drawPrimitive(PrimitiveElement element, const QStyleOption switch (element) { case PE_PanelTipLabel: { - QRectF tipRect = option->rect.marginsRemoved(QMargins(1,1,1,1)); - painter->setPen(Qt::NoPen); - painter->setBrush(option->palette.toolTipBase()); - painter->drawRoundedRect(tipRect, secondLevelRoundingRadius, secondLevelRoundingRadius); - - painter->setPen(highContrastTheme == true ? option->palette.buttonText().color() : WINUI3Colors[colorSchemeIndex][frameColorLight]); - painter->setBrush(Qt::NoBrush); - painter->drawRoundedRect(tipRect.marginsAdded(QMarginsF(0.5,0.5,0.5,0.5)), secondLevelRoundingRadius, secondLevelRoundingRadius); + const auto rect = QRectF(option->rect).marginsRemoved(QMarginsF(0.5, 0.5, 0.5, 0.5)); + const auto pen = highContrastTheme ? option->palette.buttonText().color() + : winUI3Color(frameColorLight); + drawRoundedRect(painter, rect, pen, option->palette.toolTipBase()); break; } case PE_FrameTabWidget: #if QT_CONFIG(tabwidget) if (const QStyleOptionTabWidgetFrame *frame = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(option)) { - QRectF frameRect = frame->rect.marginsRemoved(QMargins(0,0,0,0)); - painter->setPen(Qt::NoPen); - painter->setBrush(frame->palette.base()); - painter->drawRoundedRect(frameRect, secondLevelRoundingRadius, secondLevelRoundingRadius); - - painter->setPen(highContrastTheme == true ? frame->palette.buttonText().color() : WINUI3Colors[colorSchemeIndex][frameColorLight]); - painter->setBrush(Qt::NoBrush); - painter->drawRoundedRect(frameRect.marginsRemoved(QMarginsF(0.5,0.5,0.5,0.5)), secondLevelRoundingRadius, secondLevelRoundingRadius); + const auto rect = QRectF(option->rect).marginsRemoved(QMarginsF(0.5, 0.5, 0.5, 0.5)); + const auto pen = highContrastTheme ? frame->palette.buttonText().color() + : winUI3Color(frameColorLight); + drawRoundedRect(painter, rect, pen, frame->palette.base()); } #endif // QT_CONFIG(tabwidget) break; @@ -763,40 +747,41 @@ void QWindows11Style::drawPrimitive(PrimitiveElement element, const QStyleOption } } break; - case PE_IndicatorCheckBox: - { + case PE_IndicatorCheckBox: { const bool isRtl = option->direction == Qt::RightToLeft; - QNumberStyleAnimation* animation = qobject_cast<QNumberStyleAnimation*>(d->animation(option->styleObject)); - QFontMetrics fm(d->assetFont); + const bool isOn = option->state & State_On; + const bool isPartial = option->state & State_NoChange; QRectF rect = isRtl ? option->rect.adjusted(0, 0, -2, 0) : option->rect.adjusted(2, 0, 0, 0); - QPointF center = QPointF(rect.x() + rect.width() / 2, rect.y() + rect.height() / 2); + const QPointF center = rect.center(); rect.setWidth(15); rect.setHeight(15); rect.moveCenter(center); - float clipWidth = animation != nullptr ? animation->currentValue() : 1.0f; - QRectF clipRect = fm.boundingRect(QStringLiteral(u"\uE73E")); - clipRect.moveCenter(center); - clipRect.setLeft(rect.x() + (rect.width() - clipRect.width()) / 2.0); - clipRect.setWidth(clipWidth * clipRect.width()); - - painter->setPen(Qt::NoPen); - painter->setBrush(buttonFillBrush(option)); - painter->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius, Qt::AbsoluteSize); - - painter->setPen(highContrastTheme == true ? option->palette.buttonText().color() - : WINUI3Colors[colorSchemeIndex][frameColorStrong]); - painter->setBrush(Qt::NoBrush); - painter->drawRoundedRect(rect, secondLevelRoundingRadius + 0.5, secondLevelRoundingRadius + 0.5, Qt::AbsoluteSize); + QPen borderPen(Qt::NoPen); + if (!isOn && !isPartial) { + borderPen = highContrastTheme ? option->palette.buttonText().color() + : winUI3Color(frameColorStrong); + } + drawRoundedRect(painter, rect, borderPen, buttonFillBrush(option)); - painter->setFont(d->assetFont); - painter->setPen(option->palette.highlightedText().color()); - painter->setBrush(option->palette.highlightedText()); - if (option->state & State_On) + if (isOn) { + painter->setFont(d->assetFont); + painter->setPen(option->palette.color(QPalette::Window)); + QNumberStyleAnimation *animation = qobject_cast<QNumberStyleAnimation *>( + d->animation(option->styleObject)); + QFontMetrics fm(d->assetFont); + float clipWidth = animation != nullptr ? animation->currentValue() : 1.0f; + QRectF clipRect = fm.boundingRect(QStringLiteral(u"\uE73E")); + clipRect.moveCenter(center); + clipRect.setLeft(rect.x() + (rect.width() - clipRect.width()) / 2.0); + clipRect.setWidth(clipWidth * clipRect.width()); painter->drawText(clipRect, Qt::AlignVCenter | Qt::AlignLeft, QStringLiteral(u"\uE73E")); - else if (option->state & State_NoChange) - painter->drawText(rect, Qt::AlignVCenter | Qt::AlignHCenter, QStringLiteral(u"\uE73C")); + } else if (isPartial) { + painter->setFont(d->assetFont); + painter->setPen(option->palette.color(QPalette::Window)); + painter->drawText(rect, Qt::AlignCenter, QStringLiteral(u"\uE73C")); + } } break; case PE_IndicatorBranch: { @@ -814,9 +799,9 @@ void QWindows11Style::drawPrimitive(PrimitiveElement element, const QStyleOption } } break; - case PE_IndicatorRadioButton: - { + case PE_IndicatorRadioButton: { const bool isRtl = option->direction == Qt::RightToLeft; + const bool isOn = option->state & State_On; qreal innerRadius = option->state & State_On ? 4.0f :7.0f; if (option->styleObject) { if (option->styleObject->property("_q_end_radius").isNull()) @@ -826,34 +811,26 @@ void QWindows11Style::drawPrimitive(PrimitiveElement element, const QStyleOption option->styleObject->setProperty("_q_inner_radius", innerRadius); } - QPainterPath path; QRectF rect = isRtl ? option->rect.adjusted(0, 0, -2, 0) : option->rect.adjusted(2, 0, 0, 0); - QPointF center = QPoint(rect.x() + rect.width() / 2, rect.y() + rect.height() / 2); - rect.setWidth(15); - rect.setHeight(15); - rect.moveCenter(center); - QRectF innerRect = rect; - innerRect.setWidth(8); - innerRect.setHeight(8); - innerRect.moveCenter(center); - - painter->setPen(Qt::NoPen); - painter->setBrush(option->palette.accent()); - path.addEllipse(center,7,7); - path.addEllipse(center,innerRadius,innerRadius); - painter->drawPath(path); - - painter->setPen(WINUI3Colors[colorSchemeIndex][frameColorStrong]); - painter->setBrush(Qt::NoBrush); - painter->drawEllipse(center, 7.5, 7.5); - painter->drawEllipse(center,innerRadius + 0.5, innerRadius + 0.5); + const QPointF center = rect.center(); - painter->setPen(Qt::NoPen); - if (option->state & State_MouseOver && option->state & State_Enabled) - painter->setBrush(option->palette.window().color().darker(107)); - else - painter->setBrush(option->palette.window()); - painter->drawEllipse(center,innerRadius, innerRadius); + if (isOn) { + painter->setPen(Qt::NoPen); + painter->setBrush(buttonFillBrush(option)); + QPainterPath path; + path.addEllipse(center, 7.5, 7.5); + path.addEllipse(center, innerRadius, innerRadius); + painter->drawPath(path); + QColor fillColor = option->palette.window().color(); + if (option->state & State_MouseOver && option->state & State_Enabled) + fillColor = fillColor.darker(107); + painter->setBrush(fillColor); + painter->drawEllipse(center, innerRadius, innerRadius); + } else { + painter->setPen(winUI3Color(frameColorStrong)); + painter->setBrush(buttonFillBrush(option)); + painter->drawEllipse(center, 7.5, 7.5); + } } break; case PE_PanelButtonTool: @@ -910,7 +887,7 @@ void QWindows11Style::drawPrimitive(PrimitiveElement element, const QStyleOption } case PE_PanelLineEdit: if (const auto *panel = qstyleoption_cast<const QStyleOptionFrame *>(option)) { - const auto frameRect = option->rect.marginsRemoved(QMargins(1, 1, 1, 1)); + const auto frameRect = QRectF(option->rect).marginsRemoved(QMarginsF(1.5, 1.5, 1.5, 1.5)); drawRoundedRect(painter, frameRect, Qt::NoPen, option->palette.brush(QPalette::Base)); if (panel->lineWidth > 0) @@ -922,12 +899,14 @@ void QWindows11Style::drawPrimitive(PrimitiveElement element, const QStyleOption drawRoundedRect(painter, frameRect, Qt::NoPen, winUI3Color(subtleHighlightColor)); } break; - case PE_FrameLineEdit: - drawLineEditFrame(painter, option); + case PE_FrameLineEdit: { + const auto frameRect = QRectF(option->rect).marginsRemoved(QMarginsF(1.5, 1.5, 1.5, 1.5)); + drawLineEditFrame(painter, frameRect, option); break; + } case PE_Frame: { if (const auto *frame = qstyleoption_cast<const QStyleOptionFrame *>(option)) { - const auto rect = option->rect.marginsRemoved(QMargins(1, 1, 1, 1)); + const auto rect = QRectF(option->rect).marginsRemoved(QMarginsF(1.5, 1.5, 1.5, 1.5)); if (qobject_cast<const QComboBoxPrivateContainer *>(widget)) { QPen pen; if (highContrastTheme) @@ -941,7 +920,7 @@ void QWindows11Style::drawPrimitive(PrimitiveElement element, const QStyleOption if (frame->frameShape == QFrame::NoFrame) break; - drawLineEditFrame(painter, option, qobject_cast<const QTextEdit *>(widget) != nullptr); + drawLineEditFrame(painter, rect, option, qobject_cast<const QTextEdit *>(widget) != nullptr); } break; } @@ -1662,128 +1641,118 @@ void QWindows11Style::drawControl(ControlElement element, const QStyleOption *op } case CE_ItemViewItem: { if (const QStyleOptionViewItem *vopt = qstyleoption_cast<const QStyleOptionViewItem *>(option)) { - if (qobject_cast<const QAbstractItemView *>(widget)) { - QRect checkRect = proxy()->subElementRect(SE_ItemViewItemCheckIndicator, vopt, widget); - QRect iconRect = proxy()->subElementRect(SE_ItemViewItemDecoration, vopt, widget); - QRect textRect = proxy()->subElementRect(SE_ItemViewItemText, vopt, widget); + QRect checkRect = proxy()->subElementRect(SE_ItemViewItemCheckIndicator, vopt, widget); + QRect iconRect = proxy()->subElementRect(SE_ItemViewItemDecoration, vopt, widget); + QRect textRect = proxy()->subElementRect(SE_ItemViewItemText, vopt, widget); - // draw the background - proxy()->drawPrimitive(PE_PanelItemViewItem, option, painter, widget); + // draw the background + proxy()->drawPrimitive(PE_PanelItemViewItem, option, painter, widget); - const QRect &rect = vopt->rect; - const bool isRtl = option->direction == Qt::RightToLeft; - bool onlyOne = vopt->viewItemPosition == QStyleOptionViewItem::OnlyOne || - vopt->viewItemPosition == QStyleOptionViewItem::Invalid; - bool isFirst = vopt->viewItemPosition == QStyleOptionViewItem::Beginning; - bool isLast = vopt->viewItemPosition == QStyleOptionViewItem::End; + const QRect &rect = vopt->rect; + const bool isRtl = option->direction == Qt::RightToLeft; + bool onlyOne = vopt->viewItemPosition == QStyleOptionViewItem::OnlyOne || + vopt->viewItemPosition == QStyleOptionViewItem::Invalid; + bool isFirst = vopt->viewItemPosition == QStyleOptionViewItem::Beginning; + bool isLast = vopt->viewItemPosition == QStyleOptionViewItem::End; - // the tree decoration already painted the left side of the rounded rect - if (vopt->features.testFlag(QStyleOptionViewItem::IsDecoratedRootColumn) && - vopt->showDecorationSelected) { - isFirst = false; - if (onlyOne) { - onlyOne = false; - isLast = true; - } + // the tree decoration already painted the left side of the rounded rect + if (vopt->features.testFlag(QStyleOptionViewItem::IsDecoratedRootColumn) && + vopt->showDecorationSelected) { + isFirst = false; + if (onlyOne) { + onlyOne = false; + isLast = true; } + } - if (isRtl) { - if (isFirst) { - isFirst = false; - isLast = true; - } else if (isLast) { - isFirst = true; - isLast = false; - } + if (isRtl) { + if (isFirst) { + isFirst = false; + isLast = true; + } else if (isLast) { + isFirst = true; + isLast = false; } - const bool highlightCurrent = vopt->state.testAnyFlags(State_Selected | State_MouseOver); - if (highlightCurrent) { - const QAbstractItemView *view = qobject_cast<const QAbstractItemView *>(widget); - if (highContrastTheme) - painter->setBrush(vopt->palette.highlight()); - else - painter->setBrush(view->alternatingRowColors() ? vopt->palette.highlight() : WINUI3Colors[colorSchemeIndex][subtleHighlightColor]); - QWidget *editorWidget = view ? view->indexWidget(view->currentIndex()) : nullptr; - if (editorWidget) { - QPalette pal = editorWidget->palette(); - QColor editorBgColor = vopt->backgroundBrush == Qt::NoBrush ? vopt->palette.color(widget->backgroundRole()) : vopt->backgroundBrush.color(); - editorBgColor.setAlpha(255); - pal.setColor(editorWidget->backgroundRole(), editorBgColor); - editorWidget->setPalette(pal); - } + } + const bool highlightCurrent = vopt->state.testAnyFlags(State_Selected | State_MouseOver); + if (highlightCurrent) { + if (highContrastTheme) { + painter->setBrush(vopt->palette.highlight()); } else { - painter->setBrush(vopt->backgroundBrush); + const QAbstractItemView *view = qobject_cast<const QAbstractItemView *>(widget); + painter->setBrush(view && view->alternatingRowColors() + ? vopt->palette.highlight() + : winUI3Color(subtleHighlightColor)); } - painter->setPen(Qt::NoPen); + } else { + painter->setBrush(vopt->backgroundBrush); + } + painter->setPen(Qt::NoPen); - if (onlyOne) { - painter->drawRoundedRect(rect.marginsRemoved(QMargins(2, 2, 2, 2)), - secondLevelRoundingRadius, secondLevelRoundingRadius); - } else if (isFirst) { - painter->save(); - painter->setClipRect(rect); - painter->drawRoundedRect(rect.marginsRemoved(QMargins(2, 2, -secondLevelRoundingRadius, 2)), - secondLevelRoundingRadius, secondLevelRoundingRadius); - painter->restore(); - } else if (isLast) { - painter->save(); - painter->setClipRect(rect); - painter->drawRoundedRect(rect.marginsRemoved(QMargins(-secondLevelRoundingRadius, 2, 2, 2)), - secondLevelRoundingRadius, secondLevelRoundingRadius); - painter->restore(); - } else { - painter->drawRect(rect.marginsRemoved(QMargins(0, 2, 0, 2))); - } + if (onlyOne) { + painter->drawRoundedRect(rect.marginsRemoved(QMargins(2, 2, 2, 2)), + secondLevelRoundingRadius, secondLevelRoundingRadius); + } else if (isFirst) { + painter->save(); + painter->setClipRect(rect); + painter->drawRoundedRect(rect.marginsRemoved(QMargins(2, 2, -secondLevelRoundingRadius, 2)), + secondLevelRoundingRadius, secondLevelRoundingRadius); + painter->restore(); + } else if (isLast) { + painter->save(); + painter->setClipRect(rect); + painter->drawRoundedRect(rect.marginsRemoved(QMargins(-secondLevelRoundingRadius, 2, 2, 2)), + secondLevelRoundingRadius, secondLevelRoundingRadius); + painter->restore(); + } else { + painter->drawRect(rect.marginsRemoved(QMargins(0, 2, 0, 2))); + } - // draw the check mark - if (vopt->features & QStyleOptionViewItem::HasCheckIndicator) { - QStyleOptionViewItem option(*vopt); - option.rect = checkRect; - option.state = option.state & ~QStyle::State_HasFocus; + // draw the check mark + if (vopt->features & QStyleOptionViewItem::HasCheckIndicator) { + QStyleOptionViewItem option(*vopt); + option.rect = checkRect; + option.state = option.state & ~QStyle::State_HasFocus; - switch (vopt->checkState) { - case Qt::Unchecked: - option.state |= QStyle::State_Off; - break; - case Qt::PartiallyChecked: - option.state |= QStyle::State_NoChange; - break; - case Qt::Checked: - option.state |= QStyle::State_On; - break; - } - proxy()->drawPrimitive(QStyle::PE_IndicatorItemViewItemCheck, &option, painter, widget); + switch (vopt->checkState) { + case Qt::Unchecked: + option.state |= QStyle::State_Off; + break; + case Qt::PartiallyChecked: + option.state |= QStyle::State_NoChange; + break; + case Qt::Checked: + option.state |= QStyle::State_On; + break; } + proxy()->drawPrimitive(QStyle::PE_IndicatorItemViewItemCheck, &option, painter, widget); + } - // draw the icon - QIcon::Mode mode = QIcon::Normal; - if (!(vopt->state & QStyle::State_Enabled)) - mode = QIcon::Disabled; - else if (vopt->state & QStyle::State_Selected) - mode = QIcon::Selected; - QIcon::State state = vopt->state & QStyle::State_Open ? QIcon::On : QIcon::Off; - vopt->icon.paint(painter, iconRect, vopt->decorationAlignment, mode, state); - - painter->setPen(highlightCurrent && highContrastTheme ? vopt->palette.base().color() - : vopt->palette.text().color()); - d->viewItemDrawText(painter, vopt, textRect); - - // paint a vertical marker for QListView - if (vopt->state & State_Selected) { - if (const QListView *lv = qobject_cast<const QListView *>(widget); - lv && lv->viewMode() != QListView::IconMode && !highContrastTheme) { - painter->setPen(vopt->palette.accent().color()); - const auto xPos = isRtl ? rect.right() - 1 : rect.left(); - const QLineF lines[2] = { - QLineF(xPos, rect.y() + 2, xPos, rect.y() + rect.height() - 2), - QLineF(xPos + 1, rect.y() + 2, xPos + 1, rect.y() + rect.height() - 2), - }; - painter->drawLines(lines, 2); - } + // draw the icon + QIcon::Mode mode = QIcon::Normal; + if (!(vopt->state & QStyle::State_Enabled)) + mode = QIcon::Disabled; + else if (vopt->state & QStyle::State_Selected) + mode = QIcon::Selected; + QIcon::State state = vopt->state & QStyle::State_Open ? QIcon::On : QIcon::Off; + vopt->icon.paint(painter, iconRect, vopt->decorationAlignment, mode, state); + + painter->setPen(highlightCurrent && highContrastTheme ? vopt->palette.base().color() + : vopt->palette.text().color()); + d->viewItemDrawText(painter, vopt, textRect); + + // paint a vertical marker for QListView + if (vopt->state & State_Selected) { + if (const QListView *lv = qobject_cast<const QListView *>(widget); + lv && lv->viewMode() != QListView::IconMode && !highContrastTheme) { + painter->setPen(vopt->palette.accent().color()); + const auto xPos = isRtl ? rect.right() - 1 : rect.left(); + const QLineF lines[2] = { + QLineF(xPos, rect.y() + 2, xPos, rect.y() + rect.height() - 2), + QLineF(xPos + 1, rect.y() + 2, xPos + 1, rect.y() + rect.height() - 2), + }; + painter->drawLines(lines, 2); } - } else { - QRect textRect = proxy()->subElementRect(SE_ItemViewItemText, vopt, widget); - d->viewItemDrawText(painter, vopt, textRect); } } break; @@ -2217,8 +2186,9 @@ void QWindows11Style::polish(QWidget* widget) pal.setColor(scrollarea->viewport()->backgroundRole(), Qt::transparent); scrollarea->viewport()->setPalette(pal); scrollarea->viewport()->setProperty("_q_original_background_palette", originalPalette); - if (qobject_cast<QTableView *>(widget)) - widget->setAttribute(Qt::WA_Hover, true); + // QTreeView & QListView are already set in the base windowsvista style + if (auto table = qobject_cast<QTableView *>(widget)) + table->viewport()->setAttribute(Qt::WA_Hover, true); } } @@ -2254,10 +2224,11 @@ static void populateLightSystemBasePalette(QPalette &result) static QString oldStyleSheet; const bool styleSheetChanged = oldStyleSheet != qApp->styleSheet(); - const QColor textColor = QColor(0x00,0x00,0x00,0xE4); - const QColor textDisabled = QColor(0x00,0x00,0x00,0x5C); - const QColor btnFace = QColor(0xFF,0xFF,0xFF,0xB3); - const QColor alternateBase = QColor(0x00,0x00,0x00,0x09); + constexpr QColor textColor = QColor(0x00,0x00,0x00,0xE4); + constexpr QColor textDisabled = QColor(0x00, 0x00, 0x00, 0x5C); + constexpr QColor btnFace = QColor(0xFF, 0xFF, 0xFF, 0xB3); + constexpr QColor base = QColor(0xFF, 0xFF, 0xFF, 0xFF); + constexpr QColor alternateBase = QColor(0x00, 0x00, 0x00, 0x09); const QColor btnHighlight = result.accent().color(); const QColor btnColor = result.button().color(); @@ -2269,7 +2240,7 @@ static void populateLightSystemBasePalette(QPalette &result) SET_IF_UNRESOLVED(QPalette::Active, QPalette::Mid, btnColor.darker(150)); SET_IF_UNRESOLVED(QPalette::Active, QPalette::Text, textColor); SET_IF_UNRESOLVED(QPalette::Active, QPalette::BrightText, btnHighlight); - SET_IF_UNRESOLVED(QPalette::Active, QPalette::Base, btnFace); + SET_IF_UNRESOLVED(QPalette::Active, QPalette::Base, base); SET_IF_UNRESOLVED(QPalette::Active, QPalette::Window, QColor(0xF3,0xF3,0xF3,0xFF)); SET_IF_UNRESOLVED(QPalette::Active, QPalette::ButtonText, textColor); SET_IF_UNRESOLVED(QPalette::Active, QPalette::Midlight, btnColor.lighter(125)); @@ -2286,7 +2257,7 @@ static void populateLightSystemBasePalette(QPalette &result) SET_IF_UNRESOLVED(QPalette::Inactive, QPalette::Mid, btnColor.darker(150)); SET_IF_UNRESOLVED(QPalette::Inactive, QPalette::Text, textColor); SET_IF_UNRESOLVED(QPalette::Inactive, QPalette::BrightText, btnHighlight); - SET_IF_UNRESOLVED(QPalette::Inactive, QPalette::Base, btnFace); + SET_IF_UNRESOLVED(QPalette::Inactive, QPalette::Base, base); SET_IF_UNRESOLVED(QPalette::Inactive, QPalette::Window, QColor(0xF3,0xF3,0xF3,0xFF)); SET_IF_UNRESOLVED(QPalette::Inactive, QPalette::ButtonText, textColor); SET_IF_UNRESOLVED(QPalette::Inactive, QPalette::Midlight, btnColor.lighter(125)); @@ -2307,7 +2278,7 @@ static void populateDarkSystemBasePalette(QPalette &result) static QString oldStyleSheet; const bool styleSheetChanged = oldStyleSheet != qApp->styleSheet(); - const QColor alternateBase = QColor(0xFF,0xFF,0xFF,0x0F); + constexpr QColor alternateBase = QColor(0xFF, 0xFF, 0xFF, 0x0F); SET_IF_UNRESOLVED(QPalette::Active, QPalette::AlternateBase, alternateBase); @@ -2361,7 +2332,7 @@ QBrush QWindows11Style::buttonFillBrush(const QStyleOption *option) if (!isOn && option->state & QStyle::State_AutoRaise) return Qt::NoBrush; if (option->state & QStyle::State_MouseOver) - brush.setColor(isOn ? brush.color().lighter(107) : brush.color().darker(107)); + brush.setColor(isOn ? brush.color().lighter(115) : brush.color().darker(107)); return brush; } @@ -2381,9 +2352,8 @@ QColor QWindows11Style::buttonLabelColor(const QStyleOption *option, int colorSc : option->palette.buttonText().color(); } -void QWindows11Style::drawLineEditFrame(QPainter *p, const QStyleOption *o, bool isEditable) const +void QWindows11Style::drawLineEditFrame(QPainter *p, const QRectF &rect, const QStyleOption *o, bool isEditable) const { - const auto rect = QRectF(o->rect).marginsRemoved(QMarginsF(1.5, 1.5, 1.5, 1.5)); const bool isHovered = o->state & State_MouseOver; const auto frameCol = highContrastTheme ? o->palette.color(isHovered ? QPalette::Accent diff --git a/src/plugins/styles/modernwindows/qwindows11style_p.h b/src/plugins/styles/modernwindows/qwindows11style_p.h index 51514737259..eccedc5bf67 100644 --- a/src/plugins/styles/modernwindows/qwindows11style_p.h +++ b/src/plugins/styles/modernwindows/qwindows11style_p.h @@ -75,7 +75,7 @@ protected: private: static inline QBrush buttonFillBrush(const QStyleOption *option); static inline QColor buttonLabelColor(const QStyleOption *option, int colorSchemeIndex); - void drawLineEditFrame(QPainter *p, const QStyleOption *o, bool isEditable = true) const; + void drawLineEditFrame(QPainter *p, const QRectF &rect, const QStyleOption *o, bool isEditable = true) const; inline QColor winUI3Color(enum WINUI3Color col) const; private: diff --git a/src/plugins/styles/modernwindows/qwindowsvistastyle.cpp b/src/plugins/styles/modernwindows/qwindowsvistastyle.cpp index 0301b770a1e..52a98b0f9bb 100644 --- a/src/plugins/styles/modernwindows/qwindowsvistastyle.cpp +++ b/src/plugins/styles/modernwindows/qwindowsvistastyle.cpp @@ -2301,6 +2301,14 @@ int QWindowsVistaStyle::styleHint(StyleHint hint, const QStyleOption *option, co ret = 1; break; + case SH_ComboBox_ListMouseTracking_Current: + ret = 0; + break; + + case SH_ComboBox_ListMouseTracking_Active: + ret = 1; + break; + default: ret = QWindowsStyle::styleHint(hint, option, widget, returnData); break; diff --git a/src/printsupport/REUSE.toml b/src/printsupport/REUSE.toml index 8b6274a751a..e9c18925d17 100644 --- a/src/printsupport/REUSE.toml +++ b/src/printsupport/REUSE.toml @@ -3,23 +3,23 @@ version = 1 [[annotations]] path = ["dialogs/*.ui", "widgets/*.ui", "dialogs/images/*.png"] precedence = "closest" -SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." +SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd." SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only" [[annotations]] path = ["doc/**"] precedence = "closest" -SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." +SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd." SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only" [[annotations]] path = ["**.json"] precedence = "closest" -SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." +SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd." SPDX-License-Identifier = "BSD-3-Clause" [[annotations]] path = ["doc/snippets/**"] precedence = "closest" -SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." +SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd." SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR BSD-3-Clause" diff --git a/src/testlib/3rdparty/valgrind/qt_attribution.json b/src/testlib/3rdparty/valgrind/qt_attribution.json index 3146fd82c57..262bc8380b4 100644 --- a/src/testlib/3rdparty/valgrind/qt_attribution.json +++ b/src/testlib/3rdparty/valgrind/qt_attribution.json @@ -11,7 +11,7 @@ "Description": "An instrumentation framework for building dynamic analysis tools.", "Homepage": "http://valgrind.org/", - "Version": "3.24.0", + "Version": "3.25.1", "PURL": "pkg:generic/valgrind@$<VERSION>?download_url=https://valgrind.org/", "License": "BSD 4-clause \"Original\" or \"Old\" License", "LicenseId": "BSD-4-Clause", diff --git a/src/testlib/3rdparty/valgrind/valgrind_p.h b/src/testlib/3rdparty/valgrind/valgrind_p.h index 77ca3ad8692..ab49937ccd4 100644 --- a/src/testlib/3rdparty/valgrind/valgrind_p.h +++ b/src/testlib/3rdparty/valgrind/valgrind_p.h @@ -89,7 +89,7 @@ || (__VALGRIND_MAJOR__ == 3 && __VALGRIND_MINOR__ >= 6)) */ #define __VALGRIND_MAJOR__ 3 -#define __VALGRIND_MINOR__ 24 +#define __VALGRIND_MINOR__ 25 #include <stdarg.h> @@ -126,6 +126,7 @@ #undef PLAT_mips32_linux #undef PLAT_mips64_linux #undef PLAT_nanomips_linux +#undef PLAT_riscv64_linux #undef PLAT_x86_solaris #undef PLAT_amd64_solaris @@ -172,6 +173,8 @@ # define PLAT_mips32_linux 1 #elif defined(__linux__) && defined(__nanomips__) # define PLAT_nanomips_linux 1 +#elif defined(__linux__) && defined(__riscv) && (__riscv_xlen == 64) +# define PLAT_riscv64_linux 1 #elif defined(__sun) && defined(__i386__) # define PLAT_x86_solaris 1 #elif defined(__sun) && defined(__x86_64__) @@ -1129,6 +1132,87 @@ typedef } while (0) #endif + +/* ----------------------- riscv64-linux ------------------------ */ + +#if defined(PLAT_riscv64_linux) + +typedef + struct { + unsigned long int nraddr; /* where's the code? */ + } + OrigFn; + +#define __SPECIAL_INSTRUCTION_PREAMBLE \ + ".option push\n\t" \ + ".option norvc\n\t" \ + "srli zero, zero, 3\n\t" \ + "srli zero, zero, 13\n\t" \ + "srli zero, zero, 51\n\t" \ + "srli zero, zero, 61\n\t" + +#define __SPECIAL_INSTRUCTION_POSTAMBLE \ + ".option pop\n\t" \ + +#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ + _zzq_default, _zzq_request, \ + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ + \ + __extension__ \ + ({volatile unsigned long int _zzq_args[6]; \ + volatile unsigned long int _zzq_result; \ + _zzq_args[0] = (unsigned long int)(_zzq_request); \ + _zzq_args[1] = (unsigned long int)(_zzq_arg1); \ + _zzq_args[2] = (unsigned long int)(_zzq_arg2); \ + _zzq_args[3] = (unsigned long int)(_zzq_arg3); \ + _zzq_args[4] = (unsigned long int)(_zzq_arg4); \ + _zzq_args[5] = (unsigned long int)(_zzq_arg5); \ + __asm__ volatile("mv a3, %1\n\t" /*default*/ \ + "mv a4, %2\n\t" /*ptr*/ \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* a3 = client_request ( a4 ) */ \ + "or a0, a0, a0\n\t" \ + __SPECIAL_INSTRUCTION_POSTAMBLE \ + "mv %0, a3" /*result*/ \ + : "=r" (_zzq_result) \ + : "r" ((unsigned long int)(_zzq_default)), \ + "r" (&_zzq_args[0]) \ + : "memory", "a3", "a4"); \ + _zzq_result; \ + }) + +#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ + { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ + unsigned long int __addr; \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* a3 = guest_NRADDR */ \ + "or a1, a1, a1\n\t" \ + __SPECIAL_INSTRUCTION_POSTAMBLE \ + "mv %0, a3" \ + : "=r" (__addr) \ + : \ + : "memory", "a3" \ + ); \ + _zzq_orig->nraddr = __addr; \ + } + +#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_T0 \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* branch-and-link-to-noredir t0 */ \ + "or a2, a2, a2\n\t" \ + __SPECIAL_INSTRUCTION_POSTAMBLE + +#define VALGRIND_VEX_INJECT_IR() \ + do { \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + "or a3, a3, a3\n\t" \ + __SPECIAL_INSTRUCTION_POSTAMBLE \ + : : : "memory" \ + ); \ + } while (0) + +#endif /* PLAT_riscv64_linux */ + /* Insert assembly code for other platforms here... */ #endif /* NVALGRIND */ @@ -6606,6 +6690,456 @@ typedef #endif /* PLAT_mips64_linux */ +/* ----------------------- riscv64-linux ----------------------- */ + +#if defined(PLAT_riscv64_linux) + +/* These regs are trashed by the hidden call. */ +#define __CALLER_SAVED_REGS \ + "ra", \ + "t0", "t1", "t2", "t3", "t4", "t5", "t6", \ + "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", \ + "ft0", "ft1", "ft2", "ft3", "ft4", "ft5", "ft6", "ft7", \ + "ft8", "ft9", "ft10", "ft11", \ + "fa0", "fa1", "fa2", "fa3", "fa4", "fa5", "fa6", "fa7" + +/* s11 is callee-saved, so we can use it to save and restore sp around + the hidden call. */ +#define VALGRIND_ALIGN_STACK \ + "mv s11, sp\n\t" \ + "andi sp, sp, 0xfffffffffffffff0\n\t" +#define VALGRIND_RESTORE_STACK \ + "mv sp, s11\n\t" + +/* These CALL_FN_ macros assume that on riscv64-linux, + sizeof(unsigned long) == 8. */ + +#define CALL_FN_W_v(lval, orig) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[1]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ld t0, 0(%1) \n\t" /* target->t0 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_T0 \ + VALGRIND_RESTORE_STACK \ + "mv %0, a0\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS, "s11" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_W(lval, orig, arg1) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[2]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ld a0, 8(%1) \n\t" \ + "ld t0, 0(%1) \n\t" /* target->t0 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_T0 \ + VALGRIND_RESTORE_STACK \ + "mv %0, a0\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS, "s11" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[3]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ld a0, 8(%1) \n\t" \ + "ld a1, 16(%1) \n\t" \ + "ld t0, 0(%1) \n\t" /* target->t0 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_T0 \ + VALGRIND_RESTORE_STACK \ + "mv %0, a0\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS, "s11" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[4]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ld a0, 8(%1) \n\t" \ + "ld a1, 16(%1) \n\t" \ + "ld a2, 24(%1) \n\t" \ + "ld t0, 0(%1) \n\t" /* target->t0 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_T0 \ + VALGRIND_RESTORE_STACK \ + "mv %0, a0\n" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS, "s11" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[5]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ld a0, 8(%1) \n\t" \ + "ld a1, 16(%1) \n\t" \ + "ld a2, 24(%1) \n\t" \ + "ld a3, 32(%1) \n\t" \ + "ld t0, 0(%1) \n\t" /* target->t0 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_T0 \ + VALGRIND_RESTORE_STACK \ + "mv %0, a0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS, "s11" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[6]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ld a0, 8(%1) \n\t" \ + "ld a1, 16(%1) \n\t" \ + "ld a2, 24(%1) \n\t" \ + "ld a3, 32(%1) \n\t" \ + "ld a4, 40(%1) \n\t" \ + "ld t0, 0(%1) \n\t" /* target->t0 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_T0 \ + VALGRIND_RESTORE_STACK \ + "mv %0, a0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS, "s11" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[7]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ld a0, 8(%1) \n\t" \ + "ld a1, 16(%1) \n\t" \ + "ld a2, 24(%1) \n\t" \ + "ld a3, 32(%1) \n\t" \ + "ld a4, 40(%1) \n\t" \ + "ld a5, 48(%1) \n\t" \ + "ld t0, 0(%1) \n\t" /* target->t0 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_T0 \ + VALGRIND_RESTORE_STACK \ + "mv %0, a0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS, "s11" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[8]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ld a0, 8(%1) \n\t" \ + "ld a1, 16(%1) \n\t" \ + "ld a2, 24(%1) \n\t" \ + "ld a3, 32(%1) \n\t" \ + "ld a4, 40(%1) \n\t" \ + "ld a5, 48(%1) \n\t" \ + "ld a6, 56(%1) \n\t" \ + "ld t0, 0(%1) \n\t" /* target->t0 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_T0 \ + VALGRIND_RESTORE_STACK \ + "mv %0, a0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS, "s11" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[9]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "ld a0, 8(%1) \n\t" \ + "ld a1, 16(%1) \n\t" \ + "ld a2, 24(%1) \n\t" \ + "ld a3, 32(%1) \n\t" \ + "ld a4, 40(%1) \n\t" \ + "ld a5, 48(%1) \n\t" \ + "ld a6, 56(%1) \n\t" \ + "ld a7, 64(%1) \n\t" \ + "ld t0, 0(%1) \n\t" /* target->t0 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_T0 \ + VALGRIND_RESTORE_STACK \ + "mv %0, a0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS, "s11" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[10]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "addi sp, sp, -16 \n\t" \ + "ld a0, 8(%1) \n\t" \ + "ld a1, 16(%1) \n\t" \ + "ld a2, 24(%1) \n\t" \ + "ld a3, 32(%1) \n\t" \ + "ld a4, 40(%1) \n\t" \ + "ld a5, 48(%1) \n\t" \ + "ld a6, 56(%1) \n\t" \ + "ld a7, 64(%1) \n\t" \ + "ld t0, 72(%1) \n\t" \ + "sd t0, 0(sp) \n\t" \ + "ld t0, 0(%1) \n\t" /* target->t0 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_T0 \ + VALGRIND_RESTORE_STACK \ + "mv %0, a0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS, "s11" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[11]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "addi sp, sp, -16 \n\t" \ + "ld a0, 8(%1) \n\t" \ + "ld a1, 16(%1) \n\t" \ + "ld a2, 24(%1) \n\t" \ + "ld a3, 32(%1) \n\t" \ + "ld a4, 40(%1) \n\t" \ + "ld a5, 48(%1) \n\t" \ + "ld a6, 56(%1) \n\t" \ + "ld a7, 64(%1) \n\t" \ + "ld t0, 72(%1) \n\t" \ + "sd t0, 0(sp) \n\t" \ + "ld t0, 80(%1) \n\t" \ + "sd t0, 8(sp) \n\t" \ + "ld t0, 0(%1) \n\t" /* target->t0 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_T0 \ + VALGRIND_RESTORE_STACK \ + "mv %0, a0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS, "s11" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10,arg11) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[12]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + _argvec[11] = (unsigned long)(arg11); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "addi sp, sp, -32 \n\t" \ + "ld a0, 8(%1) \n\t" \ + "ld a1, 16(%1) \n\t" \ + "ld a2, 24(%1) \n\t" \ + "ld a3, 32(%1) \n\t" \ + "ld a4, 40(%1) \n\t" \ + "ld a5, 48(%1) \n\t" \ + "ld a6, 56(%1) \n\t" \ + "ld a7, 64(%1) \n\t" \ + "ld t0, 72(%1) \n\t" \ + "sd t0, 0(sp) \n\t" \ + "ld t0, 80(%1) \n\t" \ + "sd t0, 8(sp) \n\t" \ + "ld t0, 88(%1) \n\t" \ + "sd t0, 16(sp) \n\t" \ + "ld t0, 0(%1) \n\t" /* target->t0 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_T0 \ + VALGRIND_RESTORE_STACK \ + "mv %0, a0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS, "s11" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ + arg7,arg8,arg9,arg10,arg11, \ + arg12) \ + do { \ + volatile OrigFn _orig = (orig); \ + volatile unsigned long _argvec[13]; \ + volatile unsigned long _res; \ + _argvec[0] = (unsigned long)_orig.nraddr; \ + _argvec[1] = (unsigned long)(arg1); \ + _argvec[2] = (unsigned long)(arg2); \ + _argvec[3] = (unsigned long)(arg3); \ + _argvec[4] = (unsigned long)(arg4); \ + _argvec[5] = (unsigned long)(arg5); \ + _argvec[6] = (unsigned long)(arg6); \ + _argvec[7] = (unsigned long)(arg7); \ + _argvec[8] = (unsigned long)(arg8); \ + _argvec[9] = (unsigned long)(arg9); \ + _argvec[10] = (unsigned long)(arg10); \ + _argvec[11] = (unsigned long)(arg11); \ + _argvec[12] = (unsigned long)(arg12); \ + __asm__ volatile( \ + VALGRIND_ALIGN_STACK \ + "addi sp, sp, -32 \n\t" \ + "ld a0, 8(%1) \n\t" \ + "ld a1, 16(%1) \n\t" \ + "ld a2, 24(%1) \n\t" \ + "ld a3, 32(%1) \n\t" \ + "ld a4, 40(%1) \n\t" \ + "ld a5, 48(%1) \n\t" \ + "ld a6, 56(%1) \n\t" \ + "ld a7, 64(%1) \n\t" \ + "ld t0, 72(%1) \n\t" \ + "sd t0, 0(sp) \n\t" \ + "ld t0, 80(%1) \n\t" \ + "sd t0, 8(sp) \n\t" \ + "ld t0, 88(%1) \n\t" \ + "sd t0, 16(sp) \n\t" \ + "ld t0, 96(%1) \n\t" \ + "sd t0, 24(sp) \n\t" \ + "ld t0, 0(%1) \n\t" /* target->t0 */ \ + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_T0 \ + VALGRIND_RESTORE_STACK \ + "mv %0, a0" \ + : /*out*/ "=r" (_res) \ + : /*in*/ "0" (&_argvec[0]) \ + : /*trash*/ "memory", __CALLER_SAVED_REGS, "s11" \ + ); \ + lval = (__typeof__(lval)) _res; \ + } while (0) + +#endif /* PLAT_riscv64_linux */ + /* ------------------------------------------------------------------ */ /* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */ /* */ @@ -7162,6 +7696,7 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...) #undef PLAT_mips32_linux #undef PLAT_mips64_linux #undef PLAT_nanomips_linux +#undef PLAT_riscv64_linux #undef PLAT_x86_solaris #undef PLAT_amd64_solaris diff --git a/src/tools/androiddeployqt/main.cpp b/src/tools/androiddeployqt/main.cpp index e93c3038fca..a27c52f5a99 100644 --- a/src/tools/androiddeployqt/main.cpp +++ b/src/tools/androiddeployqt/main.cpp @@ -1475,10 +1475,23 @@ bool readInputFile(Options *options) for (const QJsonValue &value : permissions) { if (value.isObject()) { QJsonObject permissionObj = value.toObject(); - QString name = permissionObj.value("name"_L1).toString(); + QString name; QString extras; - if (permissionObj.contains("extras"_L1)) - extras = permissionObj.value("extras"_L1).toString().trimmed(); + for (auto it = permissionObj.begin(); it != permissionObj.end(); ++it) { + if (it.key() == "name"_L1) { + name = it.value().toString(); + } else { + extras.append(" android:"_L1) + .append(it.key()) + .append("=\""_L1) + .append(it.value().toString()) + .append("\""_L1); + } + } + if (name.isEmpty()) { + fprintf(stderr, "Missing permission 'name' in permission specification"); + return false; + } options->applicationPermissions.insert(name, extras); } } @@ -1580,8 +1593,11 @@ bool copyAndroidTemplate(const Options &options) if (options.verbose) fprintf(stdout, "Copying Android package template.\n"); - if (!copyGradleTemplate(options)) - return false; + if (!options.auxMode) { + // Gradle is not configured and is not running in aux mode + if (!copyGradleTemplate(options)) + return false; + } if (!copyAndroidTemplate(options, "/src/android/templates"_L1)) return false; diff --git a/src/tools/androidtestrunner/main.cpp b/src/tools/androidtestrunner/main.cpp index eb4c84fbd75..564a332c091 100644 --- a/src/tools/androidtestrunner/main.cpp +++ b/src/tools/androidtestrunner/main.cpp @@ -40,6 +40,7 @@ struct Options QString buildPath; QString manifestPath; QString adbCommand{"adb"_L1}; + QString bundletoolPath; QString serial; QString makeCommand; QString package; @@ -48,7 +49,7 @@ struct Options QString stdoutFileName; QHash<QString, QString> outFiles; QStringList amStarttestArgs; - QString apkPath; + QString packagePath; QString ndkStackPath; QList<QStringList> preTestRunAdbCommands; bool showLogcatOutput = false; @@ -114,6 +115,24 @@ static bool execAdbCommand(const QStringList &args, QByteArray *output = nullptr return execCommand(g_options.adbCommand, argsWithSerial, output, verbose); } +static bool execBundletoolCommand(const QStringList &args, QByteArray *output = nullptr, + bool verbose = true) +{ + QString java("java"_L1); + QStringList argsFull = QStringList() << "-jar"_L1 << g_options.bundletoolPath << args; + return execCommand(java, argsFull, output, verbose); +} + +static void setPackagePath(const QString &path) +{ + if (!g_options.packagePath.isEmpty()) { + qCritical("Both --aab and --apk options provided. This is not supported."); + g_options.helpRequested = true; + return; + } + g_options.packagePath = path; +} + static bool execCommand(const QString &command, QByteArray *output = nullptr, bool verbose = true) { auto args = QProcess::splitCommand(command); @@ -133,6 +152,11 @@ static bool parseOptions() g_options.helpRequested = true; else g_options.adbCommand = arguments.at(++i); + } else if (argument.compare("--bundletool"_L1, Qt::CaseInsensitive) == 0) { + if (i + 1 == arguments.size()) + g_options.helpRequested = true; + else + g_options.bundletoolPath = arguments.at(++i); } else if (argument.compare("--path"_L1, Qt::CaseInsensitive) == 0) { if (i + 1 == arguments.size()) g_options.helpRequested = true; @@ -152,7 +176,12 @@ static bool parseOptions() if (i + 1 == arguments.size()) g_options.helpRequested = true; else - g_options.apkPath = arguments.at(++i); + setPackagePath(arguments.at(++i)); + } else if (argument.compare("--aab"_L1, Qt::CaseInsensitive) == 0) { + if (i + 1 == arguments.size()) + g_options.helpRequested = true; + else + setPackagePath(arguments.at(++i)); } else if (argument.compare("--activity"_L1, Qt::CaseInsensitive) == 0) { if (i + 1 == arguments.size()) g_options.helpRequested = true; @@ -200,7 +229,7 @@ static bool parseOptions() for (;i < arguments.size(); ++i) g_options.testArgsList << arguments.at(i); - if (g_options.helpRequested || g_options.buildPath.isEmpty() || g_options.apkPath.isEmpty()) + if (g_options.helpRequested || g_options.buildPath.isEmpty() || g_options.packagePath.isEmpty()) return false; g_options.serial = qEnvironmentVariable("ANDROID_SERIAL"); @@ -222,52 +251,57 @@ static bool parseOptions() static void printHelp() { - qWarning( "Syntax: %s <options> -- [TESTARGS] \n" - "\n" - " Runs a Qt for Android test on an emulator or a device. Specify a device\n" - " using the environment variables ANDROID_SERIAL or ANDROID_DEVICE_SERIAL.\n" - " Returns the number of failed tests, -1 on test runner deployment related\n" - " failures or zero on success." - "\n" - " Mandatory arguments:\n" - " --path <path>: The path where androiddeployqt builds the android package.\n" - "\n" - " --make <make cmd>: make command to create an APK, for example:\n" - " \"cmake --build <build-dir> --target <target>_make_apk\".\n" - "\n" - " --apk <apk path>: The test apk path. The apk has to exist already, if it\n" - " does not exist the make command must be provided for building the apk.\n" - "\n" - " Optional arguments:\n" - " --adb <adb cmd>: The Android ADB command. If missing the one from\n" - " $PATH will be used.\n" - "\n" - " --activity <acitvity>: The Activity to run. If missing the first\n" - " activity from AndroidManifest.qml file will be used.\n" - "\n" - " --timeout <seconds>: Timeout to run the test. Default is 10 minutes.\n" - "\n" - " --skip-install-root: Do not append INSTALL_ROOT=... to the make command.\n" - "\n" - " --show-logcat: Print Logcat output to stdout. If an ANR occurs during\n" - " the test run, logs from the system_server process are included.\n" - " This argument is implied if a test crashes.\n" - "\n" - " --ndk-stack: Path to ndk-stack tool that symbolizes crash stacktraces.\n" - " By default, ANDROID_NDK_ROOT env var is used to deduce the tool path.\n" - "\n" - " -- Arguments that will be passed to the test application.\n" - "\n" - " --verbose: Prints out information during processing.\n" - "\n" - " --pre-test-adb-command <command>: call the adb <command> after\n" - " installation and before the test run.\n" - "\n" - " --manifest <path>: Custom path to the AndroidManifest.xml.\n" - "\n" - " --help: Displays this information.\n", - qPrintable(QCoreApplication::arguments().at(0)) - ); + qWarning("Syntax: %s <options> -- [TESTARGS] \n" + "\n" + " Runs a Qt for Android test on an emulator or a device. Specify a device\n" + " using the environment variables ANDROID_SERIAL or ANDROID_DEVICE_SERIAL.\n" + " Returns the number of failed tests, -1 on test runner deployment related\n" + " failures or zero on success." + "\n" + " Mandatory arguments:\n" + " --path <path>: The path where androiddeployqt builds the android package.\n" + "\n" + " --make <make cmd>: make command to create an APK, for example:\n" + " \"cmake --build <build-dir> --target <target>_make_apk\".\n" + "\n" + " --apk <apk path>: The test apk path. The apk has to exist already, if it\n" + " does not exist the make command must be provided for building the apk.\n" + "\n" + " --aab <aab path>: The test aab path. The aab has to exist already, if it\n" + " does not exist the make command must be provided for building the aab.\n" + "\n" + " Optional arguments:\n" + " --adb <adb cmd>: The Android ADB command. If missing the one from\n" + " $PATH will be used.\n" + "\n" + " --activity <acitvity>: The Activity to run. If missing the first\n" + " activity from AndroidManifest.qml file will be used.\n" + "\n" + " --timeout <seconds>: Timeout to run the test. Default is 10 minutes.\n" + "\n" + " --skip-install-root: Do not append INSTALL_ROOT=... to the make command.\n" + "\n" + " --show-logcat: Print Logcat output to stdout. If an ANR occurs during\n" + " the test run, logs from the system_server process are included.\n" + " This argument is implied if a test crashes.\n" + "\n" + " --ndk-stack: Path to ndk-stack tool that symbolizes crash stacktraces.\n" + " By default, ANDROID_NDK_ROOT env var is used to deduce the tool path.\n" + "\n" + " -- Arguments that will be passed to the test application.\n" + "\n" + " --verbose: Prints out information during processing.\n" + "\n" + " --pre-test-adb-command <command>: call the adb <command> after\n" + " installation and before the test run.\n" + "\n" + " --manifest <path>: Custom path to the AndroidManifest.xml.\n" + "\n" + " --bundletool <bundletool path>: The path to Android bundletool.\n" + " See https://developer.android.com/tools/bundletool for details.\n" + "\n" + " --help: Displays this information.\n", + qPrintable(QCoreApplication::arguments().at(0))); } static QString packageNameFromAndroidManifest(const QString &androidManifestPath) @@ -850,10 +884,10 @@ int main(int argc, char *argv[]) return EXIT_ERROR; } - if (!QFile::exists(g_options.apkPath)) { + if (!QFile::exists(g_options.packagePath)) { qCritical("No apk \"%s\" found after running the make command. " "Check the provided path and the make command.", - qPrintable(g_options.apkPath)); + qPrintable(g_options.packagePath)); return EXIT_ERROR; } @@ -886,11 +920,22 @@ int main(int argc, char *argv[]) // do not install or run packages while another test is running testRunnerLock.acquire(); - const QStringList installArgs = { "install"_L1, "-r"_L1, "-g"_L1, g_options.apkPath }; - g_testInfo.isPackageInstalled.store(execAdbCommand(installArgs, nullptr)); - if (!g_testInfo.isPackageInstalled) - return EXIT_ERROR; + if (g_options.packagePath.endsWith(".apk"_L1)) { + const QStringList installArgs = { "install"_L1, "-r"_L1, "-g"_L1, g_options.packagePath }; + g_testInfo.isPackageInstalled.store(execAdbCommand(installArgs, nullptr)); + if (!g_testInfo.isPackageInstalled) + return EXIT_ERROR; + } else if (g_options.packagePath.endsWith(".aab"_L1)) { + QFileInfo aab(g_options.packagePath); + const auto apksFilePath = aab.absoluteDir().absoluteFilePath(aab.baseName() + ".apks"_L1); + if (!execBundletoolCommand({ "build-apks"_L1, "--bundle"_L1, g_options.packagePath, + "--output"_L1, apksFilePath, "--local-testing"_L1, + "--overwrite"_L1 })) + return EXIT_ERROR; + if (!execBundletoolCommand({ "install-apks"_L1, "--apks"_L1, apksFilePath })) + return EXIT_ERROR; + } // Call additional adb command if set after installation and before starting the test for (const auto &command : g_options.preTestRunAdbCommands) { QByteArray output; diff --git a/src/tools/uic/ui4.cpp b/src/tools/uic/ui4.cpp index b6a8f4eb4bf..e26d0260682 100644 --- a/src/tools/uic/ui4.cpp +++ b/src/tools/uic/ui4.cpp @@ -54,6 +54,10 @@ void DomUI::read(QXmlStreamReader &reader) setAttributeIdbasedtr(attribute.value() == u"true"_s); continue; } + if (name == u"label"_s) { + setAttributeLabel(attribute.value().toString()); + continue; + } if (name == u"connectslotsbyname"_s) { setAttributeConnectslotsbyname(attribute.value() == u"true"_s); continue; @@ -192,6 +196,9 @@ void DomUI::write(QXmlStreamWriter &writer, const QString &tagName) const if (hasAttributeIdbasedtr()) writer.writeAttribute(u"idbasedtr"_s, (attributeIdbasedtr() ? u"true"_s : u"false"_s)); + if (hasAttributeLabel()) + writer.writeAttribute(u"label"_s, attributeLabel()); + if (hasAttributeConnectslotsbyname()) writer.writeAttribute(u"connectslotsbyname"_s, (attributeConnectslotsbyname() ? u"true"_s : u"false"_s)); diff --git a/src/tools/uic/ui4.h b/src/tools/uic/ui4.h index 333f7f4e6ad..a46a42c6b73 100644 --- a/src/tools/uic/ui4.h +++ b/src/tools/uic/ui4.h @@ -143,6 +143,11 @@ public: inline void setAttributeIdbasedtr(bool a) { m_attr_idbasedtr = a; m_has_attr_idbasedtr = true; } inline void clearAttributeIdbasedtr() { m_has_attr_idbasedtr = false; } + inline bool hasAttributeLabel() const { return m_has_attr_label; } + inline QString attributeLabel() const { return m_attr_label; } + inline void setAttributeLabel(const QString &a) { m_attr_label = a; m_has_attr_label = true; } + inline void clearAttributeLabel() { m_attr_label.clear(); } + inline bool hasAttributeConnectslotsbyname() const { return m_has_attr_connectslotsbyname; } inline bool attributeConnectslotsbyname() const { return m_attr_connectslotsbyname; } inline void setAttributeConnectslotsbyname(bool a) { m_attr_connectslotsbyname = a; m_has_attr_connectslotsbyname = true; } @@ -264,6 +269,9 @@ private: bool m_attr_idbasedtr = false; bool m_has_attr_idbasedtr = false; + QString m_attr_label; + bool m_has_attr_label = false; + bool m_attr_connectslotsbyname = false; bool m_has_attr_connectslotsbyname = false; diff --git a/src/widgets/REUSE.toml b/src/widgets/REUSE.toml index 98653c588bb..0bfd718750e 100644 --- a/src/widgets/REUSE.toml +++ b/src/widgets/REUSE.toml @@ -3,24 +3,24 @@ version = 1 [[annotations]] path = ["styles/images/*.png", "dialogs/images/*.png", "styles/images/*.svg"] precedence = "closest" -SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." +SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd." SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only" [[annotations]] path = ["doc/**"] precedence = "closest" -SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." +SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd." SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only" [[annotations]] path = ["doc/snippets/**"] precedence = "closest" -SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." +SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd." SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR BSD-3-Clause" [[annotations]] path = ["doc/snippets/common-table-model/README"] precedence = "closest" -SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." +SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd." SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only" diff --git a/src/widgets/itemviews/qheaderview.cpp b/src/widgets/itemviews/qheaderview.cpp index b2fa08e406f..06912d41582 100644 --- a/src/widgets/itemviews/qheaderview.cpp +++ b/src/widgets/itemviews/qheaderview.cpp @@ -3671,10 +3671,8 @@ void QHeaderViewPrivate::resizeSections(QHeaderView::ResizeMode globalMode, bool executePostedLayout(); - if (noSectionMemoryUsage() && - (hasAutoResizeSections() || (useGlobalMode && globalResizeMode != QHeaderView::Fixed))) { + if (noSectionMemoryUsage() && (hasAutoResizeSections() || globalMode != QHeaderView::Fixed)) setHeaderMode(HeaderMode::FlexibleWithSectionMemoryUsage); - } if (sectionCount() == 0 ) return; diff --git a/src/widgets/kernel/qtestsupport_widgets.cpp b/src/widgets/kernel/qtestsupport_widgets.cpp index 5a7200e58aa..ce40ba8c6dd 100644 --- a/src/widgets/kernel/qtestsupport_widgets.cpp +++ b/src/widgets/kernel/qtestsupport_widgets.cpp @@ -31,6 +31,17 @@ static bool qWaitForWidgetWindow(QWidget *w, Predicate predicate, QDeadlineTimer /*! \since 5.0 + \overload + + The \a timeout is in milliseconds. +*/ +bool QTest::qWaitForWindowActive(QWidget *widget, int timeout) +{ + return qWaitForWindowActive(widget, QDeadlineTimer{timeout, Qt::TimerType::PreciseTimer}); +} + +/*! + \since 6.10 Returns \c true if \a widget is active within \a timeout milliseconds. Otherwise returns \c false. @@ -45,7 +56,7 @@ static bool qWaitForWidgetWindow(QWidget *w, Predicate predicate, QDeadlineTimer \sa qWaitForWindowExposed(), QWidget::isActiveWindow() */ -Q_WIDGETS_EXPORT bool QTest::qWaitForWindowActive(QWidget *widget, int timeout) +bool QTest::qWaitForWindowActive(QWidget *widget, QDeadlineTimer timeout) { if (Q_UNLIKELY(!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))) { qWarning() << "qWaitForWindowActive was called on a platform that doesn't support window" @@ -57,9 +68,19 @@ Q_WIDGETS_EXPORT bool QTest::qWaitForWindowActive(QWidget *widget, int timeout) } return qWaitForWidgetWindow(widget, [&](QWindow *window) { return window->isActive(); }, - QDeadlineTimer{timeout, Qt::TimerType::PreciseTimer}); + timeout); } +/*! + \since 6.10 + \overload + + This function uses the default timeout of 5 seconds. +*/ +bool QTest::qWaitForWindowActive(QWidget *widget) +{ + return qWaitForWindowActive(widget, Internal::defaultTryTimeout); +} /*! \since 6.7 @@ -86,7 +107,30 @@ Q_WIDGETS_EXPORT bool QTest::qWaitForWindowFocused(QWidget *widget, QDeadlineTim } /*! + \since 6.10 + \overload + + This function uses the default timeout of 5 seconds. +*/ +bool QTest::qWaitForWindowFocused(QWidget *widget) +{ + return qWaitForWindowFocused(widget, Internal::defaultTryTimeout); +} + +/*! \since 5.0 + \overload + + The \a timeout is in milliseconds. +*/ +bool QTest::qWaitForWindowExposed(QWidget *widget, int timeout) +{ + return qWaitForWindowExposed(widget, std::chrono::milliseconds(timeout)); +} + + +/*! + \since 6.10 Returns \c true if \a widget is exposed within \a timeout milliseconds. Otherwise returns \c false. @@ -99,11 +143,22 @@ Q_WIDGETS_EXPORT bool QTest::qWaitForWindowFocused(QWidget *widget, QDeadlineTim \sa qWaitForWindowActive(), QWidget::isVisible(), QWindow::isExposed() */ -Q_WIDGETS_EXPORT bool QTest::qWaitForWindowExposed(QWidget *widget, int timeout) +bool QTest::qWaitForWindowExposed(QWidget *widget, QDeadlineTimer timeout) { return qWaitForWidgetWindow(widget, [&](QWindow *window) { return window->isExposed(); }, - QDeadlineTimer{timeout, Qt::TimerType::PreciseTimer}); + timeout); +} + +/*! + \since 6.10 + \overload + + This function uses the default timeout of 5 seconds. +*/ +bool QTest::qWaitForWindowExposed(QWidget *widget) +{ + return qWaitForWindowExposed(widget, Internal::defaultTryTimeout); } namespace QTest { diff --git a/src/widgets/kernel/qtestsupport_widgets.h b/src/widgets/kernel/qtestsupport_widgets.h index b49e68db651..4b5e5ff7772 100644 --- a/src/widgets/kernel/qtestsupport_widgets.h +++ b/src/widgets/kernel/qtestsupport_widgets.h @@ -14,9 +14,16 @@ class QWidget; namespace QTest { -[[nodiscard]] Q_WIDGETS_EXPORT bool qWaitForWindowActive(QWidget *widget, int timeout = 5000); -[[nodiscard]] Q_WIDGETS_EXPORT bool qWaitForWindowFocused(QWidget *widget, QDeadlineTimer timeout = std::chrono::seconds{5}); -[[nodiscard]] Q_WIDGETS_EXPORT bool qWaitForWindowExposed(QWidget *widget, int timeout = 5000); +[[nodiscard]] Q_WIDGETS_EXPORT bool qWaitForWindowActive(QWidget *widget, int timeout); +[[nodiscard]] Q_WIDGETS_EXPORT bool qWaitForWindowActive(QWidget *widget, QDeadlineTimer timeout); +[[nodiscard]] Q_WIDGETS_EXPORT bool qWaitForWindowActive(QWidget *widget); + +[[nodiscard]] Q_WIDGETS_EXPORT bool qWaitForWindowFocused(QWidget *widget, QDeadlineTimer timeout); +[[nodiscard]] Q_WIDGETS_EXPORT bool qWaitForWindowFocused(QWidget *widget); + +[[nodiscard]] Q_WIDGETS_EXPORT bool qWaitForWindowExposed(QWidget *widget, int timeout); +[[nodiscard]] Q_WIDGETS_EXPORT bool qWaitForWindowExposed(QWidget *widget, QDeadlineTimer timeout); +[[nodiscard]] Q_WIDGETS_EXPORT bool qWaitForWindowExposed(QWidget *widget); class Q_WIDGETS_EXPORT QTouchEventWidgetSequence : public QTouchEventSequence { diff --git a/src/widgets/kernel/qwidgetsvariant.cpp b/src/widgets/kernel/qwidgetsvariant.cpp index 17a19aa780d..c843927d366 100644 --- a/src/widgets/kernel/qwidgetsvariant.cpp +++ b/src/widgets/kernel/qwidgetsvariant.cpp @@ -11,18 +11,16 @@ QT_BEGIN_NAMESPACE namespace { - -// NOLINTNEXTLINE(cppcoreguidelines-virtual-class-destructor): this is not a base class -static constexpr struct : QMetaTypeModuleHelper +struct QVariantWidgetsHelper : QMetaTypeModuleHelper { - const QtPrivate::QMetaTypeInterface *interfaceForType(int type) const override { + static const QtPrivate::QMetaTypeInterface *interfaceForType(int type) + { switch (type) { QT_FOR_EACH_STATIC_WIDGETS_CLASS(QT_METATYPE_CONVERT_ID_TO_TYPE) default: return nullptr; } } -} qVariantWidgetsHelper; - +}; #undef QT_IMPL_METATYPEINTERFACE_WIDGETS_TYPES @@ -30,7 +28,9 @@ static constexpr struct : QMetaTypeModuleHelper void qRegisterWidgetsVariant() { - qMetaTypeWidgetsHelper = &qVariantWidgetsHelper; + qMetaTypeWidgetsHelper = QMetaTypeModuleHelper{ + &QVariantWidgetsHelper::interfaceForType, + }; } Q_CONSTRUCTOR_FUNCTION(qRegisterWidgetsVariant) diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index 4cf2934a2dc..b85446121bd 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -622,7 +622,21 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event) } } QApplicationPrivate::replayMousePress = false; +#ifndef QT_NO_CONTEXTMENU + } else if (event->type() == QGuiApplicationPrivate::contextMenuEventType() + && event->button() == Qt::RightButton) { + QWidget *receiver = activePopupWidget; + if (qt_button_down) + receiver = qt_button_down; + else if (popupChild) + receiver = popupChild; + const QPoint localPos = receiver->mapFromGlobal(event->globalPosition().toPoint()); + QContextMenuEvent e(QContextMenuEvent::Mouse, localPos, event->globalPosition().toPoint(), event->modifiers()); + QApplication::forwardEvent(receiver, &e, event); + } +#else } +#endif if (releaseAfter) { qt_button_down = nullptr; diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp index b5972411534..60ec043d094 100644 --- a/src/widgets/styles/qcommonstyle.cpp +++ b/src/widgets/styles/qcommonstyle.cpp @@ -5434,7 +5434,8 @@ int QCommonStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget case SH_Menu_AllowActiveAndDisabled: case SH_Menu_SpaceActivatesItem: case SH_ScrollView_FrameOnlyAroundContents: - case SH_ComboBox_ListMouseTracking: + case SH_ComboBox_ListMouseTracking_Current: + case SH_ComboBox_ListMouseTracking_Active: case SH_Menu_MouseTracking: case SH_MenuBar_MouseTracking: case SH_ItemView_ChangeHighlightOnFocus: diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp index e9cc250c517..c341a025115 100644 --- a/src/widgets/styles/qfusionstyle.cpp +++ b/src/widgets/styles/qfusionstyle.cpp @@ -591,7 +591,7 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem, if (option->state & State_HasFocus && option->state & State_KeyboardFocusChange) painter->setPen(highlightedOutline); else - painter->setPen(colorScheme() == Qt::ColorScheme::Dark ? outline.lighter(150) + painter->setPen(colorScheme() == Qt::ColorScheme::Dark ? outline.lighter(240) : outline.lighter(110)); painter->drawRect(rect); diff --git a/src/widgets/styles/qfusionstyle_p_p.h b/src/widgets/styles/qfusionstyle_p_p.h index 67abdd74dc8..62641609d59 100644 --- a/src/widgets/styles/qfusionstyle_p_p.h +++ b/src/widgets/styles/qfusionstyle_p_p.h @@ -70,10 +70,7 @@ public: } if (pal.window().style() == Qt::TexturePattern) return QColor(0, 0, 0, 160); - if (colorScheme() == Qt::ColorScheme::Dark) - return pal.window().color().lighter(140); - else - return pal.window().color().darker(140); + return pal.window().color().darker(140); } QColor highlightedOutline(const QPalette &pal) const { diff --git a/src/widgets/styles/qstyle.cpp b/src/widgets/styles/qstyle.cpp index 6bb0728cfd4..e72e645e69c 100644 --- a/src/widgets/styles/qstyle.cpp +++ b/src/widgets/styles/qstyle.cpp @@ -1736,8 +1736,16 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment, by pressing Alt, followed by using the arrow keys to select the desired item. - \value SH_ComboBox_ListMouseTracking Mouse tracking in combobox - drop-down lists. + \value SH_ComboBox_ListMouseTracking_Current Mouse tracking in + combobox drop-down lists, the item under the cursor is made + the current item (QStyle::State_Selected). + + \value SH_ComboBox_ListMouseTracking same as + SH_ComboBox_ListMouseTracking_Current + + \value SH_ComboBox_ListMouseTracking_Active Mouse tracking in + combobox drop-down lists, the item under the cursor is not + made the current item, only active (QStyle::State_MouseOver). \value SH_Menu_MouseTracking Mouse tracking in popup menus. diff --git a/src/widgets/styles/qstyle.h b/src/widgets/styles/qstyle.h index db09eedc70d..d6bccf9f698 100644 --- a/src/widgets/styles/qstyle.h +++ b/src/widgets/styles/qstyle.h @@ -602,6 +602,7 @@ public: SH_ScrollView_FrameOnlyAroundContents, SH_MenuBar_AltKeyNavigation, SH_ComboBox_ListMouseTracking, + SH_ComboBox_ListMouseTracking_Current = SH_ComboBox_ListMouseTracking, SH_Menu_MouseTracking, SH_MenuBar_MouseTracking, SH_ItemView_ChangeHighlightOnFocus, @@ -704,6 +705,7 @@ public: SH_TabBar_AllowWheelScrolling, SH_Table_AlwaysDrawLeftTopGridLines, SH_SpinBox_SelectOnStep, + SH_ComboBox_ListMouseTracking_Active, // Add new style hint values here SH_CustomBase = 0xf0000000 diff --git a/src/widgets/styles/qwindowsstyle.cpp b/src/widgets/styles/qwindowsstyle.cpp index 907628f224e..d6daa681798 100644 --- a/src/widgets/styles/qwindowsstyle.cpp +++ b/src/widgets/styles/qwindowsstyle.cpp @@ -461,7 +461,7 @@ int QWindowsStyle::styleHint(StyleHint hint, const QStyleOption *opt, const QWid case SH_MenuBar_AltKeyNavigation: case SH_MenuBar_MouseTracking: case SH_Menu_MouseTracking: - case SH_ComboBox_ListMouseTracking: + case SH_ComboBox_ListMouseTracking_Current: case SH_Slider_StopMouseOverSlider: case SH_MainWindow_SpaceBelowMenuBar: ret = 1; diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp index fbec606ae4a..aa58ac8d75d 100644 --- a/src/widgets/widgets/qcombobox.cpp +++ b/src/widgets/widgets/qcombobox.cpp @@ -640,8 +640,10 @@ void QComboBoxPrivateContainer::setItemView(QAbstractItemView *itemView) if (usePopup) view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); #endif - if (combo->style()->styleHint(QStyle::SH_ComboBox_ListMouseTracking, &opt, combo) || - usePopup) { + if (usePopup || + combo->style()->styleHint(QStyle::SH_ComboBox_ListMouseTracking_Current, &opt, combo) || + combo->style()->styleHint(QStyle::SH_ComboBox_ListMouseTracking_Active, &opt, combo) + ) { view->setMouseTracking(true); } view->setSelectionMode(QAbstractItemView::SingleSelection); @@ -775,10 +777,12 @@ bool QComboBoxPrivateContainer::eventFilter(QObject *o, QEvent *e) QPoint vector = widget->mapToGlobal(m->position().toPoint()) - initialClickPosition; if (vector.manhattanLength() > 9 && blockMouseReleaseTimer.isActive()) blockMouseReleaseTimer.stop(); - QModelIndex indexUnderMouse = view->indexAt(m->position().toPoint()); - if (indexUnderMouse.isValid() - && !QComboBoxDelegate::isSeparator(indexUnderMouse)) { - view->setCurrentIndex(indexUnderMouse); + if (combo->style()->styleHint(QStyle::SH_ComboBox_ListMouseTracking_Current, nullptr, combo)) { + QModelIndex indexUnderMouse = view->indexAt(m->position().toPoint()); + if (indexUnderMouse.isValid() + && !QComboBoxDelegate::isSeparator(indexUnderMouse)) { + view->setCurrentIndex(indexUnderMouse); + } } } break; diff --git a/src/widgets/widgets/qdockarealayout.cpp b/src/widgets/widgets/qdockarealayout.cpp index f5d92094f54..c1ce675d75a 100644 --- a/src/widgets/widgets/qdockarealayout.cpp +++ b/src/widgets/widgets/qdockarealayout.cpp @@ -3327,7 +3327,8 @@ int QDockAreaLayout::separatorMove(const QList<int> &separator, const QPoint &or { int delta = 0; const auto dockPosition = static_cast<QInternal::DockPosition>(separator.last()); - const bool isHorizontal = dockPosition == QInternal::LeftDock || dockPosition == QInternal::TopDock; + const bool isHorizontal = + dockPosition == QInternal::LeftDock || dockPosition == QInternal::RightDock; const bool isLeftOrTop = dockPosition == QInternal::LeftDock || dockPosition == QInternal::TopDock; const bool separatorIsWithinDock = separator.size() > 1; diff --git a/src/widgets/widgets/qscrollbar.cpp b/src/widgets/widgets/qscrollbar.cpp index af7a2e011b8..92ccfe7db9d 100644 --- a/src/widgets/widgets/qscrollbar.cpp +++ b/src/widgets/widgets/qscrollbar.cpp @@ -126,8 +126,8 @@ using namespace Qt::StringLiterals; ScrollBar inherits a comprehensive set of signals from QAbstractSlider: \list \li \l{QAbstractSlider::valueChanged()}{valueChanged()} is emitted when the - scroll bar's value has changed. The tracking() determines whether this - signal is emitted during user interaction. + scroll bar's value has changed. The \l{QAbstractSlider::}{tracking} property + determines whether this signal is emitted during user interaction. \li \l{QAbstractSlider::rangeChanged()}{rangeChanged()} is emitted when the scroll bar's range of values has changed. \li \l{QAbstractSlider::sliderPressed()}{sliderPressed()} is emitted when diff --git a/src/widgets/widgets/qtoolbararealayout.cpp b/src/widgets/widgets/qtoolbararealayout.cpp index 54c21b60387..0d7227eb038 100644 --- a/src/widgets/widgets/qtoolbararealayout.cpp +++ b/src/widgets/widgets/qtoolbararealayout.cpp @@ -564,19 +564,19 @@ int QToolBarAreaLayoutInfo::distance(const QPoint &pos) const { switch (dockPos) { case QInternal::LeftDock: - if (pos.y() < rect.bottom()) + if (pos.y() > 0 && pos.y() < rect.bottom()) return pos.x() - rect.right(); break; case QInternal::RightDock: - if (pos.y() < rect.bottom()) + if (pos.y() > 0 && pos.y() < rect.bottom()) return rect.left() - pos.x(); break; case QInternal::TopDock: - if (pos.x() < rect.right()) + if (pos.x() > 0 && pos.x() < rect.right()) return pos.y() - rect.bottom(); break; case QInternal::BottomDock: - if (pos.x() < rect.right()) + if (pos.x() > 0 && pos.x() < rect.right()) return rect.top() - pos.y(); break; |