diff --git a/.github/actions/get-workflow-artifact-ids/action.yml b/.github/actions/get-workflow-artifact-ids/action.yml new file mode 100644 index 000000000000..9361c6fff39b --- /dev/null +++ b/.github/actions/get-workflow-artifact-ids/action.yml @@ -0,0 +1,34 @@ +name: 'Get Workflow Artifact IDs' +description: 'Generates consistent artifact IDs and names based on workflow trigger' + +outputs: + filename: + description: 'Filename to use for artifacts (e.g. pr123)' + value: ${{ steps.generate-ids.outputs.filename }} + display-name: + description: 'Human readable name (e.g. PR123)' + value: ${{ steps.generate-ids.outputs.display_name }} + +runs: + using: "composite" + steps: + - id: generate-ids + shell: bash + run: | + if [ "${{ github.event_name }}" = "pull_request" ]; then + ID="pr${{ github.event.pull_request.number }}" + DISPLAY_ID="PR${{ github.event.pull_request.number }}" + elif [[ "${{ github.ref }}" == refs/tags/* ]]; then + TAG=${GITHUB_REF#refs/tags/} + ID="$TAG" + DISPLAY_ID="$TAG" + else + SHORT_SHA=$(echo ${{ github.sha }} | cut -c1-7) + BRANCH_NAME=${GITHUB_REF#refs/heads/} + ID="$BRANCH_NAME-$SHORT_SHA" + DISPLAY_ID="$BRANCH_NAME-$SHORT_SHA" + fi + + # Set outputs + echo "filename=$ID" >> $GITHUB_OUTPUT + echo "display_name=$DISPLAY_ID" >> $GITHUB_OUTPUT diff --git a/.github/actions/vcpkg_update_report/vcpkg-diff.py b/.github/actions/vcpkg_update_report/vcpkg-diff.py index 21ff42ef772f..99ee2d8da3a8 100644 --- a/.github/actions/vcpkg_update_report/vcpkg-diff.py +++ b/.github/actions/vcpkg_update_report/vcpkg-diff.py @@ -10,7 +10,7 @@ def extract_packages(data): for line in lines: # Regex to match the package format and capture features inside brackets match = re.match( - r"\s*\*\s+([^\[\]:]+)(?:\[(.*?)\])?:([^\[\]@]+)@([^\s]+)\s+--", line + r"\s*\*?\s+([^\[\]:]+)(?:\[(.*?)\])?:([^\[\]@]+)@([^\s]+)\s+--", line ) if match: package_name = match.group(1) diff --git a/.github/workflows/build-macos-qt6.yml b/.github/workflows/build-macos-qt6.yml index 37a7a79242d9..8902948e36f3 100644 --- a/.github/workflows/build-macos-qt6.yml +++ b/.github/workflows/build-macos-qt6.yml @@ -1,12 +1,13 @@ --- name: 🍎 Build - MacOS Qt6 on: - # push: - # branches: - # - main - # pull_request: - # release: - # types: ['published'] + push: + branches: + - master + - release-* + pull_request: + release: + types: ['published'] workflow_dispatch: concurrency: @@ -18,9 +19,9 @@ jobs: strategy: matrix: include: -# - os: macos-13 -# triplet: x64-osx -# deployment-target: "10.15" + - os: macos-13 + triplet: x64-osx-dynamic-release + deployment-target: "10.15" - os: macos-14 triplet: arm64-osx-dynamic-release deployment-target: "11.0" @@ -42,9 +43,13 @@ jobs: id: setup-vcpkg uses: ./.github/actions/setup-vcpkg + - name: 🎲 Get artifact ids + id: workflow-artifact-ids + uses: ./.github/actions/get-workflow-artifact-ids + - name: πŸ”¨ Prepare build env run: | - brew install automake bison flex gnu-sed create-dmg autoconf-archive nasm libtool fdupes + brew install automake bison flex gnu-sed autoconf-archive nasm libtool fdupes echo $(brew --prefix bison)/bin >> $GITHUB_PATH echo $(brew --prefix flex)/bin >> $GITHUB_PATH echo $(brew --prefix libtool)/bin >> $GITHUB_PATH @@ -58,7 +63,22 @@ jobs: with: xcode-version: latest-stable + - name: πŸ›οΈ Setup ccache + uses: hendrikmuhs/ccache-action@v1.2 + with: + max-size: 500M + key: build-ccache-${{ matrix.triplet }}-qt6-${{Β github.event.pull_request.base.ref || github.ref_name }} + save: ${{ github.event_name == 'push' }} + + - name: πŸ›οΈ Tune ccache configuration + shell: bash + run: | + # To make ccache work properly with precompiled headers + ccache --set-config sloppiness=pch_defines,time_macros,include_file_mtime,include_file_ctime + - name: 🌱 Install dependencies and generate project files + env: + X_VCPKG_ASSET_SOURCES: x-azurl,https://assetcache.open-vcpkg.org/assetcache,,read run: | echo "VCPKG_ROOT: ${VCPKG_ROOT}" @@ -67,18 +87,22 @@ jobs: cmake -S . \ -G Ninja \ -B build \ + -D QGIS_APP_NAME="QGIS-${{steps.workflow-artifact-ids.outputs.display-name}}" \ -D WITH_VCPKG=ON \ -D BUILD_WITH_QT6=ON \ -D WITH_QTWEBKIT=OFF \ -D WITH_BINDINGS=ON \ - -D QGIS_MACAPP_FRAMEWORK=OFF \ + -D WITH_ORACLE=ON \ -D VCPKG_TARGET_TRIPLET="${{ matrix.triplet }}" \ -D VCPKG_HOST_TRIPLET="${{ matrix.triplet }}" \ -D VCPKG_INSTALL_OPTIONS="--only-binarycaching" \ + -D CMAKE_OSX_DEPLOYMENT_TARGET=${{ matrix.deployment-target }} \ + -D ENABLE_UNITY_BUILDS=ON \ -D NUGET_USERNAME=${{ github.actor }} \ + -D NUGET_SOURCE="https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json" \ -D NUGET_TOKEN=${{ secrets.GITHUB_TOKEN }} || true - fdupes -r -1 build/vcpkg_installed/arm64-osx-dynamic/lib | grep libQt | while read line; do master=""; for file in ${line[*]}; do if [[ "x${master}" == "x" ]]; then master=$file; else rm "${file}"; ln -s $(basename "${master}") "${file}"; fi; done; done + fdupes -q -r -1 build/vcpkg_installed/${{ matrix.triplet }}/lib | grep libQt | while read line; do master=""; for file in ${line[*]}; do if [[ "x${master}" == "x" ]]; then master=$file; else rm "${file}"; ln -s $(basename "${master}") "${file}"; fi; done; done cmake -D VCPKG_INSTALL_OPTIONS="" build @@ -99,10 +123,100 @@ jobs: if: github.event_name == 'workflow_dispatch' || github.event_name == 'release' uses: actions/upload-artifact@v4 with: - name: kadas-albireo2-sdk-${{ matrix.triplet }} + name: qgis-sdk-${{ matrix.triplet }} path: | sdk/vcpkg-export-*.zip - name: πŸŒ‹ Build run: | + # We make sure the target "all" is built before bundling + # Ideally, we would specify each target that is required to be installed, but this workaround is sufficient for now cmake --build build + cmake --build build --target bundle + + - name: Archive app + run: | + gtar -cpvzf qgis-app-${{steps.workflow-artifact-ids.outputs.filename}}-${{ matrix.triplet }}.tar.gz ./build/_CPack_Packages/Darwin/External/*/*.app + + - name: πŸ“€ Upload app + uses: actions/upload-artifact@v4 + with: + name: qgis-app-${{steps.workflow-artifact-ids.outputs.filename}}-${{ matrix.triplet }} + path: | + qgis-app-${{steps.workflow-artifact-ids.outputs.filename}}-${{ matrix.triplet }}.tar.gz + + schedule_download_comment: + name: Create dmg + runs-on: macos-latest + needs: build + steps: + - name: 🐣 Checkout + uses: actions/checkout@v4 + + - name: πŸ”¨ Prepare build env + run: | + brew install create-dmg + + + - name: 🎲 Get artifact ids + id: workflow-artifact-ids + uses: ./.github/actions/get-workflow-artifact-ids + + - name: πŸ“€ Download app + uses: actions/download-artifact@v4 + with: + pattern: qgis-app-${{steps.workflow-artifact-ids.outputs.filename}}-* + path: | + artifacts + + - name: Create universal app + run: | + mkdir -p x64 + gtar --strip-components=5 -zxf ./artifacts/qgis-app-${{steps.workflow-artifact-ids.outputs.filename}}-x64-osx-dynamic-release/qgis-app-${{steps.workflow-artifact-ids.outputs.filename}}-x64-osx-dynamic-release.tar.gz -C x64 + mkdir -p arm64 + gtar --strip-components=5 -zxf ./artifacts/qgis-app-${{steps.workflow-artifact-ids.outputs.filename}}-arm64-osx-dynamic-release/qgis-app-${{steps.workflow-artifact-ids.outputs.filename}}-arm64-osx-dynamic-release.tar.gz -C arm64 + + pip install lipomerge + lipomerge ./x64 ./arm64 universal + + - name: Create dmg + run: | + QGIS_APP_NAME=QGIS-"${{steps.workflow-artifact-ids.outputs.display-name}}" + create-dmg --volname "${QGIS_APP_NAME} Installer" \ + --hide-extension ${QGIS_APP_NAME}.app \ + --volicon "$(pwd)/images/icons/mac/qgis.icns" \ + --background "$(pwd)/platform/macos/installer_background.png" \ + --window-pos 200 120 \ + --window-size 512 320 \ + --icon-size 100 \ + --icon "${QGIS_APP_NAME}.app" 130 160 \ + --app-drop-link 400 155 \ + ${QGIS_APP_NAME}-Installer.dmg \ + universal/*/*.app + + - name: πŸ“€ Upload app + uses: actions/upload-artifact@v4 + id: artifact-mac-qt6 + with: + name: qgis-${{steps.workflow-artifact-ids.outputs.filename}}-dmg + path: | + *.dmg + + - name: Upload release assets + uses: AButler/upload-release-assets@v3.0 + if: ${{ github.event_name == 'release' }} + with: + files: '*.dmg' + repo-token: ${{ secrets.GITHUB_TOKEN }} + + - name: Schedule download comment + uses: ./.github/actions/post_sticky_comment + if: github.event_name == 'pull_request' + with: + marker: macos-qt6 + body: | + ### 🍎 MacOS Qt6 builds + Download [MacOS Qt6 builds of this PR for testing](${{ steps.artifact-mac-qt6.outputs.artifact-url }}). + _This installer is not signed, `control`+click > `open` the app to avoid the warning_ + *(Built from commit ${{ github.event.pull_request.head.sha }})* + pr: ${{ github.event.number }} diff --git a/.github/workflows/macos-build.yml b/.github/workflows/macos-build.yml deleted file mode 100644 index 9395c1c73676..000000000000 --- a/.github/workflows/macos-build.yml +++ /dev/null @@ -1,140 +0,0 @@ -name: 🍏 Mac OS build - -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - -on: - push: - branches: - - master - - release-** - - queued_ltr_backports - paths: - pull_request: - branches: - - master - - release-** - - queued_ltr_backports - paths: - -permissions: - contents: read - -env: - QT_VERSION: 5.15.2 - QGIS_DEPS_VERSION: 0.9 - QGIS_DEPS_PATCH_VERSION: 0 - CCACHE_DIR: /Users/runner/work/ccache - BUILD_DIR: /Users/runner/work/QGIS/build-QGIS - # apparently we cannot cache /opt directory as it fails to restore - # so we copy the deps in the home directory - DEPS_CACHE_DIR: /Users/runner/work/deps-cache - -jobs: - mac_os_build: - if: github.repository == 'qgis/QGIS' - runs-on: macos-13 - steps: - - uses: actions/checkout@v4 - - - name: Restore build cache - uses: actions/cache/restore@v4 - with: - path: ${{ env.CCACHE_DIR }} - key: build-ccache-mac-${{Β github.event.pull_request.base.ref || github.ref_name }} - restore-keys: | - build-ccache-mac-master - - - name: Cache Qt - id: cache-qt - uses: actions/cache@v4 - with: - path: ${{ env.DEPS_CACHE_DIR }}/Qt/${{ env.QT_VERSION }} - key: mac-qt-${{ env.QT_VERSION }} - - - name: Restore Qt - if: steps.cache-qt.outputs.cache-hit == 'true' - run: | - sudo mkdir -p /opt - sudo mkdir -p /opt/Qt - sudo cp -r ${DEPS_CACHE_DIR}/Qt/${QT_VERSION} /opt/Qt/${QT_VERSION} - - - name: Download Qt - if: steps.cache-qt.outputs.cache-hit != 'true' - run: | - wget https://qgis.org/downloads/macos/deps/qt-${QT_VERSION}.tar.gz - mkdir -p ${DEPS_CACHE_DIR} - mkdir -p ${DEPS_CACHE_DIR}/Qt - - - # QGIS-deps caching - - name: Cache qgis-deps - id: cache-deps - uses: actions/cache@v4 - with: - path: ${{ env.DEPS_CACHE_DIR }}/QGIS/qgis-deps-${{ env.QGIS_DEPS_VERSION }}.${{ env.QGIS_DEPS_PATCH_VERSION }} - key: mac-qgis-deps-${{ env.QGIS_DEPS_VERSION }}.${{ env.QGIS_DEPS_PATCH_VERSION }} - - - name: Restore qgis-deps - if: steps.cache-deps.outputs.cache-hit == 'true' - run: | - sudo mkdir -p /opt - sudo mkdir -p /opt/QGIS - sudo cp -r ${DEPS_CACHE_DIR}/QGIS/qgis-deps-${QGIS_DEPS_VERSION}.${QGIS_DEPS_PATCH_VERSION} /opt/QGIS/qgis-deps-${QGIS_DEPS_VERSION} - - - name: Download qgis-deps - if: steps.cache-deps.outputs.cache-hit != 'true' - run: | - wget https://qgis.org/downloads/macos/deps/qgis-deps-${QGIS_DEPS_VERSION}.${QGIS_DEPS_PATCH_VERSION}.tar.gz - mkdir -p ${DEPS_CACHE_DIR} - mkdir -p ${DEPS_CACHE_DIR}/QGIS - - - name: Install Qt and deps - env: - QT_ALREADY_CACHED: ${{ steps.cache-qt.outputs.cache-hit }} - QGIS_DEPS_ALREADY_CACHED: ${{ steps.cache-deps.outputs.cache-hit }} - run: | - wget https://qgis.org/downloads/macos/deps/install_qgis_deps-${QGIS_DEPS_VERSION}.${QGIS_DEPS_PATCH_VERSION}.bash - chmod +x ./install_qgis_deps-${QGIS_DEPS_VERSION}.${QGIS_DEPS_PATCH_VERSION}.bash - echo ::group::Install deps - sudo ./install_qgis_deps-${QGIS_DEPS_VERSION}.${QGIS_DEPS_PATCH_VERSION}.bash - echo ::endgroup:: - [[ ${QT_ALREADY_CACHED} != "true" ]] && cp -r /opt/Qt/${QT_VERSION} ${DEPS_CACHE_DIR}/Qt/${QT_VERSION} || true - [[ ${QGIS_DEPS_ALREADY_CACHED} != "true" ]] && cp -r /opt/QGIS/qgis-deps-${QGIS_DEPS_VERSION} ${DEPS_CACHE_DIR}/QGIS/qgis-deps-${QGIS_DEPS_VERSION}.${QGIS_DEPS_PATCH_VERSION} || true - - - name: Install ccache - run: | - mkdir -p ${CCACHE_DIR} - brew install ccache - ccache --set-config=max_size=2.0G - # To make ccache work properly with precompiled headers - ccache --set-config sloppiness=pch_defines,time_macros,include_file_mtime,include_file_ctime - ccache -s - - - name: Run cmake - run: | - mkdir -p ${BUILD_DIR} - cd ${BUILD_DIR} - - PATH=/opt/QGIS/qgis-deps-${QGIS_DEPS_VERSION}/stage/bin:$PATH \ - cmake -DQGIS_MAC_DEPS_DIR=/opt/QGIS/qgis-deps-${QGIS_DEPS_VERSION}/stage \ - -DCMAKE_PREFIX_PATH=/opt/Qt/${QT_VERSION}/clang_64 \ - -DWITH_BINDINGS=TRUE \ - -DWITH_3D=TRUE \ - -DWITH_DRACO=FALSE \ - -DWITH_PDAL=TRUE \ - -DWITH_EPT=TRUE \ - ../QGIS - - - name: Build QGIS - run: | - cd ${BUILD_DIR} - make -j $(sysctl -n hw.ncpu) - - - name: Save build cache for push only - uses: actions/cache/save@v4 - if: ${{ github.event_name == 'push' }} - with: - path: ${{ env.CCACHE_DIR }} - key: build-ccache-mac-${{ github.ref_name }}-${{ github.run_id }} diff --git a/CMakeLists.txt b/CMakeLists.txt index ec9f69d0336e..cbcfd10cbb10 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,6 +24,7 @@ set (WITH_3D TRUE CACHE BOOL "Determines whether QGIS 3D library should be built set (WITH_QGIS_PROCESS TRUE CACHE BOOL "Determines whether the standalone \"qgis_process\" tool should be built") set (WITH_DESKTOP TRUE CACHE BOOL "Determines whether QGIS desktop should be built") set (WITH_GUI TRUE CACHE BOOL "Determines whether QGIS GUI library should be built") +set (WITH_ORACLE FALSE CACHE BOOL "Determines whether Oracle support should be built") set(WITH_VCPKG FALSE CACHE BOOL "Use the vcpkg submodule for dependency management.") set(SDK_PATH "" CACHE STRING "Build with VCPKG SDK") @@ -46,10 +47,11 @@ endif() if(WITH_VCPKG) + set(TARGET_SYSROOT "${VCPKG_INSTALL_PREFIX}/${VCPKG_TARGET_TRIPLET}") if(WIN32) - list(APPEND CMAKE_PROGRAM_PATH "${VCPKG_INSTALL_PREFIX}/${VCPKG_TARGET_TRIPLET}/tools/python3/Scripts/") + list(APPEND CMAKE_PROGRAM_PATH "${TARGET_SYSROOT}/tools/python3/Scripts/") else() - list(APPEND CMAKE_PROGRAM_PATH "${VCPKG_INSTALL_PREFIX}/${VCPKG_TARGET_TRIPLET}/bin") + list(APPEND CMAKE_PROGRAM_PATH "${TARGET_SYSROOT}/bin") endif() set(PREFER_INTERNAL_LIBS FALSE) else() @@ -65,11 +67,7 @@ set(COMPLETE_VERSION ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINO set(RELEASE_NAME "Master") project(qgis VERSION ${COMPLETE_VERSION}) -if (APPLE) - set(QGIS_APP_NAME "QGIS") -else() - set(QGIS_APP_NAME "qgis") -endif() +set(QGIS_APP_NAME "qgis" CACHE STRING "The main app name and bundle name") # Note the version no is Mmmpp for Major/minor/patch, 0-padded, thus '10100' for 1.1.0 math(EXPR QGIS_VERSION_INT "${CPACK_PACKAGE_VERSION_MAJOR}*10000+${CPACK_PACKAGE_VERSION_MINOR}*100+${CPACK_PACKAGE_VERSION_PATCH}") @@ -77,21 +75,6 @@ message(STATUS "QGIS version: ${COMPLETE_VERSION} ${RELEASE_NAME} (${QGIS_VERSIO set (ENABLE_LOCAL_BUILD_SHORTCUTS FALSE CACHE BOOL "Disables some build steps which are only relevant for releases to speed up compilation time for development") -############################################################# -if (APPLE) - # QGIS custom dependencies package from qgis/QGIS-Mac-Packager - # they can be downloaded from https://download.qgis.org/downloads/macos/deps/ - # and extracted to /opt/QGIS/qgis-deps-/stage - set (QGIS_MAC_DEPS_DIR "" CACHE PATH "Path to QGIS Mac custom dependencies directory") - - # Setup LIB_DIR and CMAKE_PREFIX_PATH to help CMake's - # find_packages to look for these libraries instead of system libraries - if ( QGIS_MAC_DEPS_DIR ) - set(ENV{LIB_DIR} ${QGIS_MAC_DEPS_DIR}) - list(APPEND CMAKE_PREFIX_PATH ${QGIS_MAC_DEPS_DIR}) - endif() -endif() - ############################################################# # Configure OpenCL if available set(HAVE_OPENCL FALSE) @@ -349,7 +332,6 @@ if(WITH_CORE) set (WITH_QSPATIALITE FALSE CACHE BOOL "Determines whether QSPATIALITE sql driver should be built") endif() - set (WITH_ORACLE FALSE CACHE BOOL "Determines whether Oracle support should be built") if(WITH_ORACLE) set(HAVE_ORACLE TRUE) set(ORACLE_INCLUDEDIR "" CACHE STRING "Path to OCI headers") @@ -913,6 +895,27 @@ if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}" ST include("cmake/modules/linker.cmake") endif() +set(MIN_PYTHON_VERSION "3.9") +set(Python_FIND_FRAMEWORK "LAST") + +if (WITH_BINDINGS) + find_package(Python ${MIN_PYTHON_VERSION} REQUIRED COMPONENTS Interpreter Development) +else() + find_package(Python ${MIN_PYTHON_VERSION} REQUIRED COMPONENTS Interpreter) +endif() + +# Fix python site-packages for Fedora +# See https://github.com/qgis/QGIS/issues/54348#issuecomment-1694216152 +if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + if(EXISTS "/etc/fedora-release") + EXECUTE_PROCESS(COMMAND ${Python_EXECUTABLE} -c "import sysconfig;print(sysconfig.get_path(\"platlib\", \"rpm_prefix\"), end=\"\")" OUTPUT_VARIABLE Python_SITEARCH) + endif() +endif() + +message("-- Found Python executable: ${Python_EXECUTABLE} (version ${Python_VERSION})") +message("-- Python library: ${Python_LIBRARIES}") +message("-- Python site-packages: ${Python_SITEARCH}") + ############################################################# # platform specific stuff if (WITH_CORE) @@ -950,64 +953,29 @@ if (WITH_CORE) else() if(APPLE) - set(QGIS_MACAPP_FRAMEWORK TRUE CACHE BOOL "Build as a framework on OSX") + set(QGIS_MAC_BUNDLE TRUE CACHE BOOL "Install into a mac bundle") endif() - if (APPLE AND QGIS_MACAPP_FRAMEWORK) - if (POLICY CMP0042) # in CMake 3.0.0+ - set (CMAKE_MACOSX_RPATH OFF) # otherwise ON by default - endif() - if (POLICY CMP0068) # in CMake 3.9.0+ - cmake_policy(SET CMP0068 NEW) - endif() - # for Mac OS X, everything is put inside an application bundle - # save the root install prefix for the app later - set (QGIS_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}) - set (QGIS_MACAPP_PREFIX ${CMAKE_INSTALL_PREFIX}/${QGIS_APP_NAME}.app/Contents) - # common prefix for components, let cmake handle it - set (CMAKE_INSTALL_PREFIX ${QGIS_MACAPP_PREFIX}/MacOS) - # 5 bundling levels, each includes previous - # -1 nothing - # 0 fixup the library paths for all QGIS libraries with @loader_path - # 1 Qt frameworks - # 2 non-system libraries, "standard" - # 3 non-system frameworks, "standalone" - set (QGIS_MACAPP_BUNDLE 1 CACHE STRING "What to bundle into app package") - set (QGIS_MACAPP_BUNDLE_USER "" CACHE STRING "Path to user bundling script") - set (QGIS_MACAPP_INSTALL_DEV FALSE CACHE BOOL "Install developer frameworks") - set (QGIS_MACAPP_DEV_PREFIX "/Library/Frameworks" CACHE STRING "Path to install developer frameworks") - - set (DEFAULT_BIN_SUBDIR bin) - set (QGIS_BIN_SUBDIR_REV ..) - set (DEFAULT_CGIBIN_SUBDIR fcgi-bin) - set (QGIS_CGIBIN_SUBDIR_REV ..) - set (DEFAULT_LIB_SUBDIR lib) - set (QGIS_LIB_SUBDIR_REV ..) - set (QGIS_FW_SUBDIR ../Frameworks) - set (QGIS_FW_SUBDIR_REV ../MacOS) - set (DEFAULT_DATA_SUBDIR ../Resources) - set (QGIS_DATA_SUBDIR_REV ../MacOS) - set (DEFAULT_LIBEXEC_SUBDIR lib/qgis) - set (QGIS_LIBEXEC_SUBDIR_REV ../..) - set (DEFAULT_PLUGIN_SUBDIR ../PlugIns/qgis) - set (QGIS_PLUGIN_SUBDIR_REV ../../MacOS) - set (DEFAULT_INCLUDE_SUBDIR include/qgis) - set (DEFAULT_QML_SUBDIR qml) - - # Set server moodules path to DEFAULT_LIBEXEC_SUBDIR+'/server' - set (DEFAULT_SERVER_MODULE_SUBDIR ${DEFAULT_LIBEXEC_SUBDIR}/server) - - # path for framework references when running from build directory - # changed later to reference in-app resources upon install - set (CMAKE_INSTALL_NAME_DIR ${CMAKE_BINARY_DIR}/output/lib) - # recent cmakes force SDKs, recent SDKs don't have user symlinks - # need to find non-system frameworks - # cmake bug #0007250 - CMAKE_SHARED_LINKER_FLAGS ignored when creating - # a framework, so these need to be manually handled with LINK_FLAGS options - set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -F/Library/Frameworks") - set (CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -F/Library/Frameworks") - set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -F/Library/Frameworks") - + if (APPLE AND QGIS_MAC_BUNDLE) + set(CMAKE_MACOSX_RPATH ON) # If this is off, the path will be stripped (completely) at install time, we want to preserve the `@rpath` prefix + set(CMAKE_SKIP_INSTALL_RPATH TRUE) + + set(APP_CONTENTS_DIR "Contents") + set(APP_MACOS_DIR "${APP_CONTENTS_DIR}/MacOS") + set(APP_FRAMEWORKS_DIR "${APP_CONTENTS_DIR}/Frameworks") + set(APP_RESOURCES_DIR "${APP_CONTENTS_DIR}/Resources") + set(APP_PLUGINS_DIR "${APP_CONTENTS_DIR}/PlugIns") + + cmake_path(RELATIVE_PATH Python_SITEARCH BASE_DIRECTORY "${TARGET_SYSROOT}" OUTPUT_VARIABLE _RELATIVE_SITEARCH) + + set(DEFAULT_BIN_SUBDIR ${APP_MACOS_DIR}) + set(DEFAULT_LIB_SUBDIR ${APP_FRAMEWORKS_DIR}) + set(DEFAULT_DATA_SUBDIR ${APP_RESOURCES_DIR}/qgis) + set(DEFAULT_LIBEXEC_SUBDIR ${APP_MACOS_DIR}) + set(DEFAULT_PLUGIN_SUBDIR ${APP_PLUGINS_DIR}/qgis) + set(DEFAULT_INCLUDE_SUBDIR include/qgis) + set(DEFAULT_QML_SUBDIR ${APP_RESOURCES_DIR}/qgis/qml) + set(DEFAULT_PYTHON_SUBDIR ${APP_FRAMEWORKS_DIR}/${_RELATIVE_SITEARCH}) else() # UNIX set (DEFAULT_BIN_SUBDIR bin) @@ -1020,13 +988,6 @@ if (WITH_CORE) set (DEFAULT_QML_SUBDIR qml) set (DEFAULT_SERVER_MODULE_SUBDIR ${DEFAULT_LIBEXEC_SUBDIR}/server) - - # QGIS_MACAPP_FRAMEWORK=FALSE - if(APPLE) - set (QGIS_MACAPP_BUNDLE -1) - set (CMAKE_FRAMEWORK FALSE) - set (QGIS_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}) - endif() endif() endif() @@ -1134,28 +1095,6 @@ option(ENABLE_UNITY_BUILDS "Enable Unity builds, that is compiling several .cpp ############################################################# # Python -set(MIN_PYTHON_VERSION "3.9") -set(Python_FIND_FRAMEWORK "LAST") - - -if (WITH_BINDINGS) - find_package(Python ${MIN_PYTHON_VERSION} REQUIRED COMPONENTS Interpreter Development) -else() - find_package(Python ${MIN_PYTHON_VERSION} REQUIRED COMPONENTS Interpreter) -endif() - -# Fix python site-packages for Fedora -# See https://github.com/qgis/QGIS/issues/54348#issuecomment-1694216152 -if(CMAKE_SYSTEM_NAME STREQUAL "Linux") - if(EXISTS "/etc/fedora-release") - EXECUTE_PROCESS(COMMAND ${Python_EXECUTABLE} -c "import sysconfig;print(sysconfig.get_path(\"platlib\", \"rpm_prefix\"), end=\"\")" OUTPUT_VARIABLE Python_SITEARCH) - endif() -endif() - -message("-- Found Python executable: ${Python_EXECUTABLE} (version ${Python_VERSION})") -message("-- Python library: ${Python_LIBRARIES}") -message("-- Python site-packages: ${Python_SITEARCH}") - if (WITH_CORE AND WITH_BINDINGS) set(PYTHON_OUTPUT_DIRECTORY ${QGIS_OUTPUT_DIRECTORY}/python) set (QGIS_PYTHON_OUTPUT_DIRECTORY ${PYTHON_OUTPUT_DIRECTORY}/qgis) @@ -1188,8 +1127,12 @@ if (WITH_CORE AND WITH_BINDINGS) set(SIP_INCLUDES ${PYQT_SIP_DIR} ${CMAKE_SOURCE_DIR}/python) set(SIP_CONCAT_PARTS 25) - if (NOT BINDINGS_GLOBAL_INSTALL) - set(Python_SITEARCH ${QGIS_DATA_DIR}/python) + if(BINDINGS_GLOBAL_INSTALL) + set(QGIS_PYTHON_INSTALL_DIR ${Python_SITEARCH}) + elseif(DEFINED DEFAULT_PYTHON_SUBDIR) + set(QGIS_PYTHON_INSTALL_DIR ${DEFAULT_PYTHON_SUBDIR}) + else() + set(QGIS_PYTHON_INSTALL_DIR ${QGIS_DATA_DIR}/python) endif() if (WITH_CUSTOM_WIDGETS) @@ -1246,22 +1189,6 @@ if (WITH_CORE) add_subdirectory(python) endif() - if (APPLE) - # must be last for install, so install_name_tool can do its work - add_subdirectory(mac) - - # allow QGIS to be run directly from build directory and to run unit tests - execute_process(COMMAND /bin/mkdir -p "${QGIS_OUTPUT_DIRECTORY}/lib") - execute_process( - COMMAND /bin/ln -fs ../../Plugins/qgis/qgisgrass6.framework lib/ - WORKING_DIRECTORY "${QGIS_OUTPUT_DIRECTORY}" - ) - execute_process( - COMMAND /bin/ln -fs ../../Plugins/qgis/qgisgrass7.framework lib/ - WORKING_DIRECTORY "${QGIS_OUTPUT_DIRECTORY}" - ) - endif() - # manual page - makes sense only on unix systems if (UNIX AND NOT APPLE) install (FILES qgis.1 DESTINATION ${QGIS_MANUAL_DIR}/man1) @@ -1301,8 +1228,8 @@ endif() ############################################################# # Enable packaging if (WITH_CORE) - include(Bundle) include(VcpkgInstallDeps) + include(Bundle) endif() if (UNIX AND NOT APPLE) diff --git a/INSTALL.md b/INSTALL.md index c314a16cb2d4..8e2d9db8115e 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -1052,7 +1052,7 @@ Install and initialize vcpkg Install build tools using [homebrew](https://brew.sh/) ```sh -brew install git cmake flex bison automake autoconf libtool nasm ninja +brew install git cmake flex bison automake autoconf autoconf-archive libtool nasm ninja ``` Get the QGIS source code @@ -1087,10 +1087,8 @@ cmake -S . \ -D BUILD_WITH_QT6=ON \ -D WITH_QTWEBKIT=OFF \ -D WITH_BINDINGS=ON \ - -D QGIS_MACAPP_FRAMEWORK=OFF \ -D VCPKG_TARGET_TRIPLET="$TRIPLET" \ - -D VCPKG_HOST_TRIPLET="$TRIPLET" \ - -D CREATE_MACOSX_BUNDLE=OFF + -D VCPKG_HOST_TRIPLET="$TRIPLET" ``` Build (switch the target to `Release` if you do not want to debug) diff --git a/cmake/Bundle.cmake b/cmake/Bundle.cmake index a1ffffd26f4e..3d399ed8a51c 100644 --- a/cmake/Bundle.cmake +++ b/cmake/Bundle.cmake @@ -2,7 +2,7 @@ set(CPACK_GENERATOR) set(CPACK_OUTPUT_CONFIG_FILE "${CMAKE_BINARY_DIR}/BundleConfig.cmake") add_custom_target(bundle - COMMAND ${CMAKE_CPACK_COMMAND} "--config" "${CMAKE_BINARY_DIR}/BundleConfig.cmake" + COMMAND ${CMAKE_CPACK_COMMAND} "--config" "${CMAKE_BINARY_DIR}/BundleConfig.cmake" "--verbose" COMMENT "Running CPACK. Please wait..." DEPENDS qgis) @@ -22,7 +22,6 @@ endif() set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "QGIS") set(CPACK_PACKAGE_VENDOR "Open Source Geospatial Foundation") -set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README") set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/COPYING") set(CPACK_PACKAGE_INSTALL_DIRECTORY "QGIS ${COMPLETE_VERSION}") set(CPACK_PACKAGE_EXECUTABLES "qgis" "QGIS") @@ -44,4 +43,22 @@ if(CREATE_ZIP) list(APPEND CPACK_GENERATOR "ZIP") endif() + +if(CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND QGIS_MAC_BUNDLE) + set(CREATE_DMG FALSE CACHE BOOL "Create a dmg bundle") + set(PYMACDEPLOYQT_EXECUTABLE "${CMAKE_SOURCE_DIR}/platform/macos/pymacdeployqt.py") + + configure_file("${CMAKE_SOURCE_DIR}/platform/macos/Info.plist.in" "${CMAKE_BINARY_DIR}/platform//macos/Info.plist" @ONLY) + install(FILES "${CMAKE_BINARY_DIR}/platform/macos/Info.plist" DESTINATION "${APP_CONTENTS_DIR}") + + set(CPACK_DMG_VOLUME_NAME "${PROJECT_NAME}") + set(CPACK_DMG_FORMAT "UDBZ") + list(APPEND CPACK_GENERATOR "External") + message(STATUS " + macdeployqt/DMG YES ") + configure_file(${CMAKE_SOURCE_DIR}/platform/macos/CPackMacDeployQt.cmake.in "${CMAKE_BINARY_DIR}/CPackExternal.cmake" @ONLY) + set(CPACK_EXTERNAL_PACKAGE_SCRIPT "${CMAKE_BINARY_DIR}/CPackExternal.cmake") + set(CPACK_EXTERNAL_ENABLE_STAGING ON) + set(CPACK_PACKAGING_INSTALL_PREFIX "/${QGIS_APP_NAME}.app") +endif() + include(CPack) diff --git a/cmake/MacBundleMacros.cmake b/cmake/MacBundleMacros.cmake deleted file mode 100644 index f724d11e71ee..000000000000 --- a/cmake/MacBundleMacros.cmake +++ /dev/null @@ -1,222 +0,0 @@ -# QGIS Mac Bundle Macros - -# BundleUtilities has functions to bundle and fixup libraries into an -# application package, but it's all-or-nothing and is missing some features: -# -# - @loader_path -# - helper functions can't get install_name, just dependencies - -# the following cmakecache vars must be set, redefine them -# with config-file substitutions in install-run scripts: -# -# CPACK_PACKAGE_VERSION_MAJOR, CPACK_PACKAGE_VERSION_MINOR -# CMAKE_INSTALL_PREFIX, CMAKE_VERBOSE_MAKEFILE, CMAKE_BUILD_TYPE -# CMAKE_OSX_ARCHITECTURES -# QGIS_APP_NAME -# QGIS_MACAPP_PREFIX -# QGIS_*_SUBDIR, QGIS_*_SUBDIR_REV -# WITH_* - -# this file must only be included after target installation is complete - -# message only if verbose makefiles - -FUNCTION (MYMESSAGE MSG) - IF (${CMAKE_VERBOSE_MAKEFILE}) - MESSAGE (STATUS "${MSG}") - ENDIF (${CMAKE_VERBOSE_MAKEFILE}) -ENDFUNCTION (MYMESSAGE) - -# get the install_name of a library or framework -# regex stuff taken from GetPrerequisites - -FUNCTION (GET_INSTALL_NAME LIBFILE LIBNAME OUTVAR) - IF (EXISTS "${LIBFILE}") - EXECUTE_PROCESS (COMMAND otool -L "${LIBFILE}" OUTPUT_VARIABLE iname_out) - # remove 1st line, it's just path to lib file - STRING (REGEX REPLACE ".*:\n" "" iname "${iname_out}") - IF (iname) - # find libname - STRING (REGEX MATCH "[^\n\t ]*${LIBNAME}[^\n]*" iname "${iname}") - STRING (REGEX REPLACE " \\(compatibility version .*, current version .*\\)" "" iname "${iname}") - ENDIF (iname) - SET (${OUTVAR} ${iname} PARENT_SCOPE) - ELSE () - SET (${OUTVAR} "" PARENT_SCOPE) - ENDIF () -ENDFUNCTION (GET_INSTALL_NAME) - -# install_name_tool -change CHANGE CHANGETO CHANGEBIN - -FUNCTION (INSTALLNAMETOOL_CHANGE CHANGE CHANGETO CHANGEBIN) - IF (EXISTS "${CHANGEBIN}" AND CHANGE AND CHANGETO) - # ensure CHANGEBIN is writable by user, e.g. Homebrew binaries are installed non-writable - EXECUTE_PROCESS (COMMAND chmod u+w "${CHANGEBIN}") - EXECUTE_PROCESS (COMMAND install_name_tool -change ${CHANGE} ${CHANGETO} "${CHANGEBIN}") - # if that didn't work, try a symlink-resolved id - # (some package systems, like Homebrew, heavily use symlinks; and, inter-package builds, like plugins, - # may point to the resolved location instead of the 'public' symlink installed to prefixes like /usr/local) - get_filename_component(_chgreal ${CHANGE} REALPATH) - EXECUTE_PROCESS (COMMAND install_name_tool -change ${_chgreal} ${CHANGETO} "${CHANGEBIN}") - ENDIF () -ENDFUNCTION (INSTALLNAMETOOL_CHANGE) - -# copy a framework, only specified archs, current version, debug dep on CMAKE_BUILD_TYPE - -FUNCTION (COPY_FRAMEWORK FWPREFIX FWNAME FWDEST) - # reconstruct framework to avoid excessive copying, then deleting - # especially when debug variants are present - # find current version - # use python because pwd not working with WORKING_DIRECTORY param - EXECUTE_PROCESS ( - COMMAND python -c "import os.path\nprint(os.path.realpath(\"${FWPREFIX}/${FWNAME}.framework/Versions/Current\"))" - OUTPUT_VARIABLE FWDIRPHYS - ) - STRING (STRIP "${FWDIRPHYS}" FWDIRPHYS) - IF (IS_DIRECTORY "${FWDIRPHYS}") - STRING (REGEX MATCH "[^/\n]+$" FWVER "${FWDIRPHYS}") - EXECUTE_PROCESS (COMMAND mkdir -p "${FWDEST}/${FWNAME}.framework/Versions/${FWVER}") - EXECUTE_PROCESS (COMMAND ln -sfn ${FWVER} "${FWDEST}/${FWNAME}.framework/Versions/Current") - EXECUTE_PROCESS (COMMAND ditto ${QARCHS} "${FWPREFIX}/${FWNAME}.framework/Versions/${FWVER}/${FWNAME}" "${FWDEST}/${FWNAME}.framework/Versions/${FWVER}/${FWNAME}") - EXECUTE_PROCESS (COMMAND ln -sf Versions/Current/${FWNAME} "${FWDEST}/${FWNAME}.framework/${FWNAME}") - IF (IS_DIRECTORY "${FWPREFIX}/${FWNAME}.framework/Versions/${FWVER}/Resources") - EXECUTE_PROCESS (COMMAND cp -Rfp "${FWPREFIX}/${FWNAME}.framework/Versions/${FWVER}/Resources" "${FWDEST}/${FWNAME}.framework/Versions/${FWVER}") - EXECUTE_PROCESS (COMMAND ln -sfn Versions/Current/Resources "${FWDEST}/${FWNAME}.framework/Resources") - ENDIF (IS_DIRECTORY "${FWPREFIX}/${FWNAME}.framework/Versions/${FWVER}/Resources") - # ensure writable by user, e.g. Homebrew frameworks are installed non-writable - EXECUTE_PROCESS (COMMAND chmod -R u+w "${FWDEST}/${FWNAME}.framework") - EXECUTE_PROCESS (COMMAND install_name_tool -id "${ATEXECUTABLE}/${QGIS_FW_SUBDIR}/${FWNAME}" "${FWDEST}/${FWNAME}.framework/${FWNAME}") - # debug variants - SET (FWD "${FWNAME}_debug") - IF ("${FWDEBUG}" STREQUAL "Debug" AND EXISTS "${FWPREFIX}/${FWNAME}.framework/Versions/${FWVER}/${FWD}") - EXECUTE_PROCESS (COMMAND ditto ${QARCHS} "${FWPREFIX}/${FWNAME}.framework/Versions/${FWVER}/${FWD}" "${FWDEST}/${FWNAME}.framework/Versions/${FWVER}/${FWD}") - EXECUTE_PROCESS (COMMAND ln -sf Versions/Current/${FWD} "${FWDEST}/${FWNAME}.framework/${FWD}") - IF (IS_DIRECTORY "${FWPREFIX}/${FWNAME}.framework/${FWD}.dSYM") - EXECUTE_PROCESS (COMMAND ditto -X ${QARCHS} "${FWPREFIX}/${FWNAME}.framework/${FWD}.dSYM" "${FWDEST}/${FWNAME}.framework") - ENDIF () - ENDIF () - ENDIF () -ENDFUNCTION (COPY_FRAMEWORK) - -# update a library path in all QGIS binary files -# if dylib, change LIBFROM to LIBTO as is -# else assumes it's a framework, change LIBFROM to LIBTO.framework/LIBTO - -FUNCTION (UPDATEQGISPATHS LIBFROM LIBTO) - IF (LIBFROM) - STRING (REGEX MATCH "\\.(dylib|so)$" ISLIB "${LIBTO}") - IF (ISLIB) - SET (LIBPOST "${LIBTO}") - SET (LIBMID "${QGIS_LIB_SUBDIR}") - ElSE () - SET (LIBPOST "${LIBTO}.framework/${LIBTO}") - SET (LIBMID "${QGIS_FW_SUBDIR}") - ENDIF () - SET (LIB_CHG_TO "${ATEXECUTABLE}/${LIBMID}/${LIBPOST}") - # app - always @executable_path - INSTALLNAMETOOL_CHANGE ("${LIBFROM}" "${LIB_CHG_TO}" "${QAPPDIR}/${QGIS_APP_NAME}") - # qgis helper apps - don't link anything else than Qt/Qgis - FOREACH (QA ${QGAPPLIST}) - INSTALLNAMETOOL_CHANGE ("${LIBFROM}" "${LIB_CHG_TO}" "${QBINDIR}/${QA}.app/Contents/MacOS/${QA}") - ENDFOREACH (QA) - # qgis-mapserver - IF (${WITH_SERVER}) - SET (LIB_CHG_TO "${ATEXECUTABLE}/${QGIS_CGIBIN_SUBDIR_REV}/${LIBMID}/${LIBPOST}") - INSTALLNAMETOOL_CHANGE ("${LIBFROM}" "${LIB_CHG_TO}" "${QCGIDIR}/qgis_mapserv.fcgi") - ENDIF () - # libs - # bundled frameworks can use short relative path - IF (ISLIB) - SET (LIB_CHG_TO "${ATLOADER}/../../../${QGIS_FW_SUBDIR_REV}/${LIBMID}/${LIBPOST}") - ElSE () - SET (LIB_CHG_TO "${ATLOADER}/../../../${LIBPOST}") - ENDIF () - FOREACH (QL ${QGFWLIST}) - INSTALLNAMETOOL_CHANGE ("${LIBFROM}" "${LIB_CHG_TO}" "${QFWDIR}/${QL}.framework/${QL}") - ENDFOREACH (QL) - # non-framework qgis libs - SET (LIB_CHG_TO "${ATLOADER}/${QGIS_LIB_SUBDIR_REV}/${LIBMID}/${LIBPOST}") - FOREACH (QL ${QGLIBLIST}) - INSTALLNAMETOOL_CHANGE ("${LIBFROM}" "${LIB_CHG_TO}" "${QLIBDIR}/${QL}") - ENDFOREACH (QL) - # crssync - SET (LIB_CHG_TO "${ATEXECUTABLE}/${QGIS_LIBEXEC_SUBDIR_REV}/${LIBMID}/${LIBPOST}") - INSTALLNAMETOOL_CHANGE ("${LIBFROM}" "${LIB_CHG_TO}" "${QLIBXDIR}/crssync") - # GRASS libexec stuff - FOREACH (QG ${QGRASSEXECLIST}) - IF (EXISTS "${QLIBXDIR}/grass/${QG}") - SET (LIB_CHG_TO "${ATLOADER}/../../${QGIS_LIBEXEC_SUBDIR_REV}/${LIBMID}/${LIBPOST}") - INSTALLNAMETOOL_CHANGE ("${LIBFROM}" "${LIB_CHG_TO}" "${QLIBXDIR}/grass/${QG}") - ENDIF () - ENDFOREACH (QG) - # plugins - SET (LIB_CHG_TO "${ATLOADER}/${QGIS_PLUGIN_SUBDIR_REV}/${LIBMID}/${LIBPOST}") - FOREACH (QP ${QGPLUGLIST}) - INSTALLNAMETOOL_CHANGE ("${LIBFROM}" "${LIB_CHG_TO}" "${QP}") - ENDFOREACH (QP) - # quick plugin - SET (LIB_CHG_TO "${ATLOADER}/../../${LIBMID}/${LIBPOST}") - INSTALLNAMETOOL_CHANGE ("${LIBFROM}" "${LIB_CHG_TO}" "${QAPPDIR}/qml/QgsQuick/libqgis_quick_plugin.dylib") - # qgis python - SET (LIB_CHG_TO "${ATLOADER}/../../${QGIS_DATA_SUBDIR_REV}/${LIBMID}/${LIBPOST}") - FOREACH (PG ${QGPYLIST}) - INSTALLNAMETOOL_CHANGE ("${LIBFROM}" "${LIB_CHG_TO}" "${PG}") - ENDFOREACH (PG) - # bin - nothing yet - # SET (LIB_CHG_TO "${ATLOADER}/${QGIS_BIN_SUBDIR_REV}/${LIBMID}/${LIBPOST}") - #FOREACH (PB ...) - # INSTALLNAMETOOL_CHANGE ("${LIBFROM}" "${LIB_CHG_TO}" "${QBINDIR}/${PB}") - #ENDFOREACH (PB) - ENDIF (LIBFROM) -ENDFUNCTION (UPDATEQGISPATHS) - - -# Find directory path for a known Python module (or package) directory or file name -# see: PYTHON_MODULE_PATHS in 0vars.cmake.in -FUNCTION (PYTHONMODULEDIR MOD_NAME OUTVAR) - FOREACH (MOD_PATH ${PYTHON_MODULE_PATHS}) - IF (EXISTS "${MOD_PATH}/${MOD_NAME}") - SET (${OUTVAR} "${MOD_PATH}" PARENT_SCOPE) - RETURN() - ENDIF() - ENDFOREACH (MOD_PATH) - SET (${OUTVAR} "" PARENT_SCOPE) -ENDFUNCTION (PYTHONMODULEDIR) - - -SET (ATEXECUTABLE "@executable_path") -SET (ATLOADER "@loader_path") -SET (Q_FWVER ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}) - -# install destinations -SET (QAPPDIRC "$ENV{DESTDIR}${QGIS_MACAPP_PREFIX}") -SET (QAPPDIR "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}") -SET (QFWDIR "${QAPPDIR}/${QGIS_FW_SUBDIR}") -SET (QBINDIR "${QAPPDIR}/${QGIS_BIN_SUBDIR}") -SET (QCGIDIR "${QAPPDIR}/${QGIS_CGIBIN_SUBDIR}") -SET (QLIBDIR "${QAPPDIR}/${QGIS_LIB_SUBDIR}") -SET (QLIBXDIR "${QAPPDIR}/${QGIS_LIBEXEC_SUBDIR}") -SET (QDATADIR "${QAPPDIR}/${QGIS_DATA_SUBDIR}") -SET (QPLUGDIR "${QAPPDIR}/${QGIS_PLUGIN_SUBDIR}") -SET (QGISPYDIR "${QAPPDIR}/${QGIS_DATA_SUBDIR}/python") - -# build arches -SET (QARCHS "") -FOREACH (QARCH ${CMAKE_OSX_ARCHITECTURES}) - SET (QARCHS ${QARCHS} "--arch" "${QARCH}") -ENDFOREACH (QARCH) - -# common file lists -FILE (GLOB QGFWLIST RELATIVE "${QFWDIR}" "${QFWDIR}/qgis*.framework") -# for some reason, REPLACE is stripping list seps -STRING(REPLACE ".framework" ";" QGFWLIST ${QGFWLIST}) -# don't collect any library symlinks, limit to versioned libs -SET (Q_LIBVER ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}) -FILE (GLOB QGLIBLIST RELATIVE "${QLIBDIR}" "${QLIBDIR}/libqgis*.dylib" "${QLIBDIR}/qgis/server/lib*.so") -FILE (GLOB QGPLUGLIST "${QPLUGDIR}/*.so") -FILE (GLOB QGPYLIST "${QGISPYDIR}/qgis/*.so") -FILE (GLOB QGAPPLIST RELATIVE "${QBINDIR}" "${QBINDIR}/q*.app") -FILE (GLOB QGRASSEXECLIST RELATIVE "${QLIBXDIR}/grass" "${QLIBXDIR}/grass/*/*") -IF (QGAPPLIST) - STRING(REPLACE ".app" ";" QGAPPLIST ${QGAPPLIST}) -ENDIF (QGAPPLIST) diff --git a/cmake/SIPMacros.cmake b/cmake/SIPMacros.cmake index 2f44b71c7bef..6ef2e786fc37 100644 --- a/cmake/SIPMacros.cmake +++ b/cmake/SIPMacros.cmake @@ -207,5 +207,5 @@ MACRO(BUILD_SIP_PYTHON_MODULE MODULE_NAME SIP_FILES EXTRA_OBJECTS) ) ENDIF(WIN32) - INSTALL(TARGETS ${_logical_name} DESTINATION "${Python_SITEARCH}/${_parent_module_path}") + INSTALL(TARGETS ${_logical_name} DESTINATION "${QGIS_PYTHON_INSTALL_DIR}/${_parent_module_path}") ENDMACRO(BUILD_SIP_PYTHON_MODULE MODULE_NAME SIP_FILES EXTRA_OBJECTS) diff --git a/cmake/VcpkgInstallDeps.cmake b/cmake/VcpkgInstallDeps.cmake index 2ff892010750..b057d7c8c6b7 100644 --- a/cmake/VcpkgInstallDeps.cmake +++ b/cmake/VcpkgInstallDeps.cmake @@ -5,12 +5,15 @@ endif() set(VCPKG_BASE_DIR "${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}") if(MSVC) - # At least python3.dll, qgis_analysis.dll and gsl.dll are missing - # Copy everything file(GLOB ALL_LIBS "${VCPKG_BASE_DIR}/bin/*.dll" ) install(FILES ${ALL_LIBS} DESTINATION "bin") +elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + file(GLOB ALL_LIBS + "${VCPKG_BASE_DIR}/lib/*.dylib" + ) + install(FILES ${ALL_LIBS} DESTINATION "${QGIS_LIB_SUBDIR}") endif() set(PROJ_DATA_PATH "${VCPKG_BASE_DIR}/share/proj") @@ -19,12 +22,134 @@ if(NOT EXISTS "${PROJ_DATA_PATH}/proj.db") message(FATAL_ERROR "proj.db not found at ${PROJ_DATA_PATH}/proj.db") endif() -install(DIRECTORY "${PROJ_DATA_PATH}/" DESTINATION "${CMAKE_INSTALL_DATADIR}/proj") -install(DIRECTORY "${VCPKG_BASE_DIR}/share/gdal/" DESTINATION "${CMAKE_INSTALL_DATADIR}/gdal") -install(DIRECTORY "${VCPKG_BASE_DIR}/bin/Qca/" DESTINATION "bin/Qca") # QCA plugins -install(DIRECTORY "${VCPKG_BASE_DIR}/Qt6/" DESTINATION "bin/Qt6") # qt plugins (qml and others) +install(DIRECTORY "${PROJ_DATA_PATH}/" DESTINATION "${QGIS_DATA_SUBDIR}/proj") +install(DIRECTORY "${VCPKG_BASE_DIR}/share/gdal/" DESTINATION "${QGIS_DATA_SUBDIR}/gdal") +if(MSVC) + install(DIRECTORY "${VCPKG_BASE_DIR}/bin/Qca/crypto/" DESTINATION "${QGIS_LIB_SUBDIR}/Qt6/plugins/crypto") # QCA plugins +else() + install(DIRECTORY "${VCPKG_BASE_DIR}/bin/Qca/crypto/" DESTINATION "${APP_PLUGINS_DIR}/crypto") # QCA plugins +endif() + +if(MSVC) + install(DIRECTORY "${VCPKG_BASE_DIR}/Qt6/" DESTINATION "${QGIS_LIB_SUBDIR}/Qt6") # qt plugins (qml and others) +else() + install(DIRECTORY "${VCPKG_BASE_DIR}/Qt6/plugins/" DESTINATION "${APP_PLUGINS_DIR}/") # qt plugins (qml and others) +endif() + if(WITH_BINDINGS) - install(DIRECTORY "${VCPKG_BASE_DIR}/tools/python3/" - DESTINATION "bin" + if(MSVC) + set(_SOURCE_PYTHON_DIR "${VCPKG_BASE_DIR}/tools/python3/") + set(_TARGET_PYTHON_DIR "bin") + elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + cmake_path(GET Python_SITEARCH PARENT_PATH _SOURCE_PYTHON_DIR) + set(_TARGET_PYTHON_DIR "${APP_FRAMEWORKS_DIR}/lib") + + get_filename_component(PYTHON_EXECUTABLE "${Python_EXECUTABLE}" NAME) + install(PROGRAMS ${Python_EXECUTABLE} + DESTINATION "${QGIS_BIN_SUBDIR}") + configure_file("${CMAKE_SOURCE_DIR}/platform/macos/python.in" "${CMAKE_BINARY_DIR}/platform/macos/python" @ONLY) + install(PROGRAMS "${CMAKE_BINARY_DIR}/platform/macos/python" + DESTINATION "${QGIS_BIN_SUBDIR}") + endif() + + install(DIRECTORY "${_SOURCE_PYTHON_DIR}" + DESTINATION "${_TARGET_PYTHON_DIR}" PATTERN "*.sip" EXCLUDE) endif() + +function(fixup_shebang INPUT_FILE OUTPUT_VARIABLE) + get_filename_component(_FILE ${INPUT_FILE} NAME) + file(READ ${INPUT_FILE} CONTENTS) + string(REGEX MATCH "^#!" SHEBANG_PRESENT "${CONTENTS}") + if (NOT SHEBANG_PRESENT) + message(FATAL_ERROR "File ${INPUT_FILE} does not start with a shebang (#!).") + endif() + + # Replace the first line + string(REGEX REPLACE "^#![^\n]*" "#!/bin/sh\n\"exec\" \"\`dirname \$0\`/python\" \"\$0\" \"\$@\"" TRANSFORMED_CONTENTS "${CONTENTS}") + + # Write the transformed contents to the output file + set(OUTPUT_FILE "${CMAKE_BINARY_DIR}/bundled_program/${_FILE}") + file(WRITE "${OUTPUT_FILE}" "${TRANSFORMED_CONTENTS}") + set(${OUTPUT_VARIABLE} ${OUTPUT_FILE} PARENT_SCOPE) +endfunction() + +if(NOT MSVC) + set(BUNDLED_PROGRAMS + "tools/gdal/gdal_contour" + "tools/gdal/gdal_create" + "tools/gdal/gdal_footprint" + "tools/gdal/gdal_grid" + "tools/gdal/gdal_rasterize" + "tools/gdal/gdal_translate" + "tools/gdal/gdal_viewshed" + "tools/gdal/gdaladdo" + "tools/gdal/gdalbuildvrt" + "tools/gdal/gdaldem" + "tools/gdal/gdalenhance" + "tools/gdal/gdalinfo" + "tools/gdal/gdallocationinfo" + "tools/gdal/gdalmanage" + "tools/gdal/gdalmdiminfo" + "tools/gdal/gdalmdimtranslate" + "tools/gdal/gdalsrsinfo" + "tools/gdal/gdaltindex" + "tools/gdal/gdaltransform" + "tools/gdal/gdalwarp" + "tools/gdal/gnmanalyse" + "tools/gdal/gnmmanage" + "tools/gdal/nearblack" + "tools/gdal/ogr2ogr" + "tools/gdal/ogrinfo" + "tools/gdal/ogrlineref" + "tools/gdal/ogrtindex" + "tools/gdal/sozip" + ) + set(PYTHON_SCRIPTS + "bin/gdal2tiles" + "bin/gdal2tiles.py" + "bin/gdal2xyz" + "bin/gdal2xyz.py" + "bin/gdal_calc" + "bin/gdal_calc.py" + "bin/gdal_edit" + "bin/gdal_edit.py" + "bin/gdal_fillnodata" + "bin/gdal_fillnodata.py" + "bin/gdal_merge" + "bin/gdal_merge.py" + "bin/gdal_pansharpen" + "bin/gdal_pansharpen.py" + "bin/gdal_polygonize" + "bin/gdal_polygonize.py" + "bin/gdal_proximity" + "bin/gdal_proximity.py" + "bin/gdal_retile" + "bin/gdal_retile.py" + "bin/gdal_sieve" + "bin/gdal_sieve.py" + "bin/gdalattachpct" + "bin/gdalattachpct.py" + "bin/gdalcompare" + "bin/gdalcompare.py" + "bin/gdalmove" + "bin/gdalmove.py" + "bin/ogr_layer_algebra" + "bin/ogr_layer_algebra.py" + "bin/ogrmerge" + "bin/ogrmerge.py" + "bin/pct2rgb" + "bin/pct2rgb.py" + "bin/rgb2pct" + "bin/rgb2pct.py" + ) + list(TRANSFORM BUNDLED_PROGRAMS PREPEND "${VCPKG_BASE_DIR}/") + list(TRANSFORM PYTHON_SCRIPTS PREPEND "${VCPKG_BASE_DIR}/") + foreach(FILE ${PYTHON_SCRIPTS}) + fixup_shebang("${FILE}" OUTPUT_FILE) + list(APPEND BUNDLED_PROGRAMS "${OUTPUT_FILE}") + endforeach() + install(PROGRAMS ${BUNDLED_PROGRAMS} + DESTINATION "${QGIS_BIN_SUBDIR}") +endif() + diff --git a/cmake/VcpkgToolchain.cmake b/cmake/VcpkgToolchain.cmake index 43f71d040817..2694fa108941 100644 --- a/cmake/VcpkgToolchain.cmake +++ b/cmake/VcpkgToolchain.cmake @@ -11,6 +11,9 @@ endif() if(WITH_GUI) list(APPEND VCPKG_MANIFEST_FEATURES "gui") endif() +if(WITH_ORACLE) + list(APPEND VCPKG_MANIFEST_FEATURES "oracle") +endif() # Binarycache can only be used on Windows or if mono is available. find_program(_VCPKG_MONO mono) diff --git a/cmake_templates/qgsconfig.h.in b/cmake_templates/qgsconfig.h.in index b8f0949c9850..ab9ac0d682e5 100644 --- a/cmake_templates/qgsconfig.h.in +++ b/cmake_templates/qgsconfig.h.in @@ -37,11 +37,6 @@ #define QSCINTILLA_VERSION_STR "${QSCINTILLA_VERSION_STR}" #endif -#if defined( __APPLE__ ) -//used by Mac to find system or bundle resources relative to amount of bundling -#define QGIS_MACAPP_BUNDLE ${QGIS_MACAPP_BUNDLE} -#endif - #define PYTHON_VERSION "${Python_VERSION}" #define PYTHON_VERSION_MAJOR "${Python_VERSION_MAJOR}" #define PYTHON_VERSION_MINOR "${Python_VERSION_MINOR}" @@ -51,6 +46,8 @@ #define PROJ_VERSION_MINOR ${PROJ_VERSION_MINOR} #define PROJ_VERSION_PATCH ${PROJ_VERSION_PATCH} +#cmakedefine QGIS_MAC_BUNDLE + #cmakedefine USING_NMAKE #cmakedefine USING_NINJA diff --git a/i18n/CMakeLists.txt b/i18n/CMakeLists.txt index e01bf8d51498..83d2edbed103 100644 --- a/i18n/CMakeLists.txt +++ b/i18n/CMakeLists.txt @@ -52,7 +52,7 @@ add_custom_target (translations ALL DEPENDS ${QM_FILES} ${MD_FILES}) # first compile sources, then compile translations if (WITH_DESKTOP) - add_dependencies (translations ${QGIS_APP_NAME}) + add_dependencies (translations qgis) endif() install (FILES ${QM_FILES} diff --git a/images/icons/mac/CMakeLists.txt b/images/icons/mac/CMakeLists.txt index b2f9c905f209..89b80eab5851 100644 --- a/images/icons/mac/CMakeLists.txt +++ b/images/icons/mac/CMakeLists.txt @@ -2,5 +2,5 @@ if (WITH_DESKTOP) file (GLOB ICONS *.icns) install (FILES ${ICONS} - DESTINATION ${CMAKE_INSTALL_PREFIX}/../Resources) + DESTINATION ${APP_RESOURCES_DIR}) endif() diff --git a/images/icons/mac/qgis-dark.icns b/images/icons/mac/qgis-dark.icns new file mode 100644 index 000000000000..f98c0921b945 Binary files /dev/null and b/images/icons/mac/qgis-dark.icns differ diff --git a/images/icons/mac/qgis.icns b/images/icons/mac/qgis.icns index 8988161c2453..e317234f0d60 100644 Binary files a/images/icons/mac/qgis.icns and b/images/icons/mac/qgis.icns differ diff --git a/images/icons/mac/qgs.icns b/images/icons/mac/qgs.icns deleted file mode 100644 index 9b3c97465f77..000000000000 Binary files a/images/icons/mac/qgs.icns and /dev/null differ diff --git a/images/images.qrc b/images/images.qrc index 6c53d82377da..f65ba14d44e7 100644 --- a/images/images.qrc +++ b/images/images.qrc @@ -339,6 +339,7 @@ themes/default/mActionKeyboardShortcuts.svg themes/default/mActionLabel.svg themes/default/mActionLabeling.svg + themes/default/mActionLayers.svg themes/default/mActionLocalCumulativeCutStretch.svg themes/default/mActionLocalHistogramStretch.svg themes/default/mActionLockItems.svg diff --git a/images/themes/default/mActionLayers.svg b/images/themes/default/mActionLayers.svg new file mode 100644 index 000000000000..a190deda4d40 --- /dev/null +++ b/images/themes/default/mActionLayers.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mac/CMakeLists.txt b/mac/CMakeLists.txt deleted file mode 100644 index 9b7a9f8cde2d..000000000000 --- a/mac/CMakeLists.txt +++ /dev/null @@ -1,31 +0,0 @@ -# mac bundling must happen at end, so all binaries installed -# and install_names can be adjusted -if (APPLE AND QGIS_MACAPP_BUNDLE GREATER -1) - # for included scripts that set policies (ie OS X bundling) - install (CODE "cmake_policy(SET CMP0011 NEW)") - configure_file (cmake/0vars.cmake.in 0vars.cmake @ONLY) - configure_file (cmake/0qgis.cmake.in 0qgis.cmake @ONLY) - install (SCRIPT ${CMAKE_BINARY_DIR}/mac/0qgis.cmake) - if (QGIS_MACAPP_BUNDLE GREATER 0) - # start with Qt - configure_file (cmake/1qt.cmake.in 1qt.cmake @ONLY) - install (SCRIPT ${CMAKE_BINARY_DIR}/mac/1qt.cmake) - if (QGIS_MACAPP_BUNDLE GREATER 1) - # next - libs - configure_file (cmake/2lib.cmake.in 2lib.cmake @ONLY) - install (SCRIPT ${CMAKE_BINARY_DIR}/mac/2lib.cmake) - if (QGIS_MACAPP_BUNDLE GREATER 2) - # last - frameworks - configure_file (cmake/3fw.cmake.in 3fw.cmake @ONLY) - install (SCRIPT ${CMAKE_BINARY_DIR}/mac/3fw.cmake) - endif() - endif() - endif() - # user bundling - if (QGIS_MACAPP_BUNDLE_USER) - configure_file (${QGIS_MACAPP_BUNDLE_USER} 4user.cmake @ONLY) - install (SCRIPT ${CMAKE_BINARY_DIR}/mac/4user.cmake) - endif() - # tickle app bundle - install (CODE "execute_process(COMMAND touch \"$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/../../.\")") -endif() diff --git a/mac/cmake/0qgis.cmake.in b/mac/cmake/0qgis.cmake.in deleted file mode 100644 index 9be19f7ab5be..000000000000 --- a/mac/cmake/0qgis.cmake.in +++ /dev/null @@ -1,31 +0,0 @@ -# 0qgis - fixup install_names for @loader_path -# ! cmakecache vars not available to external scripts -# so we configure it first to do substitutions -# make sure to use @varname@ - -# kill boolean warnings -CMAKE_POLICY (SET CMP0012 NEW) - -INCLUDE ("@CMAKE_BINARY_DIR@/mac/0vars.cmake") -INCLUDE ("@CMAKE_SOURCE_DIR@/cmake/MacBundleMacros.cmake") - -# assume all install_names start with CMAKE_INSTALL_NAME_DIR -# so we don't have to extract it from binaries -# leave main qgis executable and qgis_help with executable_paths - -MESSAGE (STATUS "Updating QGIS library paths...") -# inter-library links - do all combos, many will be noops -FOREACH (QL ${QGFWLIST}) - GET_INSTALL_NAME ("${QFWDIR}/${QL}.framework/${QL}" ${QL}.framework QQ) - SET (QFW_CHG "${QQ}") - UPDATEQGISPATHS ("${QFW_CHG}" ${QL}) - # change id of the framework - IF (NOT @QGIS_MACAPP_INSTALL_DEV@) - EXECUTE_PROCESS(COMMAND install_name_tool -id "${ATEXECUTABLE}/${QGIS_FW_SUBDIR}/${QL}.framework/${QL}" "${QFWDIR}/${QL}.framework/${QL}") - ENDIF () -ENDFOREACH (QL) -FOREACH (QLIB ${QGLIBLIST}) - GET_INSTALL_NAME ("${QLIBDIR}/${QLIB}" ${QLIB} QQ) - SET (QLIB_CHG "${QQ}") - UPDATEQGISPATHS ("${QLIB_CHG}" ${QLIB}) -ENDFOREACH (QLIB) diff --git a/mac/cmake/0vars.cmake.in b/mac/cmake/0vars.cmake.in deleted file mode 100644 index f1ff5eb39122..000000000000 --- a/mac/cmake/0vars.cmake.in +++ /dev/null @@ -1,70 +0,0 @@ -# 0vars - redefine cmakecache vars, needed by all other bundling scripts -# ! cmakecache vars not available to external scripts -# so we configure it first to do substitutions -# make sure to use @varname@ - -# kill boolean warnings -CMAKE_POLICY (SET CMP0012 NEW) - -# cmake -SET (CPACK_PACKAGE_VERSION_MAJOR @CPACK_PACKAGE_VERSION_MAJOR@) -SET (CPACK_PACKAGE_VERSION_MINOR @CPACK_PACKAGE_VERSION_MINOR@) -SET (CMAKE_VERBOSE_MAKEFILE "@CMAKE_VERBOSE_MAKEFILE@") -SET (CMAKE_INSTALL_PREFIX "@CMAKE_INSTALL_PREFIX@") -SET (CMAKE_BUILD_TYPE "@CMAKE_BUILD_TYPE@") - -# Qt5 cmake does not create overall qt prefix var, only individual lib prefixes. -# For simplicity, assume core prefix same as all others -SET (QT_LIBRARY_DIR "@_qt5Core_install_prefix@/lib") - -# OS X options -SET (CMAKE_OSX_ARCHITECTURES "@CMAKE_OSX_ARCHITECTURES@") - -# QGIS -SET (QGIS_APP_NAME "@QGIS_APP_NAME@") -SET (QGIS_MACAPP_PREFIX "@QGIS_MACAPP_PREFIX@") -SET (QGIS_FW_SUBDIR "@QGIS_FW_SUBDIR@") -SET (QGIS_FW_SUBDIR_REV "@QGIS_FW_SUBDIR_REV@") -SET (QGIS_BIN_SUBDIR "@QGIS_BIN_SUBDIR@") -SET (QGIS_BIN_SUBDIR_REV "@QGIS_BIN_SUBDIR_REV@") -SET (QGIS_CGIBIN_SUBDIR "@QGIS_CGIBIN_SUBDIR@") -SET (QGIS_CGIBIN_SUBDIR_REV "@QGIS_CGIBIN_SUBDIR_REV@") -SET (QGIS_LIB_SUBDIR "@QGIS_LIB_SUBDIR@") -SET (QGIS_LIB_SUBDIR_REV "@QGIS_LIB_SUBDIR_REV@") -SET (QGIS_LIBEXEC_SUBDIR "@QGIS_LIBEXEC_SUBDIR@") -SET (QGIS_LIBEXEC_SUBDIR_REV "@QGIS_LIBEXEC_SUBDIR_REV@") -SET (QGIS_PLUGIN_SUBDIR "@QGIS_PLUGIN_SUBDIR@") -SET (QGIS_PLUGIN_SUBDIR_REV "@QGIS_PLUGIN_SUBDIR_REV@") -SET (QGIS_DATA_SUBDIR "@QGIS_DATA_SUBDIR@") -SET (QGIS_DATA_SUBDIR_REV "@QGIS_DATA_SUBDIR_REV@") -SET (QGIS_SERVER_MODULE_SUBDIR "@QGIS_SERVER_MODULE_SUBDIR@") - -# optional components -SET (WITH_GRASS "@WITH_GRASS@") -SET (WITH_SERVER "@WITH_SERVER@") -SET (WITH_POSTGRESQL "@WITH_POSTGRESQL@") -SET (WITH_QSPATIALITE "@WITH_QSPATIALITE@") - -# tests -SET (ENABLE_TESTS "@ENABLE_TESTS@") - -# Python module search paths -# Allows overriding build variables with PYTHONPATH -# Handles case where resolved symlinked modules may not be where other resolved modules exist, e.g. -# a site-packages directory where all packages/modules are symlinked in (like Homebrew), -# and their respective install prefixes are completely different -# This also handles migration to next-gen sip/PyQt setup where sipconfig and pyqtconfig don't exist -# and the sys.paths used to import the modules dictates how the modules are found -# see: https://github.com/qgis/QGIS/pull/1508 -SET (PYTHON_MODULE_PATHS) -STRING(REPLACE ":" ";" _pythonpath "$ENV{PYTHONPATH}") -LIST(APPEND PYTHON_MODULE_PATHS ${_pythonpath}) -IF (EXISTS "@PYQT5_MOD_DIR@") - LIST(APPEND PYTHON_MODULE_PATHS "@PYQT5_MOD_DIR@") -ENDIF () -IF (EXISTS "@SIP_MODULE_DIR@") - LIST(APPEND PYTHON_MODULE_PATHS "@SIP_MODULE_DIR@") -ENDIF () -IF (EXISTS "@PYTHON_SITE_PACKAGES_SYS@") - LIST(APPEND PYTHON_MODULE_PATHS "@PYTHON_SITE_PACKAGES_SYS@") -ENDIF () diff --git a/mac/cmake/1qt.cmake.in b/mac/cmake/1qt.cmake.in deleted file mode 100644 index 25385f98e610..000000000000 --- a/mac/cmake/1qt.cmake.in +++ /dev/null @@ -1,509 +0,0 @@ -# 1qt - bundle Qt frameworks and PyQt -# ! cmakecache vars not available to external scripts -# so we configure it first to do substitutions -# make sure to use @varname@ - -# kill boolean warnings -CMAKE_POLICY (SET CMP0012 NEW) - -INCLUDE ("@CMAKE_BINARY_DIR@/mac/0vars.cmake") -INCLUDE ("@CMAKE_SOURCE_DIR@/cmake/MacBundleMacros.cmake") -INCLUDE ("@CMAKE_SOURCE_DIR@/cmake/QCAMacros.cmake") - -# Qt framework version is major version -SET (QT_FWVER "5") - -# build list of Qt frameworks to bundle - -# core list, includes dependencies and used by extra plugins -SET (QTLISTQG QtCore QtGui QtWidgets QtNetwork QtXml QtSvg QtConcurrent QtPrintSupport QtSerialPort QtPositioning QtTest QtSql QtDBus) -SET (PYQTLIST Qt QtCore QtGui QtWidgets QtNetwork QtXml QtSvg QtPrintSupport QtPositioning QtSerialPort QtTest QtSql QtDBus) - -# QtQuickWidgets appears to be implied direct dep, it needs Quick and Qml, -# whether or not WITH_QUICK specified -SET (QTLISTQG ${QTLISTQG} QtQuickWidgets QtQuick QtQml) -SET (PYQTLIST ${PYQTLIST} QtQuickWidgets QtQuick QtQml) - -IF(@WITH_QTWEBKIT@) - SET (QTLISTQG ${QTLISTQG} QtWebKit QtWebKitWidgets QtSensors QtWebChannel QtMultimedia QtMultimediaWidgets QtOpenGL) - SET (PYQTLIST ${PYQTLIST} QtWebKit QtWebKitWidgets QtSensors QtWebChannel QtMultimedia QtMultimediaWidgets QtOpenGL) -ENDIF () - -IF(@WITH_3D@) - SET (QTLISTQG ${QTLISTQG} Qt3DCore Qt3DRender Qt3DInput Qt3DLogic Qt3DExtras QtGamepad) - SET (PYQTLIST ${PYQTLIST} Qt3DCore Qt3DRender Qt3DInput Qt3DLogic Qt3DExtras QtGamepad) -ENDIF () - -# add Qsci.so, if available -IF (@QSCI_FOUND@) - SET (PYQTLIST ${PYQTLIST} Qsci) -ENDIF (@QSCI_FOUND@) - -MYMESSAGE ("Qt list: ${QTLISTQG}") - -# symlinks when only @executable_path used - -EXECUTE_PROCESS (COMMAND ln -sfn ../Frameworks "${QAPPDIR}/") -IF (IS_DIRECTORY "${QLIBDIR}/grass/bin") - EXECUTE_PROCESS (COMMAND ln -sfn ../@QGIS_LIBEXEC_SUBDIR_REV@/@QGIS_FW_SUBDIR@ "${QLIBDIR}/grass/Frameworks") -ENDIF () -EXECUTE_PROCESS (COMMAND ln -sfn @QGIS_CGIBIN_SUBDIR_REV@/@QGIS_LIB_SUBDIR@ "${QCGIDIR}/lib") - -### copy files & strip qt rpath - -# Qt frameworks -# Qt5 cmake does not create overall qt prefix var, only individual lib prefixes. -# For simplicity, assume core prefix same as all others. - -MESSAGE (STATUS "Copying Qt frameworks...") -EXECUTE_PROCESS (COMMAND mkdir -p "${QFWDIR}") -FOREACH (QFW ${QTLISTQG}) - IF (NOT IS_DIRECTORY "${QFWDIR}/${QFW}.framework") - COPY_FRAMEWORK("${QT_LIBRARY_DIR}" ${QFW} "${QFWDIR}") - EXECUTE_PROCESS (COMMAND install_name_tool -delete_rpath "@QT_LIBRARY_DIR@" "${QFWDIR}/${QFW}.framework/${QFW}") - ENDIF () -ENDFOREACH (QFW) - -# Qt plugins - -EXECUTE_PROCESS (COMMAND mkdir -p "${QPLUGDIR}/../imageformats") -FOREACH (QI qgif;qico;qjpeg;qsvg;qtiff) - IF (NOT EXISTS "${QPLUGDIR}/../imageformats/lib${QI}.dylib") - EXECUTE_PROCESS (COMMAND ditto ${QARCHS} "@QT_PLUGINS_DIR@/imageformats/lib${QI}.dylib" "${QPLUGDIR}/../imageformats/lib${QI}.dylib") - EXECUTE_PROCESS (COMMAND install_name_tool -delete_rpath "@QT_LIBRARY_DIR@" "${QPLUGDIR}/../imageformats/lib${QI}.dylib") - ENDIF () -ENDFOREACH (QI) -EXECUTE_PROCESS (COMMAND mkdir -p "${QPLUGDIR}/../platforms") -FOREACH (QTP cocoa;minimal;offscreen) - IF (NOT EXISTS "${QPLUGDIR}/../platforms/libq${QTP}.dylib") - EXECUTE_PROCESS (COMMAND ditto ${QARCHS} "@QT_PLUGINS_DIR@/platforms/libq${QTP}.dylib" "${QPLUGDIR}/../platforms/libq${QTP}.dylib") - EXECUTE_PROCESS (COMMAND install_name_tool -delete_rpath "@QT_LIBRARY_DIR@" "${QPLUGDIR}/../platforms/libq${QTP}.dylib") - ENDIF () -ENDFOREACH (QTP) -EXECUTE_PROCESS (COMMAND mkdir -p "${QPLUGDIR}/../sqldrivers") -SET (QTLISTSQL ite odbc psql mysql) -# qspatialite driver plugin is part of QGIS build -IF (@WITH_QSPATIALITE@) - LIST(APPEND QTLISTSQL spatialite) - IF (EXISTS "${QPLUGDIR}/../sqldrivers/libqsqlspatialite.dylib") - EXECUTE_PROCESS (COMMAND ${CMAKE_COMMAND} -E remove "${QPLUGDIR}/../sqldrivers/libqsqlspatialite.dylib") - EXECUTE_PROCESS (COMMAND install_name_tool -delete_rpath "@QT_LIBRARY_DIR@" "${QPLUGDIR}/../sqldrivers/libqsqlspatialite.dylib") - ENDIF () -ENDIF () -FOREACH (QSL ${QTLISTSQL}) - IF (NOT EXISTS "${QPLUGDIR}/../sqldrivers/libqsql${QSL}.dylib" AND EXISTS "@QT_PLUGINS_DIR@/sqldrivers/libqsql${QSL}.dylib") - EXECUTE_PROCESS (COMMAND ditto ${QARCHS} "@QT_PLUGINS_DIR@/sqldrivers/libqsql${QSL}.dylib" "${QPLUGDIR}/../sqldrivers/libqsql${QSL}.dylib") - EXECUTE_PROCESS (COMMAND install_name_tool -delete_rpath "@QT_LIBRARY_DIR@" "${QPLUGDIR}/../sqldrivers/libqsql${QSL}.dylib") - ENDIF () -ENDFOREACH (QSL) -IF (NOT @WITH_QSPATIALITE@ AND EXISTS "${QPLUGDIR}/../sqldrivers/libqsqlspatialite.dylib") - EXECUTE_PROCESS (COMMAND ${CMAKE_COMMAND} -E remove "${QPLUGDIR}/../sqldrivers/libqsqlspatialite.dylib") -ENDIF () -EXECUTE_PROCESS (COMMAND mkdir -p "${QPLUGDIR}/../iconengines") -IF (NOT EXISTS "${QPLUGDIR}/../iconengines/libqsvgicon.dylib") - EXECUTE_PROCESS (COMMAND ditto ${QARCHS} "@QT_PLUGINS_DIR@/iconengines/libqsvgicon.dylib" "${QPLUGDIR}/../iconengines/libqsvgicon.dylib") - EXECUTE_PROCESS (COMMAND install_name_tool -delete_rpath "@QT_LIBRARY_DIR@" "${QPLUGDIR}/../iconengines/libqsvgicon.dylib") -ENDIF () -EXECUTE_PROCESS (COMMAND mkdir -p "${QPLUGDIR}/../styles") -IF (NOT EXISTS "${QPLUGDIR}/../styles/libqmacstyle.dylib") - EXECUTE_PROCESS (COMMAND ditto ${QARCHS} "@QT_PLUGINS_DIR@/styles/libqmacstyle.dylib" "${QPLUGDIR}/../styles/libqmacstyle.dylib") - EXECUTE_PROCESS (COMMAND install_name_tool -delete_rpath "@QT_LIBRARY_DIR@" "${QPLUGDIR}/../styles/libqmacstyle.dylib") -ENDIF () - -# Qwt - -STRING (REGEX MATCH "\\.dylib$" QWT_ISLIB "@QWT_LIBRARY@") -STRING (REGEX MATCH "qwt.framework" QWT_ISFW "@QWT_LIBRARY@") -IF (QWT_ISLIB) - # shared libraries - MESSAGE (STATUS "Copying Qwt and updating library paths...") - IF (NOT EXISTS "${QLIBDIR}/libqwt.dylib") - EXECUTE_PROCESS (COMMAND ditto ${QARCHS} "@QWT_LIBRARY@" "${QLIBDIR}/libqwt.dylib") - EXECUTE_PROCESS (COMMAND install_name_tool -delete_rpath "@QT_LIBRARY_DIR@" "${QLIBDIR}/libqwt.dylib") - ENDIF () - GET_INSTALL_NAME ("@QWT_LIBRARY@" "libqwt" QWT_CHG) - IF (QWT_CHG) - UPDATEQGISPATHS (${QWT_CHG} libqwt.dylib) - ENDIF (QWT_CHG) -ELSEIF (QWT_ISFW AND EXISTS "@QWT_LIBRARY@") - # framework - MESSAGE (STATUS "Copying Qwt framework and updating library paths...") - STRING(REGEX REPLACE "/qwt.framework.*" "" QWT_PARENT "@QWT_LIBRARY@") - IF (NOT IS_DIRECTORY "${QFWDIR}/qwt.framework") - COPY_FRAMEWORK("${QWT_PARENT}" "qwt" "${QFWDIR}") - EXECUTE_PROCESS (COMMAND install_name_tool -delete_rpath "@QT_LIBRARY_DIR@" "${QFWDIR}/qwt.framework/qwt") - ENDIF () - GET_INSTALL_NAME ("${QWT_PARENT}/qwt.framework/qwt" "qwt.framework" QWT_CHG) - IF (QWT_CHG) - UPDATEQGISPATHS (${QWT_CHG} qwt) - ENDIF (QWT_CHG) -ENDIF (QWT_ISLIB) - - -# QwtPolar - -IF (@WITH_DESKTOP@) - IF (@WITH_QWTPOLAR@ AND NOT @WITH_INTERNAL_QWTPOLAR@) - STRING (REGEX MATCH "\\.dylib$" ISLIB "@QWTPOLAR_LIBRARY@") - STRING (REGEX MATCH "qwtpolar.framework" ISFW "@QWTPOLAR_LIBRARY@") - IF (ISLIB) - # shared libraries - MESSAGE (STATUS "Copying QwtPolar and updating library paths...") - IF (NOT EXISTS "${QLIBDIR}/libqwtpolar.dylib") - EXECUTE_PROCESS (COMMAND ditto ${QARCHS} "@QWT_LIBRARY@" "${QLIBDIR}/libqwtpolar.dylib") - EXECUTE_PROCESS (COMMAND install_name_tool -delete_rpath "@QT_LIBRARY_DIR@" "${QLIBDIR}/libqwtpolar.dylib") - ENDIF () - GET_INSTALL_NAME ("@QWTPOLAR_LIBRARY@" "libqwtpolar" QWTP_CHG) - IF (QWTP_CHG) - UPDATEQGISPATHS (${QWTP_CHG} libqwtpolar.dylib) - ENDIF (QWTP_CHG) - # update qwt lib in qwtpolar - IF (QWT_CHG) - IF (QWT_ISLIB) - SET (QWT_CHG_TO "${ATLOADER}/libqwt.dylib") - ElSE () - SET (QWT_CHG_TO "${ATLOADER}/${QGIS_LIB_SUBDIR_REV}/${QGIS_FW_SUBDIR}/qwt.framework/qwt") - ENDIF () - INSTALLNAMETOOL_CHANGE ("${QWT_CHG}" "${QWT_CHG_TO}" "${QLIBDIR}/libqwtpolar.dylib") - ENDIF (QWT_CHG) - ELSEIF (ISFW AND EXISTS "@QWTPOLAR_LIBRARY@") - # framework - MESSAGE (STATUS "Copying QwtPolar framework and updating library paths...") - STRING(REGEX REPLACE "/qwtpolar.framework.*" "" QWTP_PARENT "@QWTPOLAR_LIBRARY@") - IF (NOT IS_DIRECTORY "${QFWDIR}/qwtpolar.framework") - COPY_FRAMEWORK("${QWTP_PARENT}" "qwtpolar" "${QFWDIR}") - EXECUTE_PROCESS (COMMAND install_name_tool -delete_rpath "@QT_LIBRARY_DIR@" "${QFWDIR}/qwtpolar.framework/qwtpolar") - ENDIF () - GET_INSTALL_NAME ("${QWTP_PARENT}/qwtpolar.framework/qwtpolar" "qwtpolar.framework" QWTP_CHG) - IF (QWTP_CHG) - UPDATEQGISPATHS (${QWTP_CHG} qwtpolar) - ENDIF (QWTP_CHG) - # update qwt lib in qwtpolar - IF (QWT_CHG) - IF (QWT_ISLIB) - SET (QWT_CHG_TO "${ATLOADER}/../../../${QGIS_FW_SUBDIR_REV}/${QGIS_LIB_SUBDIR}/libqwt.dylib") - ElSE () - SET (QWT_CHG_TO "${ATLOADER}/../../../qwt.framework/qwt") - ENDIF () - INSTALLNAMETOOL_CHANGE ("${QWT_CHG}" "${QWT_CHG_TO}" "${QFWDIR}/qwtpolar.framework/qwtpolar") - ENDIF (QWT_CHG) - ENDIF (ISLIB) - ENDIF (@WITH_QWTPOLAR@ AND NOT @WITH_INTERNAL_QWTPOLAR@) -ENDIF (@WITH_DESKTOP@) - -# QCA - -STRING (REGEX MATCH "\\.dylib$" ISLIB "@QCA_LIBRARY@") -STRING (REGEX MATCH "qca.*.framework" ISFW "@QCA_LIBRARY@") -IF (ISLIB) - # shared libraries - MESSAGE (STATUS "Copying QCA and updating library paths...") - SET (QCA_CHG_TO "${ATLOADER}/@QGIS_PLUGIN_SUBDIR_REV@/${QGIS_LIB_SUBDIR}/libqca.dylib") - IF (NOT EXISTS "${QLIBDIR}/libqca.dylib") - EXECUTE_PROCESS (COMMAND ditto ${QARCHS} "@QCA_LIBRARY@" "${QLIBDIR}/libqca.dylib") - EXECUTE_PROCESS (COMMAND install_name_tool -delete_rpath "@QT_LIBRARY_DIR@" "${QLIBDIR}/libqca.dylib") - ENDIF () - GET_INSTALL_NAME ("@QCA_LIBRARY@" "libqca" QCA_CHG) - IF (QCA_CHG) - UPDATEQGISPATHS (${QCA_CHG} libqca.dylib) - ENDIF () -ELSEIF (ISFW AND EXISTS "@QCA_LIBRARY@") - # framework - MESSAGE (STATUS "Copying QCA framework and updating library paths...") - SET (QCA_LIBRARY "@QCA_LIBRARY@") - STRING (REGEX MATCH "qca-qt5" _has_long_name "${QCA_LIBRARY}") - IF (_has_long_name) - SET (_qca_libname "qca-qt5") - ELSE () - SET (_qca_libname "qca") - ENDIF () - STRING (REGEX MATCH "${_qca_libname}.framework/${_qca_libname}" _has_bin "${QCA_LIBRARY}") - IF (NOT _has_bin) - SET (QCA_LIBRARY "${QCA_LIBRARY}/${_qca_libname}") - ENDIF () - SET (QCA_CHG_TO "${ATLOADER}/@QGIS_PLUGIN_SUBDIR_REV@/${QGIS_FW_SUBDIR}/${_qca_libname}.framework/${_qca_libname}") - IF (NOT IS_DIRECTORY "${QFWDIR}/${_qca_libname}.framework") - STRING(REGEX REPLACE "/${_qca_libname}.framework.*" "" QCA_PARENT "@QCA_LIBRARY@") - COPY_FRAMEWORK("${QCA_PARENT}" "${_qca_libname}" "${QFWDIR}") - EXECUTE_PROCESS (COMMAND install_name_tool -delete_rpath "@QT_LIBRARY_DIR@" "${QFWDIR}/${_qca_libname}.framework/${_qca_libname}") - ENDIF () - GET_INSTALL_NAME ("${QCA_LIBRARY}" "${_qca_libname}" QCA_CHG) - IF (QCA_CHG) - UPDATEQGISPATHS (${QCA_CHG} ${_qca_libname}) - ENDIF () -ENDIF () -# copy and relink the plugins -EXECUTE_PROCESS (COMMAND mkdir -p "${QPLUGDIR}/../crypto") -FIND_QCA_PLUGIN_DIR (1) -MESSAGE (STATUS "Updating QCA plugins with QCA library path in ${QCA_PLUGIN_DIR} ...") -# don't copy over any unneeded plugins -SET(QCA_PLUGINS logger ossl softstore) -FOREACH (qca_plugin ${QCA_PLUGINS}) - EXECUTE_PROCESS (COMMAND ditto ${QARCHS} "${QCA_PLUGIN_DIR}/crypto/libqca-${qca_plugin}.dylib" "${QPLUGDIR}/../crypto/") - EXECUTE_PROCESS (COMMAND install_name_tool -delete_rpath "@QT_LIBRARY_DIR@" "${QCA_PLUGIN_DIR}/crypto/libqca-${qca_plugin}.dylib") - IF (QCA_CHG) - INSTALLNAMETOOL_CHANGE ("${QCA_CHG}" "${QCA_CHG_TO}" "${QPLUGDIR}/../crypto/libqca-${qca_plugin}.dylib") - ENDIF () -ENDFOREACH () - -# QSpatialite Qt plugin -# linked to qca and qgis_core frameworks (see also 2lib.cmake.in) -IF (@WITH_QSPATIALITE@ AND EXISTS "${QPLUGDIR}/../sqldrivers/libqsqlspatialite.dylib") - # qca.framework - EXECUTE_PROCESS (COMMAND install_name_tool -delete_rpath "@QT_LIBRARY_DIR@" "${QPLUGDIR}/../sqldrivers/libqsqlspatialite.dylib") - INSTALLNAMETOOL_CHANGE ("${QCA_CHG}" "${QCA_CHG_TO}" "${QPLUGDIR}/../sqldrivers/libqsqlspatialite.dylib") - # qgis_core.framework - GET_INSTALL_NAME ("@QGIS_OUTPUT_DIRECTORY@/lib/qgis_core.framework/qgis_core" qgis_core.framework QGCORE) - SET (QGCORE_CHG_TO "${ATLOADER}/@QGIS_PLUGIN_SUBDIR_REV@/${QGIS_FW_SUBDIR}/qgis_core.framework/qgis_core") - INSTALLNAMETOOL_CHANGE ("${QGCORE}" "${QGCORE_CHG_TO}" "${QPLUGDIR}/../sqldrivers/libqsqlspatialite.dylib") -ENDIF () - -# QScintilla2 - -IF (@QSCINTILLA_LIBRARY@ MATCHES ".*libqscintilla2_qt5.*dylib") - SET (QSCI_LIB "libqscintilla2_qt5") -ELSEIF (@QSCINTILLA_LIBRARY@ MATCHES ".*libqscintilla2.*dylib") - SET (QSCI_LIB "libqscintilla2") -ENDIF () -IF (QSCI_LIB) - MESSAGE (STATUS "Copying QScintilla2 library and updating library paths...") - EXECUTE_PROCESS (COMMAND ditto ${QARCHS} "@QSCINTILLA_LIBRARY@" "${QLIBDIR}/${QSCI_LIB}.dylib") - EXECUTE_PROCESS (COMMAND install_name_tool -delete_rpath "@QT_LIBRARY_DIR@" "${QLIBDIR}/${QSCI_LIB}.dylib") - GET_INSTALL_NAME ("@QSCINTILLA_LIBRARY@" "${QSCI_LIB}" QSCI_CHG) - IF (QSCI_CHG) - UPDATEQGISPATHS (${QSCI_CHG} ${QSCI_LIB}.dylib) - ENDIF (QSCI_CHG) -ENDIF () - -# QtKeychain - -IF (@QTKEYCHAIN_LIBRARY@ MATCHES ".*libqt5keychain.dylib") - MESSAGE (STATUS "Copying QtKeychain library and updating library paths...") - EXECUTE_PROCESS (COMMAND ditto ${QARCHS} "@QTKEYCHAIN_LIBRARY@" "${QLIBDIR}/libqt5keychain.dylib") - EXECUTE_PROCESS (COMMAND install_name_tool -delete_rpath "@QT_LIBRARY_DIR@" "${QLIBDIR}/libqt5keychain.dylib") - GET_INSTALL_NAME ("@QTKEYCHAIN_LIBRARY@" "libqt5keychain" QTKEY_CHG) - IF (QTKEY_CHG) - UPDATEQGISPATHS (${QTKEY_CHG} libqt5keychain.dylib) - ENDIF (QTKEY_CHG) -ENDIF () - -# Tell user what Python paths are being searched for modules and packages -# see: PYTHON_MODULE_PATHS in 0vars.cmake.in for why not all PyQt-related modules -# can be assumed to exist in symlinked-resolved PyQt or sip module directories -MESSAGE (STATUS "PYTHON_MODULE_PATHS to be searched:") -FOREACH (PYPATH ${PYTHON_MODULE_PATHS}) - MESSAGE (STATUS " ${PYPATH}") -ENDFOREACH (PYPATH) - -# sip and PyQt - -MESSAGE (STATUS "Copying sip...") -PYTHONMODULEDIR("sip.so" SIPMODDIR) -IF (SIPMODDIR) - IF (NOT EXISTS "${QGISPYDIR}/sip.so" AND NOT EXISTS "${QGISPYDIR}/PyQt5/sip.so") - # MYMESSAGE ("ditto ${QARCHS} \"${SIPMODDIR}/sip.so\" \"${QGISPYDIR}/\"") - IF (${SIPMODDIR} MATCHES ".*PyQt5.*") - EXECUTE_PROCESS (COMMAND ditto ${QARCHS} "${SIPMODDIR}/sip.so" "${QGISPYDIR}/PyQt5/") - EXECUTE_PROCESS (COMMAND install_name_tool -delete_rpath "@QT_LIBRARY_DIR@" "${QGISPYDIR}/PyQt5/sip.so") - ELSE () - EXECUTE_PROCESS (COMMAND ditto ${QARCHS} "${SIPMODDIR}/sip.so" "${QGISPYDIR}/") - EXECUTE_PROCESS (COMMAND install_name_tool -delete_rpath "@QT_LIBRARY_DIR@" "${QGISPYDIR}/sip.so") - ENDIF () - EXECUTE_PROCESS (COMMAND cp -fp "${SIPMODDIR}/sipconfig.py" "${QGISPYDIR}/") - ENDIF () -ELSE () - MESSAGE (STATUS " sip module not found") -ENDIF () - -MESSAGE (STATUS "Copying PyQt...") -EXECUTE_PROCESS (COMMAND mkdir -p "${QGISPYDIR}/PyQt${QT_FWVER}") -FOREACH (PQ ${PYQTLIST}) - SET (MODNAME "${PQ}.so") - SET (MODPYI "PyQt${QT_FWVER}/${PQ}.pyi") - SET (MODSUBPATH "PyQt${QT_FWVER}/${MODNAME}") - # search for each module separately, instead of only in first found PyQt directory, since PyQt may - # be installed to its a specific prefix, like with Homebrew, then symlinked into common 'site-packages' - PYTHONMODULEDIR("${MODSUBPATH}" MODDIR) - IF (MODDIR) - IF (NOT EXISTS "${QGISPYDIR}/${MODSUBPATH}") - # MESSAGE (STATUS "ditto ${QARCHS} \"${PYQT5MOD}\" \"${QGISPYDIR}/${MODSUBPATH}\"") - EXECUTE_PROCESS (COMMAND ditto ${QARCHS} "${MODDIR}/${MODSUBPATH}" "${QGISPYDIR}/${MODSUBPATH}") - EXECUTE_PROCESS (COMMAND install_name_tool -delete_rpath "@QT_LIBRARY_DIR@" "${QGISPYDIR}/${MODSUBPATH}") - IF (EXISTS "${MODDIR}/${MODPYI}") - EXECUTE_PROCESS (COMMAND ditto "${MODDIR}/${MODPYI}" "${QGISPYDIR}/${MODPYI}") - ENDIF () - ENDIF () - ELSE (MODDIR) - MESSAGE (STATUS " PyQt5 module ${MODNAME} not found") - ENDIF (MODDIR) - UNSET(PYQT5MOD) -ENDFOREACH (PQ) -PYTHONMODULEDIR("PyQt${QT_FWVER}" PYQTMODDIR) -FILE (GLOB PQPYLIST "${PYQTMODDIR}/PyQt${QT_FWVER}/*.py*") -FOREACH (PQPY ${PQPYLIST}) - EXECUTE_PROCESS (COMMAND cp -fp "${PQPY}" "${QGISPYDIR}/PyQt${QT_FWVER}/") -ENDFOREACH (PQPY) -EXECUTE_PROCESS (COMMAND cp -RfpL "${PYQTMODDIR}/PyQt${QT_FWVER}/uic" "${QGISPYDIR}/PyQt${QT_FWVER}") - -# PyQt utilities - -FOREACH (PU pylupdate5;pyrcc5) - IF (NOT EXISTS "${QBINDIR}/${PU}") - EXECUTE_PROCESS (COMMAND ditto ${QARCHS} "@PYQT5_BIN_DIR@/${PU}" "${QBINDIR}/") - ENDIF () -ENDFOREACH (PU) -IF (NOT EXISTS "${QBINDIR}/pyuic5") - EXECUTE_PROCESS (COMMAND sed -E "s, /.*/PyQt5/uic/pyuic.py, \"\$(/usr/bin/dirname \"\$0\")/../../Resources/python/PyQt5/uic/pyuic.py\"," "@PYQT5_BIN_DIR@/pyuic5" - OUTPUT_VARIABLE PYUIC_CONTENTS) - FILE (WRITE "${QBINDIR}/pyuic4" "${PYUIC_CONTENTS}") - EXECUTE_PROCESS (COMMAND chmod +x "${QBINDIR}/pyuic4") -ENDIF () - -# PyQwt -# only if it's available, not compatible with newer PyQt -PYTHONMODULEDIR("Qwt5/_iqt.so" QWT4MODDIR) -IF (QWT4MODDIR) - MESSAGE (STATUS "Copying PyQwt and updating library paths...") - EXECUTE_PROCESS (COMMAND mkdir -p "${QGISPYDIR}/PyQt${QT_FWVER}/Qwt5") - IF (NOT EXISTS "${QGISPYDIR}/PyQt${QT_FWVER}/Qwt5/_iqt.so") - EXECUTE_PROCESS (COMMAND ditto ${QARCHS} "${QWT4MODDIR}/Qwt5/_iqt.so" "${QGISPYDIR}/PyQt${QT_FWVER}/Qwt5/") - ENDIF () - IF (NOT EXISTS "${QGISPYDIR}/PyQt${QT_FWVER}/Qwt5/Qwt.so") - EXECUTE_PROCESS (COMMAND ditto ${QARCHS} "${QWT4MODDIR}/Qwt5/Qwt.so" "${QGISPYDIR}/PyQt${QT_FWVER}/Qwt5/") - ENDIF () - FILE (GLOB PQWPYLIST "${QWT4MODDIR}/Qwt5/*.py") - FOREACH (PQWPY ${PQWPYLIST}) - EXECUTE_PROCESS (COMMAND cp -fp "${PQWPY}" "${QGISPYDIR}/PyQt${QT_FWVER}/Qwt5/") - ENDFOREACH (PQWPY) - IF (QWT_CHG) - SET (QWT_CHG_TO "${ATLOADER}/../../../@QGIS_DATA_SUBDIR_REV@/@QGIS_LIB_SUBDIR@/libqwt.dylib") - FOREACH (PW _iqt;Qwt) - INSTALLNAMETOOL_CHANGE ("${QWT_CHG}" "${QWT_CHG_TO}" "${QGISPYDIR}/PyQt${QT_FWVER}/Qwt5/${PW}.so") - ENDFOREACH (PW) - ENDIF (QWT_CHG) -ENDIF () - -# QScintilla Python module -# should have already been copied with PyQt modules - -IF (EXISTS "${QGISPYDIR}/PyQt${QT_FWVER}/Qsci.so") - MESSAGE (STATUS "Updating QScintilla2 Python module library paths...") - GET_INSTALL_NAME ("${QGISPYDIR}/PyQt${QT_FWVER}/Qsci.so" "${QSCI_LIB}" QSCI_CHG) - IF (QSCI_CHG) - SET (QSCI_CHG_TO "${ATEXECUTABLE}/@QGIS_LIB_SUBDIR@/${QSCI_LIB}.dylib") - SET (QSCI_CHG_TO "${ATLOADER}/../../@QGIS_DATA_SUBDIR_REV@/@QGIS_LIB_SUBDIR@/${QSCI_LIB}.dylib") - INSTALLNAMETOOL_CHANGE ("${QSCI_CHG}" "${QSCI_CHG_TO}" "${QGISPYDIR}/PyQt${QT_FWVER}/Qsci.so") - ENDIF (QSCI_CHG) -ENDIF () - -# don't load plugins from system-installed Qt -FILE (WRITE "${QAPPDIRC}/Resources/qt.conf" "") -FOREACH (QA ${QGAPPLIST}) - FILE (WRITE "${QBINDIR}/${QA}.app/Contents/Resources/qt.conf" "") -ENDFOREACH (QA) - -### update lib paths - -MESSAGE (STATUS "Updating Qt library paths...") - -FOREACH (QFW ${QTLISTQG}) - # get install names from installed in case bundled copy already changed - # from a previous install attempt - GET_INSTALL_NAME ("${QT_LIBRARY_DIR}/${QFW}.framework/${QFW}" ${QFW}.framework QQ) - SET (QFW_CHG "${QQ}") - # qgis stuff - UPDATEQGISPATHS ("${QFW_CHG}" ${QFW}) - - SET (LIBPOST "${QFW}.framework/${QFW}") - # Qwt - STRING (REGEX MATCH "\\.dylib$" ISLIB "@QWT_LIBRARY@") - STRING (REGEX MATCH "qwt.framework" ISFW "@QWT_LIBRARY@") - IF (ISLIB) - SET (QFW_CHG_TO "${ATLOADER}/${QGIS_LIB_SUBDIR_REV}/${QGIS_FW_SUBDIR}/${LIBPOST}") - INSTALLNAMETOOL_CHANGE ("${QFW_CHG}" "${QFW_CHG_TO}" "${QLIBDIR}/libqwt.dylib") - ELSEIF (ISFW AND EXISTS "${QFWDIR}/qwt.framework/qwt") - SET (QFW_CHG_TO "${ATLOADER}/../../../${LIBPOST}") - INSTALLNAMETOOL_CHANGE ("${QFW_CHG}" "${QFW_CHG_TO}" "${QFWDIR}/qwt.framework/qwt") - ENDIF (ISLIB) - # qtkeychain - STRING (REGEX MATCH "\\.dylib$" ISLIB "@QTKEYCHAIN_LIBRARY@") - STRING (REGEX MATCH "qt5keychain.framework" ISFW "@QTKEYCHAIN_LIBRARY@") - IF (ISLIB) - SET (QFW_CHG_TO "${ATLOADER}/${QGIS_LIB_SUBDIR_REV}/${QGIS_FW_SUBDIR}/${LIBPOST}") - INSTALLNAMETOOL_CHANGE ("${QFW_CHG}" "${QFW_CHG_TO}" "${QLIBDIR}/libqt5keychain.dylib") - ELSEIF (ISFW AND EXISTS "${QFWDIR}/qt5keychain.framework/qt5keychain") - SET (QFW_CHG_TO "${ATLOADER}/../../../${LIBPOST}") - INSTALLNAMETOOL_CHANGE ("${QFW_CHG}" "${QFW_CHG_TO}" "${QFWDIR}/qt5keychain.framework/qt5keychain") - ENDIF (ISLIB) - # QwtPolar - STRING (REGEX MATCH "\\.dylib$" ISLIB "@QWTPOLAR_LIBRARY@") - STRING (REGEX MATCH "qwtpolar.framework" ISFW "@QWTPOLAR_LIBRARY@") - IF (ISLIB) - SET (QFW_CHG_TO "${ATLOADER}/${QGIS_LIB_SUBDIR_REV}/${QGIS_FW_SUBDIR}/${LIBPOST}") - INSTALLNAMETOOL_CHANGE ("${QFW_CHG}" "${QFW_CHG_TO}" "${QLIBDIR}/libqwtpolar.dylib") - ELSEIF (ISFW AND EXISTS "${QFWDIR}/qwtpolar.framework/qwtpolar") - SET (QFW_CHG_TO "${ATLOADER}/../../../${LIBPOST}") - INSTALLNAMETOOL_CHANGE ("${QFW_CHG}" "${QFW_CHG_TO}" "${QFWDIR}/qwtpolar.framework/qwtpolar") - ENDIF (ISLIB) - # QCA - STRING (REGEX MATCH "\\.dylib$" ISLIB "@QCA_LIBRARY@") - STRING (REGEX MATCH "${_qca_libname}.framework" ISFW "@QCA_LIBRARY@") - IF (ISLIB) - SET (QFW_CHG_TO "${ATLOADER}/${QGIS_LIB_SUBDIR_REV}/${QGIS_FW_SUBDIR}/${LIBPOST}") - INSTALLNAMETOOL_CHANGE ("${QFW_CHG}" "${QFW_CHG_TO}" "${QLIBDIR}/libqca.dylib") - ELSEIF (ISFW AND EXISTS "${QFWDIR}/${_qca_libname}.framework/${_qca_libname}") - SET (QFW_CHG_TO "${ATLOADER}/../../../${LIBPOST}") - INSTALLNAMETOOL_CHANGE ("${QFW_CHG}" "${QFW_CHG_TO}" "${QFWDIR}/${_qca_libname}.framework/${_qca_libname}") - ENDIF (ISLIB) - # QScintilla2 - SET (QFW_CHG_TO "${ATLOADER}/${QGIS_LIB_SUBDIR_REV}/${QGIS_FW_SUBDIR}/${LIBPOST}") - INSTALLNAMETOOL_CHANGE ("${QFW_CHG}" "${QFW_CHG_TO}" "${QLIBDIR}/${QSCI_LIB}.dylib") - # qt plugs - SET (QFW_CHG_TO "${ATLOADER}/@QGIS_PLUGIN_SUBDIR_REV@/${QGIS_FW_SUBDIR}/${LIBPOST}") - # qca plugins - FOREACH (qca_plugin ${QCA_PLUGINS}) - INSTALLNAMETOOL_CHANGE ("${QFW_CHG}" "${QFW_CHG_TO}" "${QPLUGDIR}/../crypto/libqca-${qca_plugin}.dylib") - ENDFOREACH () - FOREACH (QI qgif;qico;qjpeg;qsvg;qtiff) - INSTALLNAMETOOL_CHANGE ("${QFW_CHG}" "${QFW_CHG_TO}" "${QPLUGDIR}/../imageformats/lib${QI}.dylib") - ENDFOREACH (QI) - FOREACH (QP cocoa;minimal;offscreen) - INSTALLNAMETOOL_CHANGE ("${QFW_CHG}" "${QFW_CHG_TO}" "${QPLUGDIR}/../platforms/libq${QP}.dylib") - ENDFOREACH (QP) - FOREACH (QSL ${QTLISTSQL}) - IF (EXISTS "${QPLUGDIR}/../sqldrivers/libqsql${QSL}.dylib") - INSTALLNAMETOOL_CHANGE ("${QFW_CHG}" "${QFW_CHG_TO}" "${QPLUGDIR}/../sqldrivers/libqsql${QSL}.dylib") - ENDIF () - ENDFOREACH (QSL) - IF (@WITH_QSPATIALITE@ AND EXISTS "${QPLUGDIR}/../sqldrivers/libqsqlspatialite.dylib") - EXECUTE_PROCESS (COMMAND install_name_tool -id "libqsqlspatialite.dylib" "${QPLUGDIR}/../sqldrivers/libqsqlspatialite.dylib") - ENDIF () - INSTALLNAMETOOL_CHANGE ("${QFW_CHG}" "${QFW_CHG_TO}" "${QPLUGDIR}/../iconengines/libqsvgicon.dylib") - INSTALLNAMETOOL_CHANGE ("${QFW_CHG}" "${QFW_CHG_TO}" "${QPLUGDIR}/../phonon_backend/libphonon_qt7.dylib") - INSTALLNAMETOOL_CHANGE ("${QFW_CHG}" "${QFW_CHG_TO}" "${QPLUGDIR}/../styles/libqmacstyle.dylib") - # quick plugin - SET (QFW_CHG_TO "${ATLOADER}/../../../${LIBPOST}") - INSTALLNAMETOOL_CHANGE ("${QFW_CHG}" "${QFW_CHG_TO}" "${QAPPDIR}/qml/QgsQuick/libqgis_quick_plugin.dylib") - # qt fw - SET (QFW_CHG_TO "${ATLOADER}/../../../${LIBPOST}") - FOREACH (QF ${QTLISTQG}) - INSTALLNAMETOOL_CHANGE ("${QFW_CHG}" "${QFW_CHG_TO}" "${QFWDIR}/${QF}.framework/${QF}") - ENDFOREACH (QF) - # PyQt (includes QScintilla2 module) - SET (QFW_CHG_TO "${ATLOADER}/../../@QGIS_DATA_SUBDIR_REV@/${QGIS_FW_SUBDIR}/${LIBPOST}") - FOREACH (PQ ${PYQTLIST}) - INSTALLNAMETOOL_CHANGE ("${QFW_CHG}" "${QFW_CHG_TO}" "${QGISPYDIR}/PyQt${QT_FWVER}/${PQ}.so") - ENDFOREACH (PQ) - # PyQwt - SET (QFW_CHG_TO "${ATLOADER}/../../../@QGIS_DATA_SUBDIR_REV@/${QGIS_FW_SUBDIR}/${LIBPOST}") - FOREACH (PW _iqt;Qwt) - IF (EXISTS "${QGISPYDIR}/PyQt${QT_FWVER}/Qwt5/${PW}.so") - INSTALLNAMETOOL_CHANGE ("${QFW_CHG}" "${QFW_CHG_TO}" "${QGISPYDIR}/PyQt${QT_FWVER}/Qwt5/${PW}.so") - ENDIF () - ENDFOREACH (PW) - # bin - PyQt utils - SET (QFW_CHG_TO "${ATEXECUTABLE}/@QGIS_BIN_SUBDIR_REV@/${QGIS_FW_SUBDIR}/${LIBPOST}") - FOREACH (PB pylupdate4;pyrcc4) - INSTALLNAMETOOL_CHANGE ("${QFW_CHG}" "${QFW_CHG_TO}" "${QBINDIR}/${PB}") - ENDFOREACH (PB) -ENDFOREACH (QFW) diff --git a/mac/cmake/2lib.cmake.in b/mac/cmake/2lib.cmake.in deleted file mode 100644 index fc99ffea9c60..000000000000 --- a/mac/cmake/2lib.cmake.in +++ /dev/null @@ -1,57 +0,0 @@ -# 2lib - bundle shared libraries (but not standard frameworks) -# ! cmakecache vars not available to external scripts -# so we configure it first to do substitutions -# make sure to use @varname@ - -# for now, just libs not available as frameworks -# libpq -# libfcgi (non-system) - -# kill boolean warnings -CMAKE_POLICY (SET CMP0012 NEW) - -INCLUDE ("@CMAKE_BINARY_DIR@/mac/0vars.cmake") -INCLUDE ("@CMAKE_SOURCE_DIR@/cmake/MacBundleMacros.cmake") - -# Postgres - -IF ("@POSTGRES_LIBRARY@" MATCHES ".*libpq.dylib") - MESSAGE (STATUS "Copying libpq and updating library paths...") - EXECUTE_PROCESS (COMMAND ditto ${QARCHS} "@POSTGRES_LIBRARY@" "${QLIBDIR}/libpq.dylib") - GET_INSTALL_NAME ("@POSTGRES_LIBRARY@" "libpq" PQLIB) - UPDATEQGISPATHS (${PQLIB} libpq.dylib) - # may have been built with libintl - GET_INSTALL_NAME ("@POSTGRES_LIBRARY@" "libintl" INTLLIB) - IF (INTLLIB) - EXECUTE_PROCESS (COMMAND ditto ${QARCHS} "${INTLLIB}" "${QLIBDIR}/libintl.dylib") - SET (LIB_CHG_TO "${ATEXECUTABLE}/@QGIS_LIB_SUBDIR@/libintl.dylib") - SET (LIB_CHG_TO "${ATLOADER}/libintl.dylib") - INSTALLNAMETOOL_CHANGE ("${INTLLIB}" "${LIB_CHG_TO}" "${QLIBDIR}/libpq.dylib") - ENDIF (INTLLIB) - IF (EXISTS "${QPLUGDIR}/../sqldrivers/libqsqlpsql.dylib") - FILE (RELATIVE_PATH _relpath "${QPLUGDIR}/../sqldrivers" "${QLIBDIR}/libpq.dylib") - INSTALLNAMETOOL_CHANGE ("${PQLIB}" "${ATLOADER}/${_relpath}" "${QPLUGDIR}/../sqldrivers/libqsqlpsql.dylib") - ENDIF () -ENDIF () - -# libspatialindex - -IF ("@SPATIALINDEX_LIBRARY@" MATCHES ".*libspatialindex.dylib") - MESSAGE (STATUS "Copying libspatialindex and updating library paths...") - EXECUTE_PROCESS (COMMAND ditto ${QARCHS} "@SPATIALINDEX_LIBRARY@" "${QLIBDIR}/libspatialindex.dylib") - GET_INSTALL_NAME ("@SPATIALINDEX_LIBRARY@" "libspatialindex" SPILIB) - UPDATEQGISPATHS (${SPILIB} libspatialindex.dylib) - IF (@WITH_QSPATIALITE@ AND EXISTS "${QPLUGDIR}/../sqldrivers/libqsqlspatialite.dylib") - FILE (RELATIVE_PATH _relpath "${QPLUGDIR}/../sqldrivers" "${QLIBDIR}/libspatialindex.dylib") - INSTALLNAMETOOL_CHANGE ("${SPILIB}" "${ATLOADER}/${_relpath}" "${QPLUGDIR}/../sqldrivers/libqsqlspatialite.dylib") - ENDIF () -ENDIF () - -# libfcgi (non-system) - -IF ("@FCGI_LIBRARY@" MATCHES ".*libfcgi.dylib" AND NOT "@FCGI_LIBRARY@" MATCHES "/usr/lib/.*") - MESSAGE (STATUS "Copying libfcgi and updating library paths...") - EXECUTE_PROCESS (COMMAND ditto ${QARCHS} "@FCGI_LIBRARY@" "${QLIBDIR}/libfcgi.dylib") - GET_INSTALL_NAME ("@FCGI_LIBRARY@" "libfcgi" FCGILIB) - UPDATEQGISPATHS (${FCGILIB} libfcgi.dylib) -ENDIF () diff --git a/mac/cmake/3fw.cmake.in b/mac/cmake/3fw.cmake.in deleted file mode 100644 index bf91c46d9cf1..000000000000 --- a/mac/cmake/3fw.cmake.in +++ /dev/null @@ -1,15 +0,0 @@ -# 3fw - bundle standard frameworks -# ! cmakecache vars not available to external scripts -# so we configure it first to do substitutions -# make sure to use @varname@ - -MESSAGE (STATUS "Bundling other frameworks is not functional yet, skipping...") - -# kill boolean warnings -CMAKE_POLICY (SET CMP0012 NEW) - -INCLUDE ("@CMAKE_BINARY_DIR@/mac/0vars.cmake") -INCLUDE ("@CMAKE_SOURCE_DIR@/cmake/MacBundleMacros.cmake") - -# - diff --git a/mac/framework.info.plist.in b/mac/framework.info.plist.in deleted file mode 100644 index 435458b4f9fa..000000000000 --- a/mac/framework.info.plist.in +++ /dev/null @@ -1,26 +0,0 @@ - - - - - CFBundleDevelopmentRegion - English - CFBundleExecutable - ${MACOSX_FRAMEWORK_NAME} - CFBundleGetInfoString - ${MACOSX_FRAMEWORK_NAME} ${COMPLETE_VERSION} - CFBundleIdentifier - ${MACOSX_FRAMEWORK_IDENTIFIER} - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${MACOSX_FRAMEWORK_NAME} - CFBundlePackageType - FMWK - CFBundleShortVersionString - ${MACOSX_FRAMEWORK_SHORT_VERSION_STRING} - CFBundleSignature - ???? - CFBundleVersion - ${MACOSX_FRAMEWORK_NAME} ${COMPLETE_VERSION} - - diff --git a/mac/readme.txt b/mac/readme.txt deleted file mode 100644 index 136309e5ed60..000000000000 --- a/mac/readme.txt +++ /dev/null @@ -1,21 +0,0 @@ -Mac Notes -********* - -The 'cmake' folder scripts handle bundling dependent libraries in the QGIS -application package and fixing up the library paths. It is automatic during -installation. There are 2 levels currently, specified with the cmake config -option QGIS_MACAPP_BUNDLE, and one that always occurs: - --1 = do not run bundle install scrips -0 = (default) fixup the library paths for all QGIS libraries if @loader_path - is available in the system (OS X 10.5+) -1 = bundle Qt, PyQt, PyQwt and OSG/osgEarth -2 = additionally, bundle libraries, but not frameworks - -A third level that is not finished will additionally bundle frameworks. -This would create the "standalone" QGIS. - -There is also a configure option to set a user bundle script, -QGIS_MACAPP_BUNDLE_USER. This specifies the path to a cmake bundle script -similar to the built-in bundle scripts for the defined levels. This script is -always run independent of and after the QGIS_MACAPP_BUNDLE level specified. diff --git a/platform/macos/CPackMacDeployQt.cmake.in b/platform/macos/CPackMacDeployQt.cmake.in new file mode 100644 index 000000000000..44d3dd77b989 --- /dev/null +++ b/platform/macos/CPackMacDeployQt.cmake.in @@ -0,0 +1,31 @@ +if(NOT "$ENV{MACOS_CODE_SIGN_IDENTITY}" STREQUAL "") + # -appstore-compliant will strip away odbc, psql and webengine plugins + execute_process(COMMAND "@PYMACDEPLOYQT_EXECUTABLE@" @QGIS_APP_NAME@.app -codesign=${MACOS_CODE_SIGN_IDENTITY} -sign-for-notarization=${MACOS_CODE_SIGN_IDENTITY} + WORKING_DIRECTORY ${CPACK_TEMPORARY_DIRECTORY} + COMMAND_ERROR_IS_FATAL ANY + ) + + if (@CREATE_DMG@) + execute_process(COMMAND create-dmg --volname "@QGIS_APP_NAME@ Installer" --hide-extension @QGIS_APP_NAME@.app --volicon "@CMAKE_SOURCE_DIR@/images/icons/mac/qgis.icns" --background "@CMAKE_SOURCE_DIR@/platform/macos/installer_background.png" --window-pos 200 120 --window-size 512 384 --icon-size 100 --icon "@QGIS_APP_NAME@.app" 130 160 --app-drop-link 400 155 --codesign "${MACOS_CODE_SIGN_IDENTITY}" @CMAKE_BINARY_DIR@/@QGIS_APP_NAME@-Installer.dmg ${CPACK_TEMPORARY_DIRECTORY}/@QGIS_APP_NAME@.app + RESULT_VARIABLE CREATE_DMG_FAILURE) + + if(CREATE_DMG_FAILURE) + message(STATUS "Creating dmg failed.") + endif() + endif() +else() + # -appstore-compliant will strip away odbc, psql and webengine plugins + execute_process(COMMAND "@PYMACDEPLOYQT_EXECUTABLE@" "@QGIS_APP_NAME@.app" + WORKING_DIRECTORY ${CPACK_TEMPORARY_DIRECTORY} + COMMAND_ERROR_IS_FATAL ANY + ) + + if (@CREATE_DMG@) + execute_process(COMMAND create-dmg --volname "@QGIS_APP_NAME@ Installer" --hide-extension @QGIS_APP_NAME@.app --volicon "@CMAKE_SOURCE_DIR@/images/icons/mac/qgis.icns" --background "@CMAKE_SOURCE_DIR@/platform/macos/installer_background.png" --window-pos 200 120 --window-size 512 384 --icon-size 100 --icon "@QGIS_APP_NAME@.app" 130 160 --app-drop-link 400 155 @CMAKE_BINARY_DIR@/@QGIS_APP_NAME@-Installer.dmg ${CPACK_TEMPORARY_DIRECTORY}/@QGIS_APP_NAME@.app + RESULT_VARIABLE CREATE_DMG_FAILURE) + + if(CREATE_DMG_FAILURE) + message(STATUS "Creating dmg failed.") + endif() + endif() +endif() diff --git a/mac/app.info.plist.in b/platform/macos/Info.plist.in similarity index 90% rename from mac/app.info.plist.in rename to platform/macos/Info.plist.in index 10153c514ebe..069b8608fdd2 100644 --- a/mac/app.info.plist.in +++ b/platform/macos/Info.plist.in @@ -9,19 +9,39 @@ CFBundleIdentifier org.qgis.qgis3 CFBundleExecutable - ${QGIS_APP_NAME} + @QGIS_APP_NAME@ CFBundlePackageType APPL CFBundleSignature QGIS CFBundleGetInfoString - ${QGIS_APP_NAME} ${COMPLETE_VERSION}-${RELEASE_NAME} (${SHA}), Β© 2002-2019 QGIS Development Team + @QGIS_APP_NAME@ @COMPLETE_VERSION@-@RELEASE_NAME@ (@SHA@) CFBundleShortVersionString - ${COMPLETE_VERSION} + @COMPLETE_VERSION@ CFBundleVersion - ${COMPLETE_VERSION} (${SHA}) + @COMPLETE_VERSION@ (@SHA@) CFBundleIconFile qgis.icns + CFBundleIcons + + CFBundlePrimaryIcon + + CFBundleIconFiles + + qgis.icns + + + CFBundleAlternateIcons + + DarkModeIcon + + CFBundleIconFiles + + qgis-dark.icns + + + + CFBundleInfoDictionaryVersion 6.0 CSResourcesFileMapped @@ -34,7 +54,7 @@ CFBundleTypeRole Editor CFBundleTypeIconFile - qgs.icns + qgis.icns CFBundleTypeExtensions qgs diff --git a/platform/macos/installer_background.png b/platform/macos/installer_background.png new file mode 100644 index 000000000000..4badd146ff93 Binary files /dev/null and b/platform/macos/installer_background.png differ diff --git a/platform/macos/pymacdeployqt.py b/platform/macos/pymacdeployqt.py new file mode 100755 index 000000000000..ce3a3def045c --- /dev/null +++ b/platform/macos/pymacdeployqt.py @@ -0,0 +1,401 @@ +#!/usr/bin/env python3 + +import argparse +import os +import shutil +import subprocess + +from dataclasses import dataclass +from functools import lru_cache +from pathlib import Path +from typing import Dict, List, Set, Tuple + +# System paths that should be excluded from copying +SYSTEM_PATHS = [ + "/usr/lib", + "/System/Library", + "/Library/Frameworks", +] + + +@dataclass +class Library: + path: str + install_name: str + dependencies: list[str] + rpaths: list[str] + + +@lru_cache(maxsize=None) +def get_macho_info(path: str) -> bytes: + """Run otool -l and cache the output.""" + result = subprocess.run(["otool", "-l", path], capture_output=True, check=True) + return result.stdout + + +def parse_macho_info(path: str) -> Library: + """Parse otool -l output to extract all needed information.""" + output = get_macho_info(path).decode("utf-8").split("\n") + + install_name = path + rpaths = [] + dependencies = [] + + i = 0 + while i < len(output): + line = output[i].strip() + + # Look for load command type + if "cmd LC_" not in line: + i += 1 + continue + + cmd_type = line.split()[-1] + + if cmd_type == "LC_ID_DYLIB": + # Next line is cmdsize, name is in the line after + if i + 2 < len(output): + name_line = output[i + 2].strip() + if name_line.startswith("name"): + install_name = name_line.split()[1] + + elif cmd_type == "LC_LOAD_DYLIB" or cmd_type == "LC_LOAD_WEAK_DYLIB": + # Next line is cmdsize, name is in the line after + if i + 2 < len(output): + name_line = output[i + 2].strip() + if name_line.startswith("name"): + dep_path = name_line.split()[1] + if dep_path != install_name: + dependencies.append(dep_path) + + elif cmd_type == "LC_RPATH": + # Next line is cmdsize, path is in the line after + if i + 2 < len(output): + path_line = output[i + 2].strip() + if path_line.startswith("path"): + rpaths.append(path_line.split()[1]) + + i += 1 + + return Library(path, install_name, dependencies, rpaths) + + +def is_system_path(path: str) -> bool: + """Check if the path is a system path that should be excluded.""" + return any(path.startswith(sys_path) for sys_path in SYSTEM_PATHS) + + +def find_library(lib_name: str, search_paths: list[str]) -> str: + """Find library in search paths.""" + for path in search_paths: + full_path = os.path.join(path, lib_name) + if os.path.exists(full_path): + return full_path + return "" + + +def resolve_at_path(dep_path: str, binary_path: str, rpaths: list[str]) -> str: + """ + Resolve a path that starts with @rpath, @executable_path, or @loader_path + Returns resolved absolute path or empty string if not found + """ + if dep_path.startswith("@rpath/"): + lib_name = dep_path[len("@rpath/") :] + # Try all rpaths + for rpath in rpaths: + # Handle nested @ paths in rpaths + if rpath.startswith("@"): + rpath = resolve_at_path(rpath, binary_path, []) + if not rpath: + continue + full_path = os.path.join(rpath, lib_name) + if os.path.exists(full_path): + return full_path + elif dep_path.startswith("@executable_path/"): + lib_name = dep_path[len("@executable_path/") :] + exe_dir = os.path.dirname(binary_path) + full_path = os.path.join(exe_dir, lib_name) + if os.path.exists(full_path): + return full_path + elif dep_path.startswith("@loader_path/"): + lib_name = dep_path[len("@loader_path/") :] + loader_dir = os.path.dirname(binary_path) + full_path = os.path.join(loader_dir, lib_name) + if os.path.exists(full_path): + return full_path + return "" + + +def collect_dependencies( + binary_path: str, lib_dirs: list[str], processed: set[str] +) -> dict[str, Library]: + """Recursively collect all dependencies for a binary.""" + result = {} + search_paths = lib_dirs.copy() + + def process_binary(path: str) -> None: + if path in processed: + return + + processed.add(path) + real_path, _ = resolve_symlink(path) + lib_info = parse_macho_info(real_path) + result[path] = lib_info + + # Add library's directory to search paths if it's not a system path + lib_dir = os.path.dirname(real_path) + if lib_dir not in search_paths and not is_system_path(lib_dir): + search_paths.append(lib_dir) + + # Process dependencies + for dep in lib_info.dependencies: + if dep.startswith("@"): + # If we couldn't resolve it earlier, try again with updated search paths + resolved_path = resolve_at_path(dep, path, lib_info.rpaths) + if resolved_path: + dep = resolved_path + + if not os.path.isabs(dep): + dep = find_library(os.path.basename(dep), search_paths) + + if dep and os.path.exists(dep): + process_binary(dep) + + process_binary(binary_path) + return result + + +def resolve_symlink(path: str) -> tuple[str, list[str]]: + """ + Resolve a symlink chain to its final destination and return the real file path + along with the chain of symlinks that led to it. + """ + symlink_chain = [] + current_path = path + + while os.path.islink(current_path): + symlink_chain.append(os.path.basename(current_path)) + current_path = os.path.realpath(current_path) + + return current_path, symlink_chain + + +def is_macho(filepath: str) -> bool: + """ + Checks if a file is a Mach-O binary by reading the first 4 bytes. + + Args: + filepath: Path to the file to check + + Returns: + True if it is a Mach-O file + """ + # Mach-O magic numbers + MAGIC_64 = 0xCFFAEDFE # 64-bit mach-o + MAGIC_32 = 0xCEFAEDFE # 32-bit mach-o + + try: + # Open file in binary mode and read first 4 bytes + with open(filepath, "rb") as f: + magic = int.from_bytes(f.read(4), byteorder="big") + + if magic in (MAGIC_64, MAGIC_32): + return True + else: + return False + + except OSError: + return False + + +def handle_resources_binaries(app_bundle: str) -> None: + """ + Move Mach-O files from Contents/Resources to Contents/PlugIns/_Resources + and replace them with symlinks. + """ + resources_dir = os.path.join(app_bundle, "Contents", "Resources") + plugins_resources_dir = os.path.join( + app_bundle, "Contents", "PlugIns", "_Resources" + ) + + if not os.path.exists(resources_dir): + return + + # Find all Mach-O files in Resources + for root, _, files in os.walk(resources_dir): + for file in files: + path = os.path.join(root, file) + try: + if is_macho(file): + # Calculate relative path from Resources root + rel_path = os.path.relpath(path, resources_dir) + new_path = os.path.join(plugins_resources_dir, rel_path) + + # Create directory structure in PlugIns/_Resources + os.makedirs(os.path.dirname(new_path), exist_ok=True) + + # Move the file and create symlink + shutil.move(path, new_path) + relative_target = os.path.relpath(new_path, os.path.dirname(path)) + os.symlink(relative_target, path) + except subprocess.CalledProcessError: + continue + + +def deploy_libraries(app_bundle: str, lib_dirs: list[str]) -> None: + """Deploy all libraries to the app bundle.""" + frameworks_dir = os.path.join(app_bundle, "Contents", "Frameworks") + os.makedirs(frameworks_dir, exist_ok=True) + + print("Handle resources binaries") + # Handle Resources binaries first + handle_resources_binaries(app_bundle) + + print("Handle main binaries") + # Find all binaries in the app bundle + binaries = [] + for root, _, files in os.walk(app_bundle): + for file in files: + path = os.path.join(root, file) + try: + if not os.path.islink(path) and is_macho(path): + binaries.append(path) + except subprocess.CalledProcessError: + continue + + processed_libs = set() + all_dependencies = {} + + # Collect all dependencies + for binary in binaries: + print(f"Analyzing {binary}") + deps = collect_dependencies(binary, lib_dirs, processed_libs) + all_dependencies.update(deps) + # Copy libraries and prepare install_name_tool commands + commands = {} # path -> list of changes + lib_mapping = {} # old_install_name -> new_install_name + + # First pass: copy libraries and record their new install names + for lib_path, lib_info in all_dependencies.items(): + if lib_path.startswith(app_bundle): + continue + + # Skip system libraries + if is_system_path(lib_path): + continue + + # Resolve symlinks to get real file + real_lib_path, symlink_chain = resolve_symlink(lib_path) + + # Skip if the real file is in a system path + if is_system_path(real_lib_path): + continue + + lib_name = os.path.basename(real_lib_path) + new_path = os.path.join(frameworks_dir, lib_name) + new_install_name = f"@rpath/{lib_name}" + + # Record the mapping from old install name to new install name + lib_mapping[lib_info.install_name] = new_install_name + + # Copy the real file if not already present + if not os.path.exists(new_path): + shutil.copy2(real_lib_path, new_path) + + # Recreate symlink chain + current_name = lib_name + for link_name in reversed(symlink_chain): + link_path = os.path.join(frameworks_dir, link_name) + if not os.path.exists(link_path): + os.symlink(current_name, link_path) + current_name = link_name + + # Prepare commands for the library itself + if new_path not in commands: + commands[new_path] = [] + + # Set its own install name + commands[new_path].append(("-id", new_install_name)) + + # Second pass: update each binary's direct dependencies + for binary_path, lib_info in all_dependencies.items(): + if binary_path not in commands: + commands[binary_path] = [] + + # Update only the direct dependencies of this binary + for dep in lib_info.dependencies: + if dep in lib_mapping: + commands[binary_path].append(("-change", dep, lib_mapping[dep])) + + frameworks_dir = os.path.join(app_bundle, "Contents", "Frameworks") + + def calculate_relative_frameworks_path(binary_path: str) -> str: + """Calculate relative path from binary to Frameworks directory.""" + binary_dir = os.path.dirname(binary_path) + rel_path = os.path.relpath(frameworks_dir, binary_dir) + return rel_path + + # Set @loader_path/../Frameworks as the only rpath for all binaries + for binary in binaries: + if binary not in commands: + commands[binary] = [] + + # Get existing rpaths + lib_info = parse_macho_info(binary) + # Delete absolute rpaths + for rpath in lib_info.rpaths: + if rpath.startswith("/"): + commands[binary].append(("-delete_rpath", rpath)) + + # Add proper search path for all executables + rel_frameworks_path = calculate_relative_frameworks_path(binary) + new_path = f"@loader_path/{rel_frameworks_path}" + if ( + binary.startswith(f"{app_bundle}/Contents/MacOS") + and new_path not in lib_info.rpaths + ): + commands[binary].append(("-add_rpath", new_path)) + + # Execute install_name_tool commands + for path, changes in commands.items(): + print(f"Changing {path}") + cmd = ["install_name_tool"] + if not changes: + continue + print(f" {changes}") + for command_tuple in changes: + cmd.extend(command_tuple) + print(f"Executing {cmd} {path}") + try: + result = subprocess.run( + cmd + [path], check=True, capture_output=True, text=True + ) + print(result.stdout) + print(result.stderr) + except subprocess.CalledProcessError as e: + print(f"Command failed with exit code {e.returncode}") + print("stdout:") + print(e.stdout) + print("stderr:") + print(e.stderr) + raise + + +def main(): + parser = argparse.ArgumentParser(description="Enhanced macdeployqt implementation") + parser.add_argument("app_bundle", help="Path to the app bundle") + parser.add_argument( + "--libdir", + action="append", + default=[], + help="Additional library search directories", + ) + + args = parser.parse_args() + + lib_dirs = args.libdir + [os.path.join(args.app_bundle, "Contents", "Frameworks")] + deploy_libraries(args.app_bundle, lib_dirs) + + +if __name__ == "__main__": + main() diff --git a/platform/macos/python.in b/platform/macos/python.in new file mode 100644 index 000000000000..67274c3f01fb --- /dev/null +++ b/platform/macos/python.in @@ -0,0 +1,6 @@ +#!/bin/bash +# This is a wrapper for python, to launch python with the proper PYTHONHOME set +# to make it relocatable. +BASEDIR="$(cd "$(dirname "$0")" && pwd)" +export PYTHONHOME="${BASEDIR}/../Frameworks" +exec ${BASEDIR}/@PYTHON_EXECUTABLE@ "$@" diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index bb15706392e0..ea31a6061eb1 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -91,7 +91,7 @@ ELSE() SET(BINDING_FILES_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}) ENDIF() -set(QGIS_PYTHON_DIR ${Python_SITEARCH}/qgis) +set(QGIS_PYTHON_DIR ${QGIS_PYTHON_INSTALL_DIR}/qgis) # core module file(GLOB_RECURSE sip_files_core ${BINDING_FILES_ROOT_DIR}/core/*.sip ${BINDING_FILES_ROOT_DIR}/core/*.sip.in) diff --git a/python/PyQt/CMakeLists.txt b/python/PyQt/CMakeLists.txt index 2a8916ee52b6..b8513c9520ec 100644 --- a/python/PyQt/CMakeLists.txt +++ b/python/PyQt/CMakeLists.txt @@ -1,4 +1,4 @@ -set (QGIS_PYQT_DIR ${Python_SITEARCH}/qgis/PyQt) +set (QGIS_PYQT_DIR ${QGIS_PYTHON_INSTALL_DIR}/qgis/PyQt) set(PYQT_COMPAT_FILES __init__.py diff --git a/python/PyQt6/core/auto_additions/qgsmaplayer.py b/python/PyQt6/core/auto_additions/qgsmaplayer.py index 58b42a628e09..cad382e89de6 100644 --- a/python/PyQt6/core/auto_additions/qgsmaplayer.py +++ b/python/PyQt6/core/auto_additions/qgsmaplayer.py @@ -37,6 +37,26 @@ QgsMapLayer.FlagReadExtentFromXml = QgsMapLayer.ReadFlag.FlagReadExtentFromXml QgsMapLayer.FlagForceReadOnly = QgsMapLayer.ReadFlag.FlagForceReadOnly QgsMapLayer.ReadFlags = lambda flags=0: QgsMapLayer.ReadFlag(flags) +# monkey patching scoped based enum +QgsMapLayer.SaveStyleResult.Success.__doc__ = "Both QML and SLD formats were successfully written to the database." +QgsMapLayer.SaveStyleResult.QmlGenerationFailed.__doc__ = "Generation of the QML failed, and was not written to the database." +QgsMapLayer.SaveStyleResult.SldGenerationFailed.__doc__ = "Generation of the SLD failed, and was not written to the database." +QgsMapLayer.SaveStyleResult.DatabaseWriteFailed.__doc__ = "An error occurred when attempting to write to the database." +QgsMapLayer.SaveStyleResult.__doc__ = """Results of saving styles to database. + +.. versionadded:: 4.0 + +* ``Success``: Both QML and SLD formats were successfully written to the database. +* ``QmlGenerationFailed``: Generation of the QML failed, and was not written to the database. +* ``SldGenerationFailed``: Generation of the SLD failed, and was not written to the database. +* ``DatabaseWriteFailed``: An error occurred when attempting to write to the database. + +""" +# -- +QgsMapLayer.SaveStyleResult.baseClass = QgsMapLayer +QgsMapLayer.SaveStyleResults = lambda flags=0: QgsMapLayer.SaveStyleResult(flags) +QgsMapLayer.SaveStyleResults.baseClass = QgsMapLayer +SaveStyleResults = QgsMapLayer # dirty hack since SIP seems to introduce the flags in module from enum import Enum diff --git a/python/PyQt6/core/auto_generated/geometry/qgsgeometry.sip.in b/python/PyQt6/core/auto_generated/geometry/qgsgeometry.sip.in index cc8b70d0defd..931d6ce69111 100644 --- a/python/PyQt6/core/auto_generated/geometry/qgsgeometry.sip.in +++ b/python/PyQt6/core/auto_generated/geometry/qgsgeometry.sip.in @@ -16,7 +16,9 @@ typedef QVector QgsPolylineXY; -typedef QgsPointSequence QgsPolyline; +typedef QVector QgsPolyline; + +typedef QVector> QgsMultiPolyline; typedef QVector> QgsPolygonXY; diff --git a/python/PyQt6/core/auto_generated/qgsmaplayer.sip.in b/python/PyQt6/core/auto_generated/qgsmaplayer.sip.in index 5d023c24f577..652e47e40b53 100644 --- a/python/PyQt6/core/auto_generated/qgsmaplayer.sip.in +++ b/python/PyQt6/core/auto_generated/qgsmaplayer.sip.in @@ -825,12 +825,24 @@ Deletes a style from the database - msgError: a descriptive error message if any occurs %End - virtual void saveStyleToDatabase( const QString &name, const QString &description, - bool useAsDefault, const QString &uiFileContent, - QString &msgError /Out/, - QgsMapLayer::StyleCategories categories = QgsMapLayer::AllStyleCategories ); + enum class SaveStyleResult + { + Success, + QmlGenerationFailed, + SldGenerationFailed, + DatabaseWriteFailed, + }; + + typedef QFlags SaveStyleResults; + + + virtual void saveStyleToDatabase( const QString &name, const QString &description, + bool useAsDefault, const QString &uiFileContent, + QString &msgError /Out/, + QgsMapLayer::StyleCategories categories = QgsMapLayer::AllStyleCategories ) /Deprecated="Since 4.0. Use saveStyleToDatabaseV2() instead."/; %Docstring -Saves named and sld style of the layer to the style table in the db. +Saves QML and SLD representations of the layer's style to a table in the +database. :param name: Style name :param description: A description of the style @@ -847,9 +859,33 @@ Saves named and sld style of the layer to the style table in the db. Use :py:func:`QgsProviderRegistry.styleExists()` to test in advance if a style already exists and handle this appropriately in your client code. -:return: a descriptive error message if any occurs +:return: - msgError: a descriptive error message if any occurs + +.. deprecated:: 4.0 + + Use :py:func:`~QgsMapLayer.saveStyleToDatabaseV2` instead. %End + QgsMapLayer::SaveStyleResults saveStyleToDatabaseV2( const QString &name, const QString &description, + bool useAsDefault, const QString &uiFileContent, + QString &msgError /Out/, + QgsMapLayer::StyleCategories categories = QgsMapLayer::AllStyleCategories ); +%Docstring +Saves QML and SLD representations of the layer's style to a table in the +database. + +:param name: Style name +:param description: A description of the style +:param useAsDefault: Set to ``True`` if style should be used as the + default style for the layer +:param uiFileContent: +:param categories: the style categories to be saved. + +:return: - flags representing whether QML or SLD storing was successful + - msgError: a descriptive error message if any occurs + +.. versionadded:: 4.0 +%End virtual QString loadNamedStyle( const QString &theURI, bool &resultFlag /Out/, bool loadFromLocalDb, diff --git a/python/PyQt6/core/auto_generated/qgsogcutils.sip.in b/python/PyQt6/core/auto_generated/qgsogcutils.sip.in index 42b0eb595e52..9805e517ac8d 100644 --- a/python/PyQt6/core/auto_generated/qgsogcutils.sip.in +++ b/python/PyQt6/core/auto_generated/qgsogcutils.sip.in @@ -217,6 +217,8 @@ Creates an OGC expression XML element from the ``exp`` expression. }; + + /************************************************************************ * This file has been generated automatically from * * * diff --git a/python/PyQt6/core/class_map.yaml b/python/PyQt6/core/class_map.yaml index 0f75d2877c68..2fad5e8c775a 100644 --- a/python/PyQt6/core/class_map.yaml +++ b/python/PyQt6/core/class_map.yaml @@ -4938,205 +4938,205 @@ QgsGeographicCoordinateNumericFormat.sortKey: src/core/numericformats/qgscoordin QgsGeographicCoordinateNumericFormat.suggestSampleValue: src/core/numericformats/qgscoordinatenumericformat.h#L53 QgsGeographicCoordinateNumericFormat.visibleName: src/core/numericformats/qgscoordinatenumericformat.h#L51 QgsGeographicCoordinateNumericFormat: src/core/numericformats/qgscoordinatenumericformat.h#L28 -QgsGeometry.Error.Error: src/core/geometry/qgsgeometry.h#L2760 -QgsGeometry.Error.__repr__: src/core/geometry/qgsgeometry.h#L2783 -QgsGeometry.Error.hasWhere: src/core/geometry/qgsgeometry.h#L2780 -QgsGeometry.Error.what: src/core/geometry/qgsgeometry.h#L2770 -QgsGeometry.Error.where: src/core/geometry/qgsgeometry.h#L2775 -QgsGeometry.Error: src/core/geometry/qgsgeometry.h#L2751 -QgsGeometry.QVariant: src/core/geometry/qgsgeometry.h#L3180 -QgsGeometry.QgsGeometry: src/core/geometry/qgsgeometry.h#L184 -QgsGeometry.__repr__: src/core/geometry/qgsgeometry.h#L2185 -QgsGeometry.addPart: src/core/geometry/qgsgeometry.h#L930 -QgsGeometry.addPart: src/core/geometry/qgsgeometry.h#L948 -QgsGeometry.addPart: src/core/geometry/qgsgeometry.h#L966 -QgsGeometry.addPart: src/core/geometry/qgsgeometry.h#L982 -QgsGeometry.addPartV2: src/core/geometry/qgsgeometry.h#L939 -QgsGeometry.addPartV2: src/core/geometry/qgsgeometry.h#L957 -QgsGeometry.addPartV2: src/core/geometry/qgsgeometry.h#L975 -QgsGeometry.addRing: src/core/geometry/qgsgeometry.h#L914 -QgsGeometry.addRing: src/core/geometry/qgsgeometry.h#L921 -QgsGeometry.addTopologicalPoint: src/core/geometry/qgsgeometry.h#L815 -QgsGeometry.adjacentVertices: src/core/geometry/qgsgeometry.h#L778 -QgsGeometry.angleAtVertex: src/core/geometry/qgsgeometry.h#L764 -QgsGeometry.applyDashPattern: src/core/geometry/qgsgeometry.h#L1372 -QgsGeometry.area: src/core/geometry/qgsgeometry.h#L476 -QgsGeometry.asJson: src/core/geometry/qgsgeometry.h#L2204 -QgsGeometry.asMultiPoint: src/core/geometry/qgsgeometry.h#L2418 -QgsGeometry.asMultiPolygon: src/core/geometry/qgsgeometry.h#L2508 -QgsGeometry.asMultiPolyline: src/core/geometry/qgsgeometry.h#L2463 -QgsGeometry.asPoint: src/core/geometry/qgsgeometry.h#L2283 -QgsGeometry.asPolygon: src/core/geometry/qgsgeometry.h#L2375 -QgsGeometry.asPolyline: src/core/geometry/qgsgeometry.h#L2330 -QgsGeometry.asQPointF: src/core/geometry/qgsgeometry.h#L2538 -QgsGeometry.asQPolygonF: src/core/geometry/qgsgeometry.h#L2551 -QgsGeometry.asWkb: src/core/geometry/qgsgeometry.h#L2175 -QgsGeometry.asWkt: src/core/geometry/qgsgeometry.h#L2182 -QgsGeometry.avoidIntersections: src/core/geometry/qgsgeometry.h#L2626 -QgsGeometry.avoidIntersections: src/core/geometry/qgsgeometry.h#L2627 -QgsGeometry.avoidIntersectionsV2: src/core/geometry/qgsgeometry.h#L2640 -QgsGeometry.avoidIntersectionsV2: src/core/geometry/qgsgeometry.h#L2641 -QgsGeometry.boundingBox3D: src/core/geometry/qgsgeometry.h#L1206 -QgsGeometry.boundingBox: src/core/geometry/qgsgeometry.h#L1199 -QgsGeometry.boundingBoxIntersects: src/core/geometry/qgsgeometry.h#L1447 -QgsGeometry.boundingBoxIntersects: src/core/geometry/qgsgeometry.h#L1457 -QgsGeometry.buffer: src/core/geometry/qgsgeometry.h#L1544 -QgsGeometry.buffer: src/core/geometry/qgsgeometry.h#L1557 -QgsGeometry.centroid: src/core/geometry/qgsgeometry.h#L1686 -QgsGeometry.clipped: src/core/geometry/qgsgeometry.h#L2022 -QgsGeometry.closestSegmentWithContext: src/core/geometry/qgsgeometry.h#L907 -QgsGeometry.closestVertex: src/core/geometry/qgsgeometry.h#L747 -QgsGeometry.closestVertexWithContext: src/core/geometry/qgsgeometry.h#L894 -QgsGeometry.collectGeometry: src/core/geometry/qgsgeometry.h#L330 -QgsGeometry.combine: src/core/geometry/qgsgeometry.h#L2038 -QgsGeometry.compare: src/core/geometry/qgsgeometry.h#L3013 -QgsGeometry.concaveHull: src/core/geometry/qgsgeometry.h#L1816 -QgsGeometry.constGet: src/core/geometry/qgsgeometry.h#L205 -QgsGeometry.constParts: src/core/geometry/qgsgeometry.h#L656 -QgsGeometry.constrainedDelaunayTriangulation: src/core/geometry/qgsgeometry.h#L1858 -QgsGeometry.contains: src/core/geometry/qgsgeometry.h#L1462 -QgsGeometry.contains: src/core/geometry/qgsgeometry.h#L1469 -QgsGeometry.contains: src/core/geometry/qgsgeometry.h#L1480 -QgsGeometry.convertGeometryCollectionToSubclass: src/core/geometry/qgsgeometry.h#L2613 -QgsGeometry.convertPointList: src/core/geometry/qgsgeometry.h#L3167 -QgsGeometry.convertPointList: src/core/geometry/qgsgeometry.h#L3174 -QgsGeometry.convertToCurvedMultiType: src/core/geometry/qgsgeometry.h#L2591 -QgsGeometry.convertToCurves: src/core/geometry/qgsgeometry.h#L1671 -QgsGeometry.convertToMultiType: src/core/geometry/qgsgeometry.h#L2574 -QgsGeometry.convertToSingleType: src/core/geometry/qgsgeometry.h#L2602 -QgsGeometry.convertToStraightSegment: src/core/geometry/qgsgeometry.h#L2847 -QgsGeometry.convertToType: src/core/geometry/qgsgeometry.h#L2256 -QgsGeometry.convexHull: src/core/geometry/qgsgeometry.h#L1801 -QgsGeometry.createGeometryEngine: src/core/geometry/qgsgeometry.h#L3160 -QgsGeometry.createPolygonFromQPolygonF: src/core/geometry/qgsgeometry.h#L2956 -QgsGeometry.createPolylineFromQPolygonF: src/core/geometry/qgsgeometry.h#L2947 -QgsGeometry.createWedgeBuffer: src/core/geometry/qgsgeometry.h#L347 -QgsGeometry.createWedgeBufferFromAngles: src/core/geometry/qgsgeometry.h#L363 -QgsGeometry.crosses: src/core/geometry/qgsgeometry.h#L1535 -QgsGeometry.delaunayTriangulation: src/core/geometry/qgsgeometry.h#L1844 -QgsGeometry.deletePart: src/core/geometry/qgsgeometry.h#L2564 -QgsGeometry.deleteRing: src/core/geometry/qgsgeometry.h#L2558 -QgsGeometry.deleteVertex: src/core/geometry/qgsgeometry.h#L846 -QgsGeometry.densifyByCount: src/core/geometry/qgsgeometry.h#L1639 -QgsGeometry.densifyByDistance: src/core/geometry/qgsgeometry.h#L1654 -QgsGeometry.difference: src/core/geometry/qgsgeometry.h#L2063 -QgsGeometry.disjoint: src/core/geometry/qgsgeometry.h#L1491 -QgsGeometry.distance: src/core/geometry/qgsgeometry.h#L500 -QgsGeometry.distanceToVertex: src/core/geometry/qgsgeometry.h#L756 -QgsGeometry.draw: src/core/geometry/qgsgeometry.h#L2866 -QgsGeometry.equals: src/core/geometry/qgsgeometry.h#L414 -QgsGeometry.extendLine: src/core/geometry/qgsgeometry.h#L1626 -QgsGeometry.extrude: src/core/geometry/qgsgeometry.h#L2079 -QgsGeometry.forcePolygonClockwise: src/core/geometry/qgsgeometry.h#L2733 -QgsGeometry.forcePolygonCounterClockwise: src/core/geometry/qgsgeometry.h#L2745 -QgsGeometry.forceRHR: src/core/geometry/qgsgeometry.h#L2721 -QgsGeometry.frechetDistance: src/core/geometry/qgsgeometry.h#L709 -QgsGeometry.frechetDistanceDensify: src/core/geometry/qgsgeometry.h#L733 -QgsGeometry.fromBox3D: src/core/geometry/qgsgeometry.h#L326 -QgsGeometry.fromMultiPointXY: src/core/geometry/qgsgeometry.h#L255 -QgsGeometry.fromMultiPolygonXY: src/core/geometry/qgsgeometry.h#L314 -QgsGeometry.fromMultiPolylineXY: src/core/geometry/qgsgeometry.h#L282 -QgsGeometry.fromPoint: src/core/geometry/qgsgeometry.h#L252 -QgsGeometry.fromPointXY: src/core/geometry/qgsgeometry.h#L245 -QgsGeometry.fromPolygonXY: src/core/geometry/qgsgeometry.h#L309 -QgsGeometry.fromPolyline: src/core/geometry/qgsgeometry.h#L277 -QgsGeometry.fromPolylineXY: src/core/geometry/qgsgeometry.h#L267 -QgsGeometry.fromQPointF: src/core/geometry/qgsgeometry.h#L2930 -QgsGeometry.fromQPolygonF: src/core/geometry/qgsgeometry.h#L2938 -QgsGeometry.fromRect: src/core/geometry/qgsgeometry.h#L317 -QgsGeometry.fromWkb: src/core/geometry/qgsgeometry.h#L376 -QgsGeometry.fromWkt: src/core/geometry/qgsgeometry.h#L243 -QgsGeometry.get: src/core/geometry/qgsgeometry.h#L218 -QgsGeometry.hausdorffDistance: src/core/geometry/qgsgeometry.h#L674 -QgsGeometry.hausdorffDistanceDensify: src/core/geometry/qgsgeometry.h#L693 -QgsGeometry.insertVertex: src/core/geometry/qgsgeometry.h#L792 -QgsGeometry.insertVertex: src/core/geometry/qgsgeometry.h#L806 -QgsGeometry.interpolate: src/core/geometry/qgsgeometry.h#L1979 -QgsGeometry.interpolateAngle: src/core/geometry/qgsgeometry.h#L2001 -QgsGeometry.intersection: src/core/geometry/qgsgeometry.h#L2014 -QgsGeometry.intersects: src/core/geometry/qgsgeometry.h#L1421 -QgsGeometry.intersects: src/core/geometry/qgsgeometry.h#L1437 -QgsGeometry.isAxisParallelRectangle: src/core/geometry/qgsgeometry.h#L463 -QgsGeometry.isEmpty: src/core/geometry/qgsgeometry.h#L396 -QgsGeometry.isGeosEqual: src/core/geometry/qgsgeometry.h#L431 -QgsGeometry.isGeosValid: src/core/geometry/qgsgeometry.h#L439 -QgsGeometry.isMultipart: src/core/geometry/qgsgeometry.h#L399 -QgsGeometry.isNull: src/core/geometry/qgsgeometry.h#L240 -QgsGeometry.isPolygonClockwise: src/core/geometry/qgsgeometry.h#L2704 -QgsGeometry.isPolygonCounterClockwise: src/core/geometry/qgsgeometry.h#L2689 -QgsGeometry.isSimple: src/core/geometry/qgsgeometry.h#L448 -QgsGeometry.largestEmptyCircle: src/core/geometry/qgsgeometry.h#L1739 -QgsGeometry.lastError: src/core/geometry/qgsgeometry.h#L2897 -QgsGeometry.length: src/core/geometry/qgsgeometry.h#L491 -QgsGeometry.lineLocatePoint: src/core/geometry/qgsgeometry.h#L1991 -QgsGeometry.makeDifference: src/core/geometry/qgsgeometry.h#L1193 -QgsGeometry.makeValid: src/core/geometry/qgsgeometry.h#L2663 -QgsGeometry.mapToPixel: src/core/geometry/qgsgeometry.h#L2860 -QgsGeometry.mergeLines: src/core/geometry/qgsgeometry.h#L2050 -QgsGeometry.minimalEnclosingCircle: src/core/geometry/qgsgeometry.h#L1240 -QgsGeometry.minimumClearance: src/core/geometry/qgsgeometry.h#L1778 -QgsGeometry.minimumClearanceLine: src/core/geometry/qgsgeometry.h#L1791 -QgsGeometry.minimumWidth: src/core/geometry/qgsgeometry.h#L1755 -QgsGeometry.moveVertex: src/core/geometry/qgsgeometry.h#L824 -QgsGeometry.moveVertex: src/core/geometry/qgsgeometry.h#L833 -QgsGeometry.nearestPoint: src/core/geometry/qgsgeometry.h#L875 -QgsGeometry.node: src/core/geometry/qgsgeometry.h#L1924 -QgsGeometry.normalize: src/core/geometry/qgsgeometry.h#L2820 -QgsGeometry.offsetCurve: src/core/geometry/qgsgeometry.h#L1566 -QgsGeometry.orientedMinimumBoundingBox: src/core/geometry/qgsgeometry.h#L1220 -QgsGeometry.orthogonalize: src/core/geometry/qgsgeometry.h#L1255 -QgsGeometry.overlaps: src/core/geometry/qgsgeometry.h#L1513 -QgsGeometry.parts: src/core/geometry/qgsgeometry.h#L622 -QgsGeometry.pointOnSurface: src/core/geometry/qgsgeometry.h#L1701 -QgsGeometry.poleOfInaccessibility: src/core/geometry/qgsgeometry.h#L1714 -QgsGeometry.polygonOrientation: src/core/geometry/qgsgeometry.h#L2674 -QgsGeometry.polygonize: src/core/geometry/qgsgeometry.h#L2839 -QgsGeometry.randomPointsInPolygon: src/core/geometry/qgsgeometry.h#L2136 -QgsGeometry.removeDuplicateNodes: src/core/geometry/qgsgeometry.h#L1410 -QgsGeometry.removeInteriorRings: src/core/geometry/qgsgeometry.h#L989 -QgsGeometry.requiresConversionToStraightSegments: src/core/geometry/qgsgeometry.h#L2854 -QgsGeometry.reshapeGeometry: src/core/geometry/qgsgeometry.h#L1178 -QgsGeometry.rotate: src/core/geometry/qgsgeometry.h#L1029 -QgsGeometry.roundWaves: src/core/geometry/qgsgeometry.h#L1337 -QgsGeometry.roundWavesRandomized: src/core/geometry/qgsgeometry.h#L1357 -QgsGeometry.set: src/core/geometry/qgsgeometry.h#L231 -QgsGeometry.sharedPaths: src/core/geometry/qgsgeometry.h#L1940 -QgsGeometry.shortestLine: src/core/geometry/qgsgeometry.h#L886 -QgsGeometry.simplify: src/core/geometry/qgsgeometry.h#L1629 -QgsGeometry.simplifyCoverageVW: src/core/geometry/qgsgeometry.h#L1899 -QgsGeometry.singleSidedBuffer: src/core/geometry/qgsgeometry.h#L1582 -QgsGeometry.smooth: src/core/geometry/qgsgeometry.h#L3118 -QgsGeometry.snappedToGrid: src/core/geometry/qgsgeometry.h#L1389 -QgsGeometry.splitGeometry: src/core/geometry/qgsgeometry.h#L1092 -QgsGeometry.splitGeometry: src/core/geometry/qgsgeometry.h#L1172 -QgsGeometry.sqrDistToVertexAt: src/core/geometry/qgsgeometry.h#L869 -QgsGeometry.squareWaves: src/core/geometry/qgsgeometry.h#L1303 -QgsGeometry.squareWavesRandomized: src/core/geometry/qgsgeometry.h#L1323 -QgsGeometry.subdivide: src/core/geometry/qgsgeometry.h#L1963 -QgsGeometry.symDifference: src/core/geometry/qgsgeometry.h#L2076 -QgsGeometry.taperedBuffer: src/core/geometry/qgsgeometry.h#L1603 -QgsGeometry.toggleCircularAtVertex: src/core/geometry/qgsgeometry.h#L855 -QgsGeometry.touches: src/core/geometry/qgsgeometry.h#L1502 -QgsGeometry.transform: src/core/geometry/qgsgeometry.h#L1011 -QgsGeometry.transform: src/core/geometry/qgsgeometry.h#L1021 -QgsGeometry.translate: src/core/geometry/qgsgeometry.h#L995 -QgsGeometry.triangularWaves: src/core/geometry/qgsgeometry.h#L1269 -QgsGeometry.triangularWavesRandomized: src/core/geometry/qgsgeometry.h#L1289 -QgsGeometry.type: src/core/geometry/qgsgeometry.h#L388 -QgsGeometry.unaryUnion: src/core/geometry/qgsgeometry.h#L2830 -QgsGeometry.unionCoverage: src/core/geometry/qgsgeometry.h#L1912 -QgsGeometry.validateCoverage: src/core/geometry/qgsgeometry.h#L1877 -QgsGeometry.validateGeometry: src/core/geometry/qgsgeometry.h#L2809 -QgsGeometry.variableWidthBufferByM: src/core/geometry/qgsgeometry.h#L1619 -QgsGeometry.vertexAt: src/core/geometry/qgsgeometry.h#L862 -QgsGeometry.vertexIdFromVertexNr: src/core/geometry/qgsgeometry.h#L2877 -QgsGeometry.vertexNrFromVertexId: src/core/geometry/qgsgeometry.h#L2889 -QgsGeometry.vertices: src/core/geometry/qgsgeometry.h#L540 -QgsGeometry.voronoiDiagram: src/core/geometry/qgsgeometry.h#L1832 -QgsGeometry.within: src/core/geometry/qgsgeometry.h#L1524 -QgsGeometry.wkbSize: src/core/geometry/qgsgeometry.h#L2167 -QgsGeometry.wkbType: src/core/geometry/qgsgeometry.h#L382 -QgsGeometry: src/core/geometry/qgsgeometry.h#L161 +QgsGeometry.Error.Error: src/core/geometry/qgsgeometry.h#L2777 +QgsGeometry.Error.__repr__: src/core/geometry/qgsgeometry.h#L2800 +QgsGeometry.Error.hasWhere: src/core/geometry/qgsgeometry.h#L2797 +QgsGeometry.Error.what: src/core/geometry/qgsgeometry.h#L2787 +QgsGeometry.Error.where: src/core/geometry/qgsgeometry.h#L2792 +QgsGeometry.Error: src/core/geometry/qgsgeometry.h#L2768 +QgsGeometry.QVariant: src/core/geometry/qgsgeometry.h#L3197 +QgsGeometry.QgsGeometry: src/core/geometry/qgsgeometry.h#L201 +QgsGeometry.__repr__: src/core/geometry/qgsgeometry.h#L2202 +QgsGeometry.addPart: src/core/geometry/qgsgeometry.h#L947 +QgsGeometry.addPart: src/core/geometry/qgsgeometry.h#L965 +QgsGeometry.addPart: src/core/geometry/qgsgeometry.h#L983 +QgsGeometry.addPart: src/core/geometry/qgsgeometry.h#L999 +QgsGeometry.addPartV2: src/core/geometry/qgsgeometry.h#L956 +QgsGeometry.addPartV2: src/core/geometry/qgsgeometry.h#L974 +QgsGeometry.addPartV2: src/core/geometry/qgsgeometry.h#L992 +QgsGeometry.addRing: src/core/geometry/qgsgeometry.h#L931 +QgsGeometry.addRing: src/core/geometry/qgsgeometry.h#L938 +QgsGeometry.addTopologicalPoint: src/core/geometry/qgsgeometry.h#L832 +QgsGeometry.adjacentVertices: src/core/geometry/qgsgeometry.h#L795 +QgsGeometry.angleAtVertex: src/core/geometry/qgsgeometry.h#L781 +QgsGeometry.applyDashPattern: src/core/geometry/qgsgeometry.h#L1389 +QgsGeometry.area: src/core/geometry/qgsgeometry.h#L493 +QgsGeometry.asJson: src/core/geometry/qgsgeometry.h#L2221 +QgsGeometry.asMultiPoint: src/core/geometry/qgsgeometry.h#L2435 +QgsGeometry.asMultiPolygon: src/core/geometry/qgsgeometry.h#L2525 +QgsGeometry.asMultiPolyline: src/core/geometry/qgsgeometry.h#L2480 +QgsGeometry.asPoint: src/core/geometry/qgsgeometry.h#L2300 +QgsGeometry.asPolygon: src/core/geometry/qgsgeometry.h#L2392 +QgsGeometry.asPolyline: src/core/geometry/qgsgeometry.h#L2347 +QgsGeometry.asQPointF: src/core/geometry/qgsgeometry.h#L2555 +QgsGeometry.asQPolygonF: src/core/geometry/qgsgeometry.h#L2568 +QgsGeometry.asWkb: src/core/geometry/qgsgeometry.h#L2192 +QgsGeometry.asWkt: src/core/geometry/qgsgeometry.h#L2199 +QgsGeometry.avoidIntersections: src/core/geometry/qgsgeometry.h#L2643 +QgsGeometry.avoidIntersections: src/core/geometry/qgsgeometry.h#L2644 +QgsGeometry.avoidIntersectionsV2: src/core/geometry/qgsgeometry.h#L2657 +QgsGeometry.avoidIntersectionsV2: src/core/geometry/qgsgeometry.h#L2658 +QgsGeometry.boundingBox3D: src/core/geometry/qgsgeometry.h#L1223 +QgsGeometry.boundingBox: src/core/geometry/qgsgeometry.h#L1216 +QgsGeometry.boundingBoxIntersects: src/core/geometry/qgsgeometry.h#L1464 +QgsGeometry.boundingBoxIntersects: src/core/geometry/qgsgeometry.h#L1474 +QgsGeometry.buffer: src/core/geometry/qgsgeometry.h#L1561 +QgsGeometry.buffer: src/core/geometry/qgsgeometry.h#L1574 +QgsGeometry.centroid: src/core/geometry/qgsgeometry.h#L1703 +QgsGeometry.clipped: src/core/geometry/qgsgeometry.h#L2039 +QgsGeometry.closestSegmentWithContext: src/core/geometry/qgsgeometry.h#L924 +QgsGeometry.closestVertex: src/core/geometry/qgsgeometry.h#L764 +QgsGeometry.closestVertexWithContext: src/core/geometry/qgsgeometry.h#L911 +QgsGeometry.collectGeometry: src/core/geometry/qgsgeometry.h#L347 +QgsGeometry.combine: src/core/geometry/qgsgeometry.h#L2055 +QgsGeometry.compare: src/core/geometry/qgsgeometry.h#L3030 +QgsGeometry.concaveHull: src/core/geometry/qgsgeometry.h#L1833 +QgsGeometry.constGet: src/core/geometry/qgsgeometry.h#L222 +QgsGeometry.constParts: src/core/geometry/qgsgeometry.h#L673 +QgsGeometry.constrainedDelaunayTriangulation: src/core/geometry/qgsgeometry.h#L1875 +QgsGeometry.contains: src/core/geometry/qgsgeometry.h#L1479 +QgsGeometry.contains: src/core/geometry/qgsgeometry.h#L1486 +QgsGeometry.contains: src/core/geometry/qgsgeometry.h#L1497 +QgsGeometry.convertGeometryCollectionToSubclass: src/core/geometry/qgsgeometry.h#L2630 +QgsGeometry.convertPointList: src/core/geometry/qgsgeometry.h#L3184 +QgsGeometry.convertPointList: src/core/geometry/qgsgeometry.h#L3191 +QgsGeometry.convertToCurvedMultiType: src/core/geometry/qgsgeometry.h#L2608 +QgsGeometry.convertToCurves: src/core/geometry/qgsgeometry.h#L1688 +QgsGeometry.convertToMultiType: src/core/geometry/qgsgeometry.h#L2591 +QgsGeometry.convertToSingleType: src/core/geometry/qgsgeometry.h#L2619 +QgsGeometry.convertToStraightSegment: src/core/geometry/qgsgeometry.h#L2864 +QgsGeometry.convertToType: src/core/geometry/qgsgeometry.h#L2273 +QgsGeometry.convexHull: src/core/geometry/qgsgeometry.h#L1818 +QgsGeometry.createGeometryEngine: src/core/geometry/qgsgeometry.h#L3177 +QgsGeometry.createPolygonFromQPolygonF: src/core/geometry/qgsgeometry.h#L2973 +QgsGeometry.createPolylineFromQPolygonF: src/core/geometry/qgsgeometry.h#L2964 +QgsGeometry.createWedgeBuffer: src/core/geometry/qgsgeometry.h#L364 +QgsGeometry.createWedgeBufferFromAngles: src/core/geometry/qgsgeometry.h#L380 +QgsGeometry.crosses: src/core/geometry/qgsgeometry.h#L1552 +QgsGeometry.delaunayTriangulation: src/core/geometry/qgsgeometry.h#L1861 +QgsGeometry.deletePart: src/core/geometry/qgsgeometry.h#L2581 +QgsGeometry.deleteRing: src/core/geometry/qgsgeometry.h#L2575 +QgsGeometry.deleteVertex: src/core/geometry/qgsgeometry.h#L863 +QgsGeometry.densifyByCount: src/core/geometry/qgsgeometry.h#L1656 +QgsGeometry.densifyByDistance: src/core/geometry/qgsgeometry.h#L1671 +QgsGeometry.difference: src/core/geometry/qgsgeometry.h#L2080 +QgsGeometry.disjoint: src/core/geometry/qgsgeometry.h#L1508 +QgsGeometry.distance: src/core/geometry/qgsgeometry.h#L517 +QgsGeometry.distanceToVertex: src/core/geometry/qgsgeometry.h#L773 +QgsGeometry.draw: src/core/geometry/qgsgeometry.h#L2883 +QgsGeometry.equals: src/core/geometry/qgsgeometry.h#L431 +QgsGeometry.extendLine: src/core/geometry/qgsgeometry.h#L1643 +QgsGeometry.extrude: src/core/geometry/qgsgeometry.h#L2096 +QgsGeometry.forcePolygonClockwise: src/core/geometry/qgsgeometry.h#L2750 +QgsGeometry.forcePolygonCounterClockwise: src/core/geometry/qgsgeometry.h#L2762 +QgsGeometry.forceRHR: src/core/geometry/qgsgeometry.h#L2738 +QgsGeometry.frechetDistance: src/core/geometry/qgsgeometry.h#L726 +QgsGeometry.frechetDistanceDensify: src/core/geometry/qgsgeometry.h#L750 +QgsGeometry.fromBox3D: src/core/geometry/qgsgeometry.h#L343 +QgsGeometry.fromMultiPointXY: src/core/geometry/qgsgeometry.h#L272 +QgsGeometry.fromMultiPolygonXY: src/core/geometry/qgsgeometry.h#L331 +QgsGeometry.fromMultiPolylineXY: src/core/geometry/qgsgeometry.h#L299 +QgsGeometry.fromPoint: src/core/geometry/qgsgeometry.h#L269 +QgsGeometry.fromPointXY: src/core/geometry/qgsgeometry.h#L262 +QgsGeometry.fromPolygonXY: src/core/geometry/qgsgeometry.h#L326 +QgsGeometry.fromPolyline: src/core/geometry/qgsgeometry.h#L294 +QgsGeometry.fromPolylineXY: src/core/geometry/qgsgeometry.h#L284 +QgsGeometry.fromQPointF: src/core/geometry/qgsgeometry.h#L2947 +QgsGeometry.fromQPolygonF: src/core/geometry/qgsgeometry.h#L2955 +QgsGeometry.fromRect: src/core/geometry/qgsgeometry.h#L334 +QgsGeometry.fromWkb: src/core/geometry/qgsgeometry.h#L393 +QgsGeometry.fromWkt: src/core/geometry/qgsgeometry.h#L260 +QgsGeometry.get: src/core/geometry/qgsgeometry.h#L235 +QgsGeometry.hausdorffDistance: src/core/geometry/qgsgeometry.h#L691 +QgsGeometry.hausdorffDistanceDensify: src/core/geometry/qgsgeometry.h#L710 +QgsGeometry.insertVertex: src/core/geometry/qgsgeometry.h#L809 +QgsGeometry.insertVertex: src/core/geometry/qgsgeometry.h#L823 +QgsGeometry.interpolate: src/core/geometry/qgsgeometry.h#L1996 +QgsGeometry.interpolateAngle: src/core/geometry/qgsgeometry.h#L2018 +QgsGeometry.intersection: src/core/geometry/qgsgeometry.h#L2031 +QgsGeometry.intersects: src/core/geometry/qgsgeometry.h#L1438 +QgsGeometry.intersects: src/core/geometry/qgsgeometry.h#L1454 +QgsGeometry.isAxisParallelRectangle: src/core/geometry/qgsgeometry.h#L480 +QgsGeometry.isEmpty: src/core/geometry/qgsgeometry.h#L413 +QgsGeometry.isGeosEqual: src/core/geometry/qgsgeometry.h#L448 +QgsGeometry.isGeosValid: src/core/geometry/qgsgeometry.h#L456 +QgsGeometry.isMultipart: src/core/geometry/qgsgeometry.h#L416 +QgsGeometry.isNull: src/core/geometry/qgsgeometry.h#L257 +QgsGeometry.isPolygonClockwise: src/core/geometry/qgsgeometry.h#L2721 +QgsGeometry.isPolygonCounterClockwise: src/core/geometry/qgsgeometry.h#L2706 +QgsGeometry.isSimple: src/core/geometry/qgsgeometry.h#L465 +QgsGeometry.largestEmptyCircle: src/core/geometry/qgsgeometry.h#L1756 +QgsGeometry.lastError: src/core/geometry/qgsgeometry.h#L2914 +QgsGeometry.length: src/core/geometry/qgsgeometry.h#L508 +QgsGeometry.lineLocatePoint: src/core/geometry/qgsgeometry.h#L2008 +QgsGeometry.makeDifference: src/core/geometry/qgsgeometry.h#L1210 +QgsGeometry.makeValid: src/core/geometry/qgsgeometry.h#L2680 +QgsGeometry.mapToPixel: src/core/geometry/qgsgeometry.h#L2877 +QgsGeometry.mergeLines: src/core/geometry/qgsgeometry.h#L2067 +QgsGeometry.minimalEnclosingCircle: src/core/geometry/qgsgeometry.h#L1257 +QgsGeometry.minimumClearance: src/core/geometry/qgsgeometry.h#L1795 +QgsGeometry.minimumClearanceLine: src/core/geometry/qgsgeometry.h#L1808 +QgsGeometry.minimumWidth: src/core/geometry/qgsgeometry.h#L1772 +QgsGeometry.moveVertex: src/core/geometry/qgsgeometry.h#L841 +QgsGeometry.moveVertex: src/core/geometry/qgsgeometry.h#L850 +QgsGeometry.nearestPoint: src/core/geometry/qgsgeometry.h#L892 +QgsGeometry.node: src/core/geometry/qgsgeometry.h#L1941 +QgsGeometry.normalize: src/core/geometry/qgsgeometry.h#L2837 +QgsGeometry.offsetCurve: src/core/geometry/qgsgeometry.h#L1583 +QgsGeometry.orientedMinimumBoundingBox: src/core/geometry/qgsgeometry.h#L1237 +QgsGeometry.orthogonalize: src/core/geometry/qgsgeometry.h#L1272 +QgsGeometry.overlaps: src/core/geometry/qgsgeometry.h#L1530 +QgsGeometry.parts: src/core/geometry/qgsgeometry.h#L639 +QgsGeometry.pointOnSurface: src/core/geometry/qgsgeometry.h#L1718 +QgsGeometry.poleOfInaccessibility: src/core/geometry/qgsgeometry.h#L1731 +QgsGeometry.polygonOrientation: src/core/geometry/qgsgeometry.h#L2691 +QgsGeometry.polygonize: src/core/geometry/qgsgeometry.h#L2856 +QgsGeometry.randomPointsInPolygon: src/core/geometry/qgsgeometry.h#L2153 +QgsGeometry.removeDuplicateNodes: src/core/geometry/qgsgeometry.h#L1427 +QgsGeometry.removeInteriorRings: src/core/geometry/qgsgeometry.h#L1006 +QgsGeometry.requiresConversionToStraightSegments: src/core/geometry/qgsgeometry.h#L2871 +QgsGeometry.reshapeGeometry: src/core/geometry/qgsgeometry.h#L1195 +QgsGeometry.rotate: src/core/geometry/qgsgeometry.h#L1046 +QgsGeometry.roundWaves: src/core/geometry/qgsgeometry.h#L1354 +QgsGeometry.roundWavesRandomized: src/core/geometry/qgsgeometry.h#L1374 +QgsGeometry.set: src/core/geometry/qgsgeometry.h#L248 +QgsGeometry.sharedPaths: src/core/geometry/qgsgeometry.h#L1957 +QgsGeometry.shortestLine: src/core/geometry/qgsgeometry.h#L903 +QgsGeometry.simplify: src/core/geometry/qgsgeometry.h#L1646 +QgsGeometry.simplifyCoverageVW: src/core/geometry/qgsgeometry.h#L1916 +QgsGeometry.singleSidedBuffer: src/core/geometry/qgsgeometry.h#L1599 +QgsGeometry.smooth: src/core/geometry/qgsgeometry.h#L3135 +QgsGeometry.snappedToGrid: src/core/geometry/qgsgeometry.h#L1406 +QgsGeometry.splitGeometry: src/core/geometry/qgsgeometry.h#L1109 +QgsGeometry.splitGeometry: src/core/geometry/qgsgeometry.h#L1189 +QgsGeometry.sqrDistToVertexAt: src/core/geometry/qgsgeometry.h#L886 +QgsGeometry.squareWaves: src/core/geometry/qgsgeometry.h#L1320 +QgsGeometry.squareWavesRandomized: src/core/geometry/qgsgeometry.h#L1340 +QgsGeometry.subdivide: src/core/geometry/qgsgeometry.h#L1980 +QgsGeometry.symDifference: src/core/geometry/qgsgeometry.h#L2093 +QgsGeometry.taperedBuffer: src/core/geometry/qgsgeometry.h#L1620 +QgsGeometry.toggleCircularAtVertex: src/core/geometry/qgsgeometry.h#L872 +QgsGeometry.touches: src/core/geometry/qgsgeometry.h#L1519 +QgsGeometry.transform: src/core/geometry/qgsgeometry.h#L1028 +QgsGeometry.transform: src/core/geometry/qgsgeometry.h#L1038 +QgsGeometry.translate: src/core/geometry/qgsgeometry.h#L1012 +QgsGeometry.triangularWaves: src/core/geometry/qgsgeometry.h#L1286 +QgsGeometry.triangularWavesRandomized: src/core/geometry/qgsgeometry.h#L1306 +QgsGeometry.type: src/core/geometry/qgsgeometry.h#L405 +QgsGeometry.unaryUnion: src/core/geometry/qgsgeometry.h#L2847 +QgsGeometry.unionCoverage: src/core/geometry/qgsgeometry.h#L1929 +QgsGeometry.validateCoverage: src/core/geometry/qgsgeometry.h#L1894 +QgsGeometry.validateGeometry: src/core/geometry/qgsgeometry.h#L2826 +QgsGeometry.variableWidthBufferByM: src/core/geometry/qgsgeometry.h#L1636 +QgsGeometry.vertexAt: src/core/geometry/qgsgeometry.h#L879 +QgsGeometry.vertexIdFromVertexNr: src/core/geometry/qgsgeometry.h#L2894 +QgsGeometry.vertexNrFromVertexId: src/core/geometry/qgsgeometry.h#L2906 +QgsGeometry.vertices: src/core/geometry/qgsgeometry.h#L557 +QgsGeometry.voronoiDiagram: src/core/geometry/qgsgeometry.h#L1849 +QgsGeometry.within: src/core/geometry/qgsgeometry.h#L1541 +QgsGeometry.wkbSize: src/core/geometry/qgsgeometry.h#L2184 +QgsGeometry.wkbType: src/core/geometry/qgsgeometry.h#L399 +QgsGeometry: src/core/geometry/qgsgeometry.h#L178 QgsGeometryCollection.__bool__: src/core/geometry/qgsgeometrycollection.h#L136 QgsGeometryCollection.__delitem__: src/core/geometry/qgsgeometrycollection.h#L401 QgsGeometryCollection.__getitem__: src/core/geometry/qgsgeometrycollection.h#L373 @@ -5306,9 +5306,9 @@ QgsGeometryPaintDevice.painterPathToGeometry: src/core/painting/qgsgeometrypaint QgsGeometryPaintDevice.setSimplificationTolerance: src/core/painting/qgsgeometrypaintdevice.h#L149 QgsGeometryPaintDevice.setStrokedPathSegments: src/core/painting/qgsgeometrypaintdevice.h#L140 QgsGeometryPaintDevice: src/core/painting/qgsgeometrypaintdevice.h#L122 -QgsGeometryParameters.gridSize: src/core/geometry/qgsgeometry.h#L122 -QgsGeometryParameters.setGridSize: src/core/geometry/qgsgeometry.h#L134 -QgsGeometryParameters: src/core/geometry/qgsgeometry.h#L108 +QgsGeometryParameters.gridSize: src/core/geometry/qgsgeometry.h#L139 +QgsGeometryParameters.setGridSize: src/core/geometry/qgsgeometry.h#L151 +QgsGeometryParameters: src/core/geometry/qgsgeometry.h#L125 QgsGeometryPartIterator.__iter__: src/core/geometry/qgsabstractgeometry.h#L1286 QgsGeometryPartIterator.__next__: src/core/geometry/qgsabstractgeometry.h#L1291 QgsGeometryPartIterator.hasNext: src/core/geometry/qgsabstractgeometry.h#L1280 @@ -5508,13 +5508,13 @@ QgsGlowEffect.shadeExterior: src/core/effects/qgsgloweffect.h#L274 QgsGlowEffect.spread: src/core/effects/qgsgloweffect.h#L73 QgsGlowEffect.spreadUnit: src/core/effects/qgsgloweffect.h#L91 QgsGlowEffect: src/core/effects/qgsgloweffect.h#L37 -QgsGml.crs: src/core/qgsgml.h#L431 -QgsGml.dataProgressAndSteps: src/core/qgsgml.h#L455 -QgsGml.dataReadProgress: src/core/qgsgml.h#L440 -QgsGml.getFeatures: src/core/qgsgml.h#L408 -QgsGml.getFeatures: src/core/qgsgml.h#L420 -QgsGml.totalStepsUpdate: src/core/qgsgml.h#L447 -QgsGml: src/core/qgsgml.h#L387 +QgsGml.crs: src/core/qgsgml.h#L432 +QgsGml.dataProgressAndSteps: src/core/qgsgml.h#L456 +QgsGml.dataReadProgress: src/core/qgsgml.h#L441 +QgsGml.getFeatures: src/core/qgsgml.h#L409 +QgsGml.getFeatures: src/core/qgsgml.h#L421 +QgsGml.totalStepsUpdate: src/core/qgsgml.h#L448 +QgsGml: src/core/qgsgml.h#L388 QgsGmlFeatureClass.fieldIndex: src/core/qgsgmlschema.h#L49 QgsGmlFeatureClass.path: src/core/qgsgmlschema.h#L51 QgsGmlFeatureClass: src/core/qgsgmlschema.h#L40 @@ -8951,219 +8951,220 @@ QgsMapInfoSymbolConverter.convertFillSymbol: src/core/symbology/qgsmapinfosymbol QgsMapInfoSymbolConverter.convertLineSymbol: src/core/symbology/qgsmapinfosymbolconverter.h#L75 QgsMapInfoSymbolConverter.convertMarkerSymbol: src/core/symbology/qgsmapinfosymbolconverter.h#L91 QgsMapInfoSymbolConverter: src/core/symbology/qgsmapinfosymbolconverter.h#L66 -QgsMapLayer.__repr__: src/core/qgsmaplayer.h#L1915 +QgsMapLayer.__repr__: src/core/qgsmaplayer.h#L1955 QgsMapLayer.abstract: src/core/qgsmaplayer.h#L356 -QgsMapLayer.accept: src/core/qgsmaplayer.h#L1742 -QgsMapLayer.appendError: src/core/qgsmaplayer.h#L2279 +QgsMapLayer.accept: src/core/qgsmaplayer.h#L1782 +QgsMapLayer.appendError: src/core/qgsmaplayer.h#L2319 QgsMapLayer.attribution: src/core/qgsmaplayer.h#L412 QgsMapLayer.attributionUrl: src/core/qgsmaplayer.h#L426 -QgsMapLayer.autoRefreshInterval: src/core/qgsmaplayer.h#L1636 -QgsMapLayer.autoRefreshIntervalChanged: src/core/qgsmaplayer.h#L2080 -QgsMapLayer.autoRefreshMode: src/core/qgsmaplayer.h#L1628 -QgsMapLayer.beforeResolveReferences: src/core/qgsmaplayer.h#L1938 +QgsMapLayer.autoRefreshInterval: src/core/qgsmaplayer.h#L1676 +QgsMapLayer.autoRefreshIntervalChanged: src/core/qgsmaplayer.h#L2120 +QgsMapLayer.autoRefreshMode: src/core/qgsmaplayer.h#L1668 +QgsMapLayer.beforeResolveReferences: src/core/qgsmaplayer.h#L1978 QgsMapLayer.blendMode: src/core/qgsmaplayer.h#L516 -QgsMapLayer.blendModeChanged: src/core/qgsmaplayer.h#L2011 +QgsMapLayer.blendModeChanged: src/core/qgsmaplayer.h#L2051 QgsMapLayer.clone: src/core/qgsmaplayer.h#L214 -QgsMapLayer.clone: src/core/qgsmaplayer.h#L2187 -QgsMapLayer.configChanged: src/core/qgsmaplayer.h#L2062 +QgsMapLayer.clone: src/core/qgsmaplayer.h#L2227 +QgsMapLayer.configChanged: src/core/qgsmaplayer.h#L2102 QgsMapLayer.createMapRenderer: src/core/qgsmaplayer.h#L549 -QgsMapLayer.crs3D: src/core/qgsmaplayer.h#L1034 -QgsMapLayer.crs3DChanged: src/core/qgsmaplayer.h#L1977 -QgsMapLayer.crs: src/core/qgsmaplayer.h#L994 -QgsMapLayer.crsChanged: src/core/qgsmaplayer.h#L1966 +QgsMapLayer.crs3D: src/core/qgsmaplayer.h#L1074 +QgsMapLayer.crs3DChanged: src/core/qgsmaplayer.h#L2017 +QgsMapLayer.crs: src/core/qgsmaplayer.h#L1034 +QgsMapLayer.crsChanged: src/core/qgsmaplayer.h#L2006 QgsMapLayer.customProperty: src/core/qgsmaplayer.h#L721 -QgsMapLayer.customPropertyChanged: src/core/qgsmaplayer.h#L2125 +QgsMapLayer.customPropertyChanged: src/core/qgsmaplayer.h#L2165 QgsMapLayer.customPropertyKeys: src/core/qgsmaplayer.h#L708 -QgsMapLayer.dataChanged: src/core/qgsmaplayer.h#L2008 +QgsMapLayer.dataChanged: src/core/qgsmaplayer.h#L2048 QgsMapLayer.dataProvider: src/core/qgsmaplayer.h#L302 -QgsMapLayer.dataSourceChanged: src/core/qgsmaplayer.h#L2104 +QgsMapLayer.dataSourceChanged: src/core/qgsmaplayer.h#L2144 QgsMapLayer.dataUrl: src/core/qgsmaplayer.h#L384 QgsMapLayer.dataUrlFormat: src/core/qgsmaplayer.h#L398 -QgsMapLayer.decodedSource: src/core/qgsmaplayer.h#L2238 +QgsMapLayer.decodedSource: src/core/qgsmaplayer.h#L2278 QgsMapLayer.deleteStyleFromDatabase: src/core/qgsmaplayer.h#L758 -QgsMapLayer.dependenciesChanged: src/core/qgsmaplayer.h#L2067 -QgsMapLayer.editingStarted: src/core/qgsmaplayer.h#L2131 -QgsMapLayer.editingStopped: src/core/qgsmaplayer.h#L2137 -QgsMapLayer.elevationProperties: src/core/qgsmaplayer.h#L1763 -QgsMapLayer.emitStyleChanged: src/core/qgsmaplayer.h#L1882 -QgsMapLayer.encodedSource: src/core/qgsmaplayer.h#L2224 -QgsMapLayer.error: src/core/qgsmaplayer.h#L981 -QgsMapLayer.exportNamedMetadata: src/core/qgsmaplayer.h#L1096 -QgsMapLayer.exportNamedStyle: src/core/qgsmaplayer.h#L1244 -QgsMapLayer.exportSldStyle: src/core/qgsmaplayer.h#L1255 -QgsMapLayer.exportSldStyleV2: src/core/qgsmaplayer.h#L1264 -QgsMapLayer.exportSldStyleV3: src/core/qgsmaplayer.h#L1275 +QgsMapLayer.dependenciesChanged: src/core/qgsmaplayer.h#L2107 +QgsMapLayer.editingStarted: src/core/qgsmaplayer.h#L2171 +QgsMapLayer.editingStopped: src/core/qgsmaplayer.h#L2177 +QgsMapLayer.elevationProperties: src/core/qgsmaplayer.h#L1803 +QgsMapLayer.emitStyleChanged: src/core/qgsmaplayer.h#L1922 +QgsMapLayer.encodedSource: src/core/qgsmaplayer.h#L2264 +QgsMapLayer.error: src/core/qgsmaplayer.h#L1021 +QgsMapLayer.exportNamedMetadata: src/core/qgsmaplayer.h#L1136 +QgsMapLayer.exportNamedStyle: src/core/qgsmaplayer.h#L1284 +QgsMapLayer.exportSldStyle: src/core/qgsmaplayer.h#L1295 +QgsMapLayer.exportSldStyleV2: src/core/qgsmaplayer.h#L1304 +QgsMapLayer.exportSldStyleV3: src/core/qgsmaplayer.h#L1315 QgsMapLayer.extensionPropertyType: src/core/qgsmaplayer.h#L260 QgsMapLayer.extent3D: src/core/qgsmaplayer.h#L558 QgsMapLayer.extent: src/core/qgsmaplayer.h#L552 QgsMapLayer.flags: src/core/qgsmaplayer.h#L231 -QgsMapLayer.flagsChanged: src/core/qgsmaplayer.h#L2095 -QgsMapLayer.formatLayerName: src/core/qgsmaplayer.h#L1081 -QgsMapLayer.generateId: src/core/qgsmaplayer.h#L1731 +QgsMapLayer.flagsChanged: src/core/qgsmaplayer.h#L2135 +QgsMapLayer.formatLayerName: src/core/qgsmaplayer.h#L1121 +QgsMapLayer.generateId: src/core/qgsmaplayer.h#L1771 QgsMapLayer.getStyleFromDatabase: src/core/qgsmaplayer.h#L750 -QgsMapLayer.hasAutoRefreshEnabled: src/core/qgsmaplayer.h#L1620 -QgsMapLayer.hasDependencyCycle: src/core/qgsmaplayer.h#L2311 -QgsMapLayer.hasMapTips: src/core/qgsmaplayer.h#L1785 -QgsMapLayer.hasScaleBasedVisibility: src/core/qgsmaplayer.h#L1612 -QgsMapLayer.htmlMetadata: src/core/qgsmaplayer.h#L1683 +QgsMapLayer.hasAutoRefreshEnabled: src/core/qgsmaplayer.h#L1660 +QgsMapLayer.hasDependencyCycle: src/core/qgsmaplayer.h#L2351 +QgsMapLayer.hasMapTips: src/core/qgsmaplayer.h#L1825 +QgsMapLayer.hasScaleBasedVisibility: src/core/qgsmaplayer.h#L1652 +QgsMapLayer.htmlMetadata: src/core/qgsmaplayer.h#L1723 QgsMapLayer.id: src/core/qgsmaplayer.h#L268 -QgsMapLayer.idChanged: src/core/qgsmaplayer.h#L1951 -QgsMapLayer.importNamedMetadata: src/core/qgsmaplayer.h#L1169 -QgsMapLayer.importNamedStyle: src/core/qgsmaplayer.h#L1233 -QgsMapLayer.invalidateWgs84Extent: src/core/qgsmaplayer.h#L2289 +QgsMapLayer.idChanged: src/core/qgsmaplayer.h#L1991 +QgsMapLayer.importNamedMetadata: src/core/qgsmaplayer.h#L1209 +QgsMapLayer.importNamedStyle: src/core/qgsmaplayer.h#L1273 +QgsMapLayer.invalidateWgs84Extent: src/core/qgsmaplayer.h#L2329 QgsMapLayer.isEditable: src/core/qgsmaplayer.h#L624 -QgsMapLayer.isInScaleRange: src/core/qgsmaplayer.h#L1578 +QgsMapLayer.isInScaleRange: src/core/qgsmaplayer.h#L1618 QgsMapLayer.isModified: src/core/qgsmaplayer.h#L631 -QgsMapLayer.isRefreshOnNotifyEnabled: src/core/qgsmaplayer.h#L1706 +QgsMapLayer.isRefreshOnNotifyEnabled: src/core/qgsmaplayer.h#L1746 QgsMapLayer.isSpatial: src/core/qgsmaplayer.h#L636 QgsMapLayer.isTemporary: src/core/qgsmaplayer.h#L647 QgsMapLayer.isValid: src/core/qgsmaplayer.h#L575 -QgsMapLayer.isValidChanged: src/core/qgsmaplayer.h#L2118 +QgsMapLayer.isValidChanged: src/core/qgsmaplayer.h#L2158 QgsMapLayer.keywordList: src/core/qgsmaplayer.h#L370 -QgsMapLayer.layerModified: src/core/qgsmaplayer.h#L2143 -QgsMapLayer.legend: src/core/qgsmaplayer.h#L1553 -QgsMapLayer.legendChanged: src/core/qgsmaplayer.h#L2044 -QgsMapLayer.legendPlaceholderImage: src/core/qgsmaplayer.h#L1770 -QgsMapLayer.legendUrl: src/core/qgsmaplayer.h#L1528 -QgsMapLayer.legendUrlFormat: src/core/qgsmaplayer.h#L1542 +QgsMapLayer.layerModified: src/core/qgsmaplayer.h#L2183 +QgsMapLayer.legend: src/core/qgsmaplayer.h#L1593 +QgsMapLayer.legendChanged: src/core/qgsmaplayer.h#L2084 +QgsMapLayer.legendPlaceholderImage: src/core/qgsmaplayer.h#L1810 +QgsMapLayer.legendUrl: src/core/qgsmaplayer.h#L1568 +QgsMapLayer.legendUrlFormat: src/core/qgsmaplayer.h#L1582 QgsMapLayer.listStylesInDatabase: src/core/qgsmaplayer.h#L744 -QgsMapLayer.loadDefaultMetadata: src/core/qgsmaplayer.h#L1152 -QgsMapLayer.loadDefaultStyle: src/core/qgsmaplayer.h#L1193 -QgsMapLayer.loadNamedMetadata: src/core/qgsmaplayer.h#L1139 -QgsMapLayer.loadNamedMetadataFromDatabase: src/core/qgsmaplayer.h#L1161 -QgsMapLayer.loadNamedStyle: src/core/qgsmaplayer.h#L1214 -QgsMapLayer.loadNamedStyle: src/core/qgsmaplayer.h#L795 -QgsMapLayer.loadNamedStyleFromDatabase: src/core/qgsmaplayer.h#L1223 -QgsMapLayer.loadSldStyle: src/core/qgsmaplayer.h#L1351 -QgsMapLayer.mapTipTemplate: src/core/qgsmaplayer.h#L1794 -QgsMapLayer.mapTipTemplateChanged: src/core/qgsmaplayer.h#L2150 -QgsMapLayer.mapTipsEnabled: src/core/qgsmaplayer.h#L1817 -QgsMapLayer.mapTipsEnabledChanged: src/core/qgsmaplayer.h#L2158 -QgsMapLayer.maximumScale: src/core/qgsmaplayer.h#L1602 -QgsMapLayer.metadataChanged: src/core/qgsmaplayer.h#L2087 -QgsMapLayer.metadataUri: src/core/qgsmaplayer.h#L1089 +QgsMapLayer.loadDefaultMetadata: src/core/qgsmaplayer.h#L1192 +QgsMapLayer.loadDefaultStyle: src/core/qgsmaplayer.h#L1233 +QgsMapLayer.loadNamedMetadata: src/core/qgsmaplayer.h#L1179 +QgsMapLayer.loadNamedMetadataFromDatabase: src/core/qgsmaplayer.h#L1201 +QgsMapLayer.loadNamedStyle: src/core/qgsmaplayer.h#L1254 +QgsMapLayer.loadNamedStyle: src/core/qgsmaplayer.h#L835 +QgsMapLayer.loadNamedStyleFromDatabase: src/core/qgsmaplayer.h#L1263 +QgsMapLayer.loadSldStyle: src/core/qgsmaplayer.h#L1391 +QgsMapLayer.mapTipTemplate: src/core/qgsmaplayer.h#L1834 +QgsMapLayer.mapTipTemplateChanged: src/core/qgsmaplayer.h#L2190 +QgsMapLayer.mapTipsEnabled: src/core/qgsmaplayer.h#L1857 +QgsMapLayer.mapTipsEnabledChanged: src/core/qgsmaplayer.h#L2198 +QgsMapLayer.maximumScale: src/core/qgsmaplayer.h#L1642 +QgsMapLayer.metadataChanged: src/core/qgsmaplayer.h#L2127 +QgsMapLayer.metadataUri: src/core/qgsmaplayer.h#L1129 QgsMapLayer.metadataUrl: src/core/qgsmaplayer.h#L461 QgsMapLayer.metadataUrlFormat: src/core/qgsmaplayer.h#L503 QgsMapLayer.metadataUrlType: src/core/qgsmaplayer.h#L482 -QgsMapLayer.minimumScale: src/core/qgsmaplayer.h#L1590 +QgsMapLayer.minimumScale: src/core/qgsmaplayer.h#L1630 QgsMapLayer.name: src/core/qgsmaplayer.h#L297 -QgsMapLayer.nameChanged: src/core/qgsmaplayer.h#L1956 +QgsMapLayer.nameChanged: src/core/qgsmaplayer.h#L1996 QgsMapLayer.opacity: src/core/qgsmaplayer.h#L536 -QgsMapLayer.opacityChanged: src/core/qgsmaplayer.h#L2021 -QgsMapLayer.originalXmlProperties: src/core/qgsmaplayer.h#L1716 -QgsMapLayer.project: src/core/qgsmaplayer.h#L1928 +QgsMapLayer.opacityChanged: src/core/qgsmaplayer.h#L2061 +QgsMapLayer.originalXmlProperties: src/core/qgsmaplayer.h#L1756 +QgsMapLayer.project: src/core/qgsmaplayer.h#L1968 QgsMapLayer.properties: src/core/qgsmaplayer.h#L254 QgsMapLayer.providerMetadata: src/core/qgsmaplayer.h#L314 -QgsMapLayer.providerReadFlags: src/core/qgsmaplayer.h#L1826 -QgsMapLayer.providerType: src/core/qgsmaplayer.h#L1506 +QgsMapLayer.providerReadFlags: src/core/qgsmaplayer.h#L1866 +QgsMapLayer.providerType: src/core/qgsmaplayer.h#L1546 QgsMapLayer.publicSource: src/core/qgsmaplayer.h#L587 -QgsMapLayer.readCommonStyle: src/core/qgsmaplayer.h#L2265 -QgsMapLayer.readCustomProperties: src/core/qgsmaplayer.h#L2245 +QgsMapLayer.readCommonStyle: src/core/qgsmaplayer.h#L2305 +QgsMapLayer.readCustomProperties: src/core/qgsmaplayer.h#L2285 QgsMapLayer.readLayerXml: src/core/qgsmaplayer.h#L679 QgsMapLayer.readOnly: src/core/qgsmaplayer.h#L539 -QgsMapLayer.readSld: src/core/qgsmaplayer.h#L1354 -QgsMapLayer.readStyle: src/core/qgsmaplayer.h#L1378 -QgsMapLayer.readStyleManager: src/core/qgsmaplayer.h#L2251 -QgsMapLayer.readSymbology: src/core/qgsmaplayer.h#L1366 -QgsMapLayer.readXml: src/core/qgsmaplayer.h#L2205 -QgsMapLayer.recalculateExtents: src/core/qgsmaplayer.h#L2005 -QgsMapLayer.refreshOnNotifyMessage: src/core/qgsmaplayer.h#L1700 +QgsMapLayer.readSld: src/core/qgsmaplayer.h#L1394 +QgsMapLayer.readStyle: src/core/qgsmaplayer.h#L1418 +QgsMapLayer.readStyleManager: src/core/qgsmaplayer.h#L2291 +QgsMapLayer.readSymbology: src/core/qgsmaplayer.h#L1406 +QgsMapLayer.readXml: src/core/qgsmaplayer.h#L2245 +QgsMapLayer.recalculateExtents: src/core/qgsmaplayer.h#L2045 +QgsMapLayer.refreshOnNotifyMessage: src/core/qgsmaplayer.h#L1740 QgsMapLayer.reload: src/core/qgsmaplayer.h#L544 -QgsMapLayer.removeCustomProperty: src/core/qgsmaplayer.h#L974 -QgsMapLayer.renderer3D: src/core/qgsmaplayer.h#L1568 -QgsMapLayer.renderer3DChanged: src/core/qgsmaplayer.h#L2049 -QgsMapLayer.rendererChanged: src/core/qgsmaplayer.h#L2027 -QgsMapLayer.repaintRequested: src/core/qgsmaplayer.h#L2002 -QgsMapLayer.request3DUpdate: src/core/qgsmaplayer.h#L2056 +QgsMapLayer.removeCustomProperty: src/core/qgsmaplayer.h#L1014 +QgsMapLayer.renderer3D: src/core/qgsmaplayer.h#L1608 +QgsMapLayer.renderer3DChanged: src/core/qgsmaplayer.h#L2089 +QgsMapLayer.rendererChanged: src/core/qgsmaplayer.h#L2067 +QgsMapLayer.repaintRequested: src/core/qgsmaplayer.h#L2042 +QgsMapLayer.request3DUpdate: src/core/qgsmaplayer.h#L2096 QgsMapLayer.resolveReferences: src/core/qgsmaplayer.h#L702 -QgsMapLayer.saveDefaultMetadata: src/core/qgsmaplayer.h#L1106 -QgsMapLayer.saveDefaultStyle: src/core/qgsmaplayer.h#L1288 -QgsMapLayer.saveDefaultStyle: src/core/qgsmaplayer.h#L1301 -QgsMapLayer.saveNamedMetadata: src/core/qgsmaplayer.h#L1121 -QgsMapLayer.saveNamedStyle: src/core/qgsmaplayer.h#L1318 -QgsMapLayer.saveSldStyle: src/core/qgsmaplayer.h#L1329 -QgsMapLayer.saveSldStyleV2: src/core/qgsmaplayer.h#L1341 -QgsMapLayer.saveStyleToDatabase: src/core/qgsmaplayer.h#L776 -QgsMapLayer.selectionProperties: src/core/qgsmaplayer.h#L1749 +QgsMapLayer.saveDefaultMetadata: src/core/qgsmaplayer.h#L1146 +QgsMapLayer.saveDefaultStyle: src/core/qgsmaplayer.h#L1328 +QgsMapLayer.saveDefaultStyle: src/core/qgsmaplayer.h#L1341 +QgsMapLayer.saveNamedMetadata: src/core/qgsmaplayer.h#L1161 +QgsMapLayer.saveNamedStyle: src/core/qgsmaplayer.h#L1358 +QgsMapLayer.saveSldStyle: src/core/qgsmaplayer.h#L1369 +QgsMapLayer.saveSldStyleV2: src/core/qgsmaplayer.h#L1381 +QgsMapLayer.saveStyleToDatabase: src/core/qgsmaplayer.h#L799 +QgsMapLayer.saveStyleToDatabaseV2: src/core/qgsmaplayer.h#L817 +QgsMapLayer.selectionProperties: src/core/qgsmaplayer.h#L1789 QgsMapLayer.serverProperties: src/core/qgsmaplayer.h#L435 QgsMapLayer.setAbstract: src/core/qgsmaplayer.h#L349 QgsMapLayer.setAttribution: src/core/qgsmaplayer.h#L405 QgsMapLayer.setAttributionUrl: src/core/qgsmaplayer.h#L419 -QgsMapLayer.setAutoRefreshEnabled: src/core/qgsmaplayer.h#L1656 -QgsMapLayer.setAutoRefreshInterval: src/core/qgsmaplayer.h#L1648 -QgsMapLayer.setAutoRefreshMode: src/core/qgsmaplayer.h#L1664 +QgsMapLayer.setAutoRefreshEnabled: src/core/qgsmaplayer.h#L1696 +QgsMapLayer.setAutoRefreshInterval: src/core/qgsmaplayer.h#L1688 +QgsMapLayer.setAutoRefreshMode: src/core/qgsmaplayer.h#L1704 QgsMapLayer.setBlendMode: src/core/qgsmaplayer.h#L510 -QgsMapLayer.setCrs: src/core/qgsmaplayer.h#L1046 +QgsMapLayer.setCrs: src/core/qgsmaplayer.h#L1086 QgsMapLayer.setCustomProperties: src/core/qgsmaplayer.h#L726 QgsMapLayer.setCustomProperty: src/core/qgsmaplayer.h#L715 -QgsMapLayer.setDataSource: src/core/qgsmaplayer.h#L1439 -QgsMapLayer.setDataSource: src/core/qgsmaplayer.h#L1470 -QgsMapLayer.setDataSource: src/core/qgsmaplayer.h#L1501 +QgsMapLayer.setDataSource: src/core/qgsmaplayer.h#L1479 +QgsMapLayer.setDataSource: src/core/qgsmaplayer.h#L1510 +QgsMapLayer.setDataSource: src/core/qgsmaplayer.h#L1541 QgsMapLayer.setDataUrl: src/core/qgsmaplayer.h#L377 QgsMapLayer.setDataUrlFormat: src/core/qgsmaplayer.h#L391 -QgsMapLayer.setDependencies: src/core/qgsmaplayer.h#L1891 -QgsMapLayer.setError: src/core/qgsmaplayer.h#L2281 -QgsMapLayer.setExtent3D: src/core/qgsmaplayer.h#L2196 -QgsMapLayer.setExtent: src/core/qgsmaplayer.h#L2190 +QgsMapLayer.setDependencies: src/core/qgsmaplayer.h#L1931 +QgsMapLayer.setError: src/core/qgsmaplayer.h#L2321 +QgsMapLayer.setExtent3D: src/core/qgsmaplayer.h#L2236 +QgsMapLayer.setExtent: src/core/qgsmaplayer.h#L2230 QgsMapLayer.setFlags: src/core/qgsmaplayer.h#L243 QgsMapLayer.setId: src/core/qgsmaplayer.h#L285 QgsMapLayer.setKeywordList: src/core/qgsmaplayer.h#L363 QgsMapLayer.setLayerOrder: src/core/qgsmaplayer.h#L606 -QgsMapLayer.setLegend: src/core/qgsmaplayer.h#L1548 -QgsMapLayer.setLegendPlaceholderImage: src/core/qgsmaplayer.h#L1777 -QgsMapLayer.setLegendUrl: src/core/qgsmaplayer.h#L1521 -QgsMapLayer.setLegendUrlFormat: src/core/qgsmaplayer.h#L1535 -QgsMapLayer.setMapTipTemplate: src/core/qgsmaplayer.h#L1803 -QgsMapLayer.setMapTipsEnabled: src/core/qgsmaplayer.h#L1811 -QgsMapLayer.setMaximumScale: src/core/qgsmaplayer.h#L1850 -QgsMapLayer.setMetadata: src/core/qgsmaplayer.h#L1678 +QgsMapLayer.setLegend: src/core/qgsmaplayer.h#L1588 +QgsMapLayer.setLegendPlaceholderImage: src/core/qgsmaplayer.h#L1817 +QgsMapLayer.setLegendUrl: src/core/qgsmaplayer.h#L1561 +QgsMapLayer.setLegendUrlFormat: src/core/qgsmaplayer.h#L1575 +QgsMapLayer.setMapTipTemplate: src/core/qgsmaplayer.h#L1843 +QgsMapLayer.setMapTipsEnabled: src/core/qgsmaplayer.h#L1851 +QgsMapLayer.setMaximumScale: src/core/qgsmaplayer.h#L1890 +QgsMapLayer.setMetadata: src/core/qgsmaplayer.h#L1718 QgsMapLayer.setMetadataUrl: src/core/qgsmaplayer.h#L450 QgsMapLayer.setMetadataUrlFormat: src/core/qgsmaplayer.h#L492 QgsMapLayer.setMetadataUrlType: src/core/qgsmaplayer.h#L471 -QgsMapLayer.setMinimumScale: src/core/qgsmaplayer.h#L1839 +QgsMapLayer.setMinimumScale: src/core/qgsmaplayer.h#L1879 QgsMapLayer.setName: src/core/qgsmaplayer.h#L291 QgsMapLayer.setOpacity: src/core/qgsmaplayer.h#L526 -QgsMapLayer.setOriginalXmlProperties: src/core/qgsmaplayer.h#L1725 -QgsMapLayer.setProviderType: src/core/qgsmaplayer.h#L2269 -QgsMapLayer.setRefreshOnNofifyMessage: src/core/qgsmaplayer.h#L1905 -QgsMapLayer.setRefreshOnNotifyEnabled: src/core/qgsmaplayer.h#L1897 -QgsMapLayer.setRenderer3D: src/core/qgsmaplayer.h#L1563 -QgsMapLayer.setScaleBasedVisibility: src/core/qgsmaplayer.h#L1859 +QgsMapLayer.setOriginalXmlProperties: src/core/qgsmaplayer.h#L1765 +QgsMapLayer.setProviderType: src/core/qgsmaplayer.h#L2309 +QgsMapLayer.setRefreshOnNofifyMessage: src/core/qgsmaplayer.h#L1945 +QgsMapLayer.setRefreshOnNotifyEnabled: src/core/qgsmaplayer.h#L1937 +QgsMapLayer.setRenderer3D: src/core/qgsmaplayer.h#L1603 +QgsMapLayer.setScaleBasedVisibility: src/core/qgsmaplayer.h#L1899 QgsMapLayer.setShortName: src/core/qgsmaplayer.h#L321 QgsMapLayer.setSubLayerVisibility: src/core/qgsmaplayer.h#L613 QgsMapLayer.setTitle: src/core/qgsmaplayer.h#L335 -QgsMapLayer.setTransformContext: src/core/qgsmaplayer.h#L1912 -QgsMapLayer.setValid: src/core/qgsmaplayer.h#L2199 -QgsMapLayer.setVerticalCrs: src/core/qgsmaplayer.h#L1067 +QgsMapLayer.setTransformContext: src/core/qgsmaplayer.h#L1952 +QgsMapLayer.setValid: src/core/qgsmaplayer.h#L2239 +QgsMapLayer.setVerticalCrs: src/core/qgsmaplayer.h#L1107 QgsMapLayer.shortName: src/core/qgsmaplayer.h#L328 QgsMapLayer.source: src/core/qgsmaplayer.h#L594 -QgsMapLayer.statusChanged: src/core/qgsmaplayer.h#L1941 -QgsMapLayer.styleChanged: src/core/qgsmaplayer.h#L2039 -QgsMapLayer.styleLoaded: src/core/qgsmaplayer.h#L2111 -QgsMapLayer.styleManager: src/core/qgsmaplayer.h#L1558 -QgsMapLayer.styleURI: src/core/qgsmaplayer.h#L1179 +QgsMapLayer.statusChanged: src/core/qgsmaplayer.h#L1981 +QgsMapLayer.styleChanged: src/core/qgsmaplayer.h#L2079 +QgsMapLayer.styleLoaded: src/core/qgsmaplayer.h#L2151 +QgsMapLayer.styleManager: src/core/qgsmaplayer.h#L1598 +QgsMapLayer.styleURI: src/core/qgsmaplayer.h#L1219 QgsMapLayer.subLayers: src/core/qgsmaplayer.h#L600 QgsMapLayer.supportsEditing: src/core/qgsmaplayer.h#L621 -QgsMapLayer.temporalProperties: src/core/qgsmaplayer.h#L1756 -QgsMapLayer.timestamp: src/core/qgsmaplayer.h#L1686 +QgsMapLayer.temporalProperties: src/core/qgsmaplayer.h#L1796 +QgsMapLayer.timestamp: src/core/qgsmaplayer.h#L1726 QgsMapLayer.title: src/core/qgsmaplayer.h#L342 -QgsMapLayer.transformContext: src/core/qgsmaplayer.h#L1074 -QgsMapLayer.trigger3DUpdate: src/core/qgsmaplayer.h#L1877 -QgsMapLayer.triggerRepaint: src/core/qgsmaplayer.h#L1869 +QgsMapLayer.transformContext: src/core/qgsmaplayer.h#L1114 +QgsMapLayer.trigger3DUpdate: src/core/qgsmaplayer.h#L1917 +QgsMapLayer.triggerRepaint: src/core/qgsmaplayer.h#L1909 QgsMapLayer.type: src/core/qgsmaplayer.h#L219 -QgsMapLayer.undoStack: src/core/qgsmaplayer.h#L1509 -QgsMapLayer.undoStackStyles: src/core/qgsmaplayer.h#L1514 -QgsMapLayer.verticalCrs: src/core/qgsmaplayer.h#L1014 -QgsMapLayer.verticalCrsChanged: src/core/qgsmaplayer.h#L1994 +QgsMapLayer.undoStack: src/core/qgsmaplayer.h#L1549 +QgsMapLayer.undoStackStyles: src/core/qgsmaplayer.h#L1554 +QgsMapLayer.verticalCrs: src/core/qgsmaplayer.h#L1054 +QgsMapLayer.verticalCrsChanged: src/core/qgsmaplayer.h#L2034 QgsMapLayer.wgs84Extent: src/core/qgsmaplayer.h#L568 -QgsMapLayer.willBeDeleted: src/core/qgsmaplayer.h#L2074 -QgsMapLayer.writeCommonStyle: src/core/qgsmaplayer.h#L2258 -QgsMapLayer.writeCustomProperties: src/core/qgsmaplayer.h#L2248 +QgsMapLayer.willBeDeleted: src/core/qgsmaplayer.h#L2114 +QgsMapLayer.writeCommonStyle: src/core/qgsmaplayer.h#L2298 +QgsMapLayer.writeCustomProperties: src/core/qgsmaplayer.h#L2288 QgsMapLayer.writeLayerXml: src/core/qgsmaplayer.h#L697 -QgsMapLayer.writeStyle: src/core/qgsmaplayer.h#L1405 -QgsMapLayer.writeStyleManager: src/core/qgsmaplayer.h#L2253 -QgsMapLayer.writeSymbology: src/core/qgsmaplayer.h#L1391 -QgsMapLayer.writeXml: src/core/qgsmaplayer.h#L2211 +QgsMapLayer.writeStyle: src/core/qgsmaplayer.h#L1445 +QgsMapLayer.writeStyleManager: src/core/qgsmaplayer.h#L2293 +QgsMapLayer.writeSymbology: src/core/qgsmaplayer.h#L1431 +QgsMapLayer.writeXml: src/core/qgsmaplayer.h#L2251 QgsMapLayer: src/core/qgsmaplayer.h#L76 QgsMapLayerDependency.__hash__: src/core/qgsmaplayerdependency.h#L78 QgsMapLayerDependency.layerId: src/core/qgsmaplayerdependency.h#L67 diff --git a/python/core/auto_additions/qgsmaplayer.py b/python/core/auto_additions/qgsmaplayer.py index 187fe62a6ebd..c763e18eb029 100644 --- a/python/core/auto_additions/qgsmaplayer.py +++ b/python/core/auto_additions/qgsmaplayer.py @@ -5,6 +5,25 @@ QgsMapLayer.StyleCategory.baseClass = QgsMapLayer QgsMapLayer.StyleCategories.baseClass = QgsMapLayer StyleCategories = QgsMapLayer # dirty hack since SIP seems to introduce the flags in module +# monkey patching scoped based enum +QgsMapLayer.SaveStyleResult.Success.__doc__ = "Both QML and SLD formats were successfully written to the database." +QgsMapLayer.SaveStyleResult.QmlGenerationFailed.__doc__ = "Generation of the QML failed, and was not written to the database." +QgsMapLayer.SaveStyleResult.SldGenerationFailed.__doc__ = "Generation of the SLD failed, and was not written to the database." +QgsMapLayer.SaveStyleResult.DatabaseWriteFailed.__doc__ = "An error occurred when attempting to write to the database." +QgsMapLayer.SaveStyleResult.__doc__ = """Results of saving styles to database. + +.. versionadded:: 4.0 + +* ``Success``: Both QML and SLD formats were successfully written to the database. +* ``QmlGenerationFailed``: Generation of the QML failed, and was not written to the database. +* ``SldGenerationFailed``: Generation of the SLD failed, and was not written to the database. +* ``DatabaseWriteFailed``: An error occurred when attempting to write to the database. + +""" +# -- +QgsMapLayer.SaveStyleResult.baseClass = QgsMapLayer +QgsMapLayer.SaveStyleResults.baseClass = QgsMapLayer +SaveStyleResults = QgsMapLayer # dirty hack since SIP seems to introduce the flags in module try: QgsMapLayer.__attribute_docs__ = {'beforeResolveReferences': 'Emitted when all layers are loaded and references can be resolved, just\nbefore the references of this layer are resolved.\n\n.. versionadded:: 3.10\n', 'statusChanged': 'Emit a signal with status (e.g. to be caught by QgisApp and display a\nmsg on status bar)\n', 'idChanged': "Emitted when the layer's ID has been changed.\n\n.. seealso:: :py:func:`id`\n\n.. seealso:: :py:func:`setId`\n\n.. versionadded:: 3.38\n", 'nameChanged': 'Emitted when the name has been changed\n', 'crsChanged': 'Emitted when the :py:func:`~QgsMapLayer.crs` of the layer has changed.\n\n.. seealso:: :py:func:`crs`\n\n.. seealso:: :py:func:`setCrs`\n\n.. seealso:: :py:func:`verticalCrsChanged`\n\n.. seealso:: :py:func:`crs3DChanged`\n', 'crs3DChanged': 'Emitted when the :py:func:`~QgsMapLayer.crs3D` of the layer has changed.\n\n.. seealso:: :py:func:`crs3D`\n\n.. seealso:: :py:func:`crsChanged`\n\n.. seealso:: :py:func:`verticalCrsChanged`\n\n.. versionadded:: 3.38\n', 'verticalCrsChanged': 'Emitted when the :py:func:`~QgsMapLayer.verticalCrs` of the layer has\nchanged.\n\nThis signal will be emitted whenever the vertical CRS of the layer is\nchanged, either as a direct result of a call to\n:py:func:`~QgsMapLayer.setVerticalCrs` or when\n:py:func:`~QgsMapLayer.setCrs` is called with a compound CRS.\n\n.. seealso:: :py:func:`crsChanged`\n\n.. seealso:: :py:func:`crs3DChanged`\n\n.. seealso:: :py:func:`setCrs`\n\n.. seealso:: :py:func:`setVerticalCrs`\n\n.. seealso:: :py:func:`verticalCrs`\n\n.. versionadded:: 3.38\n', 'repaintRequested': 'By emitting this signal the layer tells that either appearance or\ncontent have been changed and any view showing the rendered layer should\nrefresh itself. If ``deferredUpdate`` is ``True`` then the layer will\nonly be repainted when the canvas is next re-rendered, and will not\ntrigger any canvas redraws itself.\n', 'recalculateExtents': 'This is used to send a request that any mapcanvas using this layer\nupdate its extents\n', 'dataChanged': 'Data of layer changed\n', 'blendModeChanged': 'Signal emitted when the blend mode is changed, through\n:py:func:`QgsMapLayer.setBlendMode()`\n', 'opacityChanged': "Emitted when the layer's opacity is changed, where ``opacity`` is a\nvalue between 0 (transparent) and 1 (opaque).\n\n.. seealso:: :py:func:`setOpacity`\n\n.. seealso:: :py:func:`opacity`\n\n.. note::\n\n Prior to QGIS 3.18, this signal was available for vector layers only\n\n.. versionadded:: 3.18\n", 'rendererChanged': 'Signal emitted when renderer is changed.\n\n.. seealso:: :py:func:`styleChanged`\n', 'styleChanged': "Signal emitted whenever a change affects the layer's style. Ie this may\nbe triggered by renderer changes, label style changes, or other style\nchanges such as blend mode or layer opacity changes.\n\n.. warning::\n\n This signal should never be manually emitted. Instead call the :py:func:`~QgsMapLayer.emitStyleChanged` method\n to ensure that the signal is only emitted when appropriate.\n\n.. seealso:: :py:func:`rendererChanged`\n", 'legendChanged': 'Signal emitted when legend of the layer has changed\n', 'renderer3DChanged': 'Signal emitted when 3D renderer associated with the layer has changed.\n', 'request3DUpdate': 'Signal emitted when a layer requires an update in any 3D maps.\n\n.. versionadded:: 3.18\n', 'configChanged': 'Emitted whenever the configuration is changed. The project listens to\nthis signal to be marked as dirty.\n', 'dependenciesChanged': 'Emitted when dependencies are changed.\n', 'willBeDeleted': 'Emitted in the destructor when the layer is about to be deleted, but it\nis still in a perfectly valid state: the last chance for other pieces of\ncode for some cleanup if they use the layer.\n', 'autoRefreshIntervalChanged': 'Emitted when the auto refresh interval changes.\n\n.. seealso:: :py:func:`setAutoRefreshInterval`\n', 'metadataChanged': "Emitted when the layer's metadata is changed.\n\n.. seealso:: :py:func:`setMetadata`\n\n.. seealso:: :py:func:`metadata`\n", 'flagsChanged': "Emitted when layer's flags have been modified.\n\n.. seealso:: :py:func:`setFlags`\n\n.. seealso:: :py:func:`flags`\n\n.. versionadded:: 3.4\n", 'dataSourceChanged': "Emitted whenever the layer's data source has been changed.\n\n.. seealso:: :py:func:`setDataSource`\n\n.. versionadded:: 3.5\n", 'styleLoaded': 'Emitted when a style has been loaded\n\n:param categories: style categories\n\n.. versionadded:: 3.12\n', 'isValidChanged': 'Emitted when the validity of this layer changed.\n\n.. versionadded:: 3.16\n', 'customPropertyChanged': 'Emitted when a custom property of the layer has been changed or removed.\n\n.. versionadded:: 3.18\n', 'editingStarted': 'Emitted when editing on this layer has started.\n\n.. versionadded:: 3.22\n', 'editingStopped': 'Emitted when edited changes have been successfully written to the data\nprovider.\n\n.. versionadded:: 3.22\n', 'layerModified': 'Emitted when modifications has been done on layer\n\n.. versionadded:: 3.22\n', 'mapTipTemplateChanged': 'Emitted when the map tip template changes\n\n.. versionadded:: 3.30\n', 'mapTipsEnabledChanged': 'Emitted when map tips are enabled or disabled for the layer.\n\n.. seealso:: :py:func:`setMapTipsEnabled`\n\n.. versionadded:: 3.32\n'} QgsMapLayer.extensionPropertyType = staticmethod(QgsMapLayer.extensionPropertyType) diff --git a/python/core/auto_generated/geometry/qgsgeometry.sip.in b/python/core/auto_generated/geometry/qgsgeometry.sip.in index 1b08201e0db0..8e46bfa96b03 100644 --- a/python/core/auto_generated/geometry/qgsgeometry.sip.in +++ b/python/core/auto_generated/geometry/qgsgeometry.sip.in @@ -16,7 +16,9 @@ typedef QVector QgsPolylineXY; -typedef QgsPointSequence QgsPolyline; +typedef QVector QgsPolyline; + +typedef QVector> QgsMultiPolyline; typedef QVector> QgsPolygonXY; diff --git a/python/core/auto_generated/qgsmaplayer.sip.in b/python/core/auto_generated/qgsmaplayer.sip.in index e7030a60334a..8b9d21bd09cb 100644 --- a/python/core/auto_generated/qgsmaplayer.sip.in +++ b/python/core/auto_generated/qgsmaplayer.sip.in @@ -825,12 +825,24 @@ Deletes a style from the database - msgError: a descriptive error message if any occurs %End - virtual void saveStyleToDatabase( const QString &name, const QString &description, - bool useAsDefault, const QString &uiFileContent, - QString &msgError /Out/, - QgsMapLayer::StyleCategories categories = QgsMapLayer::AllStyleCategories ); + enum class SaveStyleResult + { + Success, + QmlGenerationFailed, + SldGenerationFailed, + DatabaseWriteFailed, + }; + + typedef QFlags SaveStyleResults; + + + virtual void saveStyleToDatabase( const QString &name, const QString &description, + bool useAsDefault, const QString &uiFileContent, + QString &msgError /Out/, + QgsMapLayer::StyleCategories categories = QgsMapLayer::AllStyleCategories ) /Deprecated="Since 4.0. Use saveStyleToDatabaseV2() instead."/; %Docstring -Saves named and sld style of the layer to the style table in the db. +Saves QML and SLD representations of the layer's style to a table in the +database. :param name: Style name :param description: A description of the style @@ -847,9 +859,33 @@ Saves named and sld style of the layer to the style table in the db. Use :py:func:`QgsProviderRegistry.styleExists()` to test in advance if a style already exists and handle this appropriately in your client code. -:return: a descriptive error message if any occurs +:return: - msgError: a descriptive error message if any occurs + +.. deprecated:: 4.0 + + Use :py:func:`~QgsMapLayer.saveStyleToDatabaseV2` instead. %End + QgsMapLayer::SaveStyleResults saveStyleToDatabaseV2( const QString &name, const QString &description, + bool useAsDefault, const QString &uiFileContent, + QString &msgError /Out/, + QgsMapLayer::StyleCategories categories = QgsMapLayer::AllStyleCategories ); +%Docstring +Saves QML and SLD representations of the layer's style to a table in the +database. + +:param name: Style name +:param description: A description of the style +:param useAsDefault: Set to ``True`` if style should be used as the + default style for the layer +:param uiFileContent: +:param categories: the style categories to be saved. + +:return: - flags representing whether QML or SLD storing was successful + - msgError: a descriptive error message if any occurs + +.. versionadded:: 4.0 +%End virtual QString loadNamedStyle( const QString &theURI, bool &resultFlag /Out/, bool loadFromLocalDb, diff --git a/python/core/auto_generated/qgsogcutils.sip.in b/python/core/auto_generated/qgsogcutils.sip.in index 0a8910957740..e3abb4812614 100644 --- a/python/core/auto_generated/qgsogcutils.sip.in +++ b/python/core/auto_generated/qgsogcutils.sip.in @@ -217,6 +217,8 @@ Creates an OGC expression XML element from the ``exp`` expression. }; + + /************************************************************************ * This file has been generated automatically from * * * diff --git a/python/core/class_map.yaml b/python/core/class_map.yaml index 26cdcc6f8f57..c0a433093bb1 100644 --- a/python/core/class_map.yaml +++ b/python/core/class_map.yaml @@ -4938,205 +4938,205 @@ QgsGeographicCoordinateNumericFormat.sortKey: src/core/numericformats/qgscoordin QgsGeographicCoordinateNumericFormat.suggestSampleValue: src/core/numericformats/qgscoordinatenumericformat.h#L53 QgsGeographicCoordinateNumericFormat.visibleName: src/core/numericformats/qgscoordinatenumericformat.h#L51 QgsGeographicCoordinateNumericFormat: src/core/numericformats/qgscoordinatenumericformat.h#L28 -QgsGeometry.Error.Error: src/core/geometry/qgsgeometry.h#L2760 -QgsGeometry.Error.__repr__: src/core/geometry/qgsgeometry.h#L2783 -QgsGeometry.Error.hasWhere: src/core/geometry/qgsgeometry.h#L2780 -QgsGeometry.Error.what: src/core/geometry/qgsgeometry.h#L2770 -QgsGeometry.Error.where: src/core/geometry/qgsgeometry.h#L2775 -QgsGeometry.Error: src/core/geometry/qgsgeometry.h#L2751 -QgsGeometry.QVariant: src/core/geometry/qgsgeometry.h#L3180 -QgsGeometry.QgsGeometry: src/core/geometry/qgsgeometry.h#L184 -QgsGeometry.__repr__: src/core/geometry/qgsgeometry.h#L2185 -QgsGeometry.addPart: src/core/geometry/qgsgeometry.h#L930 -QgsGeometry.addPart: src/core/geometry/qgsgeometry.h#L948 -QgsGeometry.addPart: src/core/geometry/qgsgeometry.h#L966 -QgsGeometry.addPart: src/core/geometry/qgsgeometry.h#L982 -QgsGeometry.addPartV2: src/core/geometry/qgsgeometry.h#L939 -QgsGeometry.addPartV2: src/core/geometry/qgsgeometry.h#L957 -QgsGeometry.addPartV2: src/core/geometry/qgsgeometry.h#L975 -QgsGeometry.addRing: src/core/geometry/qgsgeometry.h#L914 -QgsGeometry.addRing: src/core/geometry/qgsgeometry.h#L921 -QgsGeometry.addTopologicalPoint: src/core/geometry/qgsgeometry.h#L815 -QgsGeometry.adjacentVertices: src/core/geometry/qgsgeometry.h#L778 -QgsGeometry.angleAtVertex: src/core/geometry/qgsgeometry.h#L764 -QgsGeometry.applyDashPattern: src/core/geometry/qgsgeometry.h#L1372 -QgsGeometry.area: src/core/geometry/qgsgeometry.h#L476 -QgsGeometry.asJson: src/core/geometry/qgsgeometry.h#L2204 -QgsGeometry.asMultiPoint: src/core/geometry/qgsgeometry.h#L2418 -QgsGeometry.asMultiPolygon: src/core/geometry/qgsgeometry.h#L2508 -QgsGeometry.asMultiPolyline: src/core/geometry/qgsgeometry.h#L2463 -QgsGeometry.asPoint: src/core/geometry/qgsgeometry.h#L2283 -QgsGeometry.asPolygon: src/core/geometry/qgsgeometry.h#L2375 -QgsGeometry.asPolyline: src/core/geometry/qgsgeometry.h#L2330 -QgsGeometry.asQPointF: src/core/geometry/qgsgeometry.h#L2538 -QgsGeometry.asQPolygonF: src/core/geometry/qgsgeometry.h#L2551 -QgsGeometry.asWkb: src/core/geometry/qgsgeometry.h#L2175 -QgsGeometry.asWkt: src/core/geometry/qgsgeometry.h#L2182 -QgsGeometry.avoidIntersections: src/core/geometry/qgsgeometry.h#L2626 -QgsGeometry.avoidIntersections: src/core/geometry/qgsgeometry.h#L2627 -QgsGeometry.avoidIntersectionsV2: src/core/geometry/qgsgeometry.h#L2640 -QgsGeometry.avoidIntersectionsV2: src/core/geometry/qgsgeometry.h#L2641 -QgsGeometry.boundingBox3D: src/core/geometry/qgsgeometry.h#L1206 -QgsGeometry.boundingBox: src/core/geometry/qgsgeometry.h#L1199 -QgsGeometry.boundingBoxIntersects: src/core/geometry/qgsgeometry.h#L1447 -QgsGeometry.boundingBoxIntersects: src/core/geometry/qgsgeometry.h#L1457 -QgsGeometry.buffer: src/core/geometry/qgsgeometry.h#L1544 -QgsGeometry.buffer: src/core/geometry/qgsgeometry.h#L1557 -QgsGeometry.centroid: src/core/geometry/qgsgeometry.h#L1686 -QgsGeometry.clipped: src/core/geometry/qgsgeometry.h#L2022 -QgsGeometry.closestSegmentWithContext: src/core/geometry/qgsgeometry.h#L907 -QgsGeometry.closestVertex: src/core/geometry/qgsgeometry.h#L747 -QgsGeometry.closestVertexWithContext: src/core/geometry/qgsgeometry.h#L894 -QgsGeometry.collectGeometry: src/core/geometry/qgsgeometry.h#L330 -QgsGeometry.combine: src/core/geometry/qgsgeometry.h#L2038 -QgsGeometry.compare: src/core/geometry/qgsgeometry.h#L3013 -QgsGeometry.concaveHull: src/core/geometry/qgsgeometry.h#L1816 -QgsGeometry.constGet: src/core/geometry/qgsgeometry.h#L205 -QgsGeometry.constParts: src/core/geometry/qgsgeometry.h#L656 -QgsGeometry.constrainedDelaunayTriangulation: src/core/geometry/qgsgeometry.h#L1858 -QgsGeometry.contains: src/core/geometry/qgsgeometry.h#L1462 -QgsGeometry.contains: src/core/geometry/qgsgeometry.h#L1469 -QgsGeometry.contains: src/core/geometry/qgsgeometry.h#L1480 -QgsGeometry.convertGeometryCollectionToSubclass: src/core/geometry/qgsgeometry.h#L2613 -QgsGeometry.convertPointList: src/core/geometry/qgsgeometry.h#L3167 -QgsGeometry.convertPointList: src/core/geometry/qgsgeometry.h#L3174 -QgsGeometry.convertToCurvedMultiType: src/core/geometry/qgsgeometry.h#L2591 -QgsGeometry.convertToCurves: src/core/geometry/qgsgeometry.h#L1671 -QgsGeometry.convertToMultiType: src/core/geometry/qgsgeometry.h#L2574 -QgsGeometry.convertToSingleType: src/core/geometry/qgsgeometry.h#L2602 -QgsGeometry.convertToStraightSegment: src/core/geometry/qgsgeometry.h#L2847 -QgsGeometry.convertToType: src/core/geometry/qgsgeometry.h#L2256 -QgsGeometry.convexHull: src/core/geometry/qgsgeometry.h#L1801 -QgsGeometry.createGeometryEngine: src/core/geometry/qgsgeometry.h#L3160 -QgsGeometry.createPolygonFromQPolygonF: src/core/geometry/qgsgeometry.h#L2956 -QgsGeometry.createPolylineFromQPolygonF: src/core/geometry/qgsgeometry.h#L2947 -QgsGeometry.createWedgeBuffer: src/core/geometry/qgsgeometry.h#L347 -QgsGeometry.createWedgeBufferFromAngles: src/core/geometry/qgsgeometry.h#L363 -QgsGeometry.crosses: src/core/geometry/qgsgeometry.h#L1535 -QgsGeometry.delaunayTriangulation: src/core/geometry/qgsgeometry.h#L1844 -QgsGeometry.deletePart: src/core/geometry/qgsgeometry.h#L2564 -QgsGeometry.deleteRing: src/core/geometry/qgsgeometry.h#L2558 -QgsGeometry.deleteVertex: src/core/geometry/qgsgeometry.h#L846 -QgsGeometry.densifyByCount: src/core/geometry/qgsgeometry.h#L1639 -QgsGeometry.densifyByDistance: src/core/geometry/qgsgeometry.h#L1654 -QgsGeometry.difference: src/core/geometry/qgsgeometry.h#L2063 -QgsGeometry.disjoint: src/core/geometry/qgsgeometry.h#L1491 -QgsGeometry.distance: src/core/geometry/qgsgeometry.h#L500 -QgsGeometry.distanceToVertex: src/core/geometry/qgsgeometry.h#L756 -QgsGeometry.draw: src/core/geometry/qgsgeometry.h#L2866 -QgsGeometry.equals: src/core/geometry/qgsgeometry.h#L414 -QgsGeometry.extendLine: src/core/geometry/qgsgeometry.h#L1626 -QgsGeometry.extrude: src/core/geometry/qgsgeometry.h#L2079 -QgsGeometry.forcePolygonClockwise: src/core/geometry/qgsgeometry.h#L2733 -QgsGeometry.forcePolygonCounterClockwise: src/core/geometry/qgsgeometry.h#L2745 -QgsGeometry.forceRHR: src/core/geometry/qgsgeometry.h#L2721 -QgsGeometry.frechetDistance: src/core/geometry/qgsgeometry.h#L709 -QgsGeometry.frechetDistanceDensify: src/core/geometry/qgsgeometry.h#L733 -QgsGeometry.fromBox3D: src/core/geometry/qgsgeometry.h#L326 -QgsGeometry.fromMultiPointXY: src/core/geometry/qgsgeometry.h#L255 -QgsGeometry.fromMultiPolygonXY: src/core/geometry/qgsgeometry.h#L314 -QgsGeometry.fromMultiPolylineXY: src/core/geometry/qgsgeometry.h#L282 -QgsGeometry.fromPoint: src/core/geometry/qgsgeometry.h#L252 -QgsGeometry.fromPointXY: src/core/geometry/qgsgeometry.h#L245 -QgsGeometry.fromPolygonXY: src/core/geometry/qgsgeometry.h#L309 -QgsGeometry.fromPolyline: src/core/geometry/qgsgeometry.h#L277 -QgsGeometry.fromPolylineXY: src/core/geometry/qgsgeometry.h#L267 -QgsGeometry.fromQPointF: src/core/geometry/qgsgeometry.h#L2930 -QgsGeometry.fromQPolygonF: src/core/geometry/qgsgeometry.h#L2938 -QgsGeometry.fromRect: src/core/geometry/qgsgeometry.h#L317 -QgsGeometry.fromWkb: src/core/geometry/qgsgeometry.h#L376 -QgsGeometry.fromWkt: src/core/geometry/qgsgeometry.h#L243 -QgsGeometry.get: src/core/geometry/qgsgeometry.h#L218 -QgsGeometry.hausdorffDistance: src/core/geometry/qgsgeometry.h#L674 -QgsGeometry.hausdorffDistanceDensify: src/core/geometry/qgsgeometry.h#L693 -QgsGeometry.insertVertex: src/core/geometry/qgsgeometry.h#L792 -QgsGeometry.insertVertex: src/core/geometry/qgsgeometry.h#L806 -QgsGeometry.interpolate: src/core/geometry/qgsgeometry.h#L1979 -QgsGeometry.interpolateAngle: src/core/geometry/qgsgeometry.h#L2001 -QgsGeometry.intersection: src/core/geometry/qgsgeometry.h#L2014 -QgsGeometry.intersects: src/core/geometry/qgsgeometry.h#L1421 -QgsGeometry.intersects: src/core/geometry/qgsgeometry.h#L1437 -QgsGeometry.isAxisParallelRectangle: src/core/geometry/qgsgeometry.h#L463 -QgsGeometry.isEmpty: src/core/geometry/qgsgeometry.h#L396 -QgsGeometry.isGeosEqual: src/core/geometry/qgsgeometry.h#L431 -QgsGeometry.isGeosValid: src/core/geometry/qgsgeometry.h#L439 -QgsGeometry.isMultipart: src/core/geometry/qgsgeometry.h#L399 -QgsGeometry.isNull: src/core/geometry/qgsgeometry.h#L240 -QgsGeometry.isPolygonClockwise: src/core/geometry/qgsgeometry.h#L2704 -QgsGeometry.isPolygonCounterClockwise: src/core/geometry/qgsgeometry.h#L2689 -QgsGeometry.isSimple: src/core/geometry/qgsgeometry.h#L448 -QgsGeometry.largestEmptyCircle: src/core/geometry/qgsgeometry.h#L1739 -QgsGeometry.lastError: src/core/geometry/qgsgeometry.h#L2897 -QgsGeometry.length: src/core/geometry/qgsgeometry.h#L491 -QgsGeometry.lineLocatePoint: src/core/geometry/qgsgeometry.h#L1991 -QgsGeometry.makeDifference: src/core/geometry/qgsgeometry.h#L1193 -QgsGeometry.makeValid: src/core/geometry/qgsgeometry.h#L2663 -QgsGeometry.mapToPixel: src/core/geometry/qgsgeometry.h#L2860 -QgsGeometry.mergeLines: src/core/geometry/qgsgeometry.h#L2050 -QgsGeometry.minimalEnclosingCircle: src/core/geometry/qgsgeometry.h#L1240 -QgsGeometry.minimumClearance: src/core/geometry/qgsgeometry.h#L1778 -QgsGeometry.minimumClearanceLine: src/core/geometry/qgsgeometry.h#L1791 -QgsGeometry.minimumWidth: src/core/geometry/qgsgeometry.h#L1755 -QgsGeometry.moveVertex: src/core/geometry/qgsgeometry.h#L824 -QgsGeometry.moveVertex: src/core/geometry/qgsgeometry.h#L833 -QgsGeometry.nearestPoint: src/core/geometry/qgsgeometry.h#L875 -QgsGeometry.node: src/core/geometry/qgsgeometry.h#L1924 -QgsGeometry.normalize: src/core/geometry/qgsgeometry.h#L2820 -QgsGeometry.offsetCurve: src/core/geometry/qgsgeometry.h#L1566 -QgsGeometry.orientedMinimumBoundingBox: src/core/geometry/qgsgeometry.h#L1220 -QgsGeometry.orthogonalize: src/core/geometry/qgsgeometry.h#L1255 -QgsGeometry.overlaps: src/core/geometry/qgsgeometry.h#L1513 -QgsGeometry.parts: src/core/geometry/qgsgeometry.h#L622 -QgsGeometry.pointOnSurface: src/core/geometry/qgsgeometry.h#L1701 -QgsGeometry.poleOfInaccessibility: src/core/geometry/qgsgeometry.h#L1714 -QgsGeometry.polygonOrientation: src/core/geometry/qgsgeometry.h#L2674 -QgsGeometry.polygonize: src/core/geometry/qgsgeometry.h#L2839 -QgsGeometry.randomPointsInPolygon: src/core/geometry/qgsgeometry.h#L2136 -QgsGeometry.removeDuplicateNodes: src/core/geometry/qgsgeometry.h#L1410 -QgsGeometry.removeInteriorRings: src/core/geometry/qgsgeometry.h#L989 -QgsGeometry.requiresConversionToStraightSegments: src/core/geometry/qgsgeometry.h#L2854 -QgsGeometry.reshapeGeometry: src/core/geometry/qgsgeometry.h#L1178 -QgsGeometry.rotate: src/core/geometry/qgsgeometry.h#L1029 -QgsGeometry.roundWaves: src/core/geometry/qgsgeometry.h#L1337 -QgsGeometry.roundWavesRandomized: src/core/geometry/qgsgeometry.h#L1357 -QgsGeometry.set: src/core/geometry/qgsgeometry.h#L231 -QgsGeometry.sharedPaths: src/core/geometry/qgsgeometry.h#L1940 -QgsGeometry.shortestLine: src/core/geometry/qgsgeometry.h#L886 -QgsGeometry.simplify: src/core/geometry/qgsgeometry.h#L1629 -QgsGeometry.simplifyCoverageVW: src/core/geometry/qgsgeometry.h#L1899 -QgsGeometry.singleSidedBuffer: src/core/geometry/qgsgeometry.h#L1582 -QgsGeometry.smooth: src/core/geometry/qgsgeometry.h#L3118 -QgsGeometry.snappedToGrid: src/core/geometry/qgsgeometry.h#L1389 -QgsGeometry.splitGeometry: src/core/geometry/qgsgeometry.h#L1092 -QgsGeometry.splitGeometry: src/core/geometry/qgsgeometry.h#L1172 -QgsGeometry.sqrDistToVertexAt: src/core/geometry/qgsgeometry.h#L869 -QgsGeometry.squareWaves: src/core/geometry/qgsgeometry.h#L1303 -QgsGeometry.squareWavesRandomized: src/core/geometry/qgsgeometry.h#L1323 -QgsGeometry.subdivide: src/core/geometry/qgsgeometry.h#L1963 -QgsGeometry.symDifference: src/core/geometry/qgsgeometry.h#L2076 -QgsGeometry.taperedBuffer: src/core/geometry/qgsgeometry.h#L1603 -QgsGeometry.toggleCircularAtVertex: src/core/geometry/qgsgeometry.h#L855 -QgsGeometry.touches: src/core/geometry/qgsgeometry.h#L1502 -QgsGeometry.transform: src/core/geometry/qgsgeometry.h#L1011 -QgsGeometry.transform: src/core/geometry/qgsgeometry.h#L1021 -QgsGeometry.translate: src/core/geometry/qgsgeometry.h#L995 -QgsGeometry.triangularWaves: src/core/geometry/qgsgeometry.h#L1269 -QgsGeometry.triangularWavesRandomized: src/core/geometry/qgsgeometry.h#L1289 -QgsGeometry.type: src/core/geometry/qgsgeometry.h#L388 -QgsGeometry.unaryUnion: src/core/geometry/qgsgeometry.h#L2830 -QgsGeometry.unionCoverage: src/core/geometry/qgsgeometry.h#L1912 -QgsGeometry.validateCoverage: src/core/geometry/qgsgeometry.h#L1877 -QgsGeometry.validateGeometry: src/core/geometry/qgsgeometry.h#L2809 -QgsGeometry.variableWidthBufferByM: src/core/geometry/qgsgeometry.h#L1619 -QgsGeometry.vertexAt: src/core/geometry/qgsgeometry.h#L862 -QgsGeometry.vertexIdFromVertexNr: src/core/geometry/qgsgeometry.h#L2877 -QgsGeometry.vertexNrFromVertexId: src/core/geometry/qgsgeometry.h#L2889 -QgsGeometry.vertices: src/core/geometry/qgsgeometry.h#L540 -QgsGeometry.voronoiDiagram: src/core/geometry/qgsgeometry.h#L1832 -QgsGeometry.within: src/core/geometry/qgsgeometry.h#L1524 -QgsGeometry.wkbSize: src/core/geometry/qgsgeometry.h#L2167 -QgsGeometry.wkbType: src/core/geometry/qgsgeometry.h#L382 -QgsGeometry: src/core/geometry/qgsgeometry.h#L161 +QgsGeometry.Error.Error: src/core/geometry/qgsgeometry.h#L2777 +QgsGeometry.Error.__repr__: src/core/geometry/qgsgeometry.h#L2800 +QgsGeometry.Error.hasWhere: src/core/geometry/qgsgeometry.h#L2797 +QgsGeometry.Error.what: src/core/geometry/qgsgeometry.h#L2787 +QgsGeometry.Error.where: src/core/geometry/qgsgeometry.h#L2792 +QgsGeometry.Error: src/core/geometry/qgsgeometry.h#L2768 +QgsGeometry.QVariant: src/core/geometry/qgsgeometry.h#L3197 +QgsGeometry.QgsGeometry: src/core/geometry/qgsgeometry.h#L201 +QgsGeometry.__repr__: src/core/geometry/qgsgeometry.h#L2202 +QgsGeometry.addPart: src/core/geometry/qgsgeometry.h#L947 +QgsGeometry.addPart: src/core/geometry/qgsgeometry.h#L965 +QgsGeometry.addPart: src/core/geometry/qgsgeometry.h#L983 +QgsGeometry.addPart: src/core/geometry/qgsgeometry.h#L999 +QgsGeometry.addPartV2: src/core/geometry/qgsgeometry.h#L956 +QgsGeometry.addPartV2: src/core/geometry/qgsgeometry.h#L974 +QgsGeometry.addPartV2: src/core/geometry/qgsgeometry.h#L992 +QgsGeometry.addRing: src/core/geometry/qgsgeometry.h#L931 +QgsGeometry.addRing: src/core/geometry/qgsgeometry.h#L938 +QgsGeometry.addTopologicalPoint: src/core/geometry/qgsgeometry.h#L832 +QgsGeometry.adjacentVertices: src/core/geometry/qgsgeometry.h#L795 +QgsGeometry.angleAtVertex: src/core/geometry/qgsgeometry.h#L781 +QgsGeometry.applyDashPattern: src/core/geometry/qgsgeometry.h#L1389 +QgsGeometry.area: src/core/geometry/qgsgeometry.h#L493 +QgsGeometry.asJson: src/core/geometry/qgsgeometry.h#L2221 +QgsGeometry.asMultiPoint: src/core/geometry/qgsgeometry.h#L2435 +QgsGeometry.asMultiPolygon: src/core/geometry/qgsgeometry.h#L2525 +QgsGeometry.asMultiPolyline: src/core/geometry/qgsgeometry.h#L2480 +QgsGeometry.asPoint: src/core/geometry/qgsgeometry.h#L2300 +QgsGeometry.asPolygon: src/core/geometry/qgsgeometry.h#L2392 +QgsGeometry.asPolyline: src/core/geometry/qgsgeometry.h#L2347 +QgsGeometry.asQPointF: src/core/geometry/qgsgeometry.h#L2555 +QgsGeometry.asQPolygonF: src/core/geometry/qgsgeometry.h#L2568 +QgsGeometry.asWkb: src/core/geometry/qgsgeometry.h#L2192 +QgsGeometry.asWkt: src/core/geometry/qgsgeometry.h#L2199 +QgsGeometry.avoidIntersections: src/core/geometry/qgsgeometry.h#L2643 +QgsGeometry.avoidIntersections: src/core/geometry/qgsgeometry.h#L2644 +QgsGeometry.avoidIntersectionsV2: src/core/geometry/qgsgeometry.h#L2657 +QgsGeometry.avoidIntersectionsV2: src/core/geometry/qgsgeometry.h#L2658 +QgsGeometry.boundingBox3D: src/core/geometry/qgsgeometry.h#L1223 +QgsGeometry.boundingBox: src/core/geometry/qgsgeometry.h#L1216 +QgsGeometry.boundingBoxIntersects: src/core/geometry/qgsgeometry.h#L1464 +QgsGeometry.boundingBoxIntersects: src/core/geometry/qgsgeometry.h#L1474 +QgsGeometry.buffer: src/core/geometry/qgsgeometry.h#L1561 +QgsGeometry.buffer: src/core/geometry/qgsgeometry.h#L1574 +QgsGeometry.centroid: src/core/geometry/qgsgeometry.h#L1703 +QgsGeometry.clipped: src/core/geometry/qgsgeometry.h#L2039 +QgsGeometry.closestSegmentWithContext: src/core/geometry/qgsgeometry.h#L924 +QgsGeometry.closestVertex: src/core/geometry/qgsgeometry.h#L764 +QgsGeometry.closestVertexWithContext: src/core/geometry/qgsgeometry.h#L911 +QgsGeometry.collectGeometry: src/core/geometry/qgsgeometry.h#L347 +QgsGeometry.combine: src/core/geometry/qgsgeometry.h#L2055 +QgsGeometry.compare: src/core/geometry/qgsgeometry.h#L3030 +QgsGeometry.concaveHull: src/core/geometry/qgsgeometry.h#L1833 +QgsGeometry.constGet: src/core/geometry/qgsgeometry.h#L222 +QgsGeometry.constParts: src/core/geometry/qgsgeometry.h#L673 +QgsGeometry.constrainedDelaunayTriangulation: src/core/geometry/qgsgeometry.h#L1875 +QgsGeometry.contains: src/core/geometry/qgsgeometry.h#L1479 +QgsGeometry.contains: src/core/geometry/qgsgeometry.h#L1486 +QgsGeometry.contains: src/core/geometry/qgsgeometry.h#L1497 +QgsGeometry.convertGeometryCollectionToSubclass: src/core/geometry/qgsgeometry.h#L2630 +QgsGeometry.convertPointList: src/core/geometry/qgsgeometry.h#L3184 +QgsGeometry.convertPointList: src/core/geometry/qgsgeometry.h#L3191 +QgsGeometry.convertToCurvedMultiType: src/core/geometry/qgsgeometry.h#L2608 +QgsGeometry.convertToCurves: src/core/geometry/qgsgeometry.h#L1688 +QgsGeometry.convertToMultiType: src/core/geometry/qgsgeometry.h#L2591 +QgsGeometry.convertToSingleType: src/core/geometry/qgsgeometry.h#L2619 +QgsGeometry.convertToStraightSegment: src/core/geometry/qgsgeometry.h#L2864 +QgsGeometry.convertToType: src/core/geometry/qgsgeometry.h#L2273 +QgsGeometry.convexHull: src/core/geometry/qgsgeometry.h#L1818 +QgsGeometry.createGeometryEngine: src/core/geometry/qgsgeometry.h#L3177 +QgsGeometry.createPolygonFromQPolygonF: src/core/geometry/qgsgeometry.h#L2973 +QgsGeometry.createPolylineFromQPolygonF: src/core/geometry/qgsgeometry.h#L2964 +QgsGeometry.createWedgeBuffer: src/core/geometry/qgsgeometry.h#L364 +QgsGeometry.createWedgeBufferFromAngles: src/core/geometry/qgsgeometry.h#L380 +QgsGeometry.crosses: src/core/geometry/qgsgeometry.h#L1552 +QgsGeometry.delaunayTriangulation: src/core/geometry/qgsgeometry.h#L1861 +QgsGeometry.deletePart: src/core/geometry/qgsgeometry.h#L2581 +QgsGeometry.deleteRing: src/core/geometry/qgsgeometry.h#L2575 +QgsGeometry.deleteVertex: src/core/geometry/qgsgeometry.h#L863 +QgsGeometry.densifyByCount: src/core/geometry/qgsgeometry.h#L1656 +QgsGeometry.densifyByDistance: src/core/geometry/qgsgeometry.h#L1671 +QgsGeometry.difference: src/core/geometry/qgsgeometry.h#L2080 +QgsGeometry.disjoint: src/core/geometry/qgsgeometry.h#L1508 +QgsGeometry.distance: src/core/geometry/qgsgeometry.h#L517 +QgsGeometry.distanceToVertex: src/core/geometry/qgsgeometry.h#L773 +QgsGeometry.draw: src/core/geometry/qgsgeometry.h#L2883 +QgsGeometry.equals: src/core/geometry/qgsgeometry.h#L431 +QgsGeometry.extendLine: src/core/geometry/qgsgeometry.h#L1643 +QgsGeometry.extrude: src/core/geometry/qgsgeometry.h#L2096 +QgsGeometry.forcePolygonClockwise: src/core/geometry/qgsgeometry.h#L2750 +QgsGeometry.forcePolygonCounterClockwise: src/core/geometry/qgsgeometry.h#L2762 +QgsGeometry.forceRHR: src/core/geometry/qgsgeometry.h#L2738 +QgsGeometry.frechetDistance: src/core/geometry/qgsgeometry.h#L726 +QgsGeometry.frechetDistanceDensify: src/core/geometry/qgsgeometry.h#L750 +QgsGeometry.fromBox3D: src/core/geometry/qgsgeometry.h#L343 +QgsGeometry.fromMultiPointXY: src/core/geometry/qgsgeometry.h#L272 +QgsGeometry.fromMultiPolygonXY: src/core/geometry/qgsgeometry.h#L331 +QgsGeometry.fromMultiPolylineXY: src/core/geometry/qgsgeometry.h#L299 +QgsGeometry.fromPoint: src/core/geometry/qgsgeometry.h#L269 +QgsGeometry.fromPointXY: src/core/geometry/qgsgeometry.h#L262 +QgsGeometry.fromPolygonXY: src/core/geometry/qgsgeometry.h#L326 +QgsGeometry.fromPolyline: src/core/geometry/qgsgeometry.h#L294 +QgsGeometry.fromPolylineXY: src/core/geometry/qgsgeometry.h#L284 +QgsGeometry.fromQPointF: src/core/geometry/qgsgeometry.h#L2947 +QgsGeometry.fromQPolygonF: src/core/geometry/qgsgeometry.h#L2955 +QgsGeometry.fromRect: src/core/geometry/qgsgeometry.h#L334 +QgsGeometry.fromWkb: src/core/geometry/qgsgeometry.h#L393 +QgsGeometry.fromWkt: src/core/geometry/qgsgeometry.h#L260 +QgsGeometry.get: src/core/geometry/qgsgeometry.h#L235 +QgsGeometry.hausdorffDistance: src/core/geometry/qgsgeometry.h#L691 +QgsGeometry.hausdorffDistanceDensify: src/core/geometry/qgsgeometry.h#L710 +QgsGeometry.insertVertex: src/core/geometry/qgsgeometry.h#L809 +QgsGeometry.insertVertex: src/core/geometry/qgsgeometry.h#L823 +QgsGeometry.interpolate: src/core/geometry/qgsgeometry.h#L1996 +QgsGeometry.interpolateAngle: src/core/geometry/qgsgeometry.h#L2018 +QgsGeometry.intersection: src/core/geometry/qgsgeometry.h#L2031 +QgsGeometry.intersects: src/core/geometry/qgsgeometry.h#L1438 +QgsGeometry.intersects: src/core/geometry/qgsgeometry.h#L1454 +QgsGeometry.isAxisParallelRectangle: src/core/geometry/qgsgeometry.h#L480 +QgsGeometry.isEmpty: src/core/geometry/qgsgeometry.h#L413 +QgsGeometry.isGeosEqual: src/core/geometry/qgsgeometry.h#L448 +QgsGeometry.isGeosValid: src/core/geometry/qgsgeometry.h#L456 +QgsGeometry.isMultipart: src/core/geometry/qgsgeometry.h#L416 +QgsGeometry.isNull: src/core/geometry/qgsgeometry.h#L257 +QgsGeometry.isPolygonClockwise: src/core/geometry/qgsgeometry.h#L2721 +QgsGeometry.isPolygonCounterClockwise: src/core/geometry/qgsgeometry.h#L2706 +QgsGeometry.isSimple: src/core/geometry/qgsgeometry.h#L465 +QgsGeometry.largestEmptyCircle: src/core/geometry/qgsgeometry.h#L1756 +QgsGeometry.lastError: src/core/geometry/qgsgeometry.h#L2914 +QgsGeometry.length: src/core/geometry/qgsgeometry.h#L508 +QgsGeometry.lineLocatePoint: src/core/geometry/qgsgeometry.h#L2008 +QgsGeometry.makeDifference: src/core/geometry/qgsgeometry.h#L1210 +QgsGeometry.makeValid: src/core/geometry/qgsgeometry.h#L2680 +QgsGeometry.mapToPixel: src/core/geometry/qgsgeometry.h#L2877 +QgsGeometry.mergeLines: src/core/geometry/qgsgeometry.h#L2067 +QgsGeometry.minimalEnclosingCircle: src/core/geometry/qgsgeometry.h#L1257 +QgsGeometry.minimumClearance: src/core/geometry/qgsgeometry.h#L1795 +QgsGeometry.minimumClearanceLine: src/core/geometry/qgsgeometry.h#L1808 +QgsGeometry.minimumWidth: src/core/geometry/qgsgeometry.h#L1772 +QgsGeometry.moveVertex: src/core/geometry/qgsgeometry.h#L841 +QgsGeometry.moveVertex: src/core/geometry/qgsgeometry.h#L850 +QgsGeometry.nearestPoint: src/core/geometry/qgsgeometry.h#L892 +QgsGeometry.node: src/core/geometry/qgsgeometry.h#L1941 +QgsGeometry.normalize: src/core/geometry/qgsgeometry.h#L2837 +QgsGeometry.offsetCurve: src/core/geometry/qgsgeometry.h#L1583 +QgsGeometry.orientedMinimumBoundingBox: src/core/geometry/qgsgeometry.h#L1237 +QgsGeometry.orthogonalize: src/core/geometry/qgsgeometry.h#L1272 +QgsGeometry.overlaps: src/core/geometry/qgsgeometry.h#L1530 +QgsGeometry.parts: src/core/geometry/qgsgeometry.h#L639 +QgsGeometry.pointOnSurface: src/core/geometry/qgsgeometry.h#L1718 +QgsGeometry.poleOfInaccessibility: src/core/geometry/qgsgeometry.h#L1731 +QgsGeometry.polygonOrientation: src/core/geometry/qgsgeometry.h#L2691 +QgsGeometry.polygonize: src/core/geometry/qgsgeometry.h#L2856 +QgsGeometry.randomPointsInPolygon: src/core/geometry/qgsgeometry.h#L2153 +QgsGeometry.removeDuplicateNodes: src/core/geometry/qgsgeometry.h#L1427 +QgsGeometry.removeInteriorRings: src/core/geometry/qgsgeometry.h#L1006 +QgsGeometry.requiresConversionToStraightSegments: src/core/geometry/qgsgeometry.h#L2871 +QgsGeometry.reshapeGeometry: src/core/geometry/qgsgeometry.h#L1195 +QgsGeometry.rotate: src/core/geometry/qgsgeometry.h#L1046 +QgsGeometry.roundWaves: src/core/geometry/qgsgeometry.h#L1354 +QgsGeometry.roundWavesRandomized: src/core/geometry/qgsgeometry.h#L1374 +QgsGeometry.set: src/core/geometry/qgsgeometry.h#L248 +QgsGeometry.sharedPaths: src/core/geometry/qgsgeometry.h#L1957 +QgsGeometry.shortestLine: src/core/geometry/qgsgeometry.h#L903 +QgsGeometry.simplify: src/core/geometry/qgsgeometry.h#L1646 +QgsGeometry.simplifyCoverageVW: src/core/geometry/qgsgeometry.h#L1916 +QgsGeometry.singleSidedBuffer: src/core/geometry/qgsgeometry.h#L1599 +QgsGeometry.smooth: src/core/geometry/qgsgeometry.h#L3135 +QgsGeometry.snappedToGrid: src/core/geometry/qgsgeometry.h#L1406 +QgsGeometry.splitGeometry: src/core/geometry/qgsgeometry.h#L1109 +QgsGeometry.splitGeometry: src/core/geometry/qgsgeometry.h#L1189 +QgsGeometry.sqrDistToVertexAt: src/core/geometry/qgsgeometry.h#L886 +QgsGeometry.squareWaves: src/core/geometry/qgsgeometry.h#L1320 +QgsGeometry.squareWavesRandomized: src/core/geometry/qgsgeometry.h#L1340 +QgsGeometry.subdivide: src/core/geometry/qgsgeometry.h#L1980 +QgsGeometry.symDifference: src/core/geometry/qgsgeometry.h#L2093 +QgsGeometry.taperedBuffer: src/core/geometry/qgsgeometry.h#L1620 +QgsGeometry.toggleCircularAtVertex: src/core/geometry/qgsgeometry.h#L872 +QgsGeometry.touches: src/core/geometry/qgsgeometry.h#L1519 +QgsGeometry.transform: src/core/geometry/qgsgeometry.h#L1028 +QgsGeometry.transform: src/core/geometry/qgsgeometry.h#L1038 +QgsGeometry.translate: src/core/geometry/qgsgeometry.h#L1012 +QgsGeometry.triangularWaves: src/core/geometry/qgsgeometry.h#L1286 +QgsGeometry.triangularWavesRandomized: src/core/geometry/qgsgeometry.h#L1306 +QgsGeometry.type: src/core/geometry/qgsgeometry.h#L405 +QgsGeometry.unaryUnion: src/core/geometry/qgsgeometry.h#L2847 +QgsGeometry.unionCoverage: src/core/geometry/qgsgeometry.h#L1929 +QgsGeometry.validateCoverage: src/core/geometry/qgsgeometry.h#L1894 +QgsGeometry.validateGeometry: src/core/geometry/qgsgeometry.h#L2826 +QgsGeometry.variableWidthBufferByM: src/core/geometry/qgsgeometry.h#L1636 +QgsGeometry.vertexAt: src/core/geometry/qgsgeometry.h#L879 +QgsGeometry.vertexIdFromVertexNr: src/core/geometry/qgsgeometry.h#L2894 +QgsGeometry.vertexNrFromVertexId: src/core/geometry/qgsgeometry.h#L2906 +QgsGeometry.vertices: src/core/geometry/qgsgeometry.h#L557 +QgsGeometry.voronoiDiagram: src/core/geometry/qgsgeometry.h#L1849 +QgsGeometry.within: src/core/geometry/qgsgeometry.h#L1541 +QgsGeometry.wkbSize: src/core/geometry/qgsgeometry.h#L2184 +QgsGeometry.wkbType: src/core/geometry/qgsgeometry.h#L399 +QgsGeometry: src/core/geometry/qgsgeometry.h#L178 QgsGeometryCollection.__bool__: src/core/geometry/qgsgeometrycollection.h#L136 QgsGeometryCollection.__delitem__: src/core/geometry/qgsgeometrycollection.h#L401 QgsGeometryCollection.__getitem__: src/core/geometry/qgsgeometrycollection.h#L373 @@ -5306,9 +5306,9 @@ QgsGeometryPaintDevice.painterPathToGeometry: src/core/painting/qgsgeometrypaint QgsGeometryPaintDevice.setSimplificationTolerance: src/core/painting/qgsgeometrypaintdevice.h#L149 QgsGeometryPaintDevice.setStrokedPathSegments: src/core/painting/qgsgeometrypaintdevice.h#L140 QgsGeometryPaintDevice: src/core/painting/qgsgeometrypaintdevice.h#L122 -QgsGeometryParameters.gridSize: src/core/geometry/qgsgeometry.h#L122 -QgsGeometryParameters.setGridSize: src/core/geometry/qgsgeometry.h#L134 -QgsGeometryParameters: src/core/geometry/qgsgeometry.h#L108 +QgsGeometryParameters.gridSize: src/core/geometry/qgsgeometry.h#L139 +QgsGeometryParameters.setGridSize: src/core/geometry/qgsgeometry.h#L151 +QgsGeometryParameters: src/core/geometry/qgsgeometry.h#L125 QgsGeometryPartIterator.__iter__: src/core/geometry/qgsabstractgeometry.h#L1286 QgsGeometryPartIterator.__next__: src/core/geometry/qgsabstractgeometry.h#L1291 QgsGeometryPartIterator.hasNext: src/core/geometry/qgsabstractgeometry.h#L1280 @@ -5508,13 +5508,13 @@ QgsGlowEffect.shadeExterior: src/core/effects/qgsgloweffect.h#L274 QgsGlowEffect.spread: src/core/effects/qgsgloweffect.h#L73 QgsGlowEffect.spreadUnit: src/core/effects/qgsgloweffect.h#L91 QgsGlowEffect: src/core/effects/qgsgloweffect.h#L37 -QgsGml.crs: src/core/qgsgml.h#L431 -QgsGml.dataProgressAndSteps: src/core/qgsgml.h#L455 -QgsGml.dataReadProgress: src/core/qgsgml.h#L440 -QgsGml.getFeatures: src/core/qgsgml.h#L408 -QgsGml.getFeatures: src/core/qgsgml.h#L420 -QgsGml.totalStepsUpdate: src/core/qgsgml.h#L447 -QgsGml: src/core/qgsgml.h#L387 +QgsGml.crs: src/core/qgsgml.h#L432 +QgsGml.dataProgressAndSteps: src/core/qgsgml.h#L456 +QgsGml.dataReadProgress: src/core/qgsgml.h#L441 +QgsGml.getFeatures: src/core/qgsgml.h#L409 +QgsGml.getFeatures: src/core/qgsgml.h#L421 +QgsGml.totalStepsUpdate: src/core/qgsgml.h#L448 +QgsGml: src/core/qgsgml.h#L388 QgsGmlFeatureClass.fieldIndex: src/core/qgsgmlschema.h#L49 QgsGmlFeatureClass.path: src/core/qgsgmlschema.h#L51 QgsGmlFeatureClass: src/core/qgsgmlschema.h#L40 @@ -8951,219 +8951,220 @@ QgsMapInfoSymbolConverter.convertFillSymbol: src/core/symbology/qgsmapinfosymbol QgsMapInfoSymbolConverter.convertLineSymbol: src/core/symbology/qgsmapinfosymbolconverter.h#L75 QgsMapInfoSymbolConverter.convertMarkerSymbol: src/core/symbology/qgsmapinfosymbolconverter.h#L91 QgsMapInfoSymbolConverter: src/core/symbology/qgsmapinfosymbolconverter.h#L66 -QgsMapLayer.__repr__: src/core/qgsmaplayer.h#L1915 +QgsMapLayer.__repr__: src/core/qgsmaplayer.h#L1955 QgsMapLayer.abstract: src/core/qgsmaplayer.h#L356 -QgsMapLayer.accept: src/core/qgsmaplayer.h#L1742 -QgsMapLayer.appendError: src/core/qgsmaplayer.h#L2279 +QgsMapLayer.accept: src/core/qgsmaplayer.h#L1782 +QgsMapLayer.appendError: src/core/qgsmaplayer.h#L2319 QgsMapLayer.attribution: src/core/qgsmaplayer.h#L412 QgsMapLayer.attributionUrl: src/core/qgsmaplayer.h#L426 -QgsMapLayer.autoRefreshInterval: src/core/qgsmaplayer.h#L1636 -QgsMapLayer.autoRefreshIntervalChanged: src/core/qgsmaplayer.h#L2080 -QgsMapLayer.autoRefreshMode: src/core/qgsmaplayer.h#L1628 -QgsMapLayer.beforeResolveReferences: src/core/qgsmaplayer.h#L1938 +QgsMapLayer.autoRefreshInterval: src/core/qgsmaplayer.h#L1676 +QgsMapLayer.autoRefreshIntervalChanged: src/core/qgsmaplayer.h#L2120 +QgsMapLayer.autoRefreshMode: src/core/qgsmaplayer.h#L1668 +QgsMapLayer.beforeResolveReferences: src/core/qgsmaplayer.h#L1978 QgsMapLayer.blendMode: src/core/qgsmaplayer.h#L516 -QgsMapLayer.blendModeChanged: src/core/qgsmaplayer.h#L2011 +QgsMapLayer.blendModeChanged: src/core/qgsmaplayer.h#L2051 QgsMapLayer.clone: src/core/qgsmaplayer.h#L214 -QgsMapLayer.clone: src/core/qgsmaplayer.h#L2187 -QgsMapLayer.configChanged: src/core/qgsmaplayer.h#L2062 +QgsMapLayer.clone: src/core/qgsmaplayer.h#L2227 +QgsMapLayer.configChanged: src/core/qgsmaplayer.h#L2102 QgsMapLayer.createMapRenderer: src/core/qgsmaplayer.h#L549 -QgsMapLayer.crs3D: src/core/qgsmaplayer.h#L1034 -QgsMapLayer.crs3DChanged: src/core/qgsmaplayer.h#L1977 -QgsMapLayer.crs: src/core/qgsmaplayer.h#L994 -QgsMapLayer.crsChanged: src/core/qgsmaplayer.h#L1966 +QgsMapLayer.crs3D: src/core/qgsmaplayer.h#L1074 +QgsMapLayer.crs3DChanged: src/core/qgsmaplayer.h#L2017 +QgsMapLayer.crs: src/core/qgsmaplayer.h#L1034 +QgsMapLayer.crsChanged: src/core/qgsmaplayer.h#L2006 QgsMapLayer.customProperty: src/core/qgsmaplayer.h#L721 -QgsMapLayer.customPropertyChanged: src/core/qgsmaplayer.h#L2125 +QgsMapLayer.customPropertyChanged: src/core/qgsmaplayer.h#L2165 QgsMapLayer.customPropertyKeys: src/core/qgsmaplayer.h#L708 -QgsMapLayer.dataChanged: src/core/qgsmaplayer.h#L2008 +QgsMapLayer.dataChanged: src/core/qgsmaplayer.h#L2048 QgsMapLayer.dataProvider: src/core/qgsmaplayer.h#L302 -QgsMapLayer.dataSourceChanged: src/core/qgsmaplayer.h#L2104 +QgsMapLayer.dataSourceChanged: src/core/qgsmaplayer.h#L2144 QgsMapLayer.dataUrl: src/core/qgsmaplayer.h#L384 QgsMapLayer.dataUrlFormat: src/core/qgsmaplayer.h#L398 -QgsMapLayer.decodedSource: src/core/qgsmaplayer.h#L2238 +QgsMapLayer.decodedSource: src/core/qgsmaplayer.h#L2278 QgsMapLayer.deleteStyleFromDatabase: src/core/qgsmaplayer.h#L758 -QgsMapLayer.dependenciesChanged: src/core/qgsmaplayer.h#L2067 -QgsMapLayer.editingStarted: src/core/qgsmaplayer.h#L2131 -QgsMapLayer.editingStopped: src/core/qgsmaplayer.h#L2137 -QgsMapLayer.elevationProperties: src/core/qgsmaplayer.h#L1763 -QgsMapLayer.emitStyleChanged: src/core/qgsmaplayer.h#L1882 -QgsMapLayer.encodedSource: src/core/qgsmaplayer.h#L2224 -QgsMapLayer.error: src/core/qgsmaplayer.h#L981 -QgsMapLayer.exportNamedMetadata: src/core/qgsmaplayer.h#L1096 -QgsMapLayer.exportNamedStyle: src/core/qgsmaplayer.h#L1244 -QgsMapLayer.exportSldStyle: src/core/qgsmaplayer.h#L1255 -QgsMapLayer.exportSldStyleV2: src/core/qgsmaplayer.h#L1264 -QgsMapLayer.exportSldStyleV3: src/core/qgsmaplayer.h#L1275 +QgsMapLayer.dependenciesChanged: src/core/qgsmaplayer.h#L2107 +QgsMapLayer.editingStarted: src/core/qgsmaplayer.h#L2171 +QgsMapLayer.editingStopped: src/core/qgsmaplayer.h#L2177 +QgsMapLayer.elevationProperties: src/core/qgsmaplayer.h#L1803 +QgsMapLayer.emitStyleChanged: src/core/qgsmaplayer.h#L1922 +QgsMapLayer.encodedSource: src/core/qgsmaplayer.h#L2264 +QgsMapLayer.error: src/core/qgsmaplayer.h#L1021 +QgsMapLayer.exportNamedMetadata: src/core/qgsmaplayer.h#L1136 +QgsMapLayer.exportNamedStyle: src/core/qgsmaplayer.h#L1284 +QgsMapLayer.exportSldStyle: src/core/qgsmaplayer.h#L1295 +QgsMapLayer.exportSldStyleV2: src/core/qgsmaplayer.h#L1304 +QgsMapLayer.exportSldStyleV3: src/core/qgsmaplayer.h#L1315 QgsMapLayer.extensionPropertyType: src/core/qgsmaplayer.h#L260 QgsMapLayer.extent3D: src/core/qgsmaplayer.h#L558 QgsMapLayer.extent: src/core/qgsmaplayer.h#L552 QgsMapLayer.flags: src/core/qgsmaplayer.h#L231 -QgsMapLayer.flagsChanged: src/core/qgsmaplayer.h#L2095 -QgsMapLayer.formatLayerName: src/core/qgsmaplayer.h#L1081 -QgsMapLayer.generateId: src/core/qgsmaplayer.h#L1731 +QgsMapLayer.flagsChanged: src/core/qgsmaplayer.h#L2135 +QgsMapLayer.formatLayerName: src/core/qgsmaplayer.h#L1121 +QgsMapLayer.generateId: src/core/qgsmaplayer.h#L1771 QgsMapLayer.getStyleFromDatabase: src/core/qgsmaplayer.h#L750 -QgsMapLayer.hasAutoRefreshEnabled: src/core/qgsmaplayer.h#L1620 -QgsMapLayer.hasDependencyCycle: src/core/qgsmaplayer.h#L2311 -QgsMapLayer.hasMapTips: src/core/qgsmaplayer.h#L1785 -QgsMapLayer.hasScaleBasedVisibility: src/core/qgsmaplayer.h#L1612 -QgsMapLayer.htmlMetadata: src/core/qgsmaplayer.h#L1683 +QgsMapLayer.hasAutoRefreshEnabled: src/core/qgsmaplayer.h#L1660 +QgsMapLayer.hasDependencyCycle: src/core/qgsmaplayer.h#L2351 +QgsMapLayer.hasMapTips: src/core/qgsmaplayer.h#L1825 +QgsMapLayer.hasScaleBasedVisibility: src/core/qgsmaplayer.h#L1652 +QgsMapLayer.htmlMetadata: src/core/qgsmaplayer.h#L1723 QgsMapLayer.id: src/core/qgsmaplayer.h#L268 -QgsMapLayer.idChanged: src/core/qgsmaplayer.h#L1951 -QgsMapLayer.importNamedMetadata: src/core/qgsmaplayer.h#L1169 -QgsMapLayer.importNamedStyle: src/core/qgsmaplayer.h#L1233 -QgsMapLayer.invalidateWgs84Extent: src/core/qgsmaplayer.h#L2289 +QgsMapLayer.idChanged: src/core/qgsmaplayer.h#L1991 +QgsMapLayer.importNamedMetadata: src/core/qgsmaplayer.h#L1209 +QgsMapLayer.importNamedStyle: src/core/qgsmaplayer.h#L1273 +QgsMapLayer.invalidateWgs84Extent: src/core/qgsmaplayer.h#L2329 QgsMapLayer.isEditable: src/core/qgsmaplayer.h#L624 -QgsMapLayer.isInScaleRange: src/core/qgsmaplayer.h#L1578 +QgsMapLayer.isInScaleRange: src/core/qgsmaplayer.h#L1618 QgsMapLayer.isModified: src/core/qgsmaplayer.h#L631 -QgsMapLayer.isRefreshOnNotifyEnabled: src/core/qgsmaplayer.h#L1706 +QgsMapLayer.isRefreshOnNotifyEnabled: src/core/qgsmaplayer.h#L1746 QgsMapLayer.isSpatial: src/core/qgsmaplayer.h#L636 QgsMapLayer.isTemporary: src/core/qgsmaplayer.h#L647 QgsMapLayer.isValid: src/core/qgsmaplayer.h#L575 -QgsMapLayer.isValidChanged: src/core/qgsmaplayer.h#L2118 +QgsMapLayer.isValidChanged: src/core/qgsmaplayer.h#L2158 QgsMapLayer.keywordList: src/core/qgsmaplayer.h#L370 -QgsMapLayer.layerModified: src/core/qgsmaplayer.h#L2143 -QgsMapLayer.legend: src/core/qgsmaplayer.h#L1553 -QgsMapLayer.legendChanged: src/core/qgsmaplayer.h#L2044 -QgsMapLayer.legendPlaceholderImage: src/core/qgsmaplayer.h#L1770 -QgsMapLayer.legendUrl: src/core/qgsmaplayer.h#L1528 -QgsMapLayer.legendUrlFormat: src/core/qgsmaplayer.h#L1542 +QgsMapLayer.layerModified: src/core/qgsmaplayer.h#L2183 +QgsMapLayer.legend: src/core/qgsmaplayer.h#L1593 +QgsMapLayer.legendChanged: src/core/qgsmaplayer.h#L2084 +QgsMapLayer.legendPlaceholderImage: src/core/qgsmaplayer.h#L1810 +QgsMapLayer.legendUrl: src/core/qgsmaplayer.h#L1568 +QgsMapLayer.legendUrlFormat: src/core/qgsmaplayer.h#L1582 QgsMapLayer.listStylesInDatabase: src/core/qgsmaplayer.h#L744 -QgsMapLayer.loadDefaultMetadata: src/core/qgsmaplayer.h#L1152 -QgsMapLayer.loadDefaultStyle: src/core/qgsmaplayer.h#L1193 -QgsMapLayer.loadNamedMetadata: src/core/qgsmaplayer.h#L1139 -QgsMapLayer.loadNamedMetadataFromDatabase: src/core/qgsmaplayer.h#L1161 -QgsMapLayer.loadNamedStyle: src/core/qgsmaplayer.h#L1214 -QgsMapLayer.loadNamedStyle: src/core/qgsmaplayer.h#L795 -QgsMapLayer.loadNamedStyleFromDatabase: src/core/qgsmaplayer.h#L1223 -QgsMapLayer.loadSldStyle: src/core/qgsmaplayer.h#L1351 -QgsMapLayer.mapTipTemplate: src/core/qgsmaplayer.h#L1794 -QgsMapLayer.mapTipTemplateChanged: src/core/qgsmaplayer.h#L2150 -QgsMapLayer.mapTipsEnabled: src/core/qgsmaplayer.h#L1817 -QgsMapLayer.mapTipsEnabledChanged: src/core/qgsmaplayer.h#L2158 -QgsMapLayer.maximumScale: src/core/qgsmaplayer.h#L1602 -QgsMapLayer.metadataChanged: src/core/qgsmaplayer.h#L2087 -QgsMapLayer.metadataUri: src/core/qgsmaplayer.h#L1089 +QgsMapLayer.loadDefaultMetadata: src/core/qgsmaplayer.h#L1192 +QgsMapLayer.loadDefaultStyle: src/core/qgsmaplayer.h#L1233 +QgsMapLayer.loadNamedMetadata: src/core/qgsmaplayer.h#L1179 +QgsMapLayer.loadNamedMetadataFromDatabase: src/core/qgsmaplayer.h#L1201 +QgsMapLayer.loadNamedStyle: src/core/qgsmaplayer.h#L1254 +QgsMapLayer.loadNamedStyle: src/core/qgsmaplayer.h#L835 +QgsMapLayer.loadNamedStyleFromDatabase: src/core/qgsmaplayer.h#L1263 +QgsMapLayer.loadSldStyle: src/core/qgsmaplayer.h#L1391 +QgsMapLayer.mapTipTemplate: src/core/qgsmaplayer.h#L1834 +QgsMapLayer.mapTipTemplateChanged: src/core/qgsmaplayer.h#L2190 +QgsMapLayer.mapTipsEnabled: src/core/qgsmaplayer.h#L1857 +QgsMapLayer.mapTipsEnabledChanged: src/core/qgsmaplayer.h#L2198 +QgsMapLayer.maximumScale: src/core/qgsmaplayer.h#L1642 +QgsMapLayer.metadataChanged: src/core/qgsmaplayer.h#L2127 +QgsMapLayer.metadataUri: src/core/qgsmaplayer.h#L1129 QgsMapLayer.metadataUrl: src/core/qgsmaplayer.h#L461 QgsMapLayer.metadataUrlFormat: src/core/qgsmaplayer.h#L503 QgsMapLayer.metadataUrlType: src/core/qgsmaplayer.h#L482 -QgsMapLayer.minimumScale: src/core/qgsmaplayer.h#L1590 +QgsMapLayer.minimumScale: src/core/qgsmaplayer.h#L1630 QgsMapLayer.name: src/core/qgsmaplayer.h#L297 -QgsMapLayer.nameChanged: src/core/qgsmaplayer.h#L1956 +QgsMapLayer.nameChanged: src/core/qgsmaplayer.h#L1996 QgsMapLayer.opacity: src/core/qgsmaplayer.h#L536 -QgsMapLayer.opacityChanged: src/core/qgsmaplayer.h#L2021 -QgsMapLayer.originalXmlProperties: src/core/qgsmaplayer.h#L1716 -QgsMapLayer.project: src/core/qgsmaplayer.h#L1928 +QgsMapLayer.opacityChanged: src/core/qgsmaplayer.h#L2061 +QgsMapLayer.originalXmlProperties: src/core/qgsmaplayer.h#L1756 +QgsMapLayer.project: src/core/qgsmaplayer.h#L1968 QgsMapLayer.properties: src/core/qgsmaplayer.h#L254 QgsMapLayer.providerMetadata: src/core/qgsmaplayer.h#L314 -QgsMapLayer.providerReadFlags: src/core/qgsmaplayer.h#L1826 -QgsMapLayer.providerType: src/core/qgsmaplayer.h#L1506 +QgsMapLayer.providerReadFlags: src/core/qgsmaplayer.h#L1866 +QgsMapLayer.providerType: src/core/qgsmaplayer.h#L1546 QgsMapLayer.publicSource: src/core/qgsmaplayer.h#L587 -QgsMapLayer.readCommonStyle: src/core/qgsmaplayer.h#L2265 -QgsMapLayer.readCustomProperties: src/core/qgsmaplayer.h#L2245 +QgsMapLayer.readCommonStyle: src/core/qgsmaplayer.h#L2305 +QgsMapLayer.readCustomProperties: src/core/qgsmaplayer.h#L2285 QgsMapLayer.readLayerXml: src/core/qgsmaplayer.h#L679 QgsMapLayer.readOnly: src/core/qgsmaplayer.h#L539 -QgsMapLayer.readSld: src/core/qgsmaplayer.h#L1354 -QgsMapLayer.readStyle: src/core/qgsmaplayer.h#L1378 -QgsMapLayer.readStyleManager: src/core/qgsmaplayer.h#L2251 -QgsMapLayer.readSymbology: src/core/qgsmaplayer.h#L1366 -QgsMapLayer.readXml: src/core/qgsmaplayer.h#L2205 -QgsMapLayer.recalculateExtents: src/core/qgsmaplayer.h#L2005 -QgsMapLayer.refreshOnNotifyMessage: src/core/qgsmaplayer.h#L1700 +QgsMapLayer.readSld: src/core/qgsmaplayer.h#L1394 +QgsMapLayer.readStyle: src/core/qgsmaplayer.h#L1418 +QgsMapLayer.readStyleManager: src/core/qgsmaplayer.h#L2291 +QgsMapLayer.readSymbology: src/core/qgsmaplayer.h#L1406 +QgsMapLayer.readXml: src/core/qgsmaplayer.h#L2245 +QgsMapLayer.recalculateExtents: src/core/qgsmaplayer.h#L2045 +QgsMapLayer.refreshOnNotifyMessage: src/core/qgsmaplayer.h#L1740 QgsMapLayer.reload: src/core/qgsmaplayer.h#L544 -QgsMapLayer.removeCustomProperty: src/core/qgsmaplayer.h#L974 -QgsMapLayer.renderer3D: src/core/qgsmaplayer.h#L1568 -QgsMapLayer.renderer3DChanged: src/core/qgsmaplayer.h#L2049 -QgsMapLayer.rendererChanged: src/core/qgsmaplayer.h#L2027 -QgsMapLayer.repaintRequested: src/core/qgsmaplayer.h#L2002 -QgsMapLayer.request3DUpdate: src/core/qgsmaplayer.h#L2056 +QgsMapLayer.removeCustomProperty: src/core/qgsmaplayer.h#L1014 +QgsMapLayer.renderer3D: src/core/qgsmaplayer.h#L1608 +QgsMapLayer.renderer3DChanged: src/core/qgsmaplayer.h#L2089 +QgsMapLayer.rendererChanged: src/core/qgsmaplayer.h#L2067 +QgsMapLayer.repaintRequested: src/core/qgsmaplayer.h#L2042 +QgsMapLayer.request3DUpdate: src/core/qgsmaplayer.h#L2096 QgsMapLayer.resolveReferences: src/core/qgsmaplayer.h#L702 -QgsMapLayer.saveDefaultMetadata: src/core/qgsmaplayer.h#L1106 -QgsMapLayer.saveDefaultStyle: src/core/qgsmaplayer.h#L1288 -QgsMapLayer.saveDefaultStyle: src/core/qgsmaplayer.h#L1301 -QgsMapLayer.saveNamedMetadata: src/core/qgsmaplayer.h#L1121 -QgsMapLayer.saveNamedStyle: src/core/qgsmaplayer.h#L1318 -QgsMapLayer.saveSldStyle: src/core/qgsmaplayer.h#L1329 -QgsMapLayer.saveSldStyleV2: src/core/qgsmaplayer.h#L1341 -QgsMapLayer.saveStyleToDatabase: src/core/qgsmaplayer.h#L776 -QgsMapLayer.selectionProperties: src/core/qgsmaplayer.h#L1749 +QgsMapLayer.saveDefaultMetadata: src/core/qgsmaplayer.h#L1146 +QgsMapLayer.saveDefaultStyle: src/core/qgsmaplayer.h#L1328 +QgsMapLayer.saveDefaultStyle: src/core/qgsmaplayer.h#L1341 +QgsMapLayer.saveNamedMetadata: src/core/qgsmaplayer.h#L1161 +QgsMapLayer.saveNamedStyle: src/core/qgsmaplayer.h#L1358 +QgsMapLayer.saveSldStyle: src/core/qgsmaplayer.h#L1369 +QgsMapLayer.saveSldStyleV2: src/core/qgsmaplayer.h#L1381 +QgsMapLayer.saveStyleToDatabase: src/core/qgsmaplayer.h#L799 +QgsMapLayer.saveStyleToDatabaseV2: src/core/qgsmaplayer.h#L817 +QgsMapLayer.selectionProperties: src/core/qgsmaplayer.h#L1789 QgsMapLayer.serverProperties: src/core/qgsmaplayer.h#L435 QgsMapLayer.setAbstract: src/core/qgsmaplayer.h#L349 QgsMapLayer.setAttribution: src/core/qgsmaplayer.h#L405 QgsMapLayer.setAttributionUrl: src/core/qgsmaplayer.h#L419 -QgsMapLayer.setAutoRefreshEnabled: src/core/qgsmaplayer.h#L1656 -QgsMapLayer.setAutoRefreshInterval: src/core/qgsmaplayer.h#L1648 -QgsMapLayer.setAutoRefreshMode: src/core/qgsmaplayer.h#L1664 +QgsMapLayer.setAutoRefreshEnabled: src/core/qgsmaplayer.h#L1696 +QgsMapLayer.setAutoRefreshInterval: src/core/qgsmaplayer.h#L1688 +QgsMapLayer.setAutoRefreshMode: src/core/qgsmaplayer.h#L1704 QgsMapLayer.setBlendMode: src/core/qgsmaplayer.h#L510 -QgsMapLayer.setCrs: src/core/qgsmaplayer.h#L1046 +QgsMapLayer.setCrs: src/core/qgsmaplayer.h#L1086 QgsMapLayer.setCustomProperties: src/core/qgsmaplayer.h#L726 QgsMapLayer.setCustomProperty: src/core/qgsmaplayer.h#L715 -QgsMapLayer.setDataSource: src/core/qgsmaplayer.h#L1439 -QgsMapLayer.setDataSource: src/core/qgsmaplayer.h#L1470 -QgsMapLayer.setDataSource: src/core/qgsmaplayer.h#L1501 +QgsMapLayer.setDataSource: src/core/qgsmaplayer.h#L1479 +QgsMapLayer.setDataSource: src/core/qgsmaplayer.h#L1510 +QgsMapLayer.setDataSource: src/core/qgsmaplayer.h#L1541 QgsMapLayer.setDataUrl: src/core/qgsmaplayer.h#L377 QgsMapLayer.setDataUrlFormat: src/core/qgsmaplayer.h#L391 -QgsMapLayer.setDependencies: src/core/qgsmaplayer.h#L1891 -QgsMapLayer.setError: src/core/qgsmaplayer.h#L2281 -QgsMapLayer.setExtent3D: src/core/qgsmaplayer.h#L2196 -QgsMapLayer.setExtent: src/core/qgsmaplayer.h#L2190 +QgsMapLayer.setDependencies: src/core/qgsmaplayer.h#L1931 +QgsMapLayer.setError: src/core/qgsmaplayer.h#L2321 +QgsMapLayer.setExtent3D: src/core/qgsmaplayer.h#L2236 +QgsMapLayer.setExtent: src/core/qgsmaplayer.h#L2230 QgsMapLayer.setFlags: src/core/qgsmaplayer.h#L243 QgsMapLayer.setId: src/core/qgsmaplayer.h#L285 QgsMapLayer.setKeywordList: src/core/qgsmaplayer.h#L363 QgsMapLayer.setLayerOrder: src/core/qgsmaplayer.h#L606 -QgsMapLayer.setLegend: src/core/qgsmaplayer.h#L1548 -QgsMapLayer.setLegendPlaceholderImage: src/core/qgsmaplayer.h#L1777 -QgsMapLayer.setLegendUrl: src/core/qgsmaplayer.h#L1521 -QgsMapLayer.setLegendUrlFormat: src/core/qgsmaplayer.h#L1535 -QgsMapLayer.setMapTipTemplate: src/core/qgsmaplayer.h#L1803 -QgsMapLayer.setMapTipsEnabled: src/core/qgsmaplayer.h#L1811 -QgsMapLayer.setMaximumScale: src/core/qgsmaplayer.h#L1850 -QgsMapLayer.setMetadata: src/core/qgsmaplayer.h#L1678 +QgsMapLayer.setLegend: src/core/qgsmaplayer.h#L1588 +QgsMapLayer.setLegendPlaceholderImage: src/core/qgsmaplayer.h#L1817 +QgsMapLayer.setLegendUrl: src/core/qgsmaplayer.h#L1561 +QgsMapLayer.setLegendUrlFormat: src/core/qgsmaplayer.h#L1575 +QgsMapLayer.setMapTipTemplate: src/core/qgsmaplayer.h#L1843 +QgsMapLayer.setMapTipsEnabled: src/core/qgsmaplayer.h#L1851 +QgsMapLayer.setMaximumScale: src/core/qgsmaplayer.h#L1890 +QgsMapLayer.setMetadata: src/core/qgsmaplayer.h#L1718 QgsMapLayer.setMetadataUrl: src/core/qgsmaplayer.h#L450 QgsMapLayer.setMetadataUrlFormat: src/core/qgsmaplayer.h#L492 QgsMapLayer.setMetadataUrlType: src/core/qgsmaplayer.h#L471 -QgsMapLayer.setMinimumScale: src/core/qgsmaplayer.h#L1839 +QgsMapLayer.setMinimumScale: src/core/qgsmaplayer.h#L1879 QgsMapLayer.setName: src/core/qgsmaplayer.h#L291 QgsMapLayer.setOpacity: src/core/qgsmaplayer.h#L526 -QgsMapLayer.setOriginalXmlProperties: src/core/qgsmaplayer.h#L1725 -QgsMapLayer.setProviderType: src/core/qgsmaplayer.h#L2269 -QgsMapLayer.setRefreshOnNofifyMessage: src/core/qgsmaplayer.h#L1905 -QgsMapLayer.setRefreshOnNotifyEnabled: src/core/qgsmaplayer.h#L1897 -QgsMapLayer.setRenderer3D: src/core/qgsmaplayer.h#L1563 -QgsMapLayer.setScaleBasedVisibility: src/core/qgsmaplayer.h#L1859 +QgsMapLayer.setOriginalXmlProperties: src/core/qgsmaplayer.h#L1765 +QgsMapLayer.setProviderType: src/core/qgsmaplayer.h#L2309 +QgsMapLayer.setRefreshOnNofifyMessage: src/core/qgsmaplayer.h#L1945 +QgsMapLayer.setRefreshOnNotifyEnabled: src/core/qgsmaplayer.h#L1937 +QgsMapLayer.setRenderer3D: src/core/qgsmaplayer.h#L1603 +QgsMapLayer.setScaleBasedVisibility: src/core/qgsmaplayer.h#L1899 QgsMapLayer.setShortName: src/core/qgsmaplayer.h#L321 QgsMapLayer.setSubLayerVisibility: src/core/qgsmaplayer.h#L613 QgsMapLayer.setTitle: src/core/qgsmaplayer.h#L335 -QgsMapLayer.setTransformContext: src/core/qgsmaplayer.h#L1912 -QgsMapLayer.setValid: src/core/qgsmaplayer.h#L2199 -QgsMapLayer.setVerticalCrs: src/core/qgsmaplayer.h#L1067 +QgsMapLayer.setTransformContext: src/core/qgsmaplayer.h#L1952 +QgsMapLayer.setValid: src/core/qgsmaplayer.h#L2239 +QgsMapLayer.setVerticalCrs: src/core/qgsmaplayer.h#L1107 QgsMapLayer.shortName: src/core/qgsmaplayer.h#L328 QgsMapLayer.source: src/core/qgsmaplayer.h#L594 -QgsMapLayer.statusChanged: src/core/qgsmaplayer.h#L1941 -QgsMapLayer.styleChanged: src/core/qgsmaplayer.h#L2039 -QgsMapLayer.styleLoaded: src/core/qgsmaplayer.h#L2111 -QgsMapLayer.styleManager: src/core/qgsmaplayer.h#L1558 -QgsMapLayer.styleURI: src/core/qgsmaplayer.h#L1179 +QgsMapLayer.statusChanged: src/core/qgsmaplayer.h#L1981 +QgsMapLayer.styleChanged: src/core/qgsmaplayer.h#L2079 +QgsMapLayer.styleLoaded: src/core/qgsmaplayer.h#L2151 +QgsMapLayer.styleManager: src/core/qgsmaplayer.h#L1598 +QgsMapLayer.styleURI: src/core/qgsmaplayer.h#L1219 QgsMapLayer.subLayers: src/core/qgsmaplayer.h#L600 QgsMapLayer.supportsEditing: src/core/qgsmaplayer.h#L621 -QgsMapLayer.temporalProperties: src/core/qgsmaplayer.h#L1756 -QgsMapLayer.timestamp: src/core/qgsmaplayer.h#L1686 +QgsMapLayer.temporalProperties: src/core/qgsmaplayer.h#L1796 +QgsMapLayer.timestamp: src/core/qgsmaplayer.h#L1726 QgsMapLayer.title: src/core/qgsmaplayer.h#L342 -QgsMapLayer.transformContext: src/core/qgsmaplayer.h#L1074 -QgsMapLayer.trigger3DUpdate: src/core/qgsmaplayer.h#L1877 -QgsMapLayer.triggerRepaint: src/core/qgsmaplayer.h#L1869 +QgsMapLayer.transformContext: src/core/qgsmaplayer.h#L1114 +QgsMapLayer.trigger3DUpdate: src/core/qgsmaplayer.h#L1917 +QgsMapLayer.triggerRepaint: src/core/qgsmaplayer.h#L1909 QgsMapLayer.type: src/core/qgsmaplayer.h#L219 -QgsMapLayer.undoStack: src/core/qgsmaplayer.h#L1509 -QgsMapLayer.undoStackStyles: src/core/qgsmaplayer.h#L1514 -QgsMapLayer.verticalCrs: src/core/qgsmaplayer.h#L1014 -QgsMapLayer.verticalCrsChanged: src/core/qgsmaplayer.h#L1994 +QgsMapLayer.undoStack: src/core/qgsmaplayer.h#L1549 +QgsMapLayer.undoStackStyles: src/core/qgsmaplayer.h#L1554 +QgsMapLayer.verticalCrs: src/core/qgsmaplayer.h#L1054 +QgsMapLayer.verticalCrsChanged: src/core/qgsmaplayer.h#L2034 QgsMapLayer.wgs84Extent: src/core/qgsmaplayer.h#L568 -QgsMapLayer.willBeDeleted: src/core/qgsmaplayer.h#L2074 -QgsMapLayer.writeCommonStyle: src/core/qgsmaplayer.h#L2258 -QgsMapLayer.writeCustomProperties: src/core/qgsmaplayer.h#L2248 +QgsMapLayer.willBeDeleted: src/core/qgsmaplayer.h#L2114 +QgsMapLayer.writeCommonStyle: src/core/qgsmaplayer.h#L2298 +QgsMapLayer.writeCustomProperties: src/core/qgsmaplayer.h#L2288 QgsMapLayer.writeLayerXml: src/core/qgsmaplayer.h#L697 -QgsMapLayer.writeStyle: src/core/qgsmaplayer.h#L1405 -QgsMapLayer.writeStyleManager: src/core/qgsmaplayer.h#L2253 -QgsMapLayer.writeSymbology: src/core/qgsmaplayer.h#L1391 -QgsMapLayer.writeXml: src/core/qgsmaplayer.h#L2211 +QgsMapLayer.writeStyle: src/core/qgsmaplayer.h#L1445 +QgsMapLayer.writeStyleManager: src/core/qgsmaplayer.h#L2293 +QgsMapLayer.writeSymbology: src/core/qgsmaplayer.h#L1431 +QgsMapLayer.writeXml: src/core/qgsmaplayer.h#L2251 QgsMapLayer: src/core/qgsmaplayer.h#L76 QgsMapLayerDependency.__hash__: src/core/qgsmaplayerdependency.h#L78 QgsMapLayerDependency.layerId: src/core/qgsmaplayerdependency.h#L67 diff --git a/python/plugins/processing/algs/gdal/GdalUtils.py b/python/plugins/processing/algs/gdal/GdalUtils.py index 1e0b389aee27..e974da873e39 100644 --- a/python/plugins/processing/algs/gdal/GdalUtils.py +++ b/python/plugins/processing/algs/gdal/GdalUtils.py @@ -114,14 +114,13 @@ def runGdal(commands, feedback=None): except OSError: # https://travis-ci.org/m-kuhn/QGIS#L1493-L1526 pass if isDarwin and os.path.isfile( - os.path.join(QgsApplication.prefixPath(), "bin", "gdalinfo") + os.path.join(QgsApplication.prefixPath(), "Contents", "MacOS", "gdalinfo") ): # Looks like there's a bundled gdal. Let's use it. os.environ["PATH"] = "{}{}{}".format( - os.path.join(QgsApplication.prefixPath(), "bin"), os.pathsep, envval - ) - os.environ["DYLD_LIBRARY_PATH"] = os.path.join( - QgsApplication.prefixPath(), "lib" + os.path.join(QgsApplication.prefixPath(), "Contents", "MacOS"), + os.pathsep, + envval, ) else: # Other platforms should use default gdal finder codepath diff --git a/python/plugins/processing/gui/BatchAlgorithmDialog.py b/python/plugins/processing/gui/BatchAlgorithmDialog.py index 42b66630a672..bf8eed27b07a 100644 --- a/python/plugins/processing/gui/BatchAlgorithmDialog.py +++ b/python/plugins/processing/gui/BatchAlgorithmDialog.py @@ -57,9 +57,13 @@ def __init__(self, alg, parent=None): def runAsSingle(self): self.close() - from processing.gui.AlgorithmDialog import AlgorithmDialog + alg_instance = self.algorithm().create() + dlg = alg_instance.createCustomParametersWidget(parent=iface.mainWindow()) + if not dlg: + from processing.gui.AlgorithmDialog import AlgorithmDialog + + dlg = AlgorithmDialog(alg_instance, parent=iface.mainWindow()) - dlg = AlgorithmDialog(self.algorithm().create(), parent=iface.mainWindow()) dlg.show() dlg.exec() diff --git a/python/processing/CMakeLists.txt b/python/processing/CMakeLists.txt index 81cd0be4a942..4ac96104ba84 100644 --- a/python/processing/CMakeLists.txt +++ b/python/processing/CMakeLists.txt @@ -1,6 +1,6 @@ # See ../CMakeLists.txt for info on staged-plugins* and clean-staged-plugins targets -set(QGIS_PYTHON_DIR ${Python_SITEARCH}/qgis) +set(QGIS_PYTHON_DIR ${QGIS_PYTHON_INSTALL_DIR}/qgis) set(PY_FILES __init__.py diff --git a/python/testing/CMakeLists.txt b/python/testing/CMakeLists.txt index c428e5e93594..38b9f7a89b8d 100644 --- a/python/testing/CMakeLists.txt +++ b/python/testing/CMakeLists.txt @@ -1,6 +1,6 @@ # See ../CMakeLists.txt for info on staged-plugins* and clean-staged-plugins targets -set(QGIS_PYTHON_DIR ${Python_SITEARCH}/qgis) +set(QGIS_PYTHON_DIR ${QGIS_PYTHON_INSTALL_DIR}/qgis) set(PY_FILES __init__.py diff --git a/scripts/spell_check/.agignore b/scripts/spell_check/.agignore index 36dad1553d41..d4176f228bac 100644 --- a/scripts/spell_check/.agignore +++ b/scripts/spell_check/.agignore @@ -58,6 +58,7 @@ resources/cpt-city-qgis-min/selections/reds.xml resources/cpt-city-qgis-min/wkp/schwarzwald/COPYING.xml resources/data/world_map_generalize.model3 scripts/spell_check/spelling.dat +platform/macos/pymacdeployqt.py scripts/spell_check/test.sh src/server/qgis_wms.xmi src/plugins/grass/modules/v.generalize.qgm diff --git a/src/3d/CMakeLists.txt b/src/3d/CMakeLists.txt index 9a7eb75f0e76..cbd79d563820 100644 --- a/src/3d/CMakeLists.txt +++ b/src/3d/CMakeLists.txt @@ -327,30 +327,6 @@ GENERATE_EXPORT_HEADER( set(QGIS_3D_HDRS ${QGIS_3D_HDRS} ${CMAKE_CURRENT_BINARY_DIR}/qgis_3d.h) -if(NOT APPLE OR NOT QGIS_MACAPP_FRAMEWORK) - install(FILES ${QGIS_3D_HDRS} DESTINATION ${QGIS_INCLUDE_DIR}) -else() - set_target_properties(qgis_3d PROPERTIES - # no moc headers, messes up PROPERTIES syntax - CLEAN_DIRECT_OUTPUT 1 - FRAMEWORK 1 - FRAMEWORK_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}" - MACOSX_FRAMEWORK_INFO_PLIST "${CMAKE_SOURCE_DIR}/mac/framework.info.plist.in" - MACOSX_FRAMEWORK_SHORT_VERSION_STRING ${COMPLETE_VERSION} - MACOSX_FRAMEWORK_IDENTIFIER org.qgis.qgis3_3d - BUILD_WITH_INSTALL_RPATH TRUE - PUBLIC_HEADER "${QGIS_3D_HDRS}" - LINK_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}" - ) - # generated export header does not get copied with PUBLIC_HEADER files - add_custom_command(TARGET qgis_3d - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy qgis_3d.h - "${QGIS_OUTPUT_DIRECTORY}/${QGIS_LIB_SUBDIR}/qgis_3d.framework/Headers" - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - DEPENDS qgis_3d.h - ) -endif() #generate unversioned libs for android if (NOT ANDROID) @@ -371,18 +347,11 @@ if(CLANG_TIDY_EXE) endif() # install +if(NOT QGIS_MAC_BUNDLE) + install(FILES ${QGIS_3D_HDRS} DESTINATION ${QGIS_INCLUDE_DIR}) +endif() install(TARGETS qgis_3d RUNTIME DESTINATION ${QGIS_BIN_DIR} LIBRARY DESTINATION ${QGIS_LIB_DIR} - ARCHIVE DESTINATION ${QGIS_LIB_DIR} - FRAMEWORK DESTINATION ${QGIS_FW_SUBDIR} - PUBLIC_HEADER DESTINATION ${QGIS_INCLUDE_DIR}) - -# Mac dev frameworks - -if (APPLE AND QGIS_MACAPP_INSTALL_DEV) - install(TARGETS qgis_3d FRAMEWORK DESTINATION ${QGIS_MACAPP_DEV_PREFIX}) - install(CODE "execute_process(COMMAND install_name_tool -id \"${QGIS_MACAPP_DEV_PREFIX}/qgis_3d.framework/Versions/${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}/qgis_3d\" \"$ENV{DESTDIR}${QGIS_MACAPP_DEV_PREFIX}/qgis_3d.framework/qgis_3d\")") - install(CODE "execute_process(COMMAND install_name_tool -change \"${CMAKE_INSTALL_NAME_DIR}/qgis_core.framework/Versions/${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}/qgis_core\" \"${QGIS_MACAPP_DEV_PREFIX}/qgis_core.framework/Versions/${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}/qgis_core\" \"$ENV{DESTDIR}${QGIS_MACAPP_DEV_PREFIX}/qgis_3d.framework/qgis_3d\")") -endif() + ARCHIVE DESTINATION ${QGIS_LIB_DIR}) \ No newline at end of file diff --git a/src/analysis/CMakeLists.txt b/src/analysis/CMakeLists.txt index 02bf43128717..ee212b49ba3a 100644 --- a/src/analysis/CMakeLists.txt +++ b/src/analysis/CMakeLists.txt @@ -8,7 +8,6 @@ ADD_FLEX_BISON_DEPENDENCY(QgsRasterCalcLexer QgsRasterCalcParser) set(QGIS_ANALYSIS_SRCS qgsanalysis.cpp - ${FLEX_QgsRasterCalcLexer_OUTPUTS} ${BISON_QgsRasterCalcParser_OUTPUTS} @@ -555,13 +554,6 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") ) endif() -# install headers - -if(HAVE_OPENCL) - include_directories(SYSTEM ${OpenCL_INCLUDE_DIRS}) -endif() - - ############################################################# # qgis_analysis library @@ -601,31 +593,6 @@ GENERATE_EXPORT_HEADER( set(QGIS_ANALYSIS_HDRS ${QGIS_ANALYSIS_HDRS} ${CMAKE_CURRENT_BINARY_DIR}/qgis_analysis.h) -if(NOT APPLE OR NOT QGIS_MACAPP_FRAMEWORK) - install(FILES ${QGIS_ANALYSIS_HDRS} DESTINATION ${QGIS_INCLUDE_DIR}) -else() - set_target_properties(qgis_analysis PROPERTIES - # no moc headers, messes up PROPERTIES syntax - CLEAN_DIRECT_OUTPUT 1 - FRAMEWORK 1 - FRAMEWORK_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}" - MACOSX_FRAMEWORK_INFO_PLIST "${CMAKE_SOURCE_DIR}/mac/framework.info.plist.in" - MACOSX_FRAMEWORK_SHORT_VERSION_STRING ${COMPLETE_VERSION} - MACOSX_FRAMEWORK_IDENTIFIER org.qgis.qgis3_analysis - BUILD_WITH_INSTALL_RPATH TRUE - PUBLIC_HEADER "${QGIS_ANALYSIS_HDRS}" - LINK_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}" - ) - # generated export header does not get copied with PUBLIC_HEADER files - add_custom_command(TARGET qgis_analysis - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy qgis_analysis.h - "${QGIS_OUTPUT_DIRECTORY}/${QGIS_LIB_SUBDIR}/qgis_analysis.framework/Headers" - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - DEPENDS qgis_analysis.h - ) -endif() - #generate unversioned libs for android if (NOT ANDROID) set_target_properties(qgis_analysis PROPERTIES @@ -662,18 +629,11 @@ if(CLANG_TIDY_EXE) endif() # install +if(NOT QGIS_MAC_BUNDLE) + install(FILES ${QGIS_ANALYSIS_HDRS} DESTINATION ${QGIS_INCLUDE_DIR}) +endif() install(TARGETS qgis_analysis RUNTIME DESTINATION ${QGIS_BIN_DIR} LIBRARY DESTINATION ${QGIS_LIB_DIR} - ARCHIVE DESTINATION ${QGIS_LIB_DIR} - FRAMEWORK DESTINATION ${QGIS_FW_SUBDIR} - PUBLIC_HEADER DESTINATION ${QGIS_INCLUDE_DIR}) - -# Mac dev frameworks - -if (APPLE AND QGIS_MACAPP_INSTALL_DEV) - install(TARGETS qgis_analysis FRAMEWORK DESTINATION ${QGIS_MACAPP_DEV_PREFIX}) - install(CODE "execute_process(COMMAND install_name_tool -id \"${QGIS_MACAPP_DEV_PREFIX}/qgis_analysis.framework/Versions/${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}/qgis_analysis\" \"$ENV{DESTDIR}${QGIS_MACAPP_DEV_PREFIX}/qgis_analysis.framework/qgis_analysis\")") - install(CODE "execute_process(COMMAND install_name_tool -change \"${CMAKE_INSTALL_NAME_DIR}/qgis_core.framework/Versions/${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}/qgis_core\" \"${QGIS_MACAPP_DEV_PREFIX}/qgis_core.framework/Versions/${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}/qgis_core\" \"$ENV{DESTDIR}${QGIS_MACAPP_DEV_PREFIX}/qgis_analysis.framework/qgis_analysis\")") -endif() + ARCHIVE DESTINATION ${QGIS_LIB_DIR}) diff --git a/src/analysis/processing/qgsalgorithmextractlabels.cpp b/src/analysis/processing/qgsalgorithmextractlabels.cpp index c9e1eab3c5e2..fb5bb70a24fa 100644 --- a/src/analysis/processing/qgsalgorithmextractlabels.cpp +++ b/src/analysis/processing/qgsalgorithmextractlabels.cpp @@ -554,7 +554,7 @@ QVariantMap QgsExtractLabelsAlgorithm::processAlgorithm( const QVariantMap ¶ vl->setLabelsEnabled( true ); QString errorMessage; - vl->saveStyleToDatabase( QString(), QString(), true, QString(), errorMessage ); + vl->saveStyleToDatabaseV2( QString(), QString(), true, QString(), errorMessage ); } } diff --git a/src/analysis/processing/qgsalgorithmpackage.cpp b/src/analysis/processing/qgsalgorithmpackage.cpp index 20840e07c027..b8277b79c8a7 100644 --- a/src/analysis/processing/qgsalgorithmpackage.cpp +++ b/src/analysis/processing/qgsalgorithmpackage.cpp @@ -485,9 +485,10 @@ bool QgsPackageAlgorithm::packageVectorLayer( QgsVectorLayer *layer, const QStri // this is not nice -- but needed to avoid an "overwrite" prompt messagebox from the provider! This api needs a rework to avoid this. const QVariant prevOverwriteStyle = settings.value( QStringLiteral( "qgis/overwriteStyle" ) ); settings.setValue( QStringLiteral( "qgis/overwriteStyle" ), true ); - res->saveStyleToDatabase( newLayer, QString(), true, QString(), errorMsg ); + QgsMapLayer::SaveStyleResults saveStyleResults = res->saveStyleToDatabaseV2( newLayer, QString(), true, QString(), errorMsg ); settings.setValue( QStringLiteral( "qgis/overwriteStyle" ), prevOverwriteStyle ); - if ( !errorMsg.isEmpty() ) + if ( saveStyleResults.testFlag( QgsMapLayer::SaveStyleResult::QmlGenerationFailed ) + || saveStyleResults.testFlag( QgsMapLayer::SaveStyleResult::DatabaseWriteFailed ) ) { feedback->reportError( QObject::tr( "Could not save layer style: %1 " ).arg( errorMsg ) ); } diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index d4024622f0d0..b7ddc2ec4435 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -497,10 +497,6 @@ elseif(MINGW) ) endif() -if(HAVE_OPENCL) - include_directories(SYSTEM ${OpenCL_INCLUDE_DIRS}) -endif() - if(ENABLE_MODELTEST) include_directories(../../tests/qt_modeltest) endif() @@ -515,28 +511,24 @@ endif() ############# if (ANDROID) - add_library(${QGIS_APP_NAME} ${LIBRARY_TYPE} ${QGIS_APPMAIN_SRCS}) + add_library(qgis ${LIBRARY_TYPE} ${QGIS_APPMAIN_SRCS}) # require c++17 - target_compile_features(${QGIS_APP_NAME} PRIVATE cxx_std_17) + target_compile_features(qgis PRIVATE cxx_std_17) else() - if(APPLE) - set (CREATE_MACOSX_BUNDLE TRUE CACHE BOOL "Create macosx bundle during build. Disable for development to avoid copying libraries and ease debugging.") - if(CREATE_MACOSX_BUNDLE) - set(MACOSX_BUNDLE "MACOSX_BUNDLE") - endif() - endif() - add_executable(${QGIS_APP_NAME} ${MACOSX_BUNDLE} WIN32 ${QGIS_APPMAIN_SRCS}) + add_executable(qgis WIN32 ${QGIS_APPMAIN_SRCS}) if(WIN32 AND BUILD_WITH_QT6) - qt_disable_unicode_defines(${QGIS_APP_NAME}) + qt_disable_unicode_defines(qgis) endif() # require c++17 - target_compile_features(${QGIS_APP_NAME} PRIVATE cxx_std_17) - target_compile_definitions(${QGIS_APP_NAME} PRIVATE "QT_PLUGINS_DIR=\"${QT_PLUGINS_DIR}\"") + target_compile_features(qgis PRIVATE cxx_std_17) + target_compile_definitions(qgis PRIVATE "QT_PLUGINS_DIR=\"${QT_PLUGINS_DIR}\"") endif() +set_target_properties(qgis PROPERTIES OUTPUT_NAME "${QGIS_APP_NAME}") + # Putting IMAGE_RCC_SRCS into qgis_app lib is causing problems when the lib is # loaded (by plugin for example) in test unit (qgis_layoutpicturetest). add_library(qgis_app ${LIBRARY_TYPE} ${QGIS_APP_SRCS}) @@ -664,36 +656,29 @@ if(CLANG_TIDY_EXE) endif() if(NOT WIN32) - target_link_libraries(${QGIS_APP_NAME} qgis_app) + target_link_libraries(qgis qgis_app) endif() if (ANDROID) - target_link_libraries(${QGIS_APP_NAME} log) + target_link_libraries(qgis log) endif() if(WIN32) add_definitions(-DQWT_DLL) add_definitions(-DQSCINTILLA_DLL) - target_link_libraries(${QGIS_APP_NAME} dbghelp) + target_link_libraries(qgis dbghelp) target_link_libraries(qgis_app dbghelp) endif() -target_link_libraries(${QGIS_APP_NAME} qgis_native) +target_link_libraries(qgis qgis_native) if (NOT WIN32) -target_link_libraries(${QGIS_APP_NAME} QTSignal) -endif() - -if (APPLE) - set_target_properties(${QGIS_APP_NAME} PROPERTIES - INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/${QGIS_LIB_DIR} - INSTALL_RPATH_USE_LINK_PATH true - MACOSX_BUNDLE_INFO_PLIST "${CMAKE_SOURCE_DIR}/mac/app.info.plist.in") +target_link_libraries(qgis QTSignal) endif() if (CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") find_library(EXECINFO_LIBRARY NAMES execinfo) - target_link_libraries(${QGIS_APP_NAME} ${EXECINFO_LIBRARY}) + target_link_libraries(qgis ${EXECINFO_LIBRARY}) endif() if (WITH_PDAL) @@ -708,17 +693,11 @@ install(TARGETS qgis_app RUNTIME DESTINATION ${QGIS_BIN_DIR} LIBRARY DESTINATION ${QGIS_LIB_DIR} ARCHIVE DESTINATION ${QGIS_LIB_DIR} - FRAMEWORK DESTINATION ${QGIS_FW_SUBDIR} PUBLIC_HEADER DESTINATION ${QGIS_INCLUDE_DIR}) -install(TARGETS ${QGIS_APP_NAME} +install(TARGETS qgis BUNDLE DESTINATION ${QGIS_INSTALL_PREFIX} RUNTIME DESTINATION ${QGIS_BIN_DIR} LIBRARY DESTINATION ${QGIS_LIB_DIR} ARCHIVE DESTINATION ${QGIS_LIB_DIR} - FRAMEWORK DESTINATION ${QGIS_FW_SUBDIR} PUBLIC_HEADER DESTINATION ${QGIS_INCLUDE_DIR}) - -if (APPLE) - install(CODE "execute_process(COMMAND /bin/echo -n \"APPLQGIS\" OUTPUT_FILE \"$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/../PkgInfo\")") -endif() diff --git a/src/app/maptools/qgsmaptoolshapecircle2points.cpp b/src/app/maptools/qgsmaptoolshapecircle2points.cpp index 7ab87d5b03f9..ad664dfd51a3 100644 --- a/src/app/maptools/qgsmaptoolshapecircle2points.cpp +++ b/src/app/maptools/qgsmaptoolshapecircle2points.cpp @@ -74,7 +74,7 @@ bool QgsMapToolShapeCircle2Points::cadCanvasReleaseEvent( QgsMapMouseEvent *e, Q void QgsMapToolShapeCircle2Points::cadCanvasMoveEvent( QgsMapMouseEvent *e, QgsMapToolCapture::CaptureMode mode ) { Q_UNUSED( mode ) - if ( !mTempRubberBand ) + if ( !mTempRubberBand || mPoints.isEmpty() ) return; mCircle = QgsCircle::from2Points( mPoints.at( 0 ), mParentTool->mapPoint( *e ) ); diff --git a/src/app/maptools/qgsmaptoolshapecirclecenterpoint.cpp b/src/app/maptools/qgsmaptoolshapecirclecenterpoint.cpp index 371f50a4890a..29188cf85fda 100644 --- a/src/app/maptools/qgsmaptoolshapecirclecenterpoint.cpp +++ b/src/app/maptools/qgsmaptoolshapecirclecenterpoint.cpp @@ -81,7 +81,7 @@ void QgsMapToolShapeCircleCenterPoint::cadCanvasMoveEvent( QgsMapMouseEvent *e, const QgsPoint point = mParentTool->mapPoint( *e ); - if ( mTempRubberBand ) + if ( mTempRubberBand && !mPoints.isEmpty() ) { mCircle = QgsCircle::fromCenterPoint( mPoints.at( 0 ), point ); mTempRubberBand->setGeometry( mCircle.toCircularString( true ) ); diff --git a/src/app/maptools/qgsmaptoolshaperegularpolygon2points.cpp b/src/app/maptools/qgsmaptoolshaperegularpolygon2points.cpp index 4ae5e063ae66..7f66a8675f22 100644 --- a/src/app/maptools/qgsmaptoolshaperegularpolygon2points.cpp +++ b/src/app/maptools/qgsmaptoolshaperegularpolygon2points.cpp @@ -92,7 +92,7 @@ void QgsMapToolShapeRegularPolygon2Points::cadCanvasMoveEvent( QgsMapMouseEvent const QgsPoint point = mParentTool->mapPoint( *e ); - if ( mTempRubberBand ) + if ( mTempRubberBand && !mPoints.isEmpty() ) { mRegularPolygon = QgsRegularPolygon( mPoints.at( 0 ), point, mNumberSidesSpinBox->value() ); mTempRubberBand->setGeometry( mRegularPolygon.toPolygon() ); diff --git a/src/app/maptools/qgsmaptoolshaperegularpolygoncentercorner.cpp b/src/app/maptools/qgsmaptoolshaperegularpolygoncentercorner.cpp index eb092e39278e..f41e0033075a 100644 --- a/src/app/maptools/qgsmaptoolshaperegularpolygoncentercorner.cpp +++ b/src/app/maptools/qgsmaptoolshaperegularpolygoncentercorner.cpp @@ -89,7 +89,7 @@ void QgsMapToolShapeRegularPolygonCenterCorner::cadCanvasMoveEvent( QgsMapMouseE const QgsPoint point = mParentTool->mapPoint( *e ); - if ( mTempRubberBand ) + if ( mTempRubberBand && !mPoints.isEmpty() ) { const QgsRegularPolygon::ConstructionOption option = QgsRegularPolygon::InscribedCircle; mRegularPolygon = QgsRegularPolygon( mPoints.at( 0 ), point, mNumberSidesSpinBox->value(), option ); diff --git a/src/app/maptools/qgsmaptoolshaperegularpolygoncenterpoint.cpp b/src/app/maptools/qgsmaptoolshaperegularpolygoncenterpoint.cpp index c347976d00a9..81c51354167c 100644 --- a/src/app/maptools/qgsmaptoolshaperegularpolygoncenterpoint.cpp +++ b/src/app/maptools/qgsmaptoolshaperegularpolygoncenterpoint.cpp @@ -91,7 +91,7 @@ void QgsMapToolShapeRegularPolygonCenterPoint::cadCanvasMoveEvent( QgsMapMouseEv const QgsPoint point = mParentTool->mapPoint( *e ); - if ( mTempRubberBand ) + if ( mTempRubberBand && !mPoints.isEmpty() ) { const QgsRegularPolygon::ConstructionOption option = QgsRegularPolygon::CircumscribedCircle; mRegularPolygon = QgsRegularPolygon( mPoints.at( 0 ), point, mNumberSidesSpinBox->value(), option ); diff --git a/src/app/qgisapp.cpp b/src/app/qgisapp.cpp index f172e2b93fb8..7be0ede6c547 100644 --- a/src/app/qgisapp.cpp +++ b/src/app/qgisapp.cpp @@ -3801,6 +3801,48 @@ void QgisApp::createToolBars() layout->itemAt( i )->setAlignment( Qt::AlignLeft ); } + // AAAA VEDRAN + + QToolButton *pasteButton = qobject_cast(mDigitizeToolBar->widgetForAction(mActionPasteFeatures)); + if (pasteButton) + { + QMenu *pasteMenu = new QMenu( this ); + pasteButton->setMenu( pasteMenu ); + pasteButton->setPopupMode(QToolButton::MenuButtonPopup); + // pasteButton->setEnabled(true); // Enable the pasteButton widget + // pasteButton->defaultAction()->setEnabled(false); // Disable the main action + mActionPasteFeatures->setEnabled(false); + pasteMenu->addAction( mActionPasteAsNewVector ); + pasteMenu->addAction( mActionPasteAsNewMemoryVector ); + } + + + + + //QMenu *pasteMenu = new QMenu( this ); +// + //QAction *mActionPasteAsNewVector = new QAction( tr( "Paste as new vector layer" ), this ); + //QAction *mActionPasteAsNewMemoryVector = new QAction( tr( "Paste as new memory layer" ), this ); +// + ////connect( actionPasteToLayer1, &QAction::triggered, this, &QgisApp::pasteAsNewVector ); + ////connect( actionPasteToLayer2, &QAction::triggered, this, &QgisApp::pasteToLayerB ); +// + //pasteMenu->addAction( mActionPasteAsNewVector ); + //pasteMenu->addAction( mActionPasteAsNewMemoryVector ); +// + //// Reuse the existing paste action for icon/tooltip, but disable its click + //mActionPasteFeatures->setEnabled( false ); +// + //QToolButton *pasteButton = new QToolButton(); + //pasteButton->setDefaultAction( mActionPasteFeatures ); + //pasteButton->setMenu( pasteMenu ); + //pasteButton->setPopupMode( QToolButton::MenuButtonPopup ); + //pasteButton->setEnabled( true ); // Keep dropdown active +// + //mDigitizeToolBar->addWidget( pasteButton ); + + // AAAA VEDRAN + // Cad toolbar mAdvancedDigitizeToolBar->insertAction( mAdvancedDigitizeToolBar->actions().at( 0 ), mAdvancedDigitizingDockWidget->enableAction() ); @@ -8202,10 +8244,33 @@ void QgisApp::makeMemoryLayerPermanent( QgsVectorLayer *layer ) void QgisApp::saveAsLayerDefinition() { + QString defaultFileName; + + QgsLayerTreeNode *node = mLayerTreeView->currentNode(); + if ( !node ) + return; + + if ( node->nodeType() == QgsLayerTreeNode::NodeLayer ) + { + QgsLayerTreeLayer *layerNode = dynamic_cast( node ); + if ( layerNode && layerNode->layer() ) + { + defaultFileName = QStringLiteral( "/%1.qlr" ).arg( layerNode->layer()->name() ); + } + } + else if ( node->nodeType() == QgsLayerTreeNode::NodeGroup ) + { + QgsLayerTreeGroup *groupNode = dynamic_cast( node ); + if ( groupNode ) + { + defaultFileName = QStringLiteral( "/%1.qlr" ).arg( groupNode->name() ); + } + } + QgsSettings settings; QString lastUsedDir = settings.value( QStringLiteral( "UI/lastQLRDir" ), QDir::homePath() ).toString(); - QString path = QFileDialog::getSaveFileName( this, QStringLiteral( "Save as Layer Definition File" ), lastUsedDir, QStringLiteral( "*.qlr" ) ); + QString path = QFileDialog::getSaveFileName( this, QStringLiteral( "Save as Layer Definition File" ), QStringLiteral( "%1%2" ).arg( lastUsedDir, defaultFileName ), QStringLiteral( "*.qlr" ) ); QgsDebugMsgLevel( path, 2 ); if ( path.isEmpty() ) return; @@ -15034,6 +15099,8 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer *layer ) mActionCutFeatures->setEnabled( false ); mActionCopyFeatures->setEnabled( false ); mActionPasteFeatures->setEnabled( false ); + mActionPasteAsNewVector->setEnabled( true ); //VEDRAN + mActionPasteAsNewMemoryVector->setEnabled( true ); //VEDRAN mActionCopyStyle->setEnabled( false ); mActionPasteStyle->setEnabled( mLayerTreeView && mLayerTreeView->currentNode() && QgsLayerTree::isGroup( mLayerTreeView->currentNode() ) && clipboard()->hasFormat( QStringLiteral( QGSCLIPBOARD_STYLE_MIME ) ) ); mActionCopyLayer->setEnabled( false ); diff --git a/src/app/qgsmaptoolreshape.cpp b/src/app/qgsmaptoolreshape.cpp index b83efc4db6a3..b72eaeca1019 100644 --- a/src/app/qgsmaptoolreshape.cpp +++ b/src/app/qgsmaptoolreshape.cpp @@ -67,15 +67,11 @@ void QgsMapToolReshape::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { deleteTempRubberBand(); - //find out bounding box of mCaptureList - if ( size() < 1 ) + if ( size() > 1 ) { - stopCapturing(); - return; + reshape( vlayer ); } - reshape( vlayer ); - stopCapturing(); } } @@ -164,12 +160,11 @@ void QgsMapToolReshape::reshape( QgsVectorLayer *vlayer ) QgsAvoidIntersectionsOperation avoidIntersections; connect( &avoidIntersections, &QgsAvoidIntersectionsOperation::messageEmitted, this, &QgsMapTool::messageEmitted ); - vlayer->beginEditCommand( tr( "Reshape" ) ); + QHash reshapedGeometries; + + // we first gather the features that are actually going to be reshaped and the reshaped results while ( fit.nextFeature( f ) ) { - //query geometry - //call geometry->reshape(mCaptureList) - //register changed geometry in vector layer QgsGeometry geom = f.geometry(); if ( !geom.isNull() ) { @@ -181,35 +176,44 @@ void QgsMapToolReshape::reshape( QgsVectorLayer *vlayer ) reshapeReturn = geom.reshapeGeometry( reshapeLineString ); if ( reshapeReturn == Qgis::GeometryOperationResult::Success ) { - //avoid intersections on polygon layers - if ( vlayer->geometryType() == Qgis::GeometryType::Polygon ) - { - //ignore all current layer features as they should be reshaped too - QHash> ignoreFeatures; - ignoreFeatures.insert( vlayer, vlayer->allFeatureIds() ); - - const QgsAvoidIntersectionsOperation::Result res = avoidIntersections.apply( vlayer, f.id(), geom, ignoreFeatures ); - if ( res.operationResult == Qgis::GeometryOperationResult::InvalidInputGeometryType ) - { - emit messageEmitted( tr( "An error was reported during intersection removal" ), Qgis::MessageLevel::Warning ); - vlayer->destroyEditCommand(); - stopCapturing(); - return; - } - - if ( geom.isEmpty() ) //intersection removal might have removed the whole geometry - { - emit messageEmitted( tr( "The feature cannot be reshaped because the resulting geometry is empty" ), Qgis::MessageLevel::Critical ); - vlayer->destroyEditCommand(); - return; - } - } - - vlayer->changeGeometry( f.id(), geom ); - reshapeDone = true; + reshapedGeometries.insert( f.id(), geom ); } } } + // ignore features that are going to be reshaped + // some intersected features may not be reshaped because of active selection or reshape line geometry + const QHash> ignoreFeatures { { vlayer, qgis::listToSet( reshapedGeometries.keys() ) } }; + + // then we can apply intersection avoidance logic and eventually update the layer + vlayer->beginEditCommand( tr( "Reshape" ) ); + for ( auto it = reshapedGeometries.begin(); it != reshapedGeometries.end(); ++it ) + { + QgsFeatureId fid = it.key(); + QgsGeometry geom = it.value(); + + //avoid intersections on polygon layers + if ( vlayer->geometryType() == Qgis::GeometryType::Polygon ) + { + const QgsAvoidIntersectionsOperation::Result res = avoidIntersections.apply( vlayer, fid, geom, ignoreFeatures ); + if ( res.operationResult == Qgis::GeometryOperationResult::InvalidInputGeometryType ) + { + emit messageEmitted( tr( "An error was reported during intersection removal" ), Qgis::MessageLevel::Warning ); + vlayer->destroyEditCommand(); + stopCapturing(); + return; + } + + if ( geom.isEmpty() ) //intersection removal might have removed the whole geometry + { + emit messageEmitted( tr( "The feature cannot be reshaped because the resulting geometry is empty" ), Qgis::MessageLevel::Critical ); + vlayer->destroyEditCommand(); + return; + } + } + + vlayer->changeGeometry( fid, geom ); + reshapeDone = true; + } if ( reshapeDone ) { diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 9f1a20083c7f..745dbf49d56f 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -2207,8 +2207,6 @@ if (NOT MSVC) endif() # install headers -# install qgsconfig.h and plugin.h here so they can get into -# the OS X framework target if (HAVE_OPENCL) set(QGIS_CORE_SRCS ${QGIS_CORE_SRCS} @@ -2217,7 +2215,6 @@ if (HAVE_OPENCL) set(QGIS_CORE_HDRS ${QGIS_CORE_HDRS} qgsopenclutils.h ) - include_directories(SYSTEM ${OpenCL_INCLUDE_DIRS}) endif() if (WITH_EPT) @@ -2484,37 +2481,12 @@ endif() if(HAVE_OPENCL) target_link_libraries(qgis_core ${OpenCL_LIBRARY}) + target_include_directories(qgis_core PUBLIC ${OpenCL_INCLUDE_DIRS}) endif() - -if(NOT APPLE OR NOT QGIS_MACAPP_FRAMEWORK) - install(FILES ${QGIS_CORE_HDRS} DESTINATION ${QGIS_INCLUDE_DIR}) - - if(WITH_INTERNAL_NLOHMANN_JSON) - install(FILES ${CMAKE_SOURCE_DIR}/external/nlohmann/json_fwd.hpp DESTINATION ${QGIS_INCLUDE_DIR}/nlohmann) - install(FILES ${CMAKE_SOURCE_DIR}/external/nlohmann/detail/abi_macros.hpp DESTINATION ${QGIS_INCLUDE_DIR}/nlohmann/detail) - endif() -else() - - set_target_properties(qgis_core PROPERTIES - CLEAN_DIRECT_OUTPUT 1 - FRAMEWORK 1 - FRAMEWORK_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}" - MACOSX_FRAMEWORK_INFO_PLIST "${CMAKE_SOURCE_DIR}/mac/framework.info.plist.in" - MACOSX_FRAMEWORK_SHORT_VERSION_STRING ${COMPLETE_VERSION} - MACOSX_FRAMEWORK_IDENTIFIER org.qgis.qgis3_core - BUILD_WITH_INSTALL_RPATH TRUE - PUBLIC_HEADER "${QGIS_CORE_HDRS}" - LINK_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}" - ) - # generated export header does not get copied with PUBLIC_HEADER files - add_custom_command(TARGET qgis_core - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy qgis_core.h - "${QGIS_OUTPUT_DIRECTORY}/${QGIS_LIB_SUBDIR}/qgis_core.framework/Headers" - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - DEPENDS qgis_core.h - ) +if(WITH_INTERNAL_NLOHMANN_JSON) + install(FILES ${CMAKE_SOURCE_DIR}/external/nlohmann/json_fwd.hpp DESTINATION ${QGIS_INCLUDE_DIR}/nlohmann) + install(FILES ${CMAKE_SOURCE_DIR}/external/nlohmann/detail/abi_macros.hpp DESTINATION ${QGIS_INCLUDE_DIR}/nlohmann/detail) endif() #generate unversioned libs for android @@ -2675,17 +2647,11 @@ if(CLANG_TIDY_EXE) endif() # install +if(NOT QGIS_MAC_BUNDLE) + install(FILES ${QGIS_CORE_HDRS} DESTINATION ${QGIS_INCLUDE_DIR}) +endif() install(TARGETS qgis_core RUNTIME DESTINATION ${QGIS_BIN_DIR} LIBRARY DESTINATION ${QGIS_LIB_DIR} - ARCHIVE DESTINATION ${QGIS_LIB_DIR} - FRAMEWORK DESTINATION ${QGIS_FW_SUBDIR} - PUBLIC_HEADER DESTINATION ${QGIS_INCLUDE_DIR}) - -# Mac dev frameworks - -if (APPLE AND QGIS_MACAPP_INSTALL_DEV) - install(TARGETS qgis_core FRAMEWORK DESTINATION ${QGIS_MACAPP_DEV_PREFIX}) - install(CODE "execute_process(COMMAND install_name_tool -id \"${QGIS_MACAPP_DEV_PREFIX}/qgis_core.framework/Versions/${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}/qgis_core\" \"$ENV{DESTDIR}${QGIS_MACAPP_DEV_PREFIX}/qgis_core.framework/qgis_core\")") -endif() + ARCHIVE DESTINATION ${QGIS_LIB_DIR}) diff --git a/src/core/geometry/qgsgeometry.cpp b/src/core/geometry/qgsgeometry.cpp index 325f1564c876..462434076f4f 100644 --- a/src/core/geometry/qgsgeometry.cpp +++ b/src/core/geometry/qgsgeometry.cpp @@ -1241,7 +1241,17 @@ Qgis::GeometryOperationResult QgsGeometry::reshapeGeometry( const QgsLineString return Qgis::GeometryOperationResult::InvalidBaseGeometry; } - QgsGeos geos( d->geometry.get() ); + // We're trying adding the reshape line's vertices to the geometry so that + // snap to segment always produces a valid reshape + QgsPointSequence reshapePoints; + reshapeLineString.points( reshapePoints ); + QgsGeometry tmpGeom( *this ); + for ( const QgsPoint &v : std::as_const( reshapePoints ) ) + { + tmpGeom.addTopologicalPoint( v ); + } + + QgsGeos geos( tmpGeom.get() ); QgsGeometryEngine::EngineOperationResult errorCode = QgsGeometryEngine::Success; mLastError.clear(); std::unique_ptr< QgsAbstractGeometry > geom( geos.reshapeGeometry( reshapeLineString, &errorCode, &mLastError ) ); diff --git a/src/core/geometry/qgsgeometry.h b/src/core/geometry/qgsgeometry.h index 98e40e74e141..8b87e5969a3b 100644 --- a/src/core/geometry/qgsgeometry.h +++ b/src/core/geometry/qgsgeometry.h @@ -67,7 +67,24 @@ typedef QVector QgsPolylineXY; * This type has full support for Z/M dimensions. * */ +#ifndef SIP_RUN typedef QgsPointSequence QgsPolyline; +#else +typedef QVector QgsPolyline; +#endif + +/** + * Multi polyline represented as a vector of polylines. + * + * This type has full support for Z/M dimensions. + * + * \since QGIS 3.44 + */ +#ifndef SIP_RUN +typedef QVector QgsMultiPolyline; +#else +typedef QVector> QgsMultiPolyline; +#endif //! Polygon: first item of the list is outer ring, inner rings (if any) start from second item #ifndef SIP_RUN diff --git a/src/core/geometry/qgsgeos.cpp b/src/core/geometry/qgsgeos.cpp index 833ccebec742..33a6ad08c49a 100644 --- a/src/core/geometry/qgsgeos.cpp +++ b/src/core/geometry/qgsgeos.cpp @@ -33,13 +33,13 @@ email : marco.hugentobler at sourcepole dot com #define DEFAULT_QUADRANT_SEGMENTS 8 #define CATCH_GEOS(r) \ - catch (GEOSException &) \ + catch (QgsGeosException &) \ { \ return r; \ } #define CATCH_GEOS_WITH_ERRMSG(r) \ - catch (GEOSException &e) \ + catch (QgsGeosException &e) \ { \ if ( errorMsg ) \ { \ @@ -50,7 +50,7 @@ email : marco.hugentobler at sourcepole dot com /// @cond PRIVATE -static void throwGEOSException( const char *fmt, ... ) +static void throwQgsGeosException( const char *fmt, ... ) { va_list ap; char buffer[1024]; @@ -62,14 +62,14 @@ static void throwGEOSException( const char *fmt, ... ) QString message = QString::fromUtf8( buffer ); #ifdef _MSC_VER - // stupid stupid MSVC, *SOMETIMES* raises it's own exception if we throw GEOSException, resulting in a crash! + // stupid stupid MSVC, *SOMETIMES* raises it's own exception if we throw QgsGeosException, resulting in a crash! // see https://github.com/qgis/QGIS/issues/22709 // if you want to test alternative fixes for this, run the testqgsexpression.cpp test suite - that will crash - // and burn on the "line_interpolate_point point" test if a GEOSException is thrown. + // and burn on the "line_interpolate_point point" test if a QgsGeosException is thrown. // TODO - find a real fix for the underlying issue try { - throw GEOSException( message ); + throw QgsGeosException( message ); } catch ( ... ) { @@ -77,7 +77,7 @@ static void throwGEOSException( const char *fmt, ... ) // just throw nothing instead (except your mouse at your monitor) } #else - throw GEOSException( message ); + throw QgsGeosException( message ); #endif } @@ -112,9 +112,9 @@ QgsGeosContext::QgsGeosContext() #if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=5 ) mContext = GEOS_init_r(); GEOSContext_setNoticeHandler_r( mContext, printGEOSNotice ); - GEOSContext_setErrorHandler_r( mContext, throwGEOSException ); + GEOSContext_setErrorHandler_r( mContext, throwQgsGeosException ); #else - mContext = initGEOS_r( printGEOSNotice, throwGEOSException ); + mContext = initGEOS_r( printGEOSNotice, throwQgsGeosException ); #endif } @@ -240,7 +240,7 @@ std::unique_ptr QgsGeos::makeValid( Qgis::MakeValidMethod m geos.reset( GEOSMakeValidWithParams_r( context, mGeos.get(), params ) ); GEOSMakeValidParams_destroy_r( context, params ); } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { if ( errorMsg ) { @@ -336,7 +336,7 @@ std::unique_ptr QgsGeos::clip( const QgsRectangle &rect, QS geos::unique_ptr opGeom( GEOSClipByRect_r( QgsGeosContext::get(), mGeos.get(), rect.xMinimum(), rect.yMinimum(), rect.xMaximum(), rect.yMaximum() ) ); return fromGeos( opGeom.get() ); } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { logError( QStringLiteral( "GEOS" ), e.what() ); if ( errorMsg ) @@ -741,7 +741,7 @@ bool QgsGeos::contains( double x, double y, QString *errorMsg ) const result = ( GEOSContains_r( context, mGeos.get(), point.get() ) == 1 ); } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { logError( QStringLiteral( "GEOS" ), e.what() ); if ( errorMsg ) @@ -863,7 +863,7 @@ bool QgsGeos::intersects( const QgsAbstractGeometry *geom, QString *errorMsg ) c { return GEOSPreparedIntersectsXY_r( QgsGeosContext::get(), mGeosPrepared.get(), point->x(), point->y() ) == 1; } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { logError( QStringLiteral( "GEOS" ), e.what() ); if ( errorMsg ) @@ -916,7 +916,7 @@ bool QgsGeos::contains( const QgsAbstractGeometry *geom, QString *errorMsg ) con { return GEOSPreparedContainsXY_r( QgsGeosContext::get(), mGeosPrepared.get(), point->x(), point->y() ) == 1; } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { logError( QStringLiteral( "GEOS" ), e.what() ); if ( errorMsg ) @@ -961,7 +961,7 @@ QString QgsGeos::relate( const QgsAbstractGeometry *geom, QString *errorMsg ) co GEOSFree_r( context, r ); } } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { logError( QStringLiteral( "GEOS" ), e.what() ); if ( errorMsg ) @@ -992,7 +992,7 @@ bool QgsGeos::relatePattern( const QgsAbstractGeometry *geom, const QString &pat { result = ( GEOSRelatePattern_r( context, mGeos.get(), geosGeom.get(), pattern.toLocal8Bit().constData() ) == 1 ); } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { logError( QStringLiteral( "GEOS" ), e.what() ); if ( errorMsg ) @@ -1554,7 +1554,7 @@ geos::unique_ptr QgsGeos::createGeosCollection( int typeId, std::vector QgsGeos::overlay( const QgsAbstractGeometry } return fromGeos( opGeom.get() ); } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { logError( QStringLiteral( "GEOS" ), e.what() ); if ( errorMsg ) @@ -2071,7 +2071,7 @@ bool QgsGeos::relation( const QgsAbstractGeometry *geom, Relation r, QString *er break; } } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { logError( QStringLiteral( "GEOS" ), e.what() ); if ( errorMsg ) @@ -3114,7 +3114,7 @@ std::unique_ptr QgsGeos::closestPoint( const QgsGeometry &o ( void )GEOSCoordSeq_getX_r( context, nearestCoord.get(), 0, &nx ); ( void )GEOSCoordSeq_getY_r( context, nearestCoord.get(), 0, &ny ); } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { logError( QStringLiteral( "GEOS" ), e.what() ); if ( errorMsg ) @@ -3169,7 +3169,7 @@ std::unique_ptr< QgsAbstractGeometry > QgsGeos::shortestLine( const QgsAbstractG ( void )GEOSCoordSeq_getX_r( context, nearestCoord.get(), 1, &nx2 ); ( void )GEOSCoordSeq_getY_r( context, nearestCoord.get(), 1, &ny2 ); } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { logError( QStringLiteral( "GEOS" ), e.what() ); if ( errorMsg ) @@ -3203,7 +3203,7 @@ double QgsGeos::lineLocatePoint( const QgsPoint &point, QString *errorMsg ) cons { distance = GEOSProject_r( QgsGeosContext::get(), mGeos.get(), otherGeom.get() ); } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { logError( QStringLiteral( "GEOS" ), e.what() ); if ( errorMsg ) @@ -3232,7 +3232,7 @@ double QgsGeos::lineLocatePoint( double x, double y, QString *errorMsg ) const { distance = GEOSProject_r( QgsGeosContext::get(), mGeos.get(), point.get() ); } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { logError( QStringLiteral( "GEOS" ), e.what() ); if ( errorMsg ) @@ -3270,7 +3270,7 @@ QgsGeometry QgsGeos::polygonize( const QVector &geo delete[] lineGeosGeometries; return QgsGeometry( fromGeos( result.get() ) ); } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { if ( errorMsg ) { @@ -3475,7 +3475,7 @@ geos::unique_ptr QgsGeos::reshapeLine( const GEOSGeometry *line, const GEOSGeome } } } - catch ( GEOSException & ) + catch ( QgsGeosException & ) { atLeastTwoIntersections = false; } @@ -3736,7 +3736,7 @@ geos::unique_ptr QgsGeos::reshapePolygon( const GEOSGeometry *polygon, const GEO } } } - catch ( GEOSException & ) + catch ( QgsGeosException & ) { nIntersections = 0; } @@ -3766,7 +3766,7 @@ geos::unique_ptr QgsGeos::reshapePolygon( const GEOSGeometry *polygon, const GEO { newRing = GEOSGeom_createLinearRing_r( context, newCoordSequence ); } - catch ( GEOSException & ) + catch ( QgsGeosException & ) { // nothing to do: on exception newRing will be null } diff --git a/src/core/geometry/qgsgeos.h b/src/core/geometry/qgsgeos.h index 6949f8ca711f..b21f7d7a04ca 100644 --- a/src/core/geometry/qgsgeos.h +++ b/src/core/geometry/qgsgeos.h @@ -945,10 +945,10 @@ class CORE_EXPORT QgsGeos: public QgsGeometryEngine #ifndef SIP_RUN -class GEOSException : public std::runtime_error +class QgsGeosException : public std::runtime_error { public: - explicit GEOSException( const QString &message ) + explicit QgsGeosException( const QString &message ) : std::runtime_error( message.toUtf8().constData() ) { } diff --git a/src/core/labeling/rules/qgslabelingenginerule_impl.cpp b/src/core/labeling/rules/qgslabelingenginerule_impl.cpp index cf97f92679a4..01c846b1b475 100644 --- a/src/core/labeling/rules/qgslabelingenginerule_impl.cpp +++ b/src/core/labeling/rules/qgslabelingenginerule_impl.cpp @@ -226,7 +226,7 @@ bool QgsAbstractLabelingEngineRuleDistanceFromFeature::candidateExceedsTolerance return false; #endif } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { QgsDebugError( QStringLiteral( "GEOS exception: %1" ).arg( e.what() ) ); } @@ -457,7 +457,7 @@ bool QgsLabelingEngineRuleMinimumDistanceLabelToLabel::candidatesAreConflicting( return false; #endif } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { QgsDebugError( QStringLiteral( "GEOS exception: %1" ).arg( e.what() ) ); } @@ -609,7 +609,7 @@ bool QgsLabelingEngineRuleAvoidLabelOverlapWithFeature::candidateIsIllegal( cons if ( GEOSPreparedIntersects_r( geosctxt, candidateGeos, featureCandidate.get() ) == 1 ) return true; } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { QgsDebugError( QStringLiteral( "GEOS exception: %1" ).arg( e.what() ) ); } diff --git a/src/core/layout/qgslayoutitemmap.cpp b/src/core/layout/qgslayoutitemmap.cpp index 296c5ea2e7af..7d760d7f1696 100644 --- a/src/core/layout/qgslayoutitemmap.cpp +++ b/src/core/layout/qgslayoutitemmap.cpp @@ -1135,13 +1135,13 @@ void QgsLayoutItemMap::paint( QPainter *painter, const QStyleOptionGraphicsItem { // current job was invalidated - start a new one mPreviewScaleFactor = QgsLayoutUtils::scaleFactorFromItemStyle( style, painter ); - mBackgroundUpdateTimer->start( 1 ); + mBackgroundUpdateTimer->start( 100 ); } else if ( !mPainterJob && !mDrawingPreview ) { // this is the map's very first paint - trigger a cache update mPreviewScaleFactor = QgsLayoutUtils::scaleFactorFromItemStyle( style, painter ); - mBackgroundUpdateTimer->start( 1 ); + mBackgroundUpdateTimer->start( 100 ); } renderInProgress = true; } @@ -1151,7 +1151,7 @@ void QgsLayoutItemMap::paint( QPainter *painter, const QStyleOptionGraphicsItem { // cache was invalidated - trigger a background update mPreviewScaleFactor = QgsLayoutUtils::scaleFactorFromItemStyle( style, painter ); - mBackgroundUpdateTimer->start( 1 ); + mBackgroundUpdateTimer->start( 100 ); renderInProgress = true; } diff --git a/src/core/pal/feature.cpp b/src/core/pal/feature.cpp index ceeb53e36de9..6e36c245254d 100644 --- a/src/core/pal/feature.cpp +++ b/src/core/pal/feature.cpp @@ -420,7 +420,7 @@ std::unique_ptr FeaturePart::createCandidatePointOnSurface( Point GEOSCoordSeq_getXY_r( geosctxt, coordSeq, 0, &px, &py ); } } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { qWarning( "GEOS exception: %s", e.what() ); QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) ); @@ -2424,7 +2424,7 @@ bool FeaturePart::isConnected( FeaturePart *p2 ) return ( GEOSPreparedIntersects_r( geosctxt, preparedGeom(), p2OtherEnd.get() ) != 1 ); #endif } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { qWarning( "GEOS exception: %s", e.what() ); QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) ); @@ -2465,7 +2465,7 @@ bool FeaturePart::mergeWithFeaturePart( FeaturePart *other ) extractCoords( mGeos ); return true; } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { qWarning( "GEOS exception: %s", e.what() ); QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) ); diff --git a/src/core/pal/geomfunction.cpp b/src/core/pal/geomfunction.cpp index c23be07d8c9c..e19253255d24 100644 --- a/src/core/pal/geomfunction.cpp +++ b/src/core/pal/geomfunction.cpp @@ -336,7 +336,7 @@ bool GeomFunction::containsCandidate( const GEOSPreparedGeometry *geom, double x const bool result = ( GEOSPreparedContainsProperly_r( geosctxt, geom, bboxGeos.get() ) == 1 ); return result; } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { qWarning( "GEOS exception: %s", e.what() ); Q_NOWARN_UNREACHABLE_PUSH diff --git a/src/core/pal/labelposition.cpp b/src/core/pal/labelposition.cpp index f8127be7bfac..868c8c5f9f3d 100644 --- a/src/core/pal/labelposition.cpp +++ b/src/core/pal/labelposition.cpp @@ -190,7 +190,7 @@ bool LabelPosition::intersects( const GEOSPreparedGeometry *geometry ) return mNextPart->intersects( geometry ); } } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { qWarning( "GEOS exception: %s", e.what() ); QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) ); @@ -217,7 +217,7 @@ bool LabelPosition::within( const GEOSPreparedGeometry *geometry ) return mNextPart->within( geometry ); } } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { qWarning( "GEOS exception: %s", e.what() ); QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) ); @@ -301,7 +301,7 @@ bool LabelPosition::isInConflict( const LabelPosition *lp ) const QgsMessageLog::logMessage( QStringLiteral( "label margin distance requires GEOS 3.10+" ) ); #endif } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { QgsDebugError( QStringLiteral( "GEOS exception: %1" ).arg( e.what() ) ); } @@ -318,7 +318,7 @@ bool LabelPosition::isInConflict( const LabelPosition *lp ) const mOuterBoundsGeos ? mOuterBoundsGeos.get() : mGeos ) == 1 ); return result; } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { qWarning( "GEOS exception: %s", e.what() ); QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) ); @@ -364,7 +364,7 @@ bool LabelPosition::isInConflictMultiPart( const LabelPosition *lp ) const QgsMessageLog::logMessage( QStringLiteral( "label margin distance requires GEOS 3.10+" ) ); #endif } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { QgsDebugError( QStringLiteral( "GEOS exception: %1" ).arg( e.what() ) ); } @@ -376,7 +376,7 @@ bool LabelPosition::isInConflictMultiPart( const LabelPosition *lp ) const const bool result = ( GEOSPreparedIntersects_r( geosctxt, preparedMultiPartGeom(), lp->mMultipartGeos ) == 1 ); return result; } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { qWarning( "GEOS exception: %s", e.what() ); QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) ); @@ -695,7 +695,7 @@ double LabelPosition::getDistanceToPoint( double xp, double yp, bool useOuterBou geos::unique_ptr point( GEOSGeom_createPointFromXY_r( geosctxt, xp, yp ) ); contains = ( GEOSPreparedContainsProperly_r( geosctxt, mPreparedOuterBoundsGeos, point.get() ) == 1 ); } - catch ( GEOSException & ) + catch ( QgsGeosException & ) { contains = false; } @@ -747,7 +747,7 @@ double LabelPosition::getDistanceToPoint( double xp, double yp, bool useOuterBou distance = QgsGeometryUtilsBase::sqrDistance2D( xp, yp, nx, ny ); } } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { qWarning( "GEOS exception: %s", e.what() ); QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) ); @@ -788,7 +788,7 @@ bool LabelPosition::crossesLine( PointSet *line ) const return mNextPart->crossesLine( line ); } } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { qWarning( "GEOS exception: %s", e.what() ); QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) ); @@ -820,7 +820,7 @@ bool LabelPosition::crossesBoundary( PointSet *polygon ) const return mNextPart->crossesBoundary( polygon ); } } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { qWarning( "GEOS exception: %s", e.what() ); QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) ); @@ -855,7 +855,7 @@ bool LabelPosition::intersectsWithPolygon( PointSet *polygon ) const return true; } } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { qWarning( "GEOS exception: %s", e.what() ); QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) ); @@ -914,7 +914,7 @@ double LabelPosition::polygonIntersectionCostForParts( PointSet *polygon ) const cost += 4; } } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { qWarning( "GEOS exception: %s", e.what() ); QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) ); diff --git a/src/core/pal/pal.cpp b/src/core/pal/pal.cpp index 375de075adb6..2b818a3e4bc0 100644 --- a/src/core/pal/pal.cpp +++ b/src/core/pal/pal.cpp @@ -790,7 +790,7 @@ bool Pal::candidatesAreConflicting( const LabelPosition *lp1, const LabelPositio QgsMessageLog::logMessage( QStringLiteral( "label margin distance requires GEOS 3.10+" ) ); #endif } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { QgsDebugError( QStringLiteral( "GEOS exception: %1" ).arg( e.what() ) ); } diff --git a/src/core/pal/pointset.cpp b/src/core/pal/pointset.cpp index 46c559ef45f3..ea5c41a5ae2a 100644 --- a/src/core/pal/pointset.cpp +++ b/src/core/pal/pointset.cpp @@ -278,7 +278,7 @@ bool PointSet::containsPoint( double x, double y ) const return result; } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { qWarning( "GEOS exception: %s", e.what() ); QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) ); @@ -617,7 +617,7 @@ void PointSet::offsetCurveByDistance( double distance ) x = std::move( newX ); y = std::move( newY ); } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { qWarning( "GEOS exception: %s", e.what() ); QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) ); @@ -907,7 +907,7 @@ double PointSet::minDistanceToPoint( double px, double py, double *rx, double *r return QgsGeometryUtilsBase::sqrDistance2D( px, py, nx, ny ); } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { qWarning( "GEOS exception: %s", e.what() ); QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) ); @@ -954,7 +954,7 @@ void PointSet::getCentroid( double &px, double &py, bool forceInside ) const } } } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { qWarning( "GEOS exception: %s", e.what() ); QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) ); @@ -1023,7 +1023,7 @@ geos::unique_ptr PointSet::interpolatePoint( double distance ) const geos::unique_ptr res( GEOSInterpolate_r( QgsGeosContext::get(), thisGeos, distance ) ); return res; } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { qWarning( "GEOS exception: %s", e.what() ); return nullptr; @@ -1041,7 +1041,7 @@ double PointSet::lineLocatePoint( const GEOSGeometry *point ) const { distance = GEOSProject_r( QgsGeosContext::get(), thisGeos, point ); } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { qWarning( "GEOS exception: %s", e.what() ); return -1; @@ -1076,7 +1076,7 @@ double PointSet::length() const ( void )GEOSLength_r( geosctxt, mGeos, &mLength ); return mLength; } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { qWarning( "GEOS exception: %s", e.what() ); QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) ); @@ -1103,7 +1103,7 @@ double PointSet::area() const mArea = std::fabs( mArea ); return mArea; } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { qWarning( "GEOS exception: %s", e.what() ); QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) ); @@ -1137,7 +1137,7 @@ QString PointSet::toWkt() const return res; } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { qWarning( "GEOS exception: %s", e.what() ); QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) ); diff --git a/src/core/providers/ogr/qgsogrprovider.cpp b/src/core/providers/ogr/qgsogrprovider.cpp index 87bcc5518bff..36a4bd4dd030 100644 --- a/src/core/providers/ogr/qgsogrprovider.cpp +++ b/src/core/providers/ogr/qgsogrprovider.cpp @@ -830,6 +830,20 @@ void QgsOgrProvider::loadFields() QMutexLocker locker( mutex ); mOGRGeomType = getOgrGeomType( mGDALDriverName, ogrLayer ); } + + mCrs = QgsCoordinateReferenceSystem(); + if ( mOGRGeomType != wkbNone ) + { + if ( OGRSpatialReferenceH spatialRefSys = mOgrLayer->GetSpatialRef() ) + { + mCrs = QgsOgrUtils::OGRSpatialReferenceToCrs( spatialRefSys ); + } + else + { + QgsDebugMsgLevel( QStringLiteral( "no spatial reference found" ), 2 ); + } + } + QgsOgrFeatureDefn &fdef = mOgrLayer->GetLayerDefn(); // Expose the OGR FID if it comes from a "real" column (typically GPKG) @@ -3864,20 +3878,10 @@ QString QgsOgrProvider::description() const QgsCoordinateReferenceSystem QgsOgrProvider::crs() const { - QgsCoordinateReferenceSystem srs; if ( !mValid || ( mOGRGeomType == wkbNone ) ) - return srs; - - if ( OGRSpatialReferenceH spatialRefSys = mOgrLayer->GetSpatialRef() ) - { - srs = QgsOgrUtils::OGRSpatialReferenceToCrs( spatialRefSys ); - } - else - { - QgsDebugMsgLevel( QStringLiteral( "no spatial reference found" ), 2 ); - } + return QgsCoordinateReferenceSystem(); - return srs; + return mCrs; } QString QgsOgrProvider::dataComment() const diff --git a/src/core/providers/ogr/qgsogrprovider.h b/src/core/providers/ogr/qgsogrprovider.h index bf8c4a209a8e..a8c1e645500b 100644 --- a/src/core/providers/ogr/qgsogrprovider.h +++ b/src/core/providers/ogr/qgsogrprovider.h @@ -304,6 +304,7 @@ class QgsOgrProvider final: public QgsVectorDataProvider bool mValid = false; OGRwkbGeometryType mOGRGeomType = wkbUnknown; + QgsCoordinateReferenceSystem mCrs; //! Whether the next call to featureCount() should refresh the feature count mutable bool mRefreshFeatureCount = true; diff --git a/src/core/qgsapplication.cpp b/src/core/qgsapplication.cpp index 72442e079630..99d9eeead677 100644 --- a/src/core/qgsapplication.cpp +++ b/src/core/qgsapplication.cpp @@ -358,8 +358,11 @@ void QgsApplication::init( QString profileFolder ) { if ( sPrefixPath()->isNull() ) { -#if defined(Q_OS_MACOS) || defined(Q_OS_WIN) +#if defined(Q_OS_WIN) || defined(Q_OS_MACOS) && !defined(QGIS_MAC_BUNDLE) setPrefixPath( applicationDirPath(), true ); +#elif defined(QGIS_MAC_BUNDLE) + QDir myDir( applicationDirPath() + QLatin1String( "/../.." ) ); + setPrefixPath( myDir.absolutePath(), true ); #elif defined(ANDROID) // this is "/data/data/org.qgis.qgis" in android QDir myDir( QDir::homePath() ); diff --git a/src/core/qgsgml.cpp b/src/core/qgsgml.cpp index 217edac9513c..ef3fcf1ba046 100644 --- a/src/core/qgsgml.cpp +++ b/src/core/qgsgml.cpp @@ -1075,7 +1075,7 @@ void QgsGmlStreamingParser::endElement( const XML_Char *el ) const int localNameLen = ( pszSep ) ? ( int )( elLen - nsLen ) - 1 : elLen; const ParseMode parseMode( mParseModeStack.isEmpty() ? None : mParseModeStack.top() ); - const int lastDimension = mDimensionStack.isEmpty() ? 0 : mDimensionStack.pop(); + const int lastDimension = mDimensionStack.isEmpty() ? 2 : mDimensionStack.pop(); const bool isGMLNS = ( nsLen == mGMLNameSpaceURI.size() && mGMLNameSpaceURIPtr && memcmp( el, mGMLNameSpaceURIPtr, nsLen ) == 0 ); @@ -1215,7 +1215,7 @@ void QgsGmlStreamingParser::endElement( const XML_Char *el ) } else if ( parseMode == LowerCorner && isGMLNS && LOCALNAME_EQUALS( "lowerCorner" ) ) { - QList points; + QList points; pointsFromPosListString( points, mStringCash, 2 ); if ( points.size() == 1 ) { @@ -1226,7 +1226,7 @@ void QgsGmlStreamingParser::endElement( const XML_Char *el ) } else if ( parseMode == UpperCorner && isGMLNS && LOCALNAME_EQUALS( "upperCorner" ) ) { - QList points; + QList points; pointsFromPosListString( points, mStringCash, 2 ); if ( points.size() == 1 ) { @@ -1279,12 +1279,14 @@ void QgsGmlStreamingParser::endElement( const XML_Char *el ) } else if ( !mAttributeValIsNested && isGMLNS && LOCALNAME_EQUALS( "Point" ) ) { - QList pointList; - if ( pointsFromString( pointList, mStringCash ) != 0 ) + QList pointList; + int dimension = 0; + if ( pointsFromString( pointList, mStringCash, &dimension ) != 0 ) { //error } mStringCash.clear(); + mDimension = dimension; if ( pointList.isEmpty() ) return; // error @@ -1292,20 +1294,21 @@ void QgsGmlStreamingParser::endElement( const XML_Char *el ) if ( parseMode == QgsGmlStreamingParser::Geometry ) { //directly add WKB point to the feature - if ( getPointWKB( mCurrentWKB, *( pointList.constBegin() ) ) != 0 ) + if ( getPointWKB( mCurrentWKB, *( pointList.constBegin() ), dimension ) != 0 ) { //error } - if ( mWkbType != Qgis::WkbType::MultiPoint ) //keep multitype in case of geometry type mix + if ( QgsWkbTypes::flatType( mWkbType ) != Qgis::WkbType::MultiPoint ) //keep multitype in case of geometry type mix { - mWkbType = Qgis::WkbType::Point; + mWkbType = dimension > 2 ? Qgis::WkbType::PointZ : Qgis::WkbType::Point; } + } else //multipoint, add WKB as fragment { QByteArray wkbPtr; - if ( getPointWKB( wkbPtr, *( pointList.constBegin() ) ) != 0 ) + if ( getPointWKB( wkbPtr, *( pointList.constBegin() ), dimension ) != 0 ) { //error } @@ -1324,32 +1327,40 @@ void QgsGmlStreamingParser::endElement( const XML_Char *el ) { //add WKB point to the feature - QList pointList; - if ( pointsFromString( pointList, mStringCash ) != 0 ) + QList pointList; + int dimension = 0; + if ( pointsFromString( pointList, mStringCash, &dimension ) != 0 ) { //error } mStringCash.clear(); + mDimension = dimension; if ( parseMode == QgsGmlStreamingParser::Geometry ) { - if ( getLineWKB( mCurrentWKB, pointList ) != 0 ) + if ( getLineWKB( mCurrentWKB, pointList, dimension ) != 0 ) { //error } - if ( mWkbType != Qgis::WkbType::MultiLineString )//keep multitype in case of geometry type mix + if ( QgsWkbTypes::flatType( mWkbType ) != Qgis::WkbType::MultiLineString )//keep multitype in case of geometry type mix + { + mWkbType = dimension > 2 ? Qgis::WkbType::LineStringZ : Qgis::WkbType::LineString; + } + else if ( dimension > 2 ) { - mWkbType = Qgis::WkbType::LineString; + mWkbType = Qgis::WkbType::MultiLineStringZ; } + mDimension = dimension; } else //multiline, add WKB as fragment { QByteArray wkbPtr; - if ( getLineWKB( wkbPtr, pointList ) != 0 ) + if ( getLineWKB( wkbPtr, pointList, dimension ) != 0 ) { //error } + mDimension = dimension; if ( !mCurrentWKBFragments.isEmpty() ) { mCurrentWKBFragments.last().push_back( wkbPtr ); @@ -1363,15 +1374,17 @@ void QgsGmlStreamingParser::endElement( const XML_Char *el ) else if ( ( parseMode == Geometry || parseMode == MultiPolygon ) && isGMLNS && LOCALNAME_EQUALS( "LinearRing" ) ) { - QList pointList; - if ( pointsFromString( pointList, mStringCash ) != 0 ) + QList pointList; + int dimension = 0; + if ( pointsFromString( pointList, mStringCash, &dimension ) != 0 ) { //error } mStringCash.clear(); + mDimension = dimension; QByteArray wkbPtr; - if ( getRingWKB( wkbPtr, pointList ) != 0 ) + if ( getRingWKB( wkbPtr, pointList, dimension ) != 0 ) { //error } @@ -1388,9 +1401,9 @@ void QgsGmlStreamingParser::endElement( const XML_Char *el ) else if ( ( parseMode == Geometry || parseMode == MultiPolygon ) && isGMLNS && LOCALNAME_EQUALS( "Polygon" ) ) { - if ( mWkbType != Qgis::WkbType::MultiPolygon )//keep multitype in case of geometry type mix + if ( QgsWkbTypes::flatType( mWkbType ) != Qgis::WkbType::MultiPolygon ) //keep multitype in case of geometry type mix { - mWkbType = Qgis::WkbType::Polygon; + mWkbType = mDimension > 2 ? Qgis::WkbType::PolygonZ : Qgis::WkbType::Polygon; } if ( parseMode == Geometry ) @@ -1401,21 +1414,21 @@ void QgsGmlStreamingParser::endElement( const XML_Char *el ) else if ( parseMode == MultiPoint && isGMLNS && LOCALNAME_EQUALS( "MultiPoint" ) ) { - mWkbType = Qgis::WkbType::MultiPoint; + mWkbType = mDimension > 2 ? Qgis::WkbType::MultiPointZ : Qgis::WkbType::MultiPoint; mParseModeStack.pop(); createMultiPointFromFragments(); } else if ( parseMode == MultiLine && isGMLNS && ( LOCALNAME_EQUALS( "MultiLineString" ) || LOCALNAME_EQUALS( "MultiCurve" ) ) ) { - mWkbType = Qgis::WkbType::MultiLineString; + mWkbType = mDimension > 2 ? Qgis::WkbType::MultiLineStringZ : Qgis::WkbType::MultiLineString; mParseModeStack.pop(); createMultiLineFromFragments(); } else if ( parseMode == MultiPolygon && isGMLNS && ( LOCALNAME_EQUALS( "MultiPolygon" ) || LOCALNAME_EQUALS( "MultiSurface" ) ) ) { - mWkbType = Qgis::WkbType::MultiPolygon; + mWkbType = mDimension > 2 ? Qgis::WkbType::MultiPolygonZ : Qgis::WkbType::MultiPolygon; mParseModeStack.pop(); createMultiPolygonFromFragments(); } @@ -1584,7 +1597,7 @@ QString QgsGmlStreamingParser::readAttribute( const QString &attributeName, cons bool QgsGmlStreamingParser::createBBoxFromCoordinateString( QgsRectangle &r, const QString &coordString ) const { - QList points; + QList points; if ( pointsFromCoordinateString( points, coordString ) != 0 ) { return false; @@ -1600,18 +1613,25 @@ bool QgsGmlStreamingParser::createBBoxFromCoordinateString( QgsRectangle &r, con return true; } -int QgsGmlStreamingParser::pointsFromCoordinateString( QList &points, const QString &coordString ) const +int QgsGmlStreamingParser::pointsFromCoordinateString( QList &points, const QString &coordString, int *dimension ) const { //tuples are separated by space, x/y by ',' const QStringList tuples = coordString.split( mTupleSeparator, Qt::SkipEmptyParts ); QStringList tuples_coordinates; - double x, y; + double x, y, z; bool conversionSuccess; + if ( dimension ) + *dimension = 0; + QStringList::const_iterator tupleIterator; for ( tupleIterator = tuples.constBegin(); tupleIterator != tuples.constEnd(); ++tupleIterator ) { tuples_coordinates = tupleIterator->split( mCoordinateSeparator, Qt::SkipEmptyParts ); + if ( dimension ) + { + *dimension = std::max( *dimension, static_cast( tuples_coordinates.size() ) ); + } if ( tuples_coordinates.size() < 2 ) { continue; @@ -1626,12 +1646,30 @@ int QgsGmlStreamingParser::pointsFromCoordinateString( QList &points { continue; } - points.push_back( ( mInvertAxisOrientation ) ? QgsPointXY( y, x ) : QgsPointXY( x, y ) ); + if ( tuples_coordinates.size() > 2 ) + { + z = tuples_coordinates.at( 2 ).toDouble( &conversionSuccess ); + if ( !conversionSuccess ) + { + continue; + } + } + else + { + z = std::numeric_limits::quiet_NaN(); // no Z coordinate + } + points.push_back( ( mInvertAxisOrientation ) ? QgsPoint( y, x, z ) : QgsPoint( x, y, z ) ); } + + if ( dimension && *dimension == 0 ) + { + *dimension = 2; // default dimension is 2D + } + return 0; } -int QgsGmlStreamingParser::pointsFromPosListString( QList &points, const QString &coordString, int dimension ) const +int QgsGmlStreamingParser::pointsFromPosListString( QList &points, const QString &coordString, int dimension ) const { // coordinates separated by spaces const QStringList coordinates = coordString.split( ' ', Qt::SkipEmptyParts ); @@ -1655,66 +1693,91 @@ int QgsGmlStreamingParser::pointsFromPosListString( QList &points, c { continue; } - points.append( ( mInvertAxisOrientation ) ? QgsPointXY( y, x ) : QgsPointXY( x, y ) ); + double z = std::numeric_limits::quiet_NaN(); + if ( dimension > 2 ) + { + z = coordinates.value( i * dimension + 2 ).toDouble( &conversionSuccess ); + if ( !conversionSuccess ) + { + continue; + } + } + points.append( mInvertAxisOrientation ? QgsPoint( y, x, z ) : QgsPoint( x, y, z ) ); } return 0; } -int QgsGmlStreamingParser::pointsFromString( QList &points, const QString &coordString ) const +int QgsGmlStreamingParser::pointsFromString( QList &points, const QString &coordString, int *dimension ) const { if ( mCoorMode == QgsGmlStreamingParser::Coordinate ) { - return pointsFromCoordinateString( points, coordString ); + return pointsFromCoordinateString( points, coordString, dimension ); } else if ( mCoorMode == QgsGmlStreamingParser::PosList ) { + if ( dimension ) + { + *dimension = mDimension ? mDimension : 2; // default dimension is 2D + } return pointsFromPosListString( points, coordString, mDimension ? mDimension : 2 ); } return 1; } -int QgsGmlStreamingParser::getPointWKB( QByteArray &wkbPtr, const QgsPointXY &point ) const +int QgsGmlStreamingParser::getPointWKB( QByteArray &wkbPtr, const QgsPoint &point, int dimension ) const { - const int wkbSize = 1 + sizeof( int ) + 2 * sizeof( double ); + const int wkbSize = 1 + static_cast( sizeof( int ) ) + dimension * static_cast( sizeof( double ) ); wkbPtr = QByteArray( wkbSize, Qt::Uninitialized ); QgsWkbPtr fillPtr( wkbPtr ); - fillPtr << mEndian << Qgis::WkbType::Point << point.x() << point.y(); + fillPtr << mEndian << ( dimension > 2 ? Qgis::WkbType::PointZ : Qgis::WkbType::Point ) << point.x() << point.y(); + if ( dimension > 2 ) + { + fillPtr << point.z(); // add Z coordinate if available + } return 0; } -int QgsGmlStreamingParser::getLineWKB( QByteArray &wkbPtr, const QList &lineCoordinates ) const +int QgsGmlStreamingParser::getLineWKB( QByteArray &wkbPtr, const QList &lineCoordinates, int dimension ) const { - const int wkbSize = 1 + 2 * sizeof( int ) + lineCoordinates.size() * 2 * sizeof( double ); + const int wkbSize = 1 + 2 * static_cast( sizeof( int ) ) + static_cast( lineCoordinates.size() ) * dimension * static_cast( sizeof( double ) ); wkbPtr = QByteArray( wkbSize, Qt::Uninitialized ); QgsWkbPtr fillPtr( wkbPtr ); - fillPtr << mEndian << Qgis::WkbType::LineString << lineCoordinates.size(); + fillPtr << mEndian << ( dimension > 2 ? Qgis::WkbType::LineStringZ : Qgis::WkbType::LineString ) << lineCoordinates.size(); - QList::const_iterator iter; + QList::const_iterator iter; for ( iter = lineCoordinates.constBegin(); iter != lineCoordinates.constEnd(); ++iter ) { fillPtr << iter->x() << iter->y(); + if ( dimension > 2 ) + { + fillPtr << iter->z(); // add Z coordinate if available + } } return 0; } -int QgsGmlStreamingParser::getRingWKB( QByteArray &wkbPtr, const QList &ringCoordinates ) const +int QgsGmlStreamingParser::getRingWKB( QByteArray &wkbPtr, const QList &ringCoordinates, int dimension ) const { - const int wkbSize = sizeof( int ) + ringCoordinates.size() * 2 * sizeof( double ); + const int wkbSize = static_cast( sizeof( int ) ) + static_cast( ringCoordinates.size() ) * dimension * static_cast( sizeof( double ) ); wkbPtr = QByteArray( wkbSize, Qt::Uninitialized ); QgsWkbPtr fillPtr( wkbPtr ); fillPtr << ringCoordinates.size(); - QList::const_iterator iter; + QList::const_iterator iter; for ( iter = ringCoordinates.constBegin(); iter != ringCoordinates.constEnd(); ++iter ) { fillPtr << iter->x() << iter->y(); + if ( dimension > 2 ) + { + fillPtr << iter->z(); // add Z coordinate if available + } } return 0; @@ -1722,12 +1785,12 @@ int QgsGmlStreamingParser::getRingWKB( QByteArray &wkbPtr, const QList 2 ? mDimension : 2 ) * static_cast( sizeof( int ) ) + totalWKBFragmentSize(); mCurrentWKB = QByteArray( size, Qt::Uninitialized ); QgsWkbPtr wkbPtr( mCurrentWKB ); - wkbPtr << mEndian << Qgis::WkbType::MultiLineString << mCurrentWKBFragments.constBegin()->size(); + wkbPtr << mEndian << ( mDimension > 2 ? Qgis::WkbType::MultiLineStringZ : Qgis::WkbType::MultiLineString ) << mCurrentWKBFragments.constBegin()->size(); //copy (and delete) all the wkb fragments auto wkbIt = mCurrentWKBFragments.constBegin()->constBegin(); @@ -1738,17 +1801,17 @@ int QgsGmlStreamingParser::createMultiLineFromFragments() } mCurrentWKBFragments.clear(); - mWkbType = Qgis::WkbType::MultiLineString; + mWkbType = mDimension > 2 ? Qgis::WkbType::MultiLineStringZ : Qgis::WkbType::MultiLineString; return 0; } int QgsGmlStreamingParser::createMultiPointFromFragments() { - const int size = 1 + 2 * sizeof( int ) + totalWKBFragmentSize(); + const int size = 1 + ( mDimension > 2 ? mDimension : 2 ) * static_cast( sizeof( int ) ) + totalWKBFragmentSize(); mCurrentWKB = QByteArray( size, Qt::Uninitialized ); QgsWkbPtr wkbPtr( mCurrentWKB ); - wkbPtr << mEndian << Qgis::WkbType::MultiPoint << mCurrentWKBFragments.constBegin()->size(); + wkbPtr << mEndian << ( mDimension > 2 ? Qgis::WkbType::MultiPointZ : Qgis::WkbType::MultiPoint ) << mCurrentWKBFragments.constBegin()->size(); auto wkbIt = mCurrentWKBFragments.constBegin()->constBegin(); for ( ; wkbIt != mCurrentWKBFragments.constBegin()->constEnd(); ++wkbIt ) @@ -1758,18 +1821,18 @@ int QgsGmlStreamingParser::createMultiPointFromFragments() } mCurrentWKBFragments.clear(); - mWkbType = Qgis::WkbType::MultiPoint; + mWkbType = mDimension > 2 ? Qgis::WkbType::MultiPointZ : Qgis::WkbType::MultiPoint; return 0; } int QgsGmlStreamingParser::createPolygonFromFragments() { - const int size = 1 + 2 * sizeof( int ) + totalWKBFragmentSize(); + const int size = 1 + ( mDimension > 2 ? mDimension : 2 ) * static_cast( sizeof( int ) ) + totalWKBFragmentSize(); mCurrentWKB = QByteArray( size, Qt::Uninitialized ); QgsWkbPtr wkbPtr( mCurrentWKB ); - wkbPtr << mEndian << Qgis::WkbType::Polygon << mCurrentWKBFragments.constBegin()->size(); + wkbPtr << mEndian << ( mDimension > 2 ? Qgis::WkbType::PolygonZ : Qgis::WkbType::Polygon ) << mCurrentWKBFragments.constBegin()->size(); auto wkbIt = mCurrentWKBFragments.constBegin()->constBegin(); for ( ; wkbIt != mCurrentWKBFragments.constBegin()->constEnd(); ++wkbIt ) @@ -1779,21 +1842,21 @@ int QgsGmlStreamingParser::createPolygonFromFragments() } mCurrentWKBFragments.clear(); - mWkbType = Qgis::WkbType::Polygon; + mWkbType = mDimension > 2 ? Qgis::WkbType::PolygonZ : Qgis::WkbType::Polygon; return 0; } int QgsGmlStreamingParser::createMultiPolygonFromFragments() { int size = 0; - size += 1 + 2 * sizeof( int ); + size += 1 + ( mDimension > 2 ? mDimension : 2 ) * static_cast( sizeof( int ) ); size += totalWKBFragmentSize(); - size += mCurrentWKBFragments.size() * ( 1 + 2 * sizeof( int ) ); //fragments are just the rings + size += mCurrentWKBFragments.size() * ( 1 + ( mDimension > 2 ? mDimension : 2 ) * static_cast( sizeof( int ) ) ); //fragments are just the rings mCurrentWKB = QByteArray( size, Qt::Uninitialized ); QgsWkbPtr wkbPtr( mCurrentWKB ); - wkbPtr << ( char ) mEndian << Qgis::WkbType::MultiPolygon << mCurrentWKBFragments.size(); + wkbPtr << ( char ) mEndian << ( mDimension > 2 ? Qgis::WkbType::MultiPolygonZ : Qgis::WkbType::MultiPolygon ) << mCurrentWKBFragments.size(); //have outer and inner iterators auto outerWkbIt = mCurrentWKBFragments.constBegin(); @@ -1801,7 +1864,7 @@ int QgsGmlStreamingParser::createMultiPolygonFromFragments() for ( ; outerWkbIt != mCurrentWKBFragments.constEnd(); ++outerWkbIt ) { //new polygon - wkbPtr << ( char ) mEndian << Qgis::WkbType::Polygon << outerWkbIt->size(); + wkbPtr << ( char ) mEndian << ( mDimension > 2 ? Qgis::WkbType::PolygonZ : Qgis::WkbType::Polygon ) << outerWkbIt->size(); auto innerWkbIt = outerWkbIt->constBegin(); for ( ; innerWkbIt != outerWkbIt->constEnd(); ++innerWkbIt ) @@ -1812,7 +1875,7 @@ int QgsGmlStreamingParser::createMultiPolygonFromFragments() } mCurrentWKBFragments.clear(); - mWkbType = Qgis::WkbType::MultiPolygon; + mWkbType = mDimension > 2 ? Qgis::WkbType::MultiPolygonZ : Qgis::WkbType::MultiPolygon; return 0; } diff --git a/src/core/qgsgml.h b/src/core/qgsgml.h index 547f069dfbb6..1f54f06bb5da 100644 --- a/src/core/qgsgml.h +++ b/src/core/qgsgml.h @@ -230,9 +230,10 @@ class CORE_EXPORT QgsGmlStreamingParser * Creates a set of points from a coordinate string. * \param points list that will contain the created points * \param coordString the text containing the coordinates + * \param dimension number of dimensions determined from the coordinate string * \returns 0 in case of success */ - int pointsFromCoordinateString( QList &points, const QString &coordString ) const; + int pointsFromCoordinateString( QList &points, const QString &coordString, int *dimension = nullptr ) const; /** * Creates a set of points from a gml:posList or gml:pos coordinate string. @@ -241,12 +242,12 @@ class CORE_EXPORT QgsGmlStreamingParser * \param dimension number of dimensions * \returns 0 in case of success */ - int pointsFromPosListString( QList &points, const QString &coordString, int dimension ) const; + int pointsFromPosListString( QList &points, const QString &coordString, int dimension ) const; - int pointsFromString( QList &points, const QString &coordString ) const; - int getPointWKB( QByteArray &wkbPtr, const QgsPointXY & ) const; - int getLineWKB( QByteArray &wkbPtr, const QList &lineCoordinates ) const; - int getRingWKB( QByteArray &wkbPtr, const QList &ringCoordinates ) const; + int pointsFromString( QList &points, const QString &coordString, int *dimension = nullptr ) const; + int getPointWKB( QByteArray &wkbPtr, const QgsPoint &, int dimension ) const; + int getLineWKB( QByteArray &wkbPtr, const QList &lineCoordinates, int dimension ) const; + int getRingWKB( QByteArray &wkbPtr, const QList &ringCoordinates, int dimension ) const; /** * Creates a multiline from the information in mCurrentWKBFragments and diff --git a/src/core/qgsmaplayer.cpp b/src/core/qgsmaplayer.cpp index 17078892f50d..93e9c6674a45 100644 --- a/src/core/qgsmaplayer.cpp +++ b/src/core/qgsmaplayer.cpp @@ -2657,30 +2657,46 @@ bool QgsMapLayer::deleteStyleFromDatabase( const QString &styleId, QString &msgE void QgsMapLayer::saveStyleToDatabase( const QString &name, const QString &description, bool useAsDefault, const QString &uiFileContent, QString &msgError, QgsMapLayer::StyleCategories categories ) +{ + saveStyleToDatabaseV2( name, description, useAsDefault, uiFileContent, msgError, categories ); +} + +QgsMapLayer::SaveStyleResults QgsMapLayer::saveStyleToDatabaseV2( const QString &name, const QString &description, bool useAsDefault, const QString &uiFileContent, QString &msgError, QgsMapLayer::StyleCategories categories ) { QGIS_PROTECT_QOBJECT_THREAD_ACCESS + QgsMapLayer::SaveStyleResults results; + QString sldStyle, qmlStyle; QDomDocument qmlDocument; QgsReadWriteContext context; exportNamedStyle( qmlDocument, msgError, context, categories ); - if ( !msgError.isNull() ) + if ( !msgError.isEmpty() ) { - return; + results.setFlag( QgsMapLayer::SaveStyleResult::QmlGenerationFailed ); + } + else + { + qmlStyle = qmlDocument.toString(); } - qmlStyle = qmlDocument.toString(); QgsSldExportContext sldContext; QDomDocument sldDocument = this->exportSldStyleV3( sldContext ); if ( !sldContext.errors().empty() ) { - return; + results.setFlag( QgsMapLayer::SaveStyleResult::SldGenerationFailed ); + } + else + { + sldStyle = sldDocument.toString(); } - sldStyle = sldDocument.toString(); - QgsProviderRegistry::instance()->saveStyle( mProviderKey, - mDataSource, qmlStyle, sldStyle, name, - description, uiFileContent, useAsDefault, msgError ); + if ( !QgsProviderRegistry::instance()->saveStyle( mProviderKey, + mDataSource, qmlStyle, sldStyle, name, description, uiFileContent, useAsDefault, msgError ) ) + { + results.setFlag( QgsMapLayer::SaveStyleResult::DatabaseWriteFailed ); + } + return results; } QString QgsMapLayer::loadNamedStyle( const QString &theURI, bool &resultFlag, bool loadFromLocalDB, QgsMapLayer::StyleCategories categories, Qgis::LoadStyleFlags flags ) diff --git a/src/core/qgsmaplayer.h b/src/core/qgsmaplayer.h index 46d401d93968..10d2f8d4da0c 100644 --- a/src/core/qgsmaplayer.h +++ b/src/core/qgsmaplayer.h @@ -758,7 +758,29 @@ class CORE_EXPORT QgsMapLayer : public QObject virtual bool deleteStyleFromDatabase( const QString &styleId, QString &msgError SIP_OUT ); /** - * Saves named and sld style of the layer to the style table in the db. + * Results of saving styles to database. + * + * \since QGIS 4.0 + */ + enum class SaveStyleResult SIP_ENUM_BASETYPE( IntFlag ) + { + Success = 0, //!< Both QML and SLD formats were successfully written to the database. + QmlGenerationFailed = 1 << 0, //!< Generation of the QML failed, and was not written to the database. + SldGenerationFailed = 1 << 1, //!< Generation of the SLD failed, and was not written to the database. + DatabaseWriteFailed = 1 << 2, //!< An error occurred when attempting to write to the database. + }; + Q_ENUM( SaveStyleResult ) + + /** + * Results of saving styles to database. + * + * \since QGIS 4.0 + */ + Q_DECLARE_FLAGS( SaveStyleResults, SaveStyleResult ) + Q_FLAG( SaveStyleResults ) + + /** + * Saves QML and SLD representations of the layer's style to a table in the database. * \param name Style name * \param description A description of the style * \param useAsDefault Set to TRUE if style should be used as the default style for the layer @@ -766,18 +788,36 @@ class CORE_EXPORT QgsMapLayer : public QObject * \param msgError will be set to a descriptive error message if any occurs * \param categories the style categories to be saved. * - * * \note Prior to QGIS 3.24, this method would show a message box warning when a * style with the same \a styleName already existed to confirm replacing the style with the user. * Since 3.24, calling this method will ALWAYS overwrite any existing style with the same name. * Use QgsProviderRegistry::styleExists() to test in advance if a style already exists and handle this appropriately * in your client code. + * + * \deprecated QGIS 4.0. Use saveStyleToDatabaseV2() instead. */ - virtual void saveStyleToDatabase( const QString &name, const QString &description, - bool useAsDefault, const QString &uiFileContent, - QString &msgError SIP_OUT, - QgsMapLayer::StyleCategories categories = QgsMapLayer::AllStyleCategories ); + Q_DECL_DEPRECATED virtual void saveStyleToDatabase( const QString &name, const QString &description, + bool useAsDefault, const QString &uiFileContent, + QString &msgError SIP_OUT, + QgsMapLayer::StyleCategories categories = QgsMapLayer::AllStyleCategories ) SIP_DEPRECATED; + /** + * Saves QML and SLD representations of the layer's style to a table in the database. + * \param name Style name + * \param description A description of the style + * \param useAsDefault Set to TRUE if style should be used as the default style for the layer + * \param uiFileContent + * \param msgError will be set to a descriptive error message if any occurs + * \param categories the style categories to be saved. + * + * \returns flags representing whether QML or SLD storing was successful + * + * \since QGIS 4.0 + */ + QgsMapLayer::SaveStyleResults saveStyleToDatabaseV2( const QString &name, const QString &description, + bool useAsDefault, const QString &uiFileContent, + QString &msgError SIP_OUT, + QgsMapLayer::StyleCategories categories = QgsMapLayer::AllStyleCategories ); // TODO QGIS 4.0 -- fix this. We incorrectly have a single boolean flag which in which false is used inconsistently for "a style WAS found but an error occurred loading it" vs "no style was found". // The first (style found, error occurred loading it) should trigger a user-facing warning, whereas the second (no style found) isn't reflective of an error at all. diff --git a/src/core/qgsogcutils.cpp b/src/core/qgsogcutils.cpp index 59eacd7efc02..a7cb6ac4ff7f 100644 --- a/src/core/qgsogcutils.cpp +++ b/src/core/qgsogcutils.cpp @@ -26,6 +26,9 @@ #include "qgsexpressioncontextutils.h" #include "qgslogger.h" #include "qgsstringutils.h" +#include "qgsmultipolygon.h" +#include "qgspolygon.h" +#include "qgsogrutils.h" #include #include @@ -33,6 +36,9 @@ #include #include + +#include "ogr_api.h" + #ifndef Q_OS_WIN #include #else @@ -92,7 +98,7 @@ QgsGeometry QgsOgcUtils::geometryFromGML( const QDomNode &geometryNode, const Co if ( !( geomType == QLatin1String( "Point" ) || geomType == QLatin1String( "LineString" ) || geomType == QLatin1String( "Polygon" ) || geomType == QLatin1String( "MultiPoint" ) || geomType == QLatin1String( "MultiLineString" ) || geomType == QLatin1String( "MultiPolygon" ) || - geomType == QLatin1String( "Box" ) || geomType == QLatin1String( "Envelope" ) ) ) + geomType == QLatin1String( "Box" ) || geomType == QLatin1String( "Envelope" ) || geomType == QLatin1String( "MultiCurve" ) ) ) { const QDomNode geometryChild = geometryNode.firstChild(); if ( geometryChild.isNull() ) @@ -105,7 +111,7 @@ QgsGeometry QgsOgcUtils::geometryFromGML( const QDomNode &geometryNode, const Co if ( !( geomType == QLatin1String( "Point" ) || geomType == QLatin1String( "LineString" ) || geomType == QLatin1String( "Polygon" ) || geomType == QLatin1String( "MultiPoint" ) || geomType == QLatin1String( "MultiLineString" ) || geomType == QLatin1String( "MultiPolygon" ) || - geomType == QLatin1String( "Box" ) || geomType == QLatin1String( "Envelope" ) ) ) + geomType == QLatin1String( "Box" ) || geomType == QLatin1String( "Envelope" ) || geomType == QLatin1String( "MultiCurve" ) ) ) return QgsGeometry(); if ( geomType == QLatin1String( "Point" ) ) @@ -128,6 +134,10 @@ QgsGeometry QgsOgcUtils::geometryFromGML( const QDomNode &geometryNode, const Co { geometry = geometryFromGMLMultiLineString( geometryTypeElement ); } + else if ( geomType == QLatin1String( "MultiCurve" ) ) + { + geometry = geometryFromGMLMultiCurve( geometryTypeElement ); + } else if ( geomType == QLatin1String( "MultiPolygon" ) ) { geometry = geometryFromGMLMultiPolygon( geometryTypeElement ); @@ -142,6 +152,7 @@ QgsGeometry QgsOgcUtils::geometryFromGML( const QDomNode &geometryNode, const Co } else //unknown type { + QgsDebugMsgLevel( QStringLiteral( "Unknown geometry type %1" ).arg( geomType ), 2 ); return geometry; } @@ -208,7 +219,7 @@ QgsGeometry QgsOgcUtils::geometryFromGML( const QString &xmlString, const Contex QgsGeometry QgsOgcUtils::geometryFromGMLPoint( const QDomElement &geometryElement ) { - QgsPolylineXY pointCoordinate; + QgsPolyline pointCoordinate; const QDomNodeList coordList = geometryElement.elementsByTagNameNS( GML_NAMESPACE, QStringLiteral( "coordinates" ) ); if ( !coordList.isEmpty() ) @@ -238,13 +249,14 @@ QgsGeometry QgsOgcUtils::geometryFromGMLPoint( const QDomElement &geometryElemen return QgsGeometry(); } - QgsPolylineXY::const_iterator point_it = pointCoordinate.constBegin(); - char e = htonl( 1 ) != 1; - double x = point_it->x(); - double y = point_it->y(); - const int size = 1 + sizeof( int ) + 2 * sizeof( double ); + const bool hasZ { !std::isnan( pointCoordinate.first().z() ) }; + QgsPolyline::const_iterator point_it = pointCoordinate.constBegin(); + const char e = static_cast( htonl( 1 ) != 1 ); + const double x = point_it->x(); + const double y = point_it->y(); + const int size = 1 + static_cast( sizeof( int ) ) + ( hasZ ? 3 : 2 ) * static_cast( sizeof( double ) ); - Qgis::WkbType type = Qgis::WkbType::Point; + const Qgis::WkbType type { hasZ ? Qgis::WkbType::PointZ : Qgis::WkbType::Point }; unsigned char *wkb = new unsigned char[size]; int wkbPosition = 0; //current offset from wkb beginning (in bytes) @@ -256,6 +268,13 @@ QgsGeometry QgsOgcUtils::geometryFromGMLPoint( const QDomElement &geometryElemen wkbPosition += sizeof( double ); memcpy( &( wkb )[wkbPosition], &y, sizeof( double ) ); + if ( hasZ ) + { + wkbPosition += sizeof( double ); + double z = point_it->z(); + memcpy( &( wkb )[wkbPosition], &z, sizeof( double ) ); + } + QgsGeometry g; g.fromWkb( wkb, size ); return g; @@ -263,7 +282,7 @@ QgsGeometry QgsOgcUtils::geometryFromGMLPoint( const QDomElement &geometryElemen QgsGeometry QgsOgcUtils::geometryFromGMLLineString( const QDomElement &geometryElement ) { - QgsPolylineXY lineCoordinates; + QgsPolyline lineCoordinates; const QDomNodeList coordList = geometryElement.elementsByTagNameNS( GML_NAMESPACE, QStringLiteral( "coordinates" ) ); if ( !coordList.isEmpty() ) @@ -288,10 +307,12 @@ QgsGeometry QgsOgcUtils::geometryFromGMLLineString( const QDomElement &geometryE } } - char e = htonl( 1 ) != 1; - const int size = 1 + 2 * sizeof( int ) + lineCoordinates.size() * 2 * sizeof( double ); + const bool hasZ { !std::isnan( lineCoordinates.first().z() ) }; - Qgis::WkbType type = Qgis::WkbType::LineString; + char e = static_cast( htonl( 1 ) != 1 ); + const int size = 1 + 2 * static_cast( sizeof( int ) + lineCoordinates.size() ) * ( hasZ ? 3 : 2 ) * static_cast( sizeof( double ) ); + + const Qgis::WkbType type{ hasZ ? Qgis::WkbType::LineStringZ : Qgis::WkbType::LineString }; unsigned char *wkb = new unsigned char[size]; int wkbPosition = 0; //current offset from wkb beginning (in bytes) @@ -306,7 +327,7 @@ QgsGeometry QgsOgcUtils::geometryFromGMLLineString( const QDomElement &geometryE memcpy( &( wkb )[wkbPosition], &nPoints, sizeof( int ) ); wkbPosition += sizeof( int ); - QgsPolylineXY::const_iterator iter; + QgsPolyline::const_iterator iter; for ( iter = lineCoordinates.constBegin(); iter != lineCoordinates.constEnd(); ++iter ) { x = iter->x(); @@ -315,6 +336,14 @@ QgsGeometry QgsOgcUtils::geometryFromGMLLineString( const QDomElement &geometryE wkbPosition += sizeof( double ); memcpy( &( wkb )[wkbPosition], &y, sizeof( double ) ); wkbPosition += sizeof( double ); + + if ( hasZ ) + { + double z = iter->z(); + memcpy( &( wkb )[wkbPosition], &z, sizeof( double ) ); + wkbPosition += sizeof( double ); + } + } QgsGeometry g; @@ -325,10 +354,10 @@ QgsGeometry QgsOgcUtils::geometryFromGMLLineString( const QDomElement &geometryE QgsGeometry QgsOgcUtils::geometryFromGMLPolygon( const QDomElement &geometryElement ) { //read all the coordinates (as QgsPoint) into memory. Each linear ring has an entry in the vector - QgsMultiPolylineXY ringCoordinates; + QgsMultiPolyline ringCoordinates; //read coordinates for outer boundary - QgsPolylineXY exteriorPointList; + QgsPolyline exteriorPointList; const QDomNodeList outerBoundaryList = geometryElement.elementsByTagNameNS( GML_NAMESPACE, QStringLiteral( "outerBoundaryIs" ) ); if ( !outerBoundaryList.isEmpty() ) //outer ring is necessary { @@ -347,7 +376,7 @@ QgsGeometry QgsOgcUtils::geometryFromGMLPolygon( const QDomElement &geometryElem const QDomNodeList innerBoundaryList = geometryElement.elementsByTagNameNS( GML_NAMESPACE, QStringLiteral( "innerBoundaryIs" ) ); for ( int i = 0; i < innerBoundaryList.size(); ++i ) { - QgsPolylineXY interiorPointList; + QgsPolyline interiorPointList; coordinatesElement = innerBoundaryList.at( i ).firstChild().firstChild().toElement(); if ( coordinatesElement.isNull() ) { @@ -383,7 +412,7 @@ QgsGeometry QgsOgcUtils::geometryFromGMLPolygon( const QDomElement &geometryElem const QDomNodeList interiorList = geometryElement.elementsByTagNameNS( GML_NAMESPACE, QStringLiteral( "interior" ) ); for ( int i = 0; i < interiorList.size(); ++i ) { - QgsPolylineXY interiorPointList; + QgsPolyline interiorPointList; const QDomElement posElement = interiorList.at( i ).firstChild().firstChild().toElement(); if ( posElement.isNull() ) { @@ -404,20 +433,23 @@ QgsGeometry QgsOgcUtils::geometryFromGMLPolygon( const QDomElement &geometryElem return QgsGeometry(); int npoints = 0;//total number of points - for ( QgsMultiPolylineXY::const_iterator it = ringCoordinates.constBegin(); it != ringCoordinates.constEnd(); ++it ) + for ( QgsMultiPolyline::const_iterator it = ringCoordinates.constBegin(); it != ringCoordinates.constEnd(); ++it ) { npoints += it->size(); } - const int size = 1 + 2 * sizeof( int ) + nrings * sizeof( int ) + 2 * npoints * sizeof( double ); - Qgis::WkbType type = Qgis::WkbType::Polygon; + const bool hasZ { !std::isnan( ringCoordinates.first().first().z() ) }; + + const int size = 1 + 2 * static_cast( sizeof( int ) ) + nrings * static_cast( sizeof( int ) ) + ( hasZ ? 3 : 2 ) * npoints * static_cast( sizeof( double ) ); + + const Qgis::WkbType type { hasZ ? Qgis::WkbType::PolygonZ : Qgis::WkbType::Polygon }; unsigned char *wkb = new unsigned char[size]; //char e = QgsApplication::endian(); - char e = htonl( 1 ) != 1; + char e = static_cast( htonl( 1 ) != 1 ); int wkbPosition = 0; //current offset from wkb beginning (in bytes) int nPointsInRing = 0; - double x, y; + double x, y, z; //fill the contents into *wkb memcpy( &( wkb )[wkbPosition], &e, 1 ); @@ -426,13 +458,13 @@ QgsGeometry QgsOgcUtils::geometryFromGMLPolygon( const QDomElement &geometryElem wkbPosition += sizeof( int ); memcpy( &( wkb )[wkbPosition], &nrings, sizeof( int ) ); wkbPosition += sizeof( int ); - for ( QgsMultiPolylineXY::const_iterator it = ringCoordinates.constBegin(); it != ringCoordinates.constEnd(); ++it ) + for ( QgsMultiPolyline::const_iterator it = ringCoordinates.constBegin(); it != ringCoordinates.constEnd(); ++it ) { nPointsInRing = it->size(); memcpy( &( wkb )[wkbPosition], &nPointsInRing, sizeof( int ) ); wkbPosition += sizeof( int ); //iterate through the string list converting the strings to x-/y- doubles - QgsPolylineXY::const_iterator iter; + QgsPolyline::const_iterator iter; for ( iter = it->begin(); iter != it->end(); ++iter ) { x = iter->x(); @@ -442,6 +474,13 @@ QgsGeometry QgsOgcUtils::geometryFromGMLPolygon( const QDomElement &geometryElem wkbPosition += sizeof( double ); memcpy( &( wkb )[wkbPosition], &y, sizeof( double ) ); wkbPosition += sizeof( double ); + + if ( hasZ ) + { + z = iter->z(); + memcpy( &( wkb )[wkbPosition], &z, sizeof( double ) ); + wkbPosition += sizeof( double ); + } } } @@ -452,8 +491,8 @@ QgsGeometry QgsOgcUtils::geometryFromGMLPolygon( const QDomElement &geometryElem QgsGeometry QgsOgcUtils::geometryFromGMLMultiPoint( const QDomElement &geometryElement ) { - QgsPolylineXY pointList; - QgsPolylineXY currentPoint; + QgsPolyline pointList; + QgsPolyline currentPoint; const QDomNodeList pointMemberList = geometryElement.elementsByTagNameNS( GML_NAMESPACE, QStringLiteral( "pointMember" ) ); if ( pointMemberList.size() < 1 ) { @@ -512,28 +551,30 @@ QgsGeometry QgsOgcUtils::geometryFromGMLMultiPoint( const QDomElement &geometryE if ( nPoints < 1 ) return QgsGeometry(); + const bool hasZ { !std::isnan( pointList.first().z() ) }; + //calculate the required wkb size - const int size = 1 + 2 * sizeof( int ) + pointList.size() * ( 2 * sizeof( double ) + 1 + sizeof( int ) ); + const int size = 1 + 2 * static_cast( sizeof( int ) ) + static_cast( pointList.size() ) * ( ( hasZ ? 3 : 2 ) * static_cast( sizeof( double ) ) + 1 + static_cast( sizeof( int ) ) ); - Qgis::WkbType type = Qgis::WkbType::MultiPoint; + const Qgis::WkbType type { hasZ ? Qgis::WkbType::MultiPointZ : Qgis::WkbType::MultiPoint }; unsigned char *wkb = new unsigned char[size]; //fill the wkb content - char e = htonl( 1 ) != 1; + char e = static_cast( htonl( 1 ) != 1 ); int wkbPosition = 0; //current offset from wkb beginning (in bytes) - double x, y; + double x, y, z; memcpy( &( wkb )[wkbPosition], &e, 1 ); wkbPosition += 1; memcpy( &( wkb )[wkbPosition], &type, sizeof( int ) ); wkbPosition += sizeof( int ); memcpy( &( wkb )[wkbPosition], &nPoints, sizeof( int ) ); wkbPosition += sizeof( int ); - type = Qgis::WkbType::Point; - for ( QgsPolylineXY::const_iterator it = pointList.constBegin(); it != pointList.constEnd(); ++it ) + const Qgis::WkbType pointType { hasZ ? Qgis::WkbType::PointZ : Qgis::WkbType::Point }; + for ( QgsPolyline::const_iterator it = pointList.constBegin(); it != pointList.constEnd(); ++it ) { memcpy( &( wkb )[wkbPosition], &e, 1 ); wkbPosition += 1; - memcpy( &( wkb )[wkbPosition], &type, sizeof( int ) ); + memcpy( &( wkb )[wkbPosition], &pointType, sizeof( int ) ); wkbPosition += sizeof( int ); x = it->x(); memcpy( &( wkb )[wkbPosition], &x, sizeof( double ) ); @@ -541,6 +582,13 @@ QgsGeometry QgsOgcUtils::geometryFromGMLMultiPoint( const QDomElement &geometryE y = it->y(); memcpy( &( wkb )[wkbPosition], &y, sizeof( double ) ); wkbPosition += sizeof( double ); + + if ( hasZ ) + { + z = it->z(); + memcpy( &( wkb )[wkbPosition], &z, sizeof( double ) ); + wkbPosition += sizeof( double ); + } } QgsGeometry g; @@ -559,7 +607,8 @@ QgsGeometry QgsOgcUtils::geometryFromGMLMultiLineString( const QDomElement &geom // lineCoordinates; //first list: lines, second list: points of one line + + QList< QgsPolyline > lineCoordinates; //first list: lines, second list: points of one line QDomElement currentLineStringElement; QDomNodeList currentCoordList; QDomNodeList currentPosList; @@ -578,7 +627,7 @@ QgsGeometry QgsOgcUtils::geometryFromGMLMultiLineString( const QDomElement &geom currentCoordList = currentLineStringElement.elementsByTagNameNS( GML_NAMESPACE, QStringLiteral( "coordinates" ) ); if ( !currentCoordList.isEmpty() ) { - QgsPolylineXY currentPointList; + QgsPolyline currentPointList; if ( readGMLCoordinates( currentPointList, currentCoordList.at( 0 ).toElement() ) != 0 ) { return QgsGeometry(); @@ -592,7 +641,7 @@ QgsGeometry QgsOgcUtils::geometryFromGMLMultiLineString( const QDomElement &geom { return QgsGeometry(); } - QgsPolylineXY currentPointList; + QgsPolyline currentPointList; if ( readGMLPositions( currentPointList, currentPosList.at( 0 ).toElement() ) != 0 ) { return QgsGeometry(); @@ -612,7 +661,7 @@ QgsGeometry QgsOgcUtils::geometryFromGMLMultiLineString( const QDomElement &geom currentCoordList = currentLineStringElement.elementsByTagNameNS( GML_NAMESPACE, QStringLiteral( "coordinates" ) ); if ( !currentCoordList.isEmpty() ) { - QgsPolylineXY currentPointList; + QgsPolyline currentPointList; if ( readGMLCoordinates( currentPointList, currentCoordList.at( 0 ).toElement() ) != 0 ) { return QgsGeometry(); @@ -627,7 +676,7 @@ QgsGeometry QgsOgcUtils::geometryFromGMLMultiLineString( const QDomElement &geom { return QgsGeometry(); } - QgsPolylineXY currentPointList; + QgsPolyline currentPointList; if ( readGMLPositions( currentPointList, currentPosList.at( 0 ).toElement() ) != 0 ) { return QgsGeometry(); @@ -646,38 +695,41 @@ QgsGeometry QgsOgcUtils::geometryFromGMLMultiLineString( const QDomElement &geom if ( nLines < 1 ) return QgsGeometry(); + const bool hasZ { !std::isnan( lineCoordinates.first().first().z() ) }; + const int coordSize { hasZ ? 3 : 2 }; + //calculate the required wkb size - int size = ( lineCoordinates.size() + 1 ) * ( 1 + 2 * sizeof( int ) ); - for ( QList< QgsPolylineXY >::const_iterator it = lineCoordinates.constBegin(); it != lineCoordinates.constEnd(); ++it ) + int size = static_cast( lineCoordinates.size() + 1 ) * ( 1 + 2 * sizeof( int ) ); + for ( QList< QgsPolyline >::const_iterator it = lineCoordinates.constBegin(); it != lineCoordinates.constEnd(); ++it ) { - size += it->size() * 2 * sizeof( double ); + size += it->size() * coordSize * sizeof( double ); } - Qgis::WkbType type = Qgis::WkbType::MultiLineString; + const Qgis::WkbType type { hasZ ? Qgis::WkbType::MultiLineStringZ : Qgis::WkbType::MultiLineString }; unsigned char *wkb = new unsigned char[size]; //fill the wkb content - char e = htonl( 1 ) != 1; + char e = static_cast( htonl( 1 ) != 1 ); int wkbPosition = 0; //current offset from wkb beginning (in bytes) int nPoints; //number of points in a line - double x, y; + double x, y, z; memcpy( &( wkb )[wkbPosition], &e, 1 ); wkbPosition += 1; memcpy( &( wkb )[wkbPosition], &type, sizeof( int ) ); wkbPosition += sizeof( int ); memcpy( &( wkb )[wkbPosition], &nLines, sizeof( int ) ); wkbPosition += sizeof( int ); - type = Qgis::WkbType::LineString; - for ( QList< QgsPolylineXY >::const_iterator it = lineCoordinates.constBegin(); it != lineCoordinates.constEnd(); ++it ) + const Qgis::WkbType lineType { hasZ ? Qgis::WkbType::LineStringZ : Qgis::WkbType::LineString }; + for ( QList< QgsPolyline >::const_iterator it = lineCoordinates.constBegin(); it != lineCoordinates.constEnd(); ++it ) { memcpy( &( wkb )[wkbPosition], &e, 1 ); wkbPosition += 1; - memcpy( &( wkb )[wkbPosition], &type, sizeof( int ) ); + memcpy( &( wkb )[wkbPosition], &lineType, sizeof( int ) ); wkbPosition += sizeof( int ); nPoints = it->size(); memcpy( &( wkb )[wkbPosition], &nPoints, sizeof( int ) ); wkbPosition += sizeof( int ); - for ( QgsPolylineXY::const_iterator iter = it->begin(); iter != it->end(); ++iter ) + for ( QgsPolyline::const_iterator iter = it->begin(); iter != it->end(); ++iter ) { x = iter->x(); y = iter->y(); @@ -686,6 +738,13 @@ QgsGeometry QgsOgcUtils::geometryFromGMLMultiLineString( const QDomElement &geom wkbPosition += sizeof( double ); memcpy( &( wkb )[wkbPosition], &y, sizeof( double ) ); wkbPosition += sizeof( double ); + + if ( hasZ ) + { + z = iter->z(); + memcpy( &( wkb )[wkbPosition], &z, sizeof( double ) ); + wkbPosition += sizeof( double ); + } } } @@ -697,21 +756,19 @@ QgsGeometry QgsOgcUtils::geometryFromGMLMultiLineString( const QDomElement &geom QgsGeometry QgsOgcUtils::geometryFromGMLMultiPolygon( const QDomElement &geometryElement ) { //first list: different polygons, second list: different rings, third list: different points - QgsMultiPolygonXY multiPolygonPoints; + QVector multiPolygonPoints; QDomElement currentPolygonMemberElement; QDomNodeList polygonList; QDomElement currentPolygonElement; // rings in GML2 QDomNodeList outerBoundaryList; QDomElement currentOuterBoundaryElement; - const QDomNodeList innerBoundaryList; QDomElement currentInnerBoundaryElement; // rings in GML3 QDomNodeList exteriorList; QDomElement currentExteriorElement; QDomElement currentInteriorElement; - const QDomNodeList interiorList; - // lienar ring + // linear ring QDomNodeList linearRingNodeList; QDomElement currentLinearRingElement; // Coordinates or position list @@ -719,7 +776,7 @@ QgsGeometry QgsOgcUtils::geometryFromGMLMultiPolygon( const QDomElement &geometr QDomNodeList currentPosList; const QDomNodeList polygonMemberList = geometryElement.elementsByTagNameNS( GML_NAMESPACE, QStringLiteral( "polygonMember" ) ); - QgsPolygonXY currentPolygonList; + QgsMultiPolyline currentPolygonList; for ( int i = 0; i < polygonMemberList.size(); ++i ) { currentPolygonList.resize( 0 ); // preserve capacity - don't use clear @@ -736,7 +793,7 @@ QgsGeometry QgsOgcUtils::geometryFromGMLMultiPolygon( const QDomElement &geometr if ( !outerBoundaryList.isEmpty() ) { currentOuterBoundaryElement = outerBoundaryList.at( 0 ).toElement(); - QgsPolylineXY ringCoordinates; + QgsPolyline ringCoordinates; linearRingNodeList = currentOuterBoundaryElement.elementsByTagNameNS( GML_NAMESPACE, QStringLiteral( "LinearRing" ) ); if ( linearRingNodeList.size() < 1 ) @@ -759,7 +816,7 @@ QgsGeometry QgsOgcUtils::geometryFromGMLMultiPolygon( const QDomElement &geometr const QDomNodeList innerBoundaryList = currentPolygonElement.elementsByTagNameNS( GML_NAMESPACE, QStringLiteral( "innerBoundaryIs" ) ); for ( int j = 0; j < innerBoundaryList.size(); ++j ) { - QgsPolylineXY ringCoordinates; + QgsPolyline ringCoordinates; currentInnerBoundaryElement = innerBoundaryList.at( j ).toElement(); linearRingNodeList = currentInnerBoundaryElement.elementsByTagNameNS( GML_NAMESPACE, QStringLiteral( "LinearRing" ) ); if ( linearRingNodeList.size() < 1 ) @@ -789,7 +846,7 @@ QgsGeometry QgsOgcUtils::geometryFromGMLMultiPolygon( const QDomElement &geometr } currentExteriorElement = exteriorList.at( 0 ).toElement(); - QgsPolylineXY ringPositions; + QgsPolyline ringPositions; linearRingNodeList = currentExteriorElement.elementsByTagNameNS( GML_NAMESPACE, QStringLiteral( "LinearRing" ) ); if ( linearRingNodeList.size() < 1 ) @@ -812,7 +869,7 @@ QgsGeometry QgsOgcUtils::geometryFromGMLMultiPolygon( const QDomElement &geometr const QDomNodeList interiorList = currentPolygonElement.elementsByTagNameNS( GML_NAMESPACE, QStringLiteral( "interior" ) ); for ( int j = 0; j < interiorList.size(); ++j ) { - QgsPolylineXY ringPositions; + QgsPolyline ringPositions; currentInteriorElement = interiorList.at( j ).toElement(); linearRingNodeList = currentInteriorElement.elementsByTagNameNS( GML_NAMESPACE, QStringLiteral( "LinearRing" ) ); if ( linearRingNodeList.size() < 1 ) @@ -839,21 +896,24 @@ QgsGeometry QgsOgcUtils::geometryFromGMLMultiPolygon( const QDomElement &geometr if ( nPolygons < 1 ) return QgsGeometry(); + const bool hasZ { !std::isnan( multiPolygonPoints.first().first().first().z() ) }; + int size = 1 + 2 * sizeof( int ); //calculate the wkb size - for ( QgsMultiPolygonXY::const_iterator it = multiPolygonPoints.constBegin(); it != multiPolygonPoints.constEnd(); ++it ) + + for ( auto it = multiPolygonPoints.constBegin(); it != multiPolygonPoints.constEnd(); ++it ) { size += 1 + 2 * sizeof( int ); - for ( QgsPolygonXY::const_iterator iter = it->begin(); iter != it->end(); ++iter ) + for ( auto iter = it->begin(); iter != it->end(); ++iter ) { - size += sizeof( int ) + 2 * iter->size() * sizeof( double ); + size += static_cast( sizeof( int ) ) + ( hasZ ? 3 : 2 ) * static_cast( iter->size() * sizeof( double ) ); } } - Qgis::WkbType type = Qgis::WkbType::MultiPolygon; + Qgis::WkbType type = hasZ ? Qgis::WkbType::MultiPolygonZ : Qgis::WkbType::MultiPolygon; unsigned char *wkb = new unsigned char[size]; - char e = htonl( 1 ) != 1; + char e = static_cast( htonl( 1 ) != 1 ); int wkbPosition = 0; //current offset from wkb beginning (in bytes) double x, y; int nRings; @@ -867,9 +927,9 @@ QgsGeometry QgsOgcUtils::geometryFromGMLMultiPolygon( const QDomElement &geometr memcpy( &( wkb )[wkbPosition], &nPolygons, sizeof( int ) ); wkbPosition += sizeof( int ); - type = Qgis::WkbType::Polygon; + type = hasZ ? Qgis::WkbType::PolygonZ : Qgis::WkbType::Polygon; - for ( QgsMultiPolygonXY::const_iterator it = multiPolygonPoints.constBegin(); it != multiPolygonPoints.constEnd(); ++it ) + for ( auto it = multiPolygonPoints.constBegin(); it != multiPolygonPoints.constEnd(); ++it ) { memcpy( &( wkb )[wkbPosition], &e, 1 ); wkbPosition += 1; @@ -878,12 +938,12 @@ QgsGeometry QgsOgcUtils::geometryFromGMLMultiPolygon( const QDomElement &geometr nRings = it->size(); memcpy( &( wkb )[wkbPosition], &nRings, sizeof( int ) ); wkbPosition += sizeof( int ); - for ( QgsPolygonXY::const_iterator iter = it->begin(); iter != it->end(); ++iter ) + for ( auto iter = it->begin(); iter != it->end(); ++iter ) { nPointsInRing = iter->size(); memcpy( &( wkb )[wkbPosition], &nPointsInRing, sizeof( int ) ); wkbPosition += sizeof( int ); - for ( QgsPolylineXY::const_iterator iterator = iter->begin(); iterator != iter->end(); ++iterator ) + for ( auto iterator = iter->begin(); iterator != iter->end(); ++iterator ) { x = iterator->x(); y = iterator->y(); @@ -891,6 +951,12 @@ QgsGeometry QgsOgcUtils::geometryFromGMLMultiPolygon( const QDomElement &geometr wkbPosition += sizeof( double ); memcpy( &( wkb )[wkbPosition], &y, sizeof( double ) ); wkbPosition += sizeof( double ); + if ( hasZ ) + { + double z = iterator->z(); + memcpy( &( wkb )[wkbPosition], &z, sizeof( double ) ); + wkbPosition += sizeof( double ); + } } } } @@ -920,7 +986,7 @@ QDomElement QgsOgcUtils::filterElement( QDomDocument &doc, GMLVersion gmlVersion } -bool QgsOgcUtils::readGMLCoordinates( QgsPolylineXY &coords, const QDomElement &elem ) +bool QgsOgcUtils::readGMLCoordinates( QgsPolyline &coords, const QDomElement &elem ) { QString coordSeparator = QStringLiteral( "," ); QString tupleSeparator = QStringLiteral( " " ); @@ -939,7 +1005,7 @@ bool QgsOgcUtils::readGMLCoordinates( QgsPolylineXY &coords, const QDomElement & const QStringList tupels = elem.text().split( tupleSeparator, Qt::SkipEmptyParts ); QStringList tuple_coords; - double x, y; + double x, y, z; bool conversionSuccess; QStringList::const_iterator it; @@ -960,7 +1026,19 @@ bool QgsOgcUtils::readGMLCoordinates( QgsPolylineXY &coords, const QDomElement & { return true; } - coords.push_back( QgsPointXY( x, y ) ); + if ( tuple_coords.size() > 2 ) + { + z = tuple_coords.at( 2 ).toDouble( &conversionSuccess ); + if ( !conversionSuccess ) + { + return true; + } + } + else + { + z = std::numeric_limits::quiet_NaN(); + } + coords.append( QgsPoint( x, y, z ) ); } return false; } @@ -1001,12 +1079,12 @@ QgsRectangle QgsOgcUtils::rectangleFromGMLBox( const QDomNode &boxNode ) return rect; } -bool QgsOgcUtils::readGMLPositions( QgsPolylineXY &coords, const QDomElement &elem ) +bool QgsOgcUtils::readGMLPositions( QgsPolyline &coords, const QDomElement &elem ) { coords.clear(); const QStringList pos = elem.text().split( ' ', Qt::SkipEmptyParts ); - double x, y; + double x, y, z; bool conversionSuccess; const int posSize = pos.size(); @@ -1040,7 +1118,19 @@ bool QgsOgcUtils::readGMLPositions( QgsPolylineXY &coords, const QDomElement &el { return true; } - coords.push_back( QgsPointXY( x, y ) ); + if ( srsDimension > 2 ) + { + z = pos.at( i * srsDimension + 2 ).toDouble( &conversionSuccess ); + if ( !conversionSuccess ) + { + return true; + } + } + else + { + z = std::numeric_limits::quiet_NaN(); + } + coords.append( QgsPoint( x, y, z ) ); } return false; } @@ -1250,7 +1340,9 @@ QDomElement QgsOgcUtils::geometryToGML( const QgsGeometry &geometry, { case Qgis::WkbType::Point25D: case Qgis::WkbType::Point: + case Qgis::WkbType::PointZ: case Qgis::WkbType::MultiPoint25D: + case Qgis::WkbType::MultiPointZ: case Qgis::WkbType::MultiPoint: baseCoordElem = doc.createElement( QStringLiteral( "gml:pos" ) ); break; @@ -1258,7 +1350,6 @@ QDomElement QgsOgcUtils::geometryToGML( const QgsGeometry &geometry, baseCoordElem = doc.createElement( QStringLiteral( "gml:posList" ) ); break; } - baseCoordElem.setAttribute( QStringLiteral( "srsDimension" ), QStringLiteral( "2" ) ); cs = ' '; } else @@ -1273,6 +1364,10 @@ QDomElement QgsOgcUtils::geometryToGML( const QgsGeometry &geometry, switch ( geometry.wkbType() ) { case Qgis::WkbType::Point25D: + case Qgis::WkbType::PointZ: + hasZValue = true; + //intentional fall-through + [[fallthrough]]; case Qgis::WkbType::Point: { QDomElement pointElem = doc.createElement( QStringLiteral( "gml:Point" ) ); @@ -1288,13 +1383,26 @@ QDomElement QgsOgcUtils::geometryToGML( const QgsGeometry &geometry, wkbPtr >> y >> x; else wkbPtr >> x >> y; - const QDomText coordText = doc.createTextNode( qgsDoubleToString( x, precision ) + cs + qgsDoubleToString( y, precision ) ); + + QString coordString = qgsDoubleToString( x, precision ) + cs + qgsDoubleToString( y, precision ); + + // Add Z + if ( hasZValue && gmlVersion != GML_2_1_2 ) + { + double z = 0; + wkbPtr >> z; + coordString += cs + qgsDoubleToString( z, precision ); + } + const QDomText coordText = doc.createTextNode( coordString ); coordElem.appendChild( coordText ); + if ( gmlVersion != GML_2_1_2 ) + coordElem.setAttribute( QStringLiteral( "srsDimension" ), hasZValue ? QStringLiteral( "3" ) : QStringLiteral( "2" ) ); pointElem.appendChild( coordElem ); return pointElem; } case Qgis::WkbType::MultiPoint25D: + case Qgis::WkbType::MultiPointZ: hasZValue = true; //intentional fall-through [[fallthrough]]; @@ -1325,21 +1433,38 @@ QDomElement QgsOgcUtils::geometryToGML( const QgsGeometry &geometry, wkbPtr >> y >> x; else wkbPtr >> x >> y; - const QDomText coordText = doc.createTextNode( qgsDoubleToString( x, precision ) + cs + qgsDoubleToString( y, precision ) ); - - coordElem.appendChild( coordText ); - pointElem.appendChild( coordElem ); + QString coordString = qgsDoubleToString( x, precision ) + cs + qgsDoubleToString( y, precision ); + // Add Z if ( hasZValue ) { - wkbPtr += sizeof( double ); + if ( gmlVersion != GML_2_1_2 ) + { + double z = 0; + wkbPtr >> z; + coordString += cs + qgsDoubleToString( z, precision ); + } + else + { + wkbPtr += sizeof( double ); + } } + + const QDomText coordText = doc.createTextNode( coordString ); + + coordElem.appendChild( coordText ); + if ( gmlVersion != GML_2_1_2 ) + coordElem.setAttribute( QStringLiteral( "srsDimension" ), hasZValue ? QStringLiteral( "3" ) : QStringLiteral( "2" ) ); + pointElem.appendChild( coordElem ); + + pointMemberElem.appendChild( pointElem ); multiPointElem.appendChild( pointMemberElem ); } return multiPointElem; } case Qgis::WkbType::LineString25D: + case Qgis::WkbType::LineStringZ: hasZValue = true; //intentional fall-through [[fallthrough]]; @@ -1374,15 +1499,28 @@ QDomElement QgsOgcUtils::geometryToGML( const QgsGeometry &geometry, if ( hasZValue ) { - wkbPtr += sizeof( double ); + if ( gmlVersion != GML_2_1_2 ) + { + double z = 0; + wkbPtr >> z; + coordString += cs + qgsDoubleToString( z, precision ); + } + else + { + wkbPtr += sizeof( double ); + } } + } const QDomText coordText = doc.createTextNode( coordString ); coordElem.appendChild( coordText ); + if ( gmlVersion != GML_2_1_2 ) + coordElem.setAttribute( QStringLiteral( "srsDimension" ), hasZValue ? QStringLiteral( "3" ) : QStringLiteral( "2" ) ); lineStringElem.appendChild( coordElem ); return lineStringElem; } case Qgis::WkbType::MultiLineString25D: + case Qgis::WkbType::MultiLineStringZ: hasZValue = true; //intentional fall-through [[fallthrough]]; @@ -1429,11 +1567,22 @@ QDomElement QgsOgcUtils::geometryToGML( const QgsGeometry &geometry, if ( hasZValue ) { - wkbPtr += sizeof( double ); + if ( gmlVersion != GML_2_1_2 ) + { + double z = 0; + wkbPtr >> z; + coordString += cs + qgsDoubleToString( z, precision ); + } + else + { + wkbPtr += sizeof( double ); + } } } const QDomText coordText = doc.createTextNode( coordString ); coordElem.appendChild( coordText ); + if ( gmlVersion != GML_2_1_2 ) + coordElem.setAttribute( QStringLiteral( "srsDimension" ), hasZValue ? QStringLiteral( "3" ) : QStringLiteral( "2" ) ); lineStringElem.appendChild( coordElem ); lineStringMemberElem.appendChild( lineStringElem ); multiLineStringElem.appendChild( lineStringMemberElem ); @@ -1441,6 +1590,7 @@ QDomElement QgsOgcUtils::geometryToGML( const QgsGeometry &geometry, return multiLineStringElem; } case Qgis::WkbType::Polygon25D: + case Qgis::WkbType::PolygonZ: hasZValue = true; //intentional fall-through [[fallthrough]]; @@ -1489,20 +1639,35 @@ QDomElement QgsOgcUtils::geometryToGML( const QgsGeometry &geometry, wkbPtr >> x >> y; coordString += qgsDoubleToString( x, precision ) + cs + qgsDoubleToString( y, precision ); + if ( hasZValue ) { - wkbPtr += sizeof( double ); + if ( gmlVersion != GML_2_1_2 ) + { + // Add Z + double z = 0; + wkbPtr >> z; + coordString += cs + qgsDoubleToString( z, precision ); + } + else + { + wkbPtr += sizeof( double ); + } } } const QDomText coordText = doc.createTextNode( coordString ); coordElem.appendChild( coordText ); + if ( gmlVersion != GML_2_1_2 ) + coordElem.setAttribute( QStringLiteral( "srsDimension" ), hasZValue ? QStringLiteral( "3" ) : QStringLiteral( "2" ) ); ringElem.appendChild( coordElem ); boundaryElem.appendChild( ringElem ); polygonElem.appendChild( boundaryElem ); } + return polygonElem; } case Qgis::WkbType::MultiPolygon25D: + case Qgis::WkbType::MultiPolygonZ: hasZValue = true; //intentional fall-through [[fallthrough]]; @@ -1562,11 +1727,24 @@ QDomElement QgsOgcUtils::geometryToGML( const QgsGeometry &geometry, if ( hasZValue ) { - wkbPtr += sizeof( double ); + if ( gmlVersion != GML_2_1_2 ) + { + // Add Z + double z = 0; + wkbPtr >> z; + coordString += cs + qgsDoubleToString( z, precision ); + } + else + { + wkbPtr += sizeof( double ); + } } + } const QDomText coordText = doc.createTextNode( coordString ); coordElem.appendChild( coordText ); + if ( gmlVersion != GML_2_1_2 ) + coordElem.setAttribute( QStringLiteral( "srsDimension" ), hasZValue ? QStringLiteral( "3" ) : QStringLiteral( "2" ) ); ringElem.appendChild( coordElem ); boundaryElem.appendChild( ringElem ); polygonElem.appendChild( boundaryElem ); @@ -3823,3 +4001,17 @@ QgsOgcCrsUtils::CRSFlavor QgsOgcCrsUtils::parseCrsName( const QString &crsName, return CRSFlavor::UNKNOWN; } + +QgsGeometry QgsOgcUtils::geometryFromGMLUsingGdal( const QDomElement &geometryElement ) +{ + QString gml; + QTextStream gmlStream( &gml ); + geometryElement.save( gmlStream, 0 ); + gdal::ogr_geometry_unique_ptr ogrGeom { OGR_G_CreateFromGML( gml.toUtf8().constData() ) }; + return QgsOgrUtils::ogrGeometryToQgsGeometry( ogrGeom.get() ); +} + +QgsGeometry QgsOgcUtils::geometryFromGMLMultiCurve( const QDomElement &geometryElement ) +{ + return geometryFromGMLUsingGdal( geometryElement ); +} diff --git a/src/core/qgsogcutils.h b/src/core/qgsogcutils.h index 5b76556afe1a..9eb7faebd513 100644 --- a/src/core/qgsogcutils.h +++ b/src/core/qgsogcutils.h @@ -311,8 +311,12 @@ class CORE_EXPORT QgsOgcUtils static QgsGeometry geometryFromGMLMultiPoint( const QDomElement &geometryElement ); //! Static method that creates geometry from GML MultiLineString static QgsGeometry geometryFromGMLMultiLineString( const QDomElement &geometryElement ); + //! Static method that creates geometry from GML MultiCurve + static QgsGeometry geometryFromGMLMultiCurve( const QDomElement &geometryElement ); //! Static method that creates geometry from GML MultiPolygon static QgsGeometry geometryFromGMLMultiPolygon( const QDomElement &geometryElement ); + //! Static method that creates geometry from GML using GDAL GML parser + static QgsGeometry geometryFromGMLUsingGdal( const QDomElement &geometryElement ); /** * Creates an empty \verbatim \endverbatim QDomElement @@ -330,7 +334,7 @@ class CORE_EXPORT QgsOgcUtils * \param elem the \verbatim \endverbatim element * \returns boolean FALSE on success */ - static bool readGMLCoordinates( QgsPolylineXY &coords, const QDomElement &elem ); + static bool readGMLCoordinates( QgsPolyline &coords, const QDomElement &elem ); /** * Reads the \verbatim \endverbatim or \verbatim \endverbatim @@ -340,8 +344,7 @@ class CORE_EXPORT QgsOgcUtils * \verbatim \endverbatim element * \returns boolean FALSE on success */ - static bool readGMLPositions( QgsPolylineXY &coords, const QDomElement &elem ); - + static bool readGMLPositions( QgsPolyline &coords, const QDomElement &elem ); /** * Create a GML coordinates element from a point list. @@ -379,6 +382,8 @@ class CORE_EXPORT QgsOgcUtils static QgsExpressionNodeBinaryOperator *nodePropertyIsNullFromOgcFilter( QDomElement &element, QString &errorMessage ); }; + + #ifndef SIP_RUN /** diff --git a/src/core/qgstracer.cpp b/src/core/qgstracer.cpp index 99379c376da8..895bf47da09d 100644 --- a/src/core/qgstracer.cpp +++ b/src/core/qgstracer.cpp @@ -579,7 +579,7 @@ bool QgsTracer::initGraph() mpl = noded.asMultiPolyline(); } - catch ( GEOSException &e ) + catch ( QgsGeosException &e ) { // no big deal... we will just not have nicely noded linework, potentially // missing some intersections diff --git a/src/core/qgstracer.h b/src/core/qgstracer.h index fa2e139a326a..f38b0376ce41 100644 --- a/src/core/qgstracer.h +++ b/src/core/qgstracer.h @@ -199,7 +199,7 @@ class CORE_EXPORT QgsTracer : public QObject //! Extent for graph building (empty extent means no limit) QgsRectangle mExtent; //! If FALSE, no vertices will be added on intersections unless they exist in the original layers - bool mAddPointsOnIntersections = false; + bool mAddPointsOnIntersections = true; //! Holds the input layers' intersections. Only populated when mAddPointsOnIntersections == false QgsGeometry mIntersections; diff --git a/src/core/raster/qgshuesaturationfilter.cpp b/src/core/raster/qgshuesaturationfilter.cpp index 676eba155aff..f5deb301f62f 100644 --- a/src/core/raster/qgshuesaturationfilter.cpp +++ b/src/core/raster/qgshuesaturationfilter.cpp @@ -113,10 +113,9 @@ QgsRasterBlock *QgsHueSaturationFilter::block( int bandNo, QgsRectangle const & Q_UNUSED( bandNo ) QgsDebugMsgLevel( QStringLiteral( "width = %1 height = %2 extent = %3" ).arg( width ).arg( height ).arg( extent.toString() ), 4 ); - auto outputBlock = std::make_unique(); if ( !mInput ) { - return outputBlock.release(); + return nullptr; } // At this moment we know that we read rendered image @@ -125,7 +124,7 @@ QgsRasterBlock *QgsHueSaturationFilter::block( int bandNo, QgsRectangle const & if ( !inputBlock || inputBlock->isEmpty() ) { QgsDebugError( QStringLiteral( "No raster data!" ) ); - return outputBlock.release(); + return nullptr; } if ( !mInvertColors && mSaturation == 0 && mGrayscaleMode == GrayscaleOff && !mColorizeOn ) @@ -134,87 +133,101 @@ QgsRasterBlock *QgsHueSaturationFilter::block( int bandNo, QgsRectangle const & return inputBlock.release(); } + auto outputBlock = std::make_unique(); + if ( !outputBlock->reset( Qgis::DataType::ARGB32_Premultiplied, width, height ) ) { - return outputBlock.release(); + return nullptr; } // adjust image - QRgb myNoDataColor = qRgba( 0, 0, 0, 0 ); - QRgb myRgb; - QColor myColor; + const QRgb myNoDataColor = qRgba( 0, 0, 0, 0 ); int h, s, l; - int r, g, b, alpha; + int r, g, b; double alphaFactor = 1.0; - for ( qgssize i = 0; i < ( qgssize )width * height; i++ ) - { - if ( inputBlock->color( i ) == myNoDataColor ) - { - outputBlock->setColor( i, myNoDataColor ); - continue; - } + const QRgb *inputColorData = inputBlock->colorData(); + const int imageHeight = inputBlock->image().height(); + const int imageWidth = inputBlock->image().width(); - myRgb = inputBlock->color( i ); - myColor = QColor( myRgb ); + QRgb *outputColorData = outputBlock->colorData(); - // Alpha must be taken from QRgb, since conversion from QRgb->QColor loses alpha - alpha = qAlpha( myRgb ); + for ( int row = 0; row < height; ++row ) + { + if ( feedback->isCanceled() ) + return nullptr; - if ( alpha == 0 ) + for ( int col = 0; col < width; ++col ) { - // totally transparent, no changes required - outputBlock->setColor( i, myRgb ); - continue; - } + const qgssize i = static_cast< qgssize >( row ) * width + static_cast< qgssize >( col ); - // Get rgb for color - myColor.getRgb( &r, &g, &b ); + if ( !inputColorData || row >= imageHeight || col >= imageWidth || inputColorData[i] == myNoDataColor ) + { + outputColorData[i] = myNoDataColor; + continue; + } - if ( mInvertColors || alpha != 255 ) - { - if ( alpha != 255 ) + const QRgb inputColor = inputColorData[i]; + QColor myColor = QColor( inputColor ); + + // Alpha must be taken from QRgb, since conversion from QRgb->QColor loses alpha + const int alpha = qAlpha( inputColor ); + + if ( alpha == 0 ) { - // Semi-transparent pixel. We need to adjust the colors since we are using Qgis::DataType::ARGB32_Premultiplied - // and color values have been premultiplied by alpha - alphaFactor = alpha / 255.; - r /= alphaFactor; - g /= alphaFactor; - b /= alphaFactor; + // totally transparent, no changes required + outputColorData[i] = inputColor; + continue; } - if ( mInvertColors ) + + // Get rgb for color + myColor.getRgb( &r, &g, &b ); + + if ( mInvertColors || alpha != 255 ) { - r = 255 - r; - g = 255 - g; - b = 255 - b; + if ( alpha != 255 ) + { + // Semi-transparent pixel. We need to adjust the colors since we are using Qgis::DataType::ARGB32_Premultiplied + // and color values have been premultiplied by alpha + alphaFactor = alpha / 255.; + r /= alphaFactor; + g /= alphaFactor; + b /= alphaFactor; + } + if ( mInvertColors ) + { + r = 255 - r; + g = 255 - g; + b = 255 - b; + } + myColor = QColor::fromRgb( r, g, b ); } - myColor = QColor::fromRgb( r, g, b ); - } - myColor.getHsl( &h, &s, &l ); + myColor.getHsl( &h, &s, &l ); - // Changing saturation? - if ( ( mGrayscaleMode != GrayscaleOff ) || ( mSaturationScale != 1 ) ) - { - processSaturation( r, g, b, h, s, l ); - } + // Changing saturation? + if ( ( mGrayscaleMode != GrayscaleOff ) || ( mSaturationScale != 1 ) ) + { + processSaturation( r, g, b, h, s, l ); + } - // Colorizing? - if ( mColorizeOn ) - { - processColorization( r, g, b, h, s, l ); - } + // Colorizing? + if ( mColorizeOn ) + { + processColorization( r, g, b, h, s, l ); + } - // Convert back to rgb - if ( alpha != 255 ) - { - // Transparent pixel, need to premultiply color components - r *= alphaFactor; - g *= alphaFactor; - b *= alphaFactor; - } + // Convert back to rgb + if ( alpha != 255 ) + { + // Transparent pixel, need to premultiply color components + r *= alphaFactor; + g *= alphaFactor; + b *= alphaFactor; + } - outputBlock->setColor( i, qRgba( r, g, b, alpha ) ); + outputColorData[i] = qRgba( r, g, b, alpha ); + } } return outputBlock.release(); diff --git a/src/customwidgets/CMakeLists.txt b/src/customwidgets/CMakeLists.txt index 4f4849763f41..4dabd8fa47e8 100644 --- a/src/customwidgets/CMakeLists.txt +++ b/src/customwidgets/CMakeLists.txt @@ -124,13 +124,12 @@ GENERATE_EXPORT_HEADER( EXPORT_FILE_NAME qgis_customwidgets.h ) -set(QGIS_CUSTOMWIDGETS_INSTALL_HDRS ${QGIS_CUSTOMWIDGETS_MOC_HDRS} ${CMAKE_CURRENT_BINARY_DIR}/qgis_customwidgets.h) +set(QGIS_CUSTOMWIDGETS_HDRS ${QGIS_CUSTOMWIDGETS_MOC_HDRS} ${CMAKE_CURRENT_BINARY_DIR}/qgis_customwidgets.h) # install install(TARGETS qgis_customwidgets RUNTIME DESTINATION ${QT_PLUGINS_DIR}/designer LIBRARY DESTINATION ${QT_PLUGINS_DIR}/designer ) - # TODO: apple -install(FILES ${QGIS_CUSTOMWIDGETS_INSTALL_HDRS} DESTINATION ${QGIS_INCLUDE_DIR}) +install(FILES ${QGIS_CUSTOMWIDGETS_HDRS} DESTINATION ${QGIS_INCLUDE_DIR}) diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index bdebe5749153..d148ff6d0344 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -1780,36 +1780,12 @@ GENERATE_EXPORT_HEADER( set(QGIS_GUI_HDRS ${QGIS_GUI_HDRS} ${CMAKE_CURRENT_BINARY_DIR}/qgis_gui.h) -if(NOT APPLE OR NOT QGIS_MACAPP_FRAMEWORK) - if (WIN32) - include_directories(${CMAKE_SOURCE_DIR}/src/native/win) - elseif (APPLE) - include_directories(${CMAKE_SOURCE_DIR}/src/native/mac) - elseif (UNIX) - include_directories(${CMAKE_SOURCE_DIR}/src/native/linux) - endif() - install(FILES ${QGIS_GUI_HDRS} DESTINATION ${QGIS_INCLUDE_DIR}) -else() +if (WIN32) + include_directories(${CMAKE_SOURCE_DIR}/src/native/win) +elseif (APPLE) include_directories(${CMAKE_SOURCE_DIR}/src/native/mac) - set_target_properties(qgis_gui PROPERTIES - CLEAN_DIRECT_OUTPUT 1 - FRAMEWORK 1 - FRAMEWORK_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}" - MACOSX_FRAMEWORK_INFO_PLIST "${CMAKE_SOURCE_DIR}/mac/framework.info.plist.in" - MACOSX_FRAMEWORK_SHORT_VERSION_STRING ${COMPLETE_VERSION} - MACOSX_FRAMEWORK_IDENTIFIER org.qgis.qgis3_gui - BUILD_WITH_INSTALL_RPATH TRUE - PUBLIC_HEADER "${QGIS_GUI_HDRS}" - LINK_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}" - ) - # generated export header does not get copied with PUBLIC_HEADER files - add_custom_command(TARGET qgis_gui - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy qgis_gui.h - "${QGIS_OUTPUT_DIRECTORY}/${QGIS_LIB_SUBDIR}/qgis_gui.framework/Headers" - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - DEPENDS qgis_gui.h - ) +elseif (UNIX) + include_directories(${CMAKE_SOURCE_DIR}/src/native/linux) endif() #generate unversioned libs for android @@ -1898,26 +1874,11 @@ if(CLANG_TIDY_EXE) endif() # install +if(NOT QGIS_MAC_BUNDLE) + install(FILES ${QGIS_GUI_HDRS} DESTINATION ${QGIS_INCLUDE_DIR}) +endif() install(TARGETS qgis_gui RUNTIME DESTINATION ${QGIS_BIN_DIR} LIBRARY DESTINATION ${QGIS_LIB_DIR} - ARCHIVE DESTINATION ${QGIS_LIB_DIR} - FRAMEWORK DESTINATION ${QGIS_FW_SUBDIR} - PUBLIC_HEADER DESTINATION ${QGIS_INCLUDE_DIR}) - -# ui headers to install, don't exist at target definition time, install manually -if (APPLE AND QGIS_MACAPP_FRAMEWORK) - install(FILES ${QGIS_GUI_UI_HDRS} DESTINATION ${QGIS_FW_SUBDIR}/qgis_gui.framework/Headers) -else() - install(FILES ${QGIS_GUI_UI_HDRS} DESTINATION ${QGIS_INCLUDE_DIR}) -endif() - -# Mac dev frameworks - -if (APPLE AND QGIS_MACAPP_INSTALL_DEV) - install(TARGETS qgis_gui FRAMEWORK DESTINATION ${QGIS_MACAPP_DEV_PREFIX}) - install(FILES ${QGIS_GUI_UI_HDRS} DESTINATION ${QGIS_MACAPP_DEV_PREFIX}/qgis_gui.framework/Headers) - install(CODE "execute_process(COMMAND install_name_tool -id \"${QGIS_MACAPP_DEV_PREFIX}/qgis_gui.framework/Versions/${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}/qgis_gui\" \"$ENV{DESTDIR}${QGIS_MACAPP_DEV_PREFIX}/qgis_gui.framework/qgis_gui\")") - install(CODE "execute_process(COMMAND install_name_tool -change \"${CMAKE_INSTALL_NAME_DIR}/qgis_core.framework/Versions/${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}/qgis_core\" \"${QGIS_MACAPP_DEV_PREFIX}/qgis_core.framework/Versions/${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}/qgis_core\" \"$ENV{DESTDIR}${QGIS_MACAPP_DEV_PREFIX}/qgis_gui.framework/qgis_gui\")") -endif() + ARCHIVE DESTINATION ${QGIS_LIB_DIR}) \ No newline at end of file diff --git a/src/gui/layout/qgslayoutmapwidget.cpp b/src/gui/layout/qgslayoutmapwidget.cpp index e54ec1d20938..c75c5e9c74be 100644 --- a/src/gui/layout/qgslayoutmapwidget.cpp +++ b/src/gui/layout/qgslayoutmapwidget.cpp @@ -111,10 +111,21 @@ QgsLayoutMapWidget::QgsLayoutMapWidget( QgsLayoutItemMap *item, QgsMapCanvas *ma mDockToolbar->setIconSize( QgsGuiUtils::iconSize( true ) ); + mLayersMenu = new QMenu( this ); + QToolButton *btnLayers = new QToolButton( this ); + btnLayers->setAutoRaise( true ); + btnLayers->setToolTip( tr( "Set Map Extent to Layer Extent" ) ); + btnLayers->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionLayers.svg" ) ) ); + btnLayers->setPopupMode( QToolButton::InstantPopup ); + btnLayers->setMenu( mLayersMenu ); + + mDockToolbar->insertWidget( mActionMoveContent, btnLayers ); + connect( mLayersMenu, &QMenu::aboutToShow, this, &QgsLayoutMapWidget::aboutToShowLayersMenu ); + mBookmarkMenu = new QMenu( this ); QToolButton *btnBookmarks = new QToolButton( this ); btnBookmarks->setAutoRaise( true ); - btnBookmarks->setToolTip( tr( "Bookmarks" ) ); + btnBookmarks->setToolTip( tr( "Set Map Extent to Bookmark Extent" ) ); btnBookmarks->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionShowBookmarks.svg" ) ) ); btnBookmarks->setPopupMode( QToolButton::InstantPopup ); btnBookmarks->setMenu( mBookmarkMenu ); @@ -459,6 +470,44 @@ void QgsLayoutMapWidget::switchToMoveContentTool() mInterface->activateTool( QgsLayoutDesignerInterface::ToolMoveItemContent ); } +void QgsLayoutMapWidget::aboutToShowLayersMenu() +{ + mLayersMenu->clear(); + + if ( !mMapLayerModel ) + { + mMapLayerModel = new QgsMapLayerProxyModel( this ); + mMapLayerModel->setFilters( Qgis::LayerFilter::SpatialLayer ); + } + + if ( mMapLayerModel->rowCount() == 0 ) + { + QAction *action = new QAction( tr( "No spatial layers available" ) ); + action->setEnabled( false ); + mLayersMenu->addAction( action ); + return; + } + + for ( int i = 0; i < mMapLayerModel->rowCount(); ++i ) + { + const QModelIndex index = mMapLayerModel->index( i, 0 ); + const QIcon icon = qvariant_cast( mMapLayerModel->data( index, Qt::DecorationRole ) ); + const QString text = mMapLayerModel->data( index, Qt::DisplayRole ).toString(); + const QString tooltip = mMapLayerModel->data( index, Qt::ToolTipRole ).toString(); + const QString layerId = mMapLayerModel->data( index, static_cast( QgsMapLayerModel::CustomRole::LayerId ) ).toString(); + + QAction *action = new QAction( icon, text, mLayersMenu ); + action->setToolTip( tooltip ); + connect( action, &QAction::triggered, this, [this, layerId] { + if ( QgsMapLayer *layer = QgsProject::instance()->mapLayer( layerId ) ) + { + setToCustomExtent( QgsReferencedRectangle( layer->extent(), layer->crs() ) ); + } + } ); + mLayersMenu->addAction( action ); + } +} + void QgsLayoutMapWidget::aboutToShowBookmarkMenu() { mBookmarkMenu->clear(); @@ -466,7 +515,17 @@ void QgsLayoutMapWidget::aboutToShowBookmarkMenu() // query the bookmarks now? or once during widget creation... Hmm. Either way, there's potentially a // delay if there's LOTS of bookmarks. Let's avoid the cost until bookmarks are actually required. if ( !mBookmarkModel ) + { mBookmarkModel = new QgsBookmarkManagerProxyModel( QgsApplication::bookmarkManager(), QgsProject::instance()->bookmarkManager(), this ); + } + + if ( mBookmarkModel->rowCount() == 0 ) + { + QAction *action = new QAction( tr( "No bookmarks available" ) ); + action->setEnabled( false ); + mBookmarkMenu->addAction( action ); + return; + } QMap groupMenus; for ( int i = 0; i < mBookmarkModel->rowCount(); ++i ) @@ -485,32 +544,7 @@ void QgsLayoutMapWidget::aboutToShowBookmarkMenu() QAction *action = new QAction( mBookmarkModel->data( mBookmarkModel->index( i, 0 ), static_cast( QgsBookmarkManagerModel::CustomRole::Name ) ).toString(), mBookmarkMenu ); const QgsReferencedRectangle extent = mBookmarkModel->data( mBookmarkModel->index( i, 0 ), static_cast( QgsBookmarkManagerModel::CustomRole::Extent ) ).value(); connect( action, &QAction::triggered, this, [=] { - if ( !mMapItem ) - { - return; - } - - QgsRectangle newExtent = extent; - - //transform? - if ( extent.crs() != mMapItem->crs() ) - { - try - { - QgsCoordinateTransform xForm( extent.crs(), mMapItem->crs(), QgsProject::instance() ); - xForm.setBallparkTransformsAreAppropriate( true ); - newExtent = xForm.transformBoundingBox( newExtent ); - } - catch ( QgsCsException & ) - { - //transform failed, better not proceed - return; - } - } - - mMapItem->layout()->undoStack()->beginCommand( mMapItem, tr( "Change Map Extent" ) ); - mMapItem->zoomToExtent( newExtent ); - mMapItem->layout()->undoStack()->endCommand(); + setToCustomExtent( extent ); } ); destMenu->addAction( action ); } @@ -526,6 +560,34 @@ void QgsLayoutMapWidget::aboutToShowBookmarkMenu() } } +void QgsLayoutMapWidget::setToCustomExtent( const QgsReferencedRectangle &referencedExtent ) +{ + if ( !mMapItem || referencedExtent.isEmpty() ) + { + return; + } + + QgsRectangle extent = referencedExtent; + if ( referencedExtent.crs() != mMapItem->crs() ) + { + try + { + QgsCoordinateTransform coordinateTransform( referencedExtent.crs(), mMapItem->crs(), QgsProject::instance() ); + coordinateTransform.setBallparkTransformsAreAppropriate( true ); + extent = coordinateTransform.transformBoundingBox( extent ); + } + catch ( QgsCsException & ) + { + //transform failed, better not proceed + return; + } + } + + mMapItem->layout()->undoStack()->beginCommand( mMapItem, tr( "Change Map Extent" ) ); + mMapItem->zoomToExtent( extent ); + mMapItem->layout()->undoStack()->endCommand(); +} + void QgsLayoutMapWidget::mTemporalCheckBox_toggled( bool checked ) { if ( !mMapItem ) diff --git a/src/gui/layout/qgslayoutmapwidget.h b/src/gui/layout/qgslayoutmapwidget.h index f12597e85232..c13150d8a08d 100644 --- a/src/gui/layout/qgslayoutmapwidget.h +++ b/src/gui/layout/qgslayoutmapwidget.h @@ -34,6 +34,7 @@ class QgsLayoutItemMapOverview; class QgsLayoutMapLabelingWidget; class QgsLayoutMapClippingWidget; class QgsBookmarkManagerProxyModel; +class QgsReferencedRectangle; /** * \ingroup gui @@ -144,6 +145,7 @@ class GUI_EXPORT QgsLayoutMapWidget : public QgsLayoutItemBaseWidget, private Ui void showLabelSettings(); void showClipSettings(); void switchToMoveContentTool(); + void aboutToShowLayersMenu(); void aboutToShowBookmarkMenu(); private: @@ -153,7 +155,9 @@ class GUI_EXPORT QgsLayoutMapWidget : public QgsLayoutItemBaseWidget, private Ui QgsLayoutDesignerInterface *mInterface = nullptr; QPointer mLabelWidget; QPointer mClipWidget; + QMenu *mLayersMenu = nullptr; QMenu *mBookmarkMenu = nullptr; + QgsMapLayerProxyModel *mMapLayerModel = nullptr; QgsBookmarkManagerProxyModel *mBookmarkModel = nullptr; QString mReportTypeString; int mBlockThemeComboChanges = 0; @@ -190,6 +194,8 @@ class GUI_EXPORT QgsLayoutMapWidget : public QgsLayoutItemBaseWidget, private Ui * The order will match the layer order from the map canvas */ QList orderedPresetVisibleLayers( const QString &name ) const; + + void setToCustomExtent( const QgsReferencedRectangle &extent ); }; /** diff --git a/src/gui/maptools/qgsmaptoolshapeabstract.cpp b/src/gui/maptools/qgsmaptoolshapeabstract.cpp index cab827465363..360880b63aa0 100644 --- a/src/gui/maptools/qgsmaptoolshapeabstract.cpp +++ b/src/gui/maptools/qgsmaptoolshapeabstract.cpp @@ -50,6 +50,8 @@ void QgsMapToolShapeAbstract::clean() void QgsMapToolShapeAbstract::undo() { - if ( mPoints.count() > 0 ) + if ( mPoints.count() == 1 ) + clean(); + else if ( mPoints.count() > 1 ) mPoints.removeLast(); } diff --git a/src/gui/qgslayerpropertiesdialog.cpp b/src/gui/qgslayerpropertiesdialog.cpp index 6cf88c9aacc2..23725287db47 100644 --- a/src/gui/qgslayerpropertiesdialog.cpp +++ b/src/gui/qgslayerpropertiesdialog.cpp @@ -382,7 +382,7 @@ void QgsLayerPropertiesDialog::saveDefaultStyle() return; } - mLayer->saveStyleToDatabase( QString(), QString(), true, QString(), errorMsg ); + mLayer->saveStyleToDatabaseV2( QString(), QString(), true, QString(), errorMsg ); if ( errorMsg.isNull() ) { return; @@ -457,7 +457,7 @@ void QgsLayerPropertiesDialog::saveStyleAs() return; } - mLayer->saveStyleToDatabase( dbSettings.name, dbSettings.description, dbSettings.isDefault, dbSettings.uiFileContent, errorMessage, dlg.styleCategories() ); + mLayer->saveStyleToDatabaseV2( dbSettings.name, dbSettings.description, dbSettings.isDefault, dbSettings.uiFileContent, errorMessage, dlg.styleCategories() ); if ( !errorMessage.isNull() ) { diff --git a/src/gui/vector/qgsattributesformmodel.cpp b/src/gui/vector/qgsattributesformmodel.cpp index 847d1c383fd5..dae1aae3cec3 100644 --- a/src/gui/vector/qgsattributesformmodel.cpp +++ b/src/gui/vector/qgsattributesformmodel.cpp @@ -621,9 +621,12 @@ void QgsAttributesAvailableWidgetsModel::populateLayerActions( const QList< QgsA } } - beginInsertRows( actionsIndex, 0, count ); - populateActionItems( actions ); - endInsertRows(); + if ( count > 0 ) + { + beginInsertRows( actionsIndex, 0, count - 1 ); + populateActionItems( actions ); + endInsertRows(); + } } void QgsAttributesAvailableWidgetsModel::populateActionItems( const QList actions ) diff --git a/src/gui/vector/qgsvectorlayerproperties.cpp b/src/gui/vector/qgsvectorlayerproperties.cpp index b643e219ceb0..ce73eab7dd15 100644 --- a/src/gui/vector/qgsvectorlayerproperties.cpp +++ b/src/gui/vector/qgsvectorlayerproperties.cpp @@ -1073,7 +1073,7 @@ void QgsVectorLayerProperties::saveMultipleStylesAs() return; } - mLayer->saveStyleToDatabase( name, dbSettings.description, dbSettings.isDefault, dbSettings.uiFileContent, msgError, dlg.styleCategories() ); + mLayer->saveStyleToDatabaseV2( name, dbSettings.description, dbSettings.isDefault, dbSettings.uiFileContent, msgError, dlg.styleCategories() ); if ( !msgError.isNull() ) { diff --git a/src/native/CMakeLists.txt b/src/native/CMakeLists.txt index 73edb952b1ad..0f1e17e6f7a6 100644 --- a/src/native/CMakeLists.txt +++ b/src/native/CMakeLists.txt @@ -7,34 +7,10 @@ if (IOS) endif() -set(NATIVE_LINK_LIBS) - if(UNIX AND NOT APPLE AND NOT ANDROID) find_package(${QT_VERSION_BASE} COMPONENTS DBus REQUIRED) endif() -if(APPLE) - set(APPLE_LIB_LIST ApplicationServices CoreFoundation IOKit AppKit) - foreach(_lib ${APPLE_LIB_LIST}) - string(TOUPPER ${_lib} _lib_var) - # prefer /System/Library/Frameworks, in case CMAKE_FIND_FRAMEWORK=LAST, etc. - find_library(APPLE_${_lib_var}_LIBRARY - NAMES ${_lib} - PATHS /System/Library/Frameworks - NO_DEFAULT_PATH - ) - # if not found, drop back to standard find paths - find_library(APPLE_${_lib_var}_LIBRARY ${_lib}) - - if(NOT APPLE_${_lib_var}_LIBRARY) - message(FATAL_ERROR "Couldn't find Apple's '${_lib}' framework or library") - endif() - - list(APPEND NATIVE_LINK_LIBS "-weak_framework ${_lib}") - endforeach(_lib ${APPLE_LIB_LIST}) -endif() - - ############################################################# # sources @@ -110,22 +86,6 @@ GENERATE_EXPORT_HEADER( set(QGIS_NATIVE_HDRS ${QGIS_NATIVE_HDRS} ${CMAKE_CURRENT_BINARY_DIR}/qgis_native.h) -if(NOT APPLE OR NOT QGIS_MACAPP_FRAMEWORK) - install(FILES ${QGIS_NATIVE_HDRS} DESTINATION ${QGIS_INCLUDE_DIR}) -else() - set_target_properties(qgis_native PROPERTIES - CLEAN_DIRECT_OUTPUT 1 - FRAMEWORK 1 - FRAMEWORK_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}" - MACOSX_FRAMEWORK_INFO_PLIST "${CMAKE_SOURCE_DIR}/mac/framework.info.plist.in" - MACOSX_FRAMEWORK_SHORT_VERSION_STRING ${COMPLETE_VERSION} - MACOSX_FRAMEWORK_IDENTIFIER org.qgis.qgis3_native - BUILD_WITH_INSTALL_RPATH TRUE - PUBLIC_HEADER "${QGIS_NATIVE_HDRS}" - LINK_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}" - ) -endif() - #generate unversioned libs for android if(NOT ANDROID) set_target_properties(qgis_native PROPERTIES @@ -134,11 +94,7 @@ if(NOT ANDROID) ) endif() -if (BUILD_WITH_QT6) - target_link_libraries(qgis_native ${Qt6Core_LIBRARIES} ${Qt6Gui_LIBRARIES} "${NATIVE_LINK_LIBS}") -else() - target_link_libraries(qgis_native ${Qt5Core_LIBRARIES} ${Qt5Gui_LIBRARIES} "${NATIVE_LINK_LIBS}") -endif() +target_link_libraries(qgis_native ${QT_VERSION_BASE}::Core ${QT_VERSION_BASE}::Gui) if (UNIX AND NOT APPLE AND NOT ANDROID) target_link_libraries(qgis_native ${QT_VERSION_BASE}::DBus) @@ -153,18 +109,12 @@ if (MSVC AND NOT BUILD_WITH_QT6) endif() # install +if(NOT QGIS_MAC_BUNDLE) + install(FILES ${QGIS_NATIVE_HDRS} DESTINATION ${QGIS_INCLUDE_DIR}) +endif() + install(TARGETS qgis_native RUNTIME DESTINATION ${QGIS_BIN_DIR} LIBRARY DESTINATION ${QGIS_LIB_DIR} - ARCHIVE DESTINATION ${QGIS_LIB_DIR} - FRAMEWORK DESTINATION ${QGIS_FW_SUBDIR} - PUBLIC_HEADER DESTINATION ${QGIS_INCLUDE_DIR} -) - -# Mac dev frameworks - -if (APPLE AND QGIS_MACAPP_INSTALL_DEV) - install(TARGETS qgis_native FRAMEWORK DESTINATION ${QGIS_MACAPP_DEV_PREFIX}) - install(CODE "execute_process(COMMAND install_name_tool -id \"${QGIS_MACAPP_DEV_PREFIX}/qgis_native.framework/Versions/${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}/qgis_native\" \"$ENV{DESTDIR}${QGIS_MACAPP_DEV_PREFIX}/qgis_native.framework/qgis_native\")") -endif() + ARCHIVE DESTINATION ${QGIS_LIB_DIR}) diff --git a/src/process/CMakeLists.txt b/src/process/CMakeLists.txt index ffc62d5cf2b9..7f60cfdb42e4 100644 --- a/src/process/CMakeLists.txt +++ b/src/process/CMakeLists.txt @@ -15,7 +15,7 @@ endif() ######################################################## # Build -add_executable (qgis_process MACOSX_BUNDLE ${QGIS_PROCESS_SRCS}) +add_executable (qgis_process ${QGIS_PROCESS_SRCS}) # require c++17 target_compile_features(qgis_process PRIVATE cxx_std_17) @@ -55,10 +55,6 @@ if (WITH_BINDINGS) add_definitions(-DWITH_BINDINGS) endif() -if(HAVE_OPENCL) - include_directories(SYSTEM ${OpenCL_INCLUDE_DIRS}) -endif() - # install install (TARGETS qgis_process diff --git a/src/providers/grass/CMakeLists.txt b/src/providers/grass/CMakeLists.txt index 370c66af70bf..76177185511c 100644 --- a/src/providers/grass/CMakeLists.txt +++ b/src/providers/grass/CMakeLists.txt @@ -7,9 +7,6 @@ include_directories( ${CMAKE_BINARY_DIR}/src/providers/grass ${CMAKE_CURRENT_BINARY_DIR} ) -include_directories (SYSTEM - ${POSTGRES_INCLUDE_DIR} -) # # GRASS library @@ -75,29 +72,9 @@ macro(ADD_GRASSLIB GRASS_BUILD_VERSION) set(GRASS_OFF_T_SIZE_DEF "") endif() - if(QGIS_MACAPP_FRAMEWORK) - set_target_properties(qgisgrass${GRASS_BUILD_VERSION} PROPERTIES - CLEAN_DIRECT_OUTPUT 1 - FRAMEWORK 1 - FRAMEWORK_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}" - MACOSX_FRAMEWORK_INFO_PLIST "${CMAKE_SOURCE_DIR}/mac/framework.info.plist.in" - MACOSX_FRAMEWORK_SHORT_VERSION_STRING ${COMPLETE_VERSION} - MACOSX_FRAMEWORK_IDENTIFIER org.qgis.qgis3_grass - COMPILE_FLAGS "-DGRASS_BASE=\\\"${GRASS_PREFIX}\\\" ${GRASS_OFF_T_SIZE_DEF}" - ) - else() - set_target_properties(qgisgrass${GRASS_BUILD_VERSION} PROPERTIES - CLEAN_DIRECT_OUTPUT 1 - FRAMEWORK 0 - COMPILE_FLAGS "-DGRASS_BASE=\\\"${GRASS_PREFIX}\\\" ${GRASS_OFF_T_SIZE_DEF}" - ) - endif() - - if (APPLE) - set_target_properties(qgisgrass${GRASS_BUILD_VERSION} PROPERTIES - LINK_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}" - ) - endif() + set_target_properties(qgisgrass${GRASS_BUILD_VERSION} PROPERTIES + COMPILE_FLAGS "-DGRASS_BASE=\\\"${GRASS_PREFIX}\\\" ${GRASS_OFF_T_SIZE_DEF}" + ) #generate unversioned libs for android if (NOT ANDROID) @@ -143,10 +120,6 @@ macro(ADD_GRASSLIB GRASS_BUILD_VERSION) ) endif() - if (APPLE) - set_target_properties(qgisgrass${GRASS_BUILD_VERSION} PROPERTIES BUILD_WITH_INSTALL_RPATH TRUE) - endif() - GENERATE_EXPORT_HEADER( qgisgrass${GRASS_BUILD_VERSION} BASE_NAME GRASS_LIB @@ -291,8 +264,7 @@ macro(ADD_GRASSLIB GRASS_BUILD_VERSION) install(TARGETS qgisgrass${GRASS_BUILD_VERSION} RUNTIME DESTINATION ${QGIS_BIN_DIR} - LIBRARY DESTINATION ${QGIS_LIB_DIR} - FRAMEWORK DESTINATION ${QGIS_FW_SUBDIR}) + LIBRARY DESTINATION ${QGIS_LIB_DIR}) install(TARGETS provider_grass${GRASS_BUILD_VERSION} RUNTIME DESTINATION ${QGIS_PLUGIN_DIR} diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index 3323d3985f17..e6398e70f993 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -30,10 +30,6 @@ GENERATE_EXPORT_HEADER( EXPORT_FILE_NAME qgis_python.h ) -if (APPLE) - set_target_properties(qgispython PROPERTIES BUILD_WITH_INSTALL_RPATH TRUE) -endif() - install(TARGETS qgispython RUNTIME DESTINATION ${QGIS_BIN_DIR} LIBRARY DESTINATION ${QGIS_LIB_DIR} diff --git a/src/python/qgspythonutilsimpl.cpp b/src/python/qgspythonutilsimpl.cpp index 0d5854b2475f..6c05105d4db4 100644 --- a/src/python/qgspythonutilsimpl.cpp +++ b/src/python/qgspythonutilsimpl.cpp @@ -218,8 +218,27 @@ void QgsPythonUtilsImpl::init() } #endif - // initialize python - Py_Initialize(); + PyConfig config; + PyConfig_InitPythonConfig( &config ); + +#ifdef QGIS_MAC_BUNDLE + // If we package QGIS as a mac app, we deploy Qt plugins into [app]/Contents/PlugIns + if ( qgetenv( "PYTHONHOME" ).isNull() ) + { + status = PyConfig_SetString( &config, &config.home, QgsApplication::libraryPath().toStdWString().c_str() ); + if ( PyStatus_Exception( status ) ) + { + qWarning() << "Failed to set python home"; + } + } +#endif + + status = Py_InitializeFromConfig( &config ); + if ( PyStatus_Exception( status ) ) + { + qWarning() << "Failed to initialize from config"; + } + PyConfig_Clear( &config ); mPythonEnabled = true; diff --git a/src/quickgui/CMakeLists.txt b/src/quickgui/CMakeLists.txt index a1f70a30e492..872b9e4c6e2f 100644 --- a/src/quickgui/CMakeLists.txt +++ b/src/quickgui/CMakeLists.txt @@ -69,36 +69,12 @@ GENERATE_EXPORT_HEADER( ) # Installation -if(NOT APPLE OR NOT QGIS_MACAPP_FRAMEWORK) - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/qgis_quick.h ${QGIS_QUICK_GUI_HDRS} ${QGIS_QUICK_GUI_MOC_HDRS} DESTINATION ${QGIS_INCLUDE_DIR}) -else() - set_target_properties(qgis_quick PROPERTIES - CLEAN_DIRECT_OUTPUT 1 - FRAMEWORK 1 - FRAMEWORK_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}" - MACOSX_FRAMEWORK_INFO_PLIST "${CMAKE_SOURCE_DIR}/mac/framework.info.plist.in" - MACOSX_FRAMEWORK_SHORT_VERSION_STRING ${COMPLETE_VERSION} - MACOSX_FRAMEWORK_IDENTIFIER org.qgis.qgis3_quick - BUILD_WITH_INSTALL_RPATH TRUE - PUBLIC_HEADER "${QGIS_QUICK_GUI_HDRS};${QGIS_QUICK_GUI_MOC_HDRS}" - LINK_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}" - ) - # generated export header does not get copied with PUBLIC_HEADER files - add_custom_command(TARGET qgis_quick - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy qgis_quick.h - "${QGIS_OUTPUT_DIRECTORY}/${QGIS_LIB_SUBDIR}/qgis_quick.framework/Headers" - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - DEPENDS qgis_quick.h - ) -endif() +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/qgis_quick.h ${QGIS_QUICK_GUI_HDRS} DESTINATION ${QGIS_INCLUDE_DIR}) install(TARGETS qgis_quick RUNTIME DESTINATION ${QGIS_BIN_DIR} LIBRARY DESTINATION ${QGIS_LIB_DIR} - ARCHIVE DESTINATION ${QGIS_LIB_DIR} - FRAMEWORK DESTINATION ${QGIS_FW_SUBDIR} - PUBLIC_HEADER DESTINATION ${QGIS_INCLUDE_DIR}) + ARCHIVE DESTINATION ${QGIS_LIB_DIR}) ############################################################ # qgis_quick_plugin module (QML) library diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index a116faa9bf47..ddec913d6528 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -29,8 +29,4 @@ GENERATE_EXPORT_HEADER( EXPORT_FILE_NAME qgis_test.h ) -target_link_libraries(qgis_test qgis_core ${QT_VERSION_BASE}::Test) - -set(QGIS_TEST_HDRS ${QGIS_TEST_HDRS} ${CMAKE_CURRENT_BINARY_DIR}/qgis_test.h) - -install(FILES ${QGIS_TEST_HDRS} DESTINATION ${QGIS_INCLUDE_DIR}) +target_link_libraries(qgis_test qgis_core ${QT_VERSION_BASE}::Test) \ No newline at end of file diff --git a/tests/bench/CMakeLists.txt b/tests/bench/CMakeLists.txt index 481e449d9d7f..216a90067b01 100644 --- a/tests/bench/CMakeLists.txt +++ b/tests/bench/CMakeLists.txt @@ -9,7 +9,7 @@ set (BENCH_SRCS ######################################################## # Build -add_executable (qgis_bench MACOSX_BUNDLE WIN32 ${BENCH_SRCS} ) +add_executable (qgis_bench WIN32 ${BENCH_SRCS} ) # require c++17 target_compile_features(qgis_bench PRIVATE cxx_std_17) @@ -46,13 +46,3 @@ install (TARGETS qgis_bench BUNDLE DESTINATION ${QGIS_BIN_DIR} RUNTIME DESTINATION ${QGIS_BIN_DIR} ) -if (APPLE) - install (CODE "execute_process(COMMAND ln -sfn ../../../${QGIS_FW_SUBDIR} \"$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/${QGIS_BIN_DIR}/qgis_bench.app/Contents/Frameworks\")") - install (CODE "execute_process(COMMAND ln -sfn ../../../../${QGIS_LIB_SUBDIR} \"$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/${QGIS_BIN_DIR}/qgis_bench.app/Contents/MacOS/lib\")") - install (CODE "execute_process(COMMAND ln -sfn ../../../${QGIS_PLUGIN_SUBDIR}/.. \"$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/${QGIS_BIN_DIR}/qgis_bench.app/Contents/Plugins\")") - install (CODE "execute_process(COMMAND ln -sfn ../../../${QGIS_DATA_SUBDIR} \"$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/${QGIS_BIN_DIR}/qgis_bench.app/Contents/Resources\")") - # may not exist, unless BundleUtilities are used - install (CODE "execute_process(COMMAND ln -sfn ../../../../share \"$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/${QGIS_BIN_DIR}/qgis_bench.app/Contents/MacOS/share\")") - -endif() - diff --git a/tests/src/3d/testqgs3dcameracontroller.cpp b/tests/src/3d/testqgs3dcameracontroller.cpp index 8de91cae2306..4cf9c1d26fd6 100644 --- a/tests/src/3d/testqgs3dcameracontroller.cpp +++ b/tests/src/3d/testqgs3dcameracontroller.cpp @@ -16,6 +16,7 @@ #include "qgstest.h" #include "qgs3d.h" +#include "qgs3dmapcanvas.h" #include "qgs3dmapscene.h" #include "qgs3dmapsettings.h" #include "qgs3dutils.h" @@ -29,6 +30,8 @@ #include "qgsvectorlayer.h" #include "qgsvectorlayer3drenderer.h" +#include + class TestQgs3DCameraController : public QgsTest { @@ -54,6 +57,7 @@ class TestQgs3DCameraController : public QgsTest void testRotationCenterRotationCameraRotationCenter(); void testResetViewRaster(); void testResetViewPointCloud(); + void testChangeNavigationMode(); private: void waitForNearPlane( QgsOffscreen3DEngine &engine, Qgs3DMapScene *scene, float atLeast ); //#spellok @@ -1213,6 +1217,9 @@ void TestQgs3DCameraController::testResetViewRaster() Qgs3DMapScene *scene = new Qgs3DMapScene( *mapSettings, &engine ); engine.setRootEntity( scene ); + // This ensures that the OpenGL context is properly created + Qgs3DUtils::captureSceneImage( engine, scene ); + // compare raster layer + vector layer scene->viewZoomFull(); QGSCOMPARENEAR( scene->cameraController()->distance(), 2172, 1 ); @@ -1243,6 +1250,9 @@ void TestQgs3DCameraController::testResetViewPointCloud() Qgs3DMapScene *scene = new Qgs3DMapScene( *mapSettings, &engine ); engine.setRootEntity( scene ); + // This ensures that the OpenGL context is properly created + Qgs3DUtils::captureSceneImage( engine, scene ); + // compare virtual point cloud layer scene->viewZoomFull(); QGSCOMPARENEAR( scene->cameraController()->distance(), 86, 1 ); @@ -1264,5 +1274,28 @@ void TestQgs3DCameraController::testResetViewPointCloud() delete pcLayer; } +void TestQgs3DCameraController::testChangeNavigationMode() +{ + auto canvas3D = std::unique_ptr( new Qgs3DMapCanvas() ); + canvas3D->show(); + QVERIFY( QTest::qWaitForWindowExposed( canvas3D.get() ) ); + + Qgs3DMapSettings *mapSettings = new Qgs3DMapSettings; + canvas3D->setMapSettings( mapSettings ); + + QCOMPARE( mapSettings->cameraNavigationMode(), Qgis::NavigationMode::TerrainBased ); + QCOMPARE( canvas3D->cameraController()->cameraNavigationMode(), Qgis::NavigationMode::TerrainBased ); + + QKeyEvent changeNavigationModeEvent( QEvent::ShortcutOverride, Qt::Key_QuoteLeft, Qt::ControlModifier ); + QApplication::sendEvent( canvas3D.get(), &changeNavigationModeEvent ); + + QCOMPARE( canvas3D->cameraController()->cameraNavigationMode(), Qgis::NavigationMode::Walk ); + QCOMPARE( mapSettings->cameraNavigationMode(), Qgis::NavigationMode::Walk ); + + QApplication::sendEvent( canvas3D.get(), &changeNavigationModeEvent ); + QCOMPARE( canvas3D->cameraController()->cameraNavigationMode(), Qgis::NavigationMode::TerrainBased ); + QCOMPARE( mapSettings->cameraNavigationMode(), Qgis::NavigationMode::TerrainBased ); +} + QGSTEST_MAIN( TestQgs3DCameraController ) #include "testqgs3dcameracontroller.moc" diff --git a/tests/src/app/testqgsmaptoolreshape.cpp b/tests/src/app/testqgsmaptoolreshape.cpp index cf7ee1e51625..052ea24b084d 100644 --- a/tests/src/app/testqgsmaptoolreshape.cpp +++ b/tests/src/app/testqgsmaptoolreshape.cpp @@ -27,6 +27,8 @@ #include "qgsmapcanvastracer.h" #include "testqgsmaptoolutils.h" +#include + /** * \ingroup UnitTests @@ -42,14 +44,18 @@ class TestQgsMapToolReshape : public QObject void initTestCase(); // will be called before the first testfunction is executed. void cleanupTestCase(); // will be called after the last testfunction was executed. + void testReshapeNotEnoughPoints(); void testReshapeNoChange(); void testReshapeZ(); void testTopologicalEditing(); void testTopologicalEditingNoSnap(); void testAvoidIntersectionAndTopoEdit(); + void testAvoidIntersectionAndTopoEditSameLayer(); + void testAvoidIntersectionAndTopoEditSameLayerSelection(); void reshapeWithBindingLine(); void testWithTracing(); void testKeepDirection(); + void testWithSnapToSegment(); private: QgisApp *mQgisApp = nullptr; @@ -220,6 +226,27 @@ void TestQgsMapToolReshape::cleanupTestCase() QgsApplication::exitQgis(); } +void TestQgsMapToolReshape::testReshapeNotEnoughPoints() +{ + TestQgsMapToolAdvancedDigitizingUtils utils( mCaptureTool ); + // no snapping for this test + QgsSnappingConfig cfg = mCanvas->snappingUtils()->config(); + cfg.setEnabled( false ); + mCanvas->snappingUtils()->setConfig( cfg ); + + const QSignalSpy editCommandSpy( mLayerLineZ, &QgsVectorLayer::editCommandStarted ); + + utils.mouseClick( 2, 2, Qt::LeftButton ); + utils.mouseClick( 3, 2, Qt::RightButton ); + + // activate back snapping + cfg.setEnabled( true ); + mCanvas->snappingUtils()->setConfig( cfg ); + + QCOMPARE( editCommandSpy.count(), 0 ); + QCOMPARE( mLayerLineZ->undoStack()->index(), 0 ); +} + void TestQgsMapToolReshape::testReshapeNoChange() { TestQgsMapToolAdvancedDigitizingUtils utils( mCaptureTool ); @@ -385,6 +412,97 @@ void TestQgsMapToolReshape::testAvoidIntersectionAndTopoEdit() mCaptureTool->setAutoSnapEnabled( isAutoSnapEnabled ); } +void TestQgsMapToolReshape::testAvoidIntersectionAndTopoEditSameLayer() +{ + QList layers = { mLayerTopo, mLayerTopo2 }; + QgsProject::instance()->addMapLayers( layers ); + mCanvas->setLayers( layers ); + + // backup project settings + const bool topologicalEditing = QgsProject::instance()->topologicalEditing(); + const Qgis::AvoidIntersectionsMode mode( QgsProject::instance()->avoidIntersectionsMode() ); + const QList vlayers = QgsProject::instance()->avoidIntersectionsLayers(); + const bool isAutoSnapEnabled = mCaptureTool->isAutoSnapEnabled(); + + QgsProject::instance()->setAvoidIntersectionsMode( Qgis::AvoidIntersectionsMode::AvoidIntersectionsLayers ); + QgsProject::instance()->setAvoidIntersectionsLayers( { mLayerTopo, mLayerTopo2 } ); + QgsProject::instance()->setTopologicalEditing( true ); + mCanvas->setCurrentLayer( mLayerTopo ); + mCaptureTool->setAutoSnapEnabled( false ); + TestQgsMapToolAdvancedDigitizingUtils utils( mCaptureTool ); + + // reshape mLayerTopo feature 1 with two points inside mLayerTopo feature 2, both features should be reshaped + utils.mouseClick( 4, 4, Qt::LeftButton, Qt::KeyboardModifiers() ); + utils.mouseClick( 7, 4, Qt::LeftButton, Qt::KeyboardModifiers() ); + utils.mouseClick( 7.5, 3, Qt::LeftButton, Qt::KeyboardModifiers() ); + utils.mouseClick( 7.5, 1, Qt::LeftButton, Qt::KeyboardModifiers() ); + utils.mouseClick( 7, 0, Qt::LeftButton, Qt::KeyboardModifiers() ); + utils.mouseClick( 4, 0, Qt::LeftButton, Qt::KeyboardModifiers() ); + utils.mouseClick( 4, 0, Qt::RightButton ); + + QCOMPARE( mLayerTopo2->getFeature( 1 ).geometry().asWkt(), QStringLiteral( "Polygon ((0 5, 4 5, 4 7, 0 7, 0 5))" ) ); + QCOMPARE( mLayerTopo->getFeature( 1 ).geometry().asWkt(), QStringLiteral( "Polygon ((4 0, 7 0, 7.5 1, 7.5 3, 7 4, 4 4, 0 4, 0 0, 4 0))" ) ); + QCOMPARE( mLayerTopo->getFeature( 2 ).geometry().asWkt(), QStringLiteral( "Polygon ((7 0, 8 0, 8 4, 7 4, 7.5 3, 7.5 1, 7 0))" ) ); + + mLayerTopo->undoStack()->undo(); + + QCOMPARE( mLayerTopo2->getFeature( 1 ).geometry().asWkt(), QStringLiteral( "Polygon ((0 5, 4 5, 4 7, 0 7, 0 5))" ) ); + QCOMPARE( mLayerTopo->getFeature( 1 ).geometry().asWkt(), QStringLiteral( "Polygon ((0 0, 4 0, 4 4, 0 4, 0 0))" ) ); + QCOMPARE( mLayerTopo->getFeature( 2 ).geometry().asWkt(), QStringLiteral( "Polygon ((7 0, 8 0, 8 4, 7 4, 7 0))" ) ); + + QgsProject::instance()->setTopologicalEditing( topologicalEditing ); + QgsProject::instance()->setAvoidIntersectionsMode( mode ); + QgsProject::instance()->setAvoidIntersectionsLayers( vlayers ); + mCaptureTool->setAutoSnapEnabled( isAutoSnapEnabled ); +} + +void TestQgsMapToolReshape::testAvoidIntersectionAndTopoEditSameLayerSelection() +{ + QList layers = { mLayerTopo, mLayerTopo2 }; + QgsProject::instance()->addMapLayers( layers ); + mCanvas->setLayers( layers ); + + // backup project settings + const bool topologicalEditing = QgsProject::instance()->topologicalEditing(); + const Qgis::AvoidIntersectionsMode mode( QgsProject::instance()->avoidIntersectionsMode() ); + const QList vlayers = QgsProject::instance()->avoidIntersectionsLayers(); + const bool isAutoSnapEnabled = mCaptureTool->isAutoSnapEnabled(); + + QgsProject::instance()->setAvoidIntersectionsMode( Qgis::AvoidIntersectionsMode::AvoidIntersectionsLayers ); + QgsProject::instance()->setAvoidIntersectionsLayers( { mLayerTopo, mLayerTopo2 } ); + QgsProject::instance()->setTopologicalEditing( true ); + mCanvas->setCurrentLayer( mLayerTopo ); + mCaptureTool->setAutoSnapEnabled( false ); + TestQgsMapToolAdvancedDigitizingUtils utils( mCaptureTool ); + + mLayerTopo->selectByIds( { 1 } ); + + // reshape mLayerTopo feature 1 with two points inside mLayerTopo feature 2, only the selected feature should be reshaped + utils.mouseClick( 4, 4, Qt::LeftButton, Qt::KeyboardModifiers() ); + utils.mouseClick( 7, 4, Qt::LeftButton, Qt::KeyboardModifiers() ); + utils.mouseClick( 7.5, 3, Qt::LeftButton, Qt::KeyboardModifiers() ); + utils.mouseClick( 7.5, 1, Qt::LeftButton, Qt::KeyboardModifiers() ); + utils.mouseClick( 7, 0, Qt::LeftButton, Qt::KeyboardModifiers() ); + utils.mouseClick( 4, 0, Qt::LeftButton, Qt::KeyboardModifiers() ); + utils.mouseClick( 4, 0, Qt::RightButton ); + + QCOMPARE( mLayerTopo2->getFeature( 1 ).geometry().asWkt(), QStringLiteral( "Polygon ((0 5, 4 5, 4 7, 0 7, 0 5))" ) ); + QCOMPARE( mLayerTopo->getFeature( 1 ).geometry().asWkt(), QStringLiteral( "Polygon ((4 0, 0 0, 0 4, 4 4, 7 4, 7 0, 4 0))" ) ); + QCOMPARE( mLayerTopo->getFeature( 2 ).geometry().asWkt(), QStringLiteral( "Polygon ((7 0, 8 0, 8 4, 7 4, 7 0))" ) ); + + mLayerTopo->undoStack()->undo(); + + QCOMPARE( mLayerTopo2->getFeature( 1 ).geometry().asWkt(), QStringLiteral( "Polygon ((0 5, 4 5, 4 7, 0 7, 0 5))" ) ); + QCOMPARE( mLayerTopo->getFeature( 1 ).geometry().asWkt(), QStringLiteral( "Polygon ((0 0, 4 0, 4 4, 0 4, 0 0))" ) ); + QCOMPARE( mLayerTopo->getFeature( 2 ).geometry().asWkt(), QStringLiteral( "Polygon ((7 0, 8 0, 8 4, 7 4, 7 0))" ) ); + + mLayerTopo->removeSelection(); + QgsProject::instance()->setTopologicalEditing( topologicalEditing ); + QgsProject::instance()->setAvoidIntersectionsMode( mode ); + QgsProject::instance()->setAvoidIntersectionsLayers( vlayers ); + mCaptureTool->setAutoSnapEnabled( isAutoSnapEnabled ); +} + void TestQgsMapToolReshape::reshapeWithBindingLine() { // prepare vector layer @@ -531,11 +649,42 @@ void TestQgsMapToolReshape::testKeepDirection() QString wkt3 = QStringLiteral( "LineString (13 1, 12 1, 12 3, 13 3, 14 3, 14 5, 13 5, 12 5, 12 7, 13 7, 13 8, 19 11, 25 8, 25 0, 13 0, 13 1)" ); QCOMPARE( mLayerLine->getFeature( 3 ).geometry().asWkt(), wkt3 ); + // undo the three changes + mLayerLine->undoStack()->undo(); + mLayerLine->undoStack()->undo(); + mLayerLine->undoStack()->undo(); + // activate back snapping cfg.setEnabled( true ); mCanvas->snappingUtils()->setConfig( cfg ); } +void TestQgsMapToolReshape::testWithSnapToSegment() +{ + TestQgsMapToolAdvancedDigitizingUtils utils( mCaptureTool ); + mCanvas->setLayers( { mLayerPolygonZ } ); + mCanvas->setCurrentLayer( mLayerPolygonZ ); + mCanvas->setDestinationCrs( mLayerPolygonZ->crs() ); + + QgsSnappingConfig cfg = mCanvas->snappingUtils()->config(); + cfg.setTypeFlag( static_cast( Qgis::SnappingType::Segment ) ); + mCanvas->snappingUtils()->setConfig( cfg ); + + QCOMPARE( mLayerPolygonZ->getFeature( 1 ).geometry().asWkt(), QStringLiteral( "Polygon Z ((7 5 4, 3 2 1, 0 1 2, 7 5 4))" ) ); + + // snap to segment on a diagonal + utils.mouseClick( 5.5, 4.5, Qt::LeftButton, {}, true ); + utils.mouseClick( 1, 5, Qt::LeftButton ); + utils.mouseClick( 1, 2, Qt::LeftButton, {}, true ); + utils.mouseClick( 1, 2, Qt::RightButton ); + + QCOMPARE( mLayerPolygonZ->getFeature( 1 ).geometry().asWkt( 1 ), QStringLiteral( "Polygon Z ((1.2 1.7 333, 1 5 333, 5.7 4.2 333, 7 5 4, 3 2 1, 0 1 2, 1.2 1.7 333))" ) ); + + mLayerLine->undoStack()->undo(); + + cfg.setTypeFlag( static_cast( Qgis::SnappingType::Vertex | Qgis::SnappingType::Segment ) ); + mCanvas->snappingUtils()->setConfig( cfg ); +} QGSTEST_MAIN( TestQgsMapToolReshape ) #include "testqgsmaptoolreshape.moc" diff --git a/tests/src/core/testqgsauthcertutils.cpp b/tests/src/core/testqgsauthcertutils.cpp index 3d440246c4f8..361d38ffeb97 100644 --- a/tests/src/core/testqgsauthcertutils.cpp +++ b/tests/src/core/testqgsauthcertutils.cpp @@ -64,6 +64,9 @@ void TestQgsAuthCertUtils::cleanupTestCase() void TestQgsAuthCertUtils::testValidationUtils() { + // FIXME + QSKIP( "Broken test. See https://github.com/qgis/QGIS/issues/62373", SkipSingle ); + // null cert QSslCertificate cert; QVERIFY( !QgsAuthCertUtils::certIsCurrent( cert ) ); diff --git a/tests/src/core/testqgsauthconfig.cpp b/tests/src/core/testqgsauthconfig.cpp index 1a7e5c4881ba..dafc07ac1b2f 100644 --- a/tests/src/core/testqgsauthconfig.cpp +++ b/tests/src/core/testqgsauthconfig.cpp @@ -125,6 +125,9 @@ void TestQgsAuthConfig::testMethodConfig() void TestQgsAuthConfig::testPkiBundle() { + // FIXME + QSKIP( "Broken test. See https://github.com/qgis/QGIS/issues/62373", SkipSingle ); + QgsPkiBundle bundle; QVERIFY( bundle.isNull() ); QVERIFY( !bundle.isValid() ); diff --git a/tests/src/core/testqgsgml.cpp b/tests/src/core/testqgsgml.cpp index 09d308f7ab04..2b0013b432cc 100644 --- a/tests/src/core/testqgsgml.cpp +++ b/tests/src/core/testqgsgml.cpp @@ -53,6 +53,7 @@ class TestQgsGML : public QObject void testStreamingParser(); void testStreamingParserInvalidGML(); void testPointGML2(); + void testPointZGML2(); void testLineStringGML2(); void testPolygonGML2(); void testMultiPointGML2(); @@ -90,6 +91,8 @@ class TestQgsGML : public QObject void testUnknownEncoding(); void testUnhandledEncoding(); void testXPath(); + void testZ(); + void testZ_data(); }; const QString data1( "" + "" + "" + "" + "" + "1,2,3" + "" + "" + "" + "" + "" ), + true ), + true ); + QCOMPARE( gmlParser.wkbType(), Qgis::WkbType::PointZ ); + QVector features = gmlParser.getAndStealReadyFeatures(); + QCOMPARE( features.size(), 1 ); + QVERIFY( features[0].first->hasGeometry() ); + QCOMPARE( features[0].first->geometry().wkbType(), Qgis::WkbType::PointZ ); + QCOMPARE( features[0].first->geometry().asPoint(), QgsPoint( 1, 2, 3 ) ); + delete features[0].first; +} + void TestQgsGML::testLineStringGML2() { const QgsFields fields; @@ -749,11 +780,11 @@ void TestQgsGML::testPolygonGML3_srsDimension_on_Polygon() "" ), true ), true ); - QCOMPARE( gmlParser.wkbType(), Qgis::WkbType::Polygon ); + QCOMPARE( gmlParser.wkbType(), Qgis::WkbType::PolygonZ ); QVector features = gmlParser.getAndStealReadyFeatures(); QCOMPARE( features.size(), 1 ); QVERIFY( features[0].first->hasGeometry() ); - QCOMPARE( features[0].first->geometry().wkbType(), Qgis::WkbType::Polygon ); + QCOMPARE( features[0].first->geometry().wkbType(), Qgis::WkbType::PolygonZ ); QgsPolygonXY poly = features[0].first->geometry().asPolygon(); QCOMPARE( poly.size(), 1 ); QCOMPARE( poly[0].size(), 5 ); @@ -783,11 +814,11 @@ void TestQgsGML::testPolygonGML3_srsDimension_on_posList() "" ), true ), true ); - QCOMPARE( gmlParser.wkbType(), Qgis::WkbType::Polygon ); + QCOMPARE( gmlParser.wkbType(), Qgis::WkbType::PolygonZ ); QVector features = gmlParser.getAndStealReadyFeatures(); QCOMPARE( features.size(), 1 ); QVERIFY( features[0].first->hasGeometry() ); - QCOMPARE( features[0].first->geometry().wkbType(), Qgis::WkbType::Polygon ); + QCOMPARE( features[0].first->geometry().wkbType(), Qgis::WkbType::PolygonZ ); QgsPolygonXY poly = features[0].first->geometry().asPolygon(); QCOMPARE( poly.size(), 1 ); QCOMPARE( poly[0].size(), 5 ); @@ -821,11 +852,11 @@ void TestQgsGML::testPolygonGML3_pos() "" ), true ), true ); - QCOMPARE( gmlParser.wkbType(), Qgis::WkbType::Polygon ); + QCOMPARE( gmlParser.wkbType(), Qgis::WkbType::PolygonZ ); QVector features = gmlParser.getAndStealReadyFeatures(); QCOMPARE( features.size(), 1 ); QVERIFY( features[0].first->hasGeometry() ); - QCOMPARE( features[0].first->geometry().wkbType(), Qgis::WkbType::Polygon ); + QCOMPARE( features[0].first->geometry().wkbType(), Qgis::WkbType::PolygonZ ); QgsPolygonXY poly = features[0].first->geometry().asPolygon(); QCOMPARE( poly.size(), 1 ); QCOMPARE( poly[0].size(), 5 ); @@ -1604,5 +1635,90 @@ void TestQgsGML::testXPath() QCOMPARE( f.attribute( QStringLiteral( "complex_repeated" ) ).toString(), QStringLiteral( "[\"foo\",\"bar\"]" ) ); } +void TestQgsGML::testZ_data() +{ + QTest::addColumn( "xml" ); + QTest::addColumn( "expectedWkbType" ); + QTest::addColumn( "expectedWkt" ); + + QTest::newRow( "point with z gml 2" ) << QStringLiteral( R"gml(0,1,2)gml" ) + << static_cast( Qgis::WkbType::PointZ ) + << QStringLiteral( "POINT Z (0 1 2)" ); + + QTest::newRow( "point with z gml 3" ) << QStringLiteral( R"gml(0 1 2)gml" ) + << static_cast( Qgis::WkbType::PointZ ) + << QStringLiteral( "POINT Z (0 1 2)" ); + + // Note: this is not supported "point with z gml 3 no srsDimension" 0 1 2 + + QTest::newRow( "linestring with z gml 2" ) << QStringLiteral( R"gml(0,1,2 3,4,5)gml" ) + << static_cast( Qgis::WkbType::LineStringZ ) + << QStringLiteral( "LINESTRING Z (0 1 2, 3 4 5)" ); + + QTest::newRow( "linestring with z gml 3" ) << QStringLiteral( R"gml(0 1 2 3 4 5)gml" ) + << static_cast( Qgis::WkbType::LineStringZ ) + << QStringLiteral( "LINESTRING Z (0 1 2, 3 4 5)" ); + + QTest::newRow( "polygon with z gml 2" ) << QStringLiteral( R"gml(0,1,2 3,4,5 6,7,8 0,1,2)gml" ) + << static_cast( Qgis::WkbType::PolygonZ ) + << QStringLiteral( "POLYGON Z ((0 1 2, 3 4 5, 6 7 8, 0 1 2))" ); + + QTest::newRow( "polygon with z gml 3" ) << QStringLiteral( R"gml(0 1 2 3 4 5 6 7 8 0 1 2)gml" ) + << static_cast( Qgis::WkbType::PolygonZ ) + << QStringLiteral( "POLYGON Z ((0 1 2, 3 4 5, 6 7 8, 0 1 2))" ); + + // Multi-geometries + QTest::newRow( "multipoint with z gml 2" ) << QStringLiteral( R"gml(0,1,23,4,5)gml" ) + << static_cast( Qgis::WkbType::MultiPointZ ) + << QStringLiteral( "MULTIPOINT Z ((0 1 2),(3 4 5))" ); + + QTest::newRow( "multipoint with z gml 3" ) << QStringLiteral( R"gml(0 1 23 4 5)gml" ) + << static_cast( Qgis::WkbType::MultiPointZ ) + << QStringLiteral( "MULTIPOINT Z ((0 1 2),(3 4 5))" ); + + QTest::newRow( "multilinestring with z gml 2" ) << QStringLiteral( R"gml(0,1,2 3,4,56,7,8 9,10,11)gml" ) + << static_cast( Qgis::WkbType::MultiLineStringZ ) + << QStringLiteral( "MULTILINESTRING Z ((0 1 2, 3 4 5),(6 7 8, 9 10 11))" ); + + QTest::newRow( "multilinestring with z gml 3" ) << QStringLiteral( R"gml(0 1 2 3 4 56 7 8 9 10 11)gml" ) + << static_cast( Qgis::WkbType::MultiLineStringZ ) + << QStringLiteral( "MULTILINESTRING Z ((0 1 2, 3 4 5),(6 7 8, 9 10 11))" ); + + QTest::newRow( "multipolygon with z gml 2" ) << QStringLiteral( R"gml(0,1,2 3,4,5 6,7,8 0,1,29,10,11 12,13,14 15,16,17 9,10,11)gml" ) + << static_cast( Qgis::WkbType::MultiPolygonZ ) + << QStringLiteral( "MULTIPOLYGON Z (((0 1 2, 3 4 5, 6 7 8, 0 1 2)),((9 10 11, 12 13 14, 15 16 17, 9 10 11)))" ); + + QTest::newRow( "multipolygon with z gml 3" ) << QStringLiteral( R"gml(0,1,2 3,4,5 6,7,8 0,1,29,10,11 12,13,14 15,16,17 9,10,11)gml" ) + << static_cast( Qgis::WkbType::MultiPolygonZ ) + << QStringLiteral( "MULTIPOLYGON Z (((0 1 2, 3 4 5, 6 7 8, 0 1 2)),((9 10 11, 12 13 14, 15 16 17, 9 10 11)))" ); +} + +void TestQgsGML::testZ() +{ + QFETCH( QString, xml ); + QFETCH( int, expectedWkbType ); + QFETCH( QString, expectedWkt ); + + const QString wrappedXml = QStringLiteral( R"gml( + + + + %1 + + +)gml" ) + .arg( xml ); + + const QgsFields fields; + QgsGmlStreamingParser gmlParser( QString::fromUtf8( QByteArray( "mytypename" ) ), QString::fromUtf8( QByteArray( "mygeom" ) ), fields ); + QCOMPARE( gmlParser.processData( wrappedXml.toUtf8(), true ), true ); + QCOMPARE( gmlParser.wkbType(), static_cast( expectedWkbType ) ); + QVector features = gmlParser.getAndStealReadyFeatures(); + QCOMPARE( features.size(), 1 ); + QVERIFY( features[0].first->hasGeometry() ); + QCOMPARE( features[0].first->geometry().wkbType(), static_cast( expectedWkbType ) ); + QCOMPARE( features[0].first->geometry().asWkt().toUpper(), expectedWkt ); +} + QGSTEST_MAIN( TestQgsGML ) #include "testqgsgml.moc" diff --git a/tests/src/core/testqgsogcutils.cpp b/tests/src/core/testqgsogcutils.cpp index bcfd3ff468bd..b21c655b2a2d 100644 --- a/tests/src/core/testqgsogcutils.cpp +++ b/tests/src/core/testqgsogcutils.cpp @@ -54,8 +54,15 @@ class TestQgsOgcUtils : public QObject } void testGeometryFromGML(); + + void testGeometryFromGMLWithZ_data(); + void testGeometryFromGMLWithZ(); + void testGeometryToGML(); + void testGeometryZToGML(); + void testGeometryZToGML_data(); + void testExpressionFromOgcFilter(); void testExpressionFromOgcFilter_data(); @@ -108,6 +115,82 @@ void TestQgsOgcUtils::testGeometryFromGML() geomBox = QgsOgcUtils::geometryFromGML( QStringLiteral( "135.2239 34.4879135.8578 34.8471" ) ); QVERIFY( !geomBox.isNull() ); QVERIFY( geomBox.wkbType() == Qgis::WkbType::Polygon ); + + // Test point GML3 Z + geom = QgsOgcUtils::geometryFromGML( QStringLiteral( "0 1 2" ) ); + QVERIFY( !geom.isNull() ); + QVERIFY( geom.wkbType() == Qgis::WkbType::PointZ ); + QVERIFY( geom.equals( QgsGeometry::fromWkt( QStringLiteral( "POINTZ(0 1 2)" ) ) ) ); + + // Test polygon GML3 Z + geom = QgsOgcUtils::geometryFromGML( QStringLiteral( R"GML(0 0 1200 0 1 1250 1 1 1230 1 0 1210 0 0 1200)GML" ) ); + QVERIFY( !geom.isNull() ); + QVERIFY( geom.wkbType() == Qgis::WkbType::PolygonZ ); + QVERIFY( geom.equals( QgsGeometry::fromWkt( QStringLiteral( "POLYGONZ((0 0 1200, 0 1 1250, 1 1 1230, 1 0 1210, 0 0 1200))" ) ) ) ); + + // Test linestring GML3 Z + geom = QgsOgcUtils::geometryFromGML( QStringLiteral( R"GML(0 0 1200 0 1 1250 1 1 1230 1 0 1210)GML" ) ); + QVERIFY( !geom.isNull() ); + QVERIFY( geom.wkbType() == Qgis::WkbType::LineStringZ ); + QVERIFY( geom.equals( QgsGeometry::fromWkt( QStringLiteral( "LINESTRINGZ(0 0 1200, 0 1 1250, 1 1 1230, 1 0 1210)" ) ) ) ); +} + +void TestQgsOgcUtils::testGeometryFromGMLWithZ_data() +{ + QTest::addColumn( "xmlText" ); + QTest::addColumn( "type" ); + QTest::addColumn( "WKT" ); + + QTest::newRow( "PointZ" ) + << QStringLiteral( "0 1 2" ) + << Qgis::WkbType::PointZ + << QStringLiteral( "POINTZ( 0 1 2)" ); + + QTest::newRow( "LineStringZ" ) + << QStringLiteral( R"GML(0 0 1200 0 1 1250 1 1 1230 1 0 1210)GML" ) + << Qgis::WkbType::LineStringZ + << QStringLiteral( "LINESTRINGZ(0 0 1200, 0 1 1250, 1 1 1230, 1 0 1210)" ); + + QTest::newRow( "PolygonZ" ) + << QStringLiteral( R"GML(0 0 1200 0 1 1250 1 1 1230 1 0 1210 0 0 1200)GML" ) + << Qgis::WkbType::PolygonZ + << QStringLiteral( "POLYGONZ((0 0 1200, 0 1 1250, 1 1 1230, 1 0 1210, 0 0 1200))" ); + + // Test multipoint GML3 Z + QTest::newRow( "MultiPointZ" ) + << QStringLiteral( R"GML(0 1 23 4 5)GML" ) + << Qgis::WkbType::MultiPointZ + << QStringLiteral( "MULTIPOINTZ((0 1 2), (3 4 5))" ); + + // Test multilinestring GML2 Z + QTest::newRow( "MultiLineStringZ GML2" ) + << QStringLiteral( R"GML(0,0,1200 0,1,1250 1,1,1230 1,0,12102,2,2200 2,3,2250 3,3,2230 3,2,2210)GML" ) + << Qgis::WkbType::MultiLineStringZ + << QStringLiteral( "MULTILINESTRINGZ((0 0 1200, 0 1 1250, 1 1 1230, 1 0 1210), (2 2 2200, 2 3 2250, 3 3 2230, 3 2 2210))" ); + + QTest::newRow( "MultiLineStringZ no curve" ) + << QStringLiteral( R"GML(0 0 1200 0 1 1250 1 1 1230 1 0 12102 2 2200 2 3 2250 3 3 2230 3 2 2210)GML" ) + << Qgis::WkbType::MultiLineStringZ + << QStringLiteral( "MULTILINESTRINGZ((0 0 1200, 0 1 1250, 1 1 1230, 1 0 1210), (2 2 2200, 2 3 2250, 3 3 2230, 3 2 2210))" ); + + // Test multilinestring GML3 Z + QTest::newRow( "MultiLineStringZ" ) + << QStringLiteral( R"GML(0 0 1200 0 1 1250 1 1 1230 1 0 12102 2 2200 2 3 2250 3 3 2230 3 2 2210)GML" ) + << Qgis::WkbType::MultiLineStringZ + << QStringLiteral( "MULTILINESTRINGZ((0 0 1200, 0 1 1250, 1 1 1230, 1 0 1210), (2 2 2200, 2 3 2250, 3 3 2230, 3 2 2210))" ); +} + + +void TestQgsOgcUtils::testGeometryFromGMLWithZ() +{ + QFETCH( QString, xmlText ); + QFETCH( Qgis::WkbType, type ); + QFETCH( QString, WKT ); + + QgsGeometry geom = QgsOgcUtils::geometryFromGML( xmlText ); + QVERIFY( !geom.isNull() ); + QCOMPARE( geom.wkbType(), type ); + QVERIFY( geom.equals( QgsGeometry::fromWkt( WKT ) ) ); } static QDomElement comparableElement( const QString &xmlText ) @@ -174,6 +257,44 @@ void TestQgsOgcUtils::testGeometryToGML() doc.removeChild( elemLine ); } +void TestQgsOgcUtils::testGeometryZToGML_data() +{ + QTest::addColumn( "wkt" ); + + QTest::newRow( "PointZ" ) << QStringLiteral( "POINT Z(0 1 2)" ); + QTest::newRow( "LineStringZ" ) << QStringLiteral( "LINESTRING Z(0 0 1200, 0 1 1250, 1 1 1230, 1 0 1210)" ); + QTest::newRow( "PolygonZ" ) << QStringLiteral( "POLYGON Z((0 0 1200, 0 1 1250, 1 1 1230, 1 0 1210, 0 0 1200))" ); + + // Multi + QTest::newRow( "MultiPointZ" ) << QStringLiteral( "MULTIPOINT Z((0 1 2), (3 4 5))" ); + QTest::newRow( "MultiLineStringZ" ) << QStringLiteral( "MULTILINESTRING Z((0 0 1200, 0 1 1250, 1 1 1230, 1 0 1210), (2 2 2200, 2 3 2250, 3 3 2230, 3 2 2210))" ); + QTest::newRow( "MultiPolygonZ" ) << QStringLiteral( "MULTIPOLYGON Z(((0 0 1200, 0 1 1250, 1 1 1230, 1 0 1210, 0 0 1200)), ((2 2 2200, 2 3 2250, 3 3 2230, 3 2 2210, 2 2 2200)))" ); +} + +void TestQgsOgcUtils::testGeometryZToGML() +{ + // Round trip test + + QFETCH( QString, wkt ); + + const QgsGeometry geom( QgsGeometry::fromWkt( wkt ) ); + + QVERIFY( !geom.isNull() ); + QVERIFY( QgsWkbTypes::hasZ( geom.wkbType() ) ); + + // Test GML3 + QDomDocument doc; + QDomElement elem = QgsOgcUtils::geometryToGML( geom, doc, QStringLiteral( "GML3" ) ); + QVERIFY( !elem.isNull() ); + + // Dump element to string + QString str; + QTextStream stream( &str ); + elem.save( stream, 0 /*indent*/ ); + + QCOMPARE( QgsOgcUtils::geometryFromGML( str ).asWkt(), geom.asWkt() ); +} + void TestQgsOgcUtils::testExpressionFromOgcFilterWFS20_data() { QTest::addColumn( "xmlText" ); @@ -227,8 +348,8 @@ void TestQgsOgcUtils::testExpressionFromOgcFilterWFS20() std::unique_ptr expr( QgsOgcUtils::expressionFromOgcFilter( rootElem, QgsOgcUtils::FILTER_FES_2_0, &layer ) ); QVERIFY( expr.get() ); - qDebug( "OGC XML : %s", xmlText.toLatin1().data() ); - qDebug( "EXPR-DUMP: %s", expr->expression().toLatin1().data() ); + //qDebug( "OGC XML : %s", xmlText.toLatin1().data() ); + //qDebug( "EXPR-DUMP: %s", expr->expression().toLatin1().data() ); if ( expr->hasParserError() ) qDebug( "ERROR: %s ", expr->parserErrorString().toLatin1().data() ); @@ -432,8 +553,8 @@ void TestQgsOgcUtils::testExpressionFromOgcFilter() std::unique_ptr expr( QgsOgcUtils::expressionFromOgcFilter( rootElem, &layer ) ); QVERIFY( expr.get() ); - qDebug( "OGC XML : %s", xmlText.toLatin1().data() ); - qDebug( "EXPR-DUMP: %s", expr->expression().toLatin1().data() ); + //qDebug( "OGC XML : %s", xmlText.toLatin1().data() ); + //qDebug( "EXPR-DUMP: %s", expr->expression().toLatin1().data() ); if ( expr->hasParserError() ) qDebug( "ERROR: %s ", expr->parserErrorString().toLatin1().data() ); @@ -485,8 +606,8 @@ void TestQgsOgcUtils::testExpressionFromOgcFilterWithLongLong() std::unique_ptr expr( QgsOgcUtils::expressionFromOgcFilter( rootElem, &layer ) ); QVERIFY( expr.get() ); - qDebug( "OGC XML : %s", xmlText.toLatin1().data() ); - qDebug( "EXPR-DUMP: %s", expr->expression().toLatin1().data() ); + //qDebug( "OGC XML : %s", xmlText.toLatin1().data() ); + //qDebug( "EXPR-DUMP: %s", expr->expression().toLatin1().data() ); if ( expr->hasParserError() ) qDebug( "ERROR: %s ", expr->parserErrorString().toLatin1().data() ); @@ -514,8 +635,8 @@ void TestQgsOgcUtils::testExpressionToOgcFilter() doc.appendChild( filterElem ); - qDebug( "EXPR: %s", exp.expression().toLatin1().data() ); - qDebug( "OGC : %s", doc.toString( -1 ).toLatin1().data() ); + //qDebug( "EXPR: %s", exp.expression().toLatin1().data() ); + //qDebug( "OGC : %s", doc.toString( -1 ).toLatin1().data() ); QDomElement xmlElem = comparableElement( xmlText ); @@ -702,9 +823,9 @@ void TestQgsOgcUtils::testExpressionToOgcFilterWFS11() doc.appendChild( filterElem ); - qDebug( "EXPR: %s", exp.expression().toLatin1().data() ); - qDebug( "SRSNAME: %s", srsName.toLatin1().data() ); - qDebug( "OGC : %s", doc.toString( -1 ).toLatin1().data() ); + //qDebug( "EXPR: %s", exp.expression().toLatin1().data() ); + //qDebug( "SRSNAME: %s", srsName.toLatin1().data() ); + //qDebug( "OGC : %s", doc.toString( -1 ).toLatin1().data() ); QDomElement xmlElem = comparableElement( xmlText ); @@ -771,9 +892,9 @@ void TestQgsOgcUtils::testExpressionToOgcFilterWFS20() doc.appendChild( filterElem ); - qDebug( "EXPR: %s", exp.expression().toLatin1().data() ); - qDebug( "SRSNAME: %s", srsName.toLatin1().data() ); - qDebug( "OGC : %s", doc.toString( -1 ).toLatin1().data() ); + //qDebug( "EXPR: %s", exp.expression().toLatin1().data() ); + //qDebug( "SRSNAME: %s", srsName.toLatin1().data() ); + //qDebug( "OGC : %s", doc.toString( -1 ).toLatin1().data() ); QDomElement xmlElem = comparableElement( xmlText ); QDomElement ogcElem = comparableElement( doc.toString( -1 ) ); @@ -920,7 +1041,7 @@ void TestQgsOgcUtils::testSQLStatementToOgcFilter() const QgsSQLStatement statement( statementText ); if ( !statement.hasParserError() ) { - qDebug( "%s", statement.parserErrorString().toLatin1().data() ); + //qDebug( "%s", statement.parserErrorString().toLatin1().data() ); QVERIFY( !statement.hasParserError() ); } @@ -940,6 +1061,7 @@ void TestQgsOgcUtils::testSQLStatementToOgcFilter() doc.appendChild( filterElem ); +#if 0 qDebug( "SQL: %s", statement.statement().toLatin1().data() ); qDebug( "GML: %s", gmlVersion == QgsOgcUtils::GML_2_1_2 ? "2.1.2" : gmlVersion == QgsOgcUtils::GML_3_1_0 ? "3.1.0" : gmlVersion == QgsOgcUtils::GML_3_2_1 ? "3.2.1" @@ -948,6 +1070,7 @@ void TestQgsOgcUtils::testSQLStatementToOgcFilter() : filterVersion == QgsOgcUtils::FILTER_FES_2_0 ? "FES 2.0" : "unknown" ); qDebug( "OGC : %s", doc.toString( -1 ).toLatin1().data() ); +#endif QDomElement xmlElem = comparableElement( xmlText ); QDomElement ogcElem = comparableElement( doc.toString( -1 ) ); @@ -1245,7 +1368,7 @@ void TestQgsOgcUtils::testExpressionToOgcFilterWithXPath() QDomElement xmlElem = comparableElement( QStringLiteral( "myns:foo/myns:bar/otherns:a1" ) ); doc.appendChild( filterElem ); - qDebug( "OGC : %s", doc.toString( -1 ).toLatin1().data() ); + //qDebug( "OGC : %s", doc.toString( -1 ).toLatin1().data() ); QDomElement ogcElem = comparableElement( doc.toString( -1 ) ); QVERIFY( QgsTestUtils::compareDomElements( xmlElem, ogcElem ) ); @@ -1283,7 +1406,7 @@ void TestQgsOgcUtils::testSQLStatementToOgcFilterWithXPath() QDomElement xmlElem = comparableElement( QStringLiteral( "myns:foo/myns:bar/otherns:a1" ) ); doc.appendChild( filterElem ); - qDebug( "OGC : %s", doc.toString( -1 ).toLatin1().data() ); + //qDebug( "OGC : %s", doc.toString( -1 ).toLatin1().data() ); QDomElement ogcElem = comparableElement( doc.toString( -1 ) ); QVERIFY( QgsTestUtils::compareDomElements( xmlElem, ogcElem ) ); diff --git a/tests/src/core/testqgsogrutils.cpp b/tests/src/core/testqgsogrutils.cpp index 0ced946249e7..e1059fea93e2 100644 --- a/tests/src/core/testqgsogrutils.cpp +++ b/tests/src/core/testqgsogrutils.cpp @@ -1057,18 +1057,18 @@ void TestQgsOgrUtils::testOgrUtilsStoredStyle() symbol->setColor( QColor( 255, 0, 0 ) ); renderer->setSymbol( symbol ); - vl.saveStyleToDatabase( "style1", "style1", false, QString(), error ); + vl.saveStyleToDatabaseV2( "style1", "style1", false, QString(), error ); // Default symbol = renderer->symbol()->clone(); symbol->setColor( QColor( 0, 255, 0 ) ); renderer->setSymbol( symbol ); - vl.saveStyleToDatabase( "style2", "style2", true, QString(), error ); + vl.saveStyleToDatabaseV2( "style2", "style2", true, QString(), error ); symbol = renderer->symbol()->clone(); symbol->setColor( QColor( 0, 0, 255 ) ); renderer->setSymbol( symbol ); - vl.saveStyleToDatabase( "style3", "style3", false, QString(), error ); + vl.saveStyleToDatabaseV2( "style3", "style3", false, QString(), error ); } gdal::ogr_datasource_unique_ptr hDS( OGROpen( testFile.toUtf8().constData(), false, nullptr ) ); diff --git a/tests/src/core/testqgstracer.cpp b/tests/src/core/testqgstracer.cpp index 7bf48587beee..d3b96469d0f3 100644 --- a/tests/src/core/testqgstracer.cpp +++ b/tests/src/core/testqgstracer.cpp @@ -322,6 +322,7 @@ void TestQgsTracer::testAddPointsOnIntersections() QgsTracer tracer; tracer.setLayers( QList() << vl ); + tracer.setAddPointsOnIntersectionsEnabled( false ); QgsPolylineXY points = tracer.findShortestPath( QgsPointXY( 0, 0 ), QgsPointXY( 10, 10 ) ); diff --git a/tests/src/python/test_qgsauthsystem.py b/tests/src/python/test_qgsauthsystem.py index 07591b33f45d..47a344f23dcc 100644 --- a/tests/src/python/test_qgsauthsystem.py +++ b/tests/src/python/test_qgsauthsystem.py @@ -147,6 +147,9 @@ def test_030_auth_settings(self): def test_040_authorities(self): + # FIXME + self.skipTest("Broken test. See https://github.com/qgis/QGIS/issues/62373") + def rebuild_caches(): m = "Authorities cache could not be rebuilt" self.assertTrue(self.authm.rebuildCaCertsCache(), m) @@ -660,6 +663,9 @@ def test_140_cas_remove_self_signed(self): def test_150_verify_keychain(self): """Test the verify keychain function""" + # FIXME + self.skipTest("Broken test. See https://github.com/qgis/QGIS/issues/62373") + def testChain(path): # Test that a chain with an untrusted CA is not valid @@ -736,6 +742,9 @@ def testChain(path): def test_validate_pki_bundle(self): """Text the pki bundle validation""" + # FIXME + self.skipTest("Broken test. See https://github.com/qgis/QGIS/issues/62373") + # Valid bundle: bundle = self.mkPEMBundle( "fra_cert.pem", "fra_key.pem", "password", "chain_subissuer-issuer-root.pem" @@ -927,6 +936,9 @@ def test_validate_pki_bundle(self): def test_160_cert_viable(self): """Text the viability of a given certificate""" + # FIXME + self.skipTest("Broken test. See https://github.com/qgis/QGIS/issues/62373") + # null cert cert = QSslCertificate() self.assertFalse(QgsAuthCertUtils.certIsCurrent(cert)) @@ -956,6 +968,9 @@ def test_160_cert_viable(self): def test_170_pki_key_encoding(self): """Test that a DER/PEM RSA/DSA/EC keys can be opened whatever the extension is""" + # FIXME + self.skipTest("Broken test. See https://github.com/qgis/QGIS/issues/62373") + self.assertFalse( QgsAuthCertUtils.keyFromFile(PKIDATA + "/" + "ptolemy_key.pem").isNull() ) diff --git a/vcpkg/ports/oracle-instantclient/portfile.cmake b/vcpkg/ports/oracle-instantclient/portfile.cmake new file mode 100644 index 000000000000..3edecdf9aa4d --- /dev/null +++ b/vcpkg/ports/oracle-instantclient/portfile.cmake @@ -0,0 +1,102 @@ +if(VCPKG_TARGET_IS_OSX) + if(VCPKG_TARGET_ARCHITECTURE STREQUAL "arm64") + vcpkg_download_distfile(BASIC_PACKAGE + URLS https://download.oracle.com/otn_software/mac/instantclient/233023/instantclient-basic-macos.arm64-${VERSION}-1.dmg + FILENAME instantclient-basic-arm.dmg + SHA512 beb9ed7c3bf61721eff4c6cd375aeb0deaf5941e9297ca8b4c5efd9d5e154a9052445e0f3612ff2b5ddfa50cd40c83eda6ead8159b98810ae644ec60f41ef82c + ) + + vcpkg_download_distfile(SDK_PACKAGE + URLS https://download.oracle.com/otn_software/mac/instantclient/233023/instantclient-sdk-macos.arm64-${VERSION}.dmg + FILENAME instantclient-sdk-arm.dmg + SHA512 bb8e9e7b7f11281b7897271ae92a7e2fa485075c9b027e18823e639dd419f3ebddcfcdfa2df62bed9ae92d908cae622d51dfc86ca93e6242c74cae49e2b7b34a + ) + else() + # 19.16.0.0.0 is the latest release for x64 at the moment on https://www.oracle.com/database/technologies/instant-client/macos-intel-x86-downloads.html + vcpkg_download_distfile(BASIC_PACKAGE + URLS https://download.oracle.com/otn_software/mac/instantclient/1916000/instantclient-basic-macos.x64-19.16.0.0.0dbru.dmg + FILENAME instantclient-basic-x64.dmg + SHA512 91deb1c0f12d14cf0217567c3018aa2f922b248afb948858075bd9175115aa077cc797a4c5698b52c01b14aa8d205424f25e295e1845b94adab7c3d6e2e9364c + ) + + vcpkg_download_distfile(SDK_PACKAGE + URLS https://download.oracle.com/otn_software/mac/instantclient/1916000/instantclient-sdk-macos.x64-19.16.0.0.0dbru.dmg + FILENAME instantclient-sdk-x64.dmg + SHA512 c910b764003bccd6f61cbf740d74865dbec0f9ab67898f78947e779ef5ee913e20f975b967b7bc31f31c78a0b8c63414c632de51c4f1c51746f0c4f3054a02c9 + ) + endif() + + vcpkg_execute_required_process( + COMMAND "hdiutil" "mount" "${BASIC_PACKAGE}" "-mountpoint" "${CURRENT_BUILDTREES_DIR}/instantclient-basic" + WORKING_DIRECTORY ${CURRENT_PACKAGES_DIR} + LOGNAME hdiutil-mount-basic + ) + vcpkg_execute_required_process( + COMMAND "hdiutil" "mount" "${SDK_PACKAGE}" "-mountpoint" "${CURRENT_BUILDTREES_DIR}/instantclient-sdk" + WORKING_DIRECTORY ${CURRENT_PACKAGES_DIR} + LOGNAME hdiutil-mount-sdk + ) + +function(install_versioned_libraries) + # Parse arguments + set(options) + set(oneValueArgs TARGET_DIR) + set(multiValueArgs LIBRARIES) + cmake_parse_arguments(INSTALL "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + # Check for required arguments + if(NOT DEFINED INSTALL_TARGET_DIR) + message(FATAL_ERROR "TARGET_DIR must be specified") + endif() + + if(NOT DEFINED INSTALL_LIBRARIES) + message(FATAL_ERROR "LIBRARIES must be specified") + endif() + + # Make sure target directory exists + file(MAKE_DIRECTORY ${INSTALL_TARGET_DIR}) + + foreach(lib ${INSTALL_LIBRARIES}) + # Get the real file (full version) + get_filename_component(lib_real_path ${lib} REALPATH) + get_filename_component(lib_filename ${lib} NAME) + get_filename_component(lib_real_filename ${lib_real_path} NAME) + + # Extract the base name (without extension) + string(REGEX REPLACE "\\..*$" "" lib_basename ${lib_filename}) + + message(STATUS "Installing ${lib_real_path} as ${lib_basename}.dylib") + + # Copy the actual library file directly to the target with the base name + configure_file(${lib_real_path} ${INSTALL_TARGET_DIR}/${lib_basename}.dylib COPYONLY) + endforeach() +endfunction() + + + install_versioned_libraries( + TARGET_DIR "${CURRENT_PACKAGES_DIR}/lib" + LIBRARIES + "${CURRENT_BUILDTREES_DIR}/instantclient-basic/libocci.dylib" + "${CURRENT_BUILDTREES_DIR}/instantclient-basic/libclntsh.dylib" + ) + + file(INSTALL + "${CURRENT_BUILDTREES_DIR}/instantclient-sdk/sdk/include" + DESTINATION + "${CURRENT_PACKAGES_DIR}/" + ) + + # Handle copyright + file(INSTALL "${CURRENT_BUILDTREES_DIR}/instantclient-basic/BASIC_LICENSE" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}" RENAME copyright) + + vcpkg_execute_required_process( + COMMAND "hdiutil" "detach" "${CURRENT_BUILDTREES_DIR}/instantclient-basic" + WORKING_DIRECTORY ${CURRENT_PACKAGES_DIR} + LOGNAME hdiutil-detach-basic + ) + vcpkg_execute_required_process( + COMMAND "hdiutil" "detach" "${CURRENT_BUILDTREES_DIR}/instantclient-sdk" + WORKING_DIRECTORY ${CURRENT_PACKAGES_DIR} + LOGNAME hdiutil-detach-sdk + ) +endif() diff --git a/vcpkg/ports/oracle-instantclient/vcpkg.json b/vcpkg/ports/oracle-instantclient/vcpkg.json new file mode 100644 index 000000000000..a1f6f0f524f8 --- /dev/null +++ b/vcpkg/ports/oracle-instantclient/vcpkg.json @@ -0,0 +1,6 @@ +{ + "name": "oracle-instantclient", + "description": "Oracle Instant Client", + "homepage": "https://www.oracle.com/database/technologies/instant-client.html", + "version-string": "23.3.0.23.09" +} diff --git a/vcpkg/ports/qtbase/GLIB2-static.patch b/vcpkg/ports/qtbase/GLIB2-static.patch new file mode 100644 index 000000000000..c384b741cef8 --- /dev/null +++ b/vcpkg/ports/qtbase/GLIB2-static.patch @@ -0,0 +1,75 @@ +diff --git a/cmake/3rdparty/extra-cmake-modules/find-modules/FindGLIB2.cmake b/cmake/3rdparty/extra-cmake-modules/find-modules/FindGLIB2.cmake +index 24a194c..91c8e41 100644 +--- a/cmake/3rdparty/extra-cmake-modules/find-modules/FindGLIB2.cmake ++++ b/cmake/3rdparty/extra-cmake-modules/find-modules/FindGLIB2.cmake +@@ -95,6 +95,18 @@ find_library(GLIB2_GIO_LIBRARIES + HINTS ${PC_GIO_LIBDIR} + ) + ++pkg_check_modules(PC_GMODULE QUIET gmodule-2.0) ++ ++find_path(GLIB2_GMODULE_INCLUDE_DIRS ++ NAMES gmodule.h ++ HINTS ${PC_GMODULE} ++ PATH_SUFFIXES glib-2.0) ++ ++find_library(GLIB2_GMODULE_LIBRARIES ++ NAMES gmodule-2.0 ++ HINTS ${PC_GMODULE} ++) ++ + # search the glibconfig.h include dir under the same root where the library is found + get_filename_component(glib2LibDir "${GLIB2_LIBRARIES}" PATH) + +@@ -126,6 +138,11 @@ if(GLIB2_GIO_LIBRARIES AND GLIB2_GIO_INCLUDE_DIRS) + set(GLIB2_GIO_FOUND TRUE) + endif() + ++if(GLIB2_GMODULE_LIBRARIES AND GLIB2_GMODULE_INCLUDE_DIRS) ++ set(GLIB2_GMODULE_FOUND TRUE) ++endif() ++ ++ + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(GLIB2 + REQUIRED_VARS GLIB2_LIBRARIES GTHREAD2_LIBRARIES GLIB2_INCLUDE_DIRS +@@ -137,6 +154,16 @@ if(GLIB2_FOUND AND NOT TARGET GLIB2::GLIB2) + IMPORTED_LOCATION "${GLIB2_LIBRARIES}" + INTERFACE_LINK_LIBRARIES "${GTHREAD2_LIBRARIES}" + INTERFACE_INCLUDE_DIRECTORIES "${GLIB2_INCLUDE_DIRS}") ++ #vcpkg specific ++ pkg_check_modules(PC_PCRE2_8BIT QUIET libpcre2-8) ++ find_library(PCRE2_8BIT_LIBRARIES ++ NAMES pcre2-8 ++ HINTS ${PC_PCRE2_8BIT} ++ ) ++ target_link_libraries(GLIB2::GLIB2 INTERFACE ${PCRE2_8BIT_LIBRARIES}) ++ find_package(Iconv) ++ find_package(Intl) ++ target_link_libraries(GLIB2::GLIB2 INTERFACE Intl::Intl Iconv::Iconv) + endif() + + if(GLIB2_GOBJECT_FOUND AND NOT TARGET GLIB2::GOBJECT) +@@ -153,12 +180,21 @@ if(GLIB2_GIO_FOUND AND NOT TARGET GLIB2::GIO) + INTERFACE_INCLUDE_DIRECTORIES "${GLIB2_GIO_INCLUDE_DIRS}") + endif() + ++if(GLIB2_GMODULE_FOUND AND NOT TARGET GLIB2::GMODULE) ++ add_library(GLIB2::GMODULE UNKNOWN IMPORTED) ++ set_target_properties(GLIB2::GMODULE PROPERTIES ++ IMPORTED_LOCATION "${GLIB2_GMODULE_LIBRARIES}" ++ INTERFACE_INCLUDE_DIRECTORIES "${GLIB2_GMODULE_INCLUDE_DIRS}") ++endif() ++ ++ + mark_as_advanced(GLIB2_INCLUDE_DIRS GLIB2_INCLUDE_DIR + GLIB2_LIBRARIES GLIB2_LIBRARY + GLIB2_GOBJECT_INCLUDE_DIRS GLIB2_GOBJECT_INCLUDE_DIR + GLIB2_GOBJECT_LIBRARIES GLIB2_GOBJECT_LIBRARY + GLIB2_GIO_INCLUDE_DIRS GLIB2_GIO_INCLUDE_DIR +- GLIB2_GIO_LIBRARIES GLIB2_GIO_LIBRARY) ++ GLIB2_GIO_LIBRARIES GLIB2_GIO_LIBRARY ++ GLIB2_GMODULE_LIBRARIES GLIB2_GMODULE_INCLUDE_DIRS) + + include(FeatureSummary) + set_package_properties(GLIB2 PROPERTIES diff --git a/vcpkg/ports/qtbase/allow_outside_prefix.patch b/vcpkg/ports/qtbase/allow_outside_prefix.patch new file mode 100644 index 000000000000..eeb503bcbc84 --- /dev/null +++ b/vcpkg/ports/qtbase/allow_outside_prefix.patch @@ -0,0 +1,17 @@ +diff --git a/cmake/QtBuildPathsHelpers.cmake b/cmake/QtBuildPathsHelpers.cmake +index bd186c28b..2c1994d2e 100644 +--- a/cmake/QtBuildPathsHelpers.cmake ++++ b/cmake/QtBuildPathsHelpers.cmake +@@ -141,11 +141,9 @@ function(qt_configure_process_path name default docstring) + elseif(rel_path MATCHES "^\.\./") + # INSTALL_SYSCONFDIR is allowed to be outside the prefix. + if(NOT name STREQUAL "INSTALL_SYSCONFDIR") +- message(FATAL_ERROR +- "Path component '${name}' is outside computed install prefix: ${rel_path} ") + endif() + # Keep the absolute path. + set(new_value "${${name}}") + else() + # Use the canonicalized path. + set(new_value "${rel_path}") + diff --git a/vcpkg/ports/qtbase/clang-cl_QGADGET_fix.diff b/vcpkg/ports/qtbase/clang-cl_QGADGET_fix.diff new file mode 100644 index 000000000000..e400649b4e84 --- /dev/null +++ b/vcpkg/ports/qtbase/clang-cl_QGADGET_fix.diff @@ -0,0 +1,38 @@ +diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h +index e40cd85..ba68a01 100644 +--- a/src/corelib/kernel/qmetatype.h ++++ b/src/corelib/kernel/qmetatype.h +@@ -18,6 +18,7 @@ + #include + #include + ++#include + #include + #include + #include +@@ -826,7 +829,13 @@ + struct IsGadgetHelper { enum { IsRealGadget = false, IsGadgetOrDerivedFrom = false }; }; + + template ++#if defined(__clang__) && (__clang_major__ > 11) ++ // Clang does not reject T::QtGadgetHelper as ambiguous if a class inherits from two QGADGETS ++ // but is not a QGADGET itself ++ struct IsGadgetHelper> ++#else + struct IsGadgetHelper ++#endif + { + template + static char checkType(void (X::*)()); +@@ -841,7 +850,11 @@ + struct IsPointerToGadgetHelper { enum { IsRealGadget = false, IsGadgetOrDerivedFrom = false }; }; + + template ++#if defined(__clang__) && (__clang_major__ > 11) ++ struct IsPointerToGadgetHelper> ++#else + struct IsPointerToGadgetHelper ++#endif + { + using BaseType = T; + template diff --git a/vcpkg/ports/qtbase/clang-cl_source_location.patch b/vcpkg/ports/qtbase/clang-cl_source_location.patch new file mode 100644 index 000000000000..5155fb4bbb53 --- /dev/null +++ b/vcpkg/ports/qtbase/clang-cl_source_location.patch @@ -0,0 +1,14 @@ +diff --git a/src/corelib/kernel/qproperty.h b/src/corelib/kernel/qproperty.h +index 823b2057b..4a8cd4fa8 100644 +--- a/src/corelib/kernel/qproperty.h ++++ b/src/corelib/kernel/qproperty.h +@@ -16,8 +16,8 @@ + + #include + +-#if __has_include() && __cplusplus >= 202002L && !defined(Q_QDOC) ++#if __has_include() && __cplusplus >= 202002L && !defined(Q_QDOC) && ( (defined(__cpp_consteval) && defined(_MSC_VER)) || !defined(_MSC_VER) ) + #include + #if defined(__cpp_lib_source_location) + #define QT_SOURCE_LOCATION_NAMESPACE std + #define QT_PROPERTY_COLLECT_BINDING_LOCATION diff --git a/vcpkg/ports/qtbase/cmake/qt_install_copyright.cmake b/vcpkg/ports/qtbase/cmake/qt_install_copyright.cmake new file mode 100644 index 000000000000..8ec395fe6270 --- /dev/null +++ b/vcpkg/ports/qtbase/cmake/qt_install_copyright.cmake @@ -0,0 +1,27 @@ +include_guard(GLOBAL) + +#Could probably be the beginning of a vcpkg_install_copyright? +function(qt_install_copyright SOURCE_PATH) + #Find the relevant license file and install it + if(EXISTS "${SOURCE_PATH}/LICENSE.LGPLv3") + set(LICENSE_PATH "${SOURCE_PATH}/LICENSE.LGPLv3") + elseif(EXISTS "${SOURCE_PATH}/LICENSE.LGPL3") + set(LICENSE_PATH "${SOURCE_PATH}/LICENSE.LGPL3") + elseif(EXISTS "${SOURCE_PATH}/LICENSE.GPLv3") + set(LICENSE_PATH "${SOURCE_PATH}/LICENSE.GPLv3") + elseif(EXISTS "${SOURCE_PATH}/LICENSE.GPL3") + set(LICENSE_PATH "${SOURCE_PATH}/LICENSE.GPL3") + elseif(EXISTS "${SOURCE_PATH}/LICENSE.GPL3-EXCEPT") + set(LICENSE_PATH "${SOURCE_PATH}/LICENSE.GPL3-EXCEPT") + elseif(EXISTS "${SOURCE_PATH}/LICENSE.FDL") + set(LICENSE_PATH "${SOURCE_PATH}/LICENSE.FDL") + endif() + if(LICENSE_PATH) + file(INSTALL "${LICENSE_PATH}" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}" RENAME copyright) + elseif(EXISTS "${SOURCE_PATH}/LICENSES") + file(GLOB LICENSES "${SOURCE_PATH}/LICENSES/*") + vcpkg_install_copyright(FILE_LIST ${LICENSES}) + else() + message(WARNING "No license/copyright file found!") + endif() +endfunction() diff --git a/vcpkg/ports/qtbase/cmake/qt_install_submodule.cmake b/vcpkg/ports/qtbase/cmake/qt_install_submodule.cmake new file mode 100644 index 000000000000..0456a9653aba --- /dev/null +++ b/vcpkg/ports/qtbase/cmake/qt_install_submodule.cmake @@ -0,0 +1,384 @@ +include_guard(GLOBAL) + +include("${CURRENT_HOST_INSTALLED_DIR}/share/vcpkg-cmake/vcpkg-port-config.cmake") +include("${CURRENT_HOST_INSTALLED_DIR}/share/vcpkg-cmake-config/vcpkg-port-config.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/qt_install_copyright.cmake") + +if(NOT DEFINED QT6_DIRECTORY_PREFIX) + set(QT6_DIRECTORY_PREFIX "Qt6/") +endif() + +if(VCPKG_TARGET_IS_ANDROID) + # ANDROID_HOME: canonical SDK environment variable + # ANDROID_SDK_ROOT: legacy qtbase triplet variable + if(NOT ANDROID_SDK_ROOT) + if("$ENV{ANDROID_HOME}" STREQUAL "") + message(FATAL_ERROR "${PORT} requires environment variable ANDROID_HOME to be set.") + endif() + set(ANDROID_SDK_ROOT "$ENV{ANDROID_HOME}") + endif() +endif() + +function(qt_download_submodule_impl) + cmake_parse_arguments(PARSE_ARGV 0 "_qarg" "" "SUBMODULE" "PATCHES") + + if("${_qarg_SUBMODULE}" IN_LIST QT_FROM_QT_GIT) + # qtinterfaceframework is not available in the release, so we fall back to a `git clone`. + vcpkg_from_git( + OUT_SOURCE_PATH SOURCE_PATH + URL "https://code.qt.io/qt/${_qarg_SUBMODULE}.git" + REF "${${_qarg_SUBMODULE}_REF}" + PATCHES ${_qarg_PATCHES} + ) + if(PORT STREQUAL "qttools") # Keep this for beta & rc's + vcpkg_from_git( + OUT_SOURCE_PATH SOURCE_PATH_QLITEHTML + URL https://code.qt.io/playground/qlitehtml.git + REF "${${PORT}_qlitehtml_REF}" + FETCH_REF master + HEAD_REF master + ) + # port 'litehtml' is not in vcpkg! + vcpkg_from_github( + OUT_SOURCE_PATH SOURCE_PATH_LITEHTML + REPO litehtml/litehtml + REF "${${PORT}_litehtml_REF}" + SHA512 "${${PORT}_litehtml_HASH}" + HEAD_REF master + ) + file(COPY "${SOURCE_PATH_QLITEHTML}/" DESTINATION "${SOURCE_PATH}/src/assistant/qlitehtml") + file(COPY "${SOURCE_PATH_LITEHTML}/" DESTINATION "${SOURCE_PATH}/src/assistant/qlitehtml/src/3rdparty/litehtml") + elseif(PORT STREQUAL "qtwebengine") + vcpkg_from_git( + OUT_SOURCE_PATH SOURCE_PATH_WEBENGINE + URL https://code.qt.io/qt/qtwebengine-chromium.git + REF "${${PORT}_chromium_REF}" + ) + if(NOT EXISTS "${SOURCE_PATH}/src/3rdparty/chromium") + file(RENAME "${SOURCE_PATH_WEBENGINE}/chromium" "${SOURCE_PATH}/src/3rdparty/chromium") + endif() + if(NOT EXISTS "${SOURCE_PATH}/src/3rdparty/gn") + file(RENAME "${SOURCE_PATH_WEBENGINE}/gn" "${SOURCE_PATH}/src/3rdparty/gn") + endif() + endif() + else() + if(VCPKG_USE_HEAD_VERSION) + set(sha512 SKIP_SHA512) + elseif(NOT DEFINED "${_qarg_SUBMODULE}_HASH") + message(FATAL_ERROR "No information for ${_qarg_SUBMODULE} -- add it to QT_PORTS and run qtbase in QT_UPDATE_VERSION mode first") + else() + set(sha512 SHA512 "${${_qarg_SUBMODULE}_HASH}") + endif() + + qt_get_url_filename("${_qarg_SUBMODULE}" urls filename) + vcpkg_download_distfile(archive + URLS ${urls} + FILENAME "${filename}" + ${sha512} + ) + vcpkg_extract_source_archive( + SOURCE_PATH + ARCHIVE "${archive}" + PATCHES ${_qarg_PATCHES} + ) + endif() + set(SOURCE_PATH "${SOURCE_PATH}" PARENT_SCOPE) +endfunction() + +function(qt_download_submodule) + cmake_parse_arguments(PARSE_ARGV 0 "_qarg" "" "" "PATCHES") + + qt_download_submodule_impl(SUBMODULE "${PORT}" PATCHES ${_qarg_PATCHES}) + + set(SOURCE_PATH "${SOURCE_PATH}" PARENT_SCOPE) +endfunction() + + +function(qt_cmake_configure) + cmake_parse_arguments(PARSE_ARGV 0 "_qarg" "DISABLE_NINJA;DISABLE_PARALLEL_CONFIGURE" + "" + "TOOL_NAMES;OPTIONS;OPTIONS_DEBUG;OPTIONS_RELEASE;OPTIONS_MAYBE_UNUSED") + + vcpkg_find_acquire_program(PERL) # Perl is probably required by all qt ports for syncqt + get_filename_component(PERL_PATH ${PERL} DIRECTORY) + vcpkg_add_to_path(${PERL_PATH}) + if(NOT PORT STREQUAL "qtwebengine" OR QT_IS_LATEST) # qtwebengine requires python2; since 6.3 python3 + vcpkg_find_acquire_program(PYTHON3) # Python is required by some qt ports + get_filename_component(PYTHON3_PATH ${PYTHON3} DIRECTORY) + vcpkg_add_to_path(${PYTHON3_PATH}) + endif() + + if(NOT PORT MATCHES "^qtbase") + list(APPEND _qarg_OPTIONS "-DQT_SYNCQT:PATH=${CURRENT_HOST_INSTALLED_DIR}/tools/Qt6/bin/syncqt.pl") + endif() + set(PERL_OPTION "-DHOST_PERL:PATH=${PERL}") + + set(ninja_option "") + if(_qarg_DISABLE_NINJA) + set(ninja_option WINDOWS_USE_MSBUILD) + endif() + + set(disable_parallel "") + if(_qarg_DISABLE_PARALLEL_CONFIGURE) + set(disable_parallel DISABLE_PARALLEL_CONFIGURE) + endif() + + if(VCPKG_CROSSCOMPILING) + list(APPEND _qarg_OPTIONS "-DQT_HOST_PATH=${CURRENT_HOST_INSTALLED_DIR}") + list(APPEND _qarg_OPTIONS "-DQT_HOST_PATH_CMAKE_DIR:PATH=${CURRENT_HOST_INSTALLED_DIR}/share") + endif() + + # Disable warning for CMAKE_(REQUIRE|DISABLE)_FIND_PACKAGE_ + string(REGEX MATCHALL "CMAKE_DISABLE_FIND_PACKAGE_[^:=]+" disabled_find_package "${_qarg_OPTIONS}") + list(APPEND _qarg_OPTIONS_MAYBE_UNUSED ${disabled_find_package}) + + string(REGEX MATCHALL "CMAKE_REQUIRE_FIND_PACKAGE_[^:=]+(:BOOL)?=OFF" require_find_package "${_qarg_OPTIONS}") + list(TRANSFORM require_find_package REPLACE "(:BOOL)?=OFF" "") + list(APPEND _qarg_OPTIONS_MAYBE_UNUSED ${require_find_package}) + + # Disable unused warnings for disabled features. Qt might decide to not emit the feature variables if other features are deactivated. + string(REGEX MATCHALL "(QT_)?FEATURE_[^:=]+(:BOOL)?=OFF" disabled_features "${_qarg_OPTIONS}") + list(TRANSFORM disabled_features REPLACE "(:BOOL)?=OFF" "") + list(APPEND _qarg_OPTIONS_MAYBE_UNUSED ${disabled_features}) + + list(APPEND _qarg_OPTIONS "-DQT_NO_FORCE_SET_CMAKE_BUILD_TYPE:BOOL=ON") + + if(VCPKG_TARGET_IS_ANDROID) + list(APPEND _qarg_OPTIONS "-DANDROID_SDK_ROOT=${ANDROID_SDK_ROOT}") + endif() + + if(NOT PORT MATCHES "qtbase") + list(APPEND _qarg_OPTIONS "-DQT_MKSPECS_DIR:PATH=${CURRENT_HOST_INSTALLED_DIR}/share/Qt6/mkspecs") + endif() + + if(NOT DEFINED VCPKG_OSX_DEPLOYMENT_TARGET) + list(APPEND _qarg_OPTIONS "-DCMAKE_OSX_DEPLOYMENT_TARGET=14") + endif() + + vcpkg_cmake_configure( + SOURCE_PATH "${SOURCE_PATH}" + ${ninja_option} + ${disable_parallel} + OPTIONS + -DQT_FORCE_WARN_APPLE_SDK_AND_XCODE_CHECK=ON + -DQT_NO_FORCE_SET_CMAKE_BUILD_TYPE:BOOL=ON + -DQT_USE_DEFAULT_CMAKE_OPTIMIZATION_FLAGS:BOOL=ON # We don't want Qt to mess with users toolchain settings. + -DCMAKE_FIND_PACKAGE_TARGETS_GLOBAL=ON # Because Qt doesn't correctly scope find_package calls. + #-DQT_HOST_PATH= # For crosscompiling + #-DQT_PLATFORM_DEFINITION_DIR=mkspecs/win32-msvc + #-DQT_QMAKE_TARGET_MKSPEC=win32-msvc + #-DQT_USE_CCACHE + -DQT_BUILD_EXAMPLES:BOOL=OFF + -DQT_BUILD_TESTS:BOOL=OFF + -DQT_BUILD_BENCHMARKS:BOOL=OFF + ${PERL_OPTION} + -DINSTALL_BINDIR:STRING=bin + -DINSTALL_LIBEXECDIR:STRING=bin + -DINSTALL_PLUGINSDIR:STRING=${qt_plugindir} + -DINSTALL_QMLDIR:STRING=${qt_qmldir} + ${_qarg_OPTIONS} + OPTIONS_RELEASE + ${_qarg_OPTIONS_RELEASE} + -DINSTALL_DOCDIR:STRING=doc/${QT6_DIRECTORY_PREFIX} + -DINSTALL_INCLUDEDIR:STRING=include/${QT6_DIRECTORY_PREFIX} + -DINSTALL_DESCRIPTIONSDIR:STRING=share/Qt6/modules + -DINSTALL_MKSPECSDIR:STRING=share/Qt6/mkspecs + -DINSTALL_TRANSLATIONSDIR:STRING=translations/${QT6_DIRECTORY_PREFIX} + OPTIONS_DEBUG + # -DFEATURE_debug:BOOL=ON only needed by qtbase and auto detected? + -DINSTALL_DOCDIR:STRING=../doc/${QT6_DIRECTORY_PREFIX} + -DINSTALL_INCLUDEDIR:STRING=../include/${QT6_DIRECTORY_PREFIX} + -DINSTALL_TRANSLATIONSDIR:STRING=../translations/${QT6_DIRECTORY_PREFIX} + -DINSTALL_DESCRIPTIONSDIR:STRING=../share/Qt6/modules + -DINSTALL_MKSPECSDIR:STRING=../share/Qt6/mkspecs + ${_qarg_OPTIONS_DEBUG} + MAYBE_UNUSED_VARIABLES + INSTALL_BINDIR + INSTALL_DOCDIR + INSTALL_LIBEXECDIR + INSTALL_QMLDIR # No qml files + INSTALL_TRANSLATIONSDIR # No translations + INSTALL_PLUGINSDIR # No plugins + INSTALL_DESCRIPTIONSDIR + INSTALL_INCLUDEDIR + HOST_PERL + QT_SYNCQT + QT_NO_FORCE_SET_CMAKE_BUILD_TYPE + QT_FORCE_WARN_APPLE_SDK_AND_XCODE_CHECK + ${_qarg_OPTIONS_MAYBE_UNUSED} + INPUT_bundled_xcb_xinput + INPUT_freetype + INPUT_harfbuzz + INPUT_libjpeg + INPUT_libmd4c + INPUT_libpng + INPUT_opengl + INPUT_openssl + INPUT_xcb + INPUT_xkbcommon + ) + foreach(suffix IN ITEMS dbg rel) + if(EXISTS "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-${suffix}/config.summary") + file(COPY_FILE + "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-${suffix}/config.summary" + "${CURRENT_BUILDTREES_DIR}/config.summary-${TARGET_TRIPLET}-${suffix}.log" + ) + endif() + endforeach() +endfunction() + +function(qt_fix_prl_files) + file(TO_CMAKE_PATH "${CURRENT_PACKAGES_DIR}/lib" package_dir) + file(TO_CMAKE_PATH "${package_dir}/lib" lib_path) + file(TO_CMAKE_PATH "${package_dir}/include/Qt6" include_path) + file(TO_CMAKE_PATH "${CURRENT_INSTALLED_DIR}" install_prefix) + file(GLOB_RECURSE prl_files "${CURRENT_PACKAGES_DIR}/*.prl" "${CURRENT_PACKAGES_DIR}/*.pri") + foreach(prl_file IN LISTS prl_files) + file(READ "${prl_file}" _contents) + string(REPLACE "${lib_path}" "\$\$[QT_INSTALL_LIBS]" _contents "${_contents}") + string(REPLACE "${include_path}" "\$\$[QT_INSTALL_HEADERS]" _contents "${_contents}") + string(REPLACE "${install_prefix}" "\$\$[QT_INSTALL_PREFIX]" _contents "${_contents}") + string(REPLACE "[QT_INSTALL_PREFIX]/lib/objects-Debug" "[QT_INSTALL_LIBS]/objects-Debug" _contents "${_contents}") + string(REPLACE "[QT_INSTALL_PREFIX]/Qt6/qml" "[QT_INSTALL_QML]" _contents "${_contents}") + #Note: This only works without an extra if case since QT_INSTALL_PREFIX is the same for debug and release + file(WRITE "${prl_file}" "${_contents}") + endforeach() +endfunction() + +function(qt_fixup_and_cleanup) + cmake_parse_arguments(PARSE_ARGV 0 "_qarg" "" + "" + "TOOL_NAMES") + vcpkg_copy_pdbs() + + ## Handle PRL files + qt_fix_prl_files() + + ## Handle CMake files. + set(COMPONENTS) + file(GLOB COMPONENTS_OR_FILES LIST_DIRECTORIES true "${CURRENT_PACKAGES_DIR}/share/Qt6*") + list(REMOVE_ITEM COMPONENTS_OR_FILES "${CURRENT_PACKAGES_DIR}/share/Qt6") + foreach(_glob IN LISTS COMPONENTS_OR_FILES) + if(IS_DIRECTORY "${_glob}") + string(REPLACE "${CURRENT_PACKAGES_DIR}/share/Qt6" "" _component "${_glob}") + debug_message("Adding cmake component: '${_component}'") + list(APPEND COMPONENTS ${_component}) + endif() + endforeach() + + foreach(_comp IN LISTS COMPONENTS) + if(EXISTS "${CURRENT_PACKAGES_DIR}/share/Qt6${_comp}") + vcpkg_cmake_config_fixup(PACKAGE_NAME "Qt6${_comp}" CONFIG_PATH "share/Qt6${_comp}" TOOLS_PATH "tools/Qt6/bin") + # Would rather put it into share/cmake as before but the import_prefix correction in vcpkg_cmake_config_fixup is working against that. + else() + message(STATUS "WARNING: Qt component ${_comp} not found/built!") + endif() + endforeach() + #fix debug plugin paths (should probably be fixed in vcpkg_cmake_config_fixup) + file(GLOB_RECURSE DEBUG_CMAKE_TARGETS "${CURRENT_PACKAGES_DIR}/share/**/*Targets-debug.cmake") + debug_message("DEBUG_CMAKE_TARGETS:${DEBUG_CMAKE_TARGETS}") + foreach(_debug_target IN LISTS DEBUG_CMAKE_TARGETS) + vcpkg_replace_string("${_debug_target}" "{_IMPORT_PREFIX}/${qt_plugindir}" "{_IMPORT_PREFIX}/debug/${qt_plugindir}" IGNORE_UNCHANGED) + vcpkg_replace_string("${_debug_target}" "{_IMPORT_PREFIX}/${qt_qmldir}" "{_IMPORT_PREFIX}/debug/${qt_qmldir}" IGNORE_UNCHANGED) + endforeach() + + file(GLOB_RECURSE STATIC_CMAKE_TARGETS "${CURRENT_PACKAGES_DIR}/share/Qt6Qml/QmlPlugins/*.cmake") + foreach(_plugin_target IN LISTS STATIC_CMAKE_TARGETS) + # restore a single get_filename_component which was remove by vcpkg_cmake_config_fixup + vcpkg_replace_string("${_plugin_target}" + [[get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH)]] + "get_filename_component(_IMPORT_PREFIX \"\${CMAKE_CURRENT_LIST_FILE}\" PATH)\nget_filename_component(_IMPORT_PREFIX \"\${_IMPORT_PREFIX}\" PATH)" + IGNORE_UNCHANGED) + endforeach() + + set(qt_tooldest "${CURRENT_PACKAGES_DIR}/tools/Qt6/bin") + set(qt_searchdir "${CURRENT_PACKAGES_DIR}/bin") + ## Handle Tools + foreach(_tool IN LISTS _qarg_TOOL_NAMES) + if(NOT EXISTS "${CURRENT_PACKAGES_DIR}/bin/${_tool}${VCPKG_TARGET_EXECUTABLE_SUFFIX}") + debug_message("Removed '${_tool}' from copy tools list since it was not found!") + list(REMOVE_ITEM _qarg_TOOL_NAMES ${_tool}) + endif() + endforeach() + if(_qarg_TOOL_NAMES) + set(tool_names ${_qarg_TOOL_NAMES}) + vcpkg_copy_tools(TOOL_NAMES ${tool_names} SEARCH_DIR "${qt_searchdir}" DESTINATION "${qt_tooldest}" AUTO_CLEAN) + endif() + + if(VCPKG_TARGET_IS_WINDOWS AND VCPKG_LIBRARY_LINKAGE STREQUAL "dynamic") + if(EXISTS "${CURRENT_PACKAGES_DIR}/bin/") + file(COPY "${CURRENT_PACKAGES_DIR}/bin/" DESTINATION "${CURRENT_PACKAGES_DIR}/tools/Qt6/bin") + endif() + file(GLOB_RECURSE _installed_dll_files RELATIVE "${CURRENT_INSTALLED_DIR}/tools/Qt6/bin" "${CURRENT_INSTALLED_DIR}/tools/Qt6/bin/*.dll") + foreach(_dll_to_remove IN LISTS _installed_dll_files) + file(GLOB_RECURSE _packaged_dll_file "${CURRENT_PACKAGES_DIR}/tools/Qt6/bin/${_dll_to_remove}") + if(EXISTS "${_packaged_dll_file}") + file(REMOVE "${_packaged_dll_file}") + endif() + endforeach() + file(GLOB_RECURSE _folders LIST_DIRECTORIES true "${CURRENT_PACKAGES_DIR}/tools/Qt6/bin/**/") + file(GLOB_RECURSE _files "${CURRENT_PACKAGES_DIR}/tools/Qt6/bin/**/") + if(_files) + list(REMOVE_ITEM _folders ${_files}) + endif() + foreach(_dir IN LISTS _folders) + if(NOT "${_remaining_dll_files}" MATCHES "${_dir}") + file(REMOVE_RECURSE "${_dir}") + endif() + endforeach() + endif() + file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/lib/cmake/" + "${CURRENT_PACKAGES_DIR}/debug/share" + "${CURRENT_PACKAGES_DIR}/lib/cmake/" + "${CURRENT_PACKAGES_DIR}/debug/include" + ) + + if(VCPKG_LIBRARY_LINKAGE STREQUAL "static") + file(GLOB_RECURSE _bin_files "${CURRENT_PACKAGES_DIR}/bin/*") + if(NOT _bin_files STREQUAL "") + message(STATUS "Remaining files in bin: '${_bin_files}'") + else() # Only clean if empty otherwise let vcpkg throw and error. + file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/bin/" "${CURRENT_PACKAGES_DIR}/debug/bin/") + endif() + endif() + + vcpkg_fixup_pkgconfig() +endfunction() + +function(qt_install_submodule) + cmake_parse_arguments(PARSE_ARGV 0 "_qis" "DISABLE_NINJA" + "" + "PATCHES;TOOL_NAMES;CONFIGURE_OPTIONS;CONFIGURE_OPTIONS_DEBUG;CONFIGURE_OPTIONS_RELEASE;CONFIGURE_OPTIONS_MAYBE_UNUSED") + + set(qt_plugindir ${QT6_DIRECTORY_PREFIX}plugins) + set(qt_qmldir ${QT6_DIRECTORY_PREFIX}qml) + + qt_download_submodule(PATCHES ${_qis_PATCHES}) + + if(VCPKG_TARGET_IS_ANDROID) + # Qt only supports dynamic linkage on Android, + # https://bugreports.qt.io/browse/QTBUG-32618. + # It requires libc++_shared, cf. /cmake/QtPlatformAndroid.cmake + # and https://developer.android.com/ndk/guides/cpp-support#sr + vcpkg_check_linkage(ONLY_DYNAMIC_LIBRARY) + endif() + + if(_qis_DISABLE_NINJA) + set(_opt DISABLE_NINJA) + endif() + qt_cmake_configure(${_opt} + OPTIONS ${_qis_CONFIGURE_OPTIONS} + OPTIONS_DEBUG ${_qis_CONFIGURE_OPTIONS_DEBUG} + OPTIONS_RELEASE ${_qis_CONFIGURE_OPTIONS_RELEASE} + OPTIONS_MAYBE_UNUSED ${_qis_CONFIGURE_OPTIONS_MAYBE_UNUSED} + ) + + vcpkg_cmake_install(ADD_BIN_TO_PATH) + + qt_fixup_and_cleanup(TOOL_NAMES ${_qis_TOOL_NAMES}) + + qt_install_copyright("${SOURCE_PATH}") + set(SOURCE_PATH "${SOURCE_PATH}" PARENT_SCOPE) +endfunction() + +include("${CMAKE_CURRENT_LIST_DIR}/qt_port_details.cmake") diff --git a/vcpkg/ports/qtbase/cmake/qt_port_data.cmake b/vcpkg/ports/qtbase/cmake/qt_port_data.cmake new file mode 100644 index 000000000000..254593037ef7 --- /dev/null +++ b/vcpkg/ports/qtbase/cmake/qt_port_data.cmake @@ -0,0 +1,50 @@ +set(qtbase_HASH "ef364f939f23b622f67d21833c2dbf1fb74531d9a1e25b6d2e94ea5d747a40f20c6c3a24abef1e9710287366b7cb54dd090350d315601317779235c20743cc81") +set(qttools_HASH "77141b310f63932678f28682c490ccc75776493994d96582d546545c17937605efac312c008c75fda991b78c369320d0a2c4b543b568a459cc90051d1ed2b9da") +set(qtdeclarative_HASH "75c9fdc8ba26ef95ae8ff0c82b18589b74d7ff3065e86e5bd8427bc36336e569eaa22fa07863f99d0592eec0c1a69c3409c7b3941eae14361ff523c058e56084") +set(qtsvg_HASH "213af7fdf92fb64c9b824dbe044f51d89e661ccc02c17cf109e65b962a7b1de84c71e1b1b58d6cad0cc9fccee80b97efe9ebcab3491b478fb9b64bcfd33986a4") +set(qt5compat_HASH "e049508efda201e5d12a2dc0e023fc096611b18810f695be213a26bfbf8cdda1ae04c353c2a8b9be0c30b014e3d4f9280921acd1e8ec3834cd309143de82f570") +set(qtshadertools_HASH "5f326bb097e09f9f9259b550ccf5fb05634d748eebf8b8c416225e3cd328c2b532c764a41b98a4d47633be446edaeaa3d4e5da1f4951b31e3da6ddc4392a47fc") +set(qtquicktimeline_HASH "3f9aef0eb8b495cda9bcab22e7f544e9dd1894e556e162654c87903406cd3c73820f54a543bc3861d49c7863d2fc8d92f79bb8e90cdcc23a99cf64bbeb816885") +set(qtquick3d_HASH "5a5c04dfd1581905fb0b40cb35ef9e7370ffaf451287d84a9d444c0871f495ecfe59c8ab15cacc8e7314af45c16598fad5e63cd9466384c5ba245ad0c28315f2") +set(qttranslations_HASH "d5df6136d3f66c93c0dd6d98c7a467c8b939d7bf5c90b5acff69262163c1e7cccc0c4f2f83b5ef06179601578b4a109f2f0c76c3897a31d3fb2567995fc55328") +set(qtwayland_HASH "2edb6d3e85c06bcf689c3acfcc38b6ff0505569dfeec8bfb5a434fad563087ff917875ea56e639405af3cca8adc98206ab9f68dfaf8e2449300d010ffbb16699") +set(qtdoc_HASH "839fbff235f67ade032f25120fbd7f394d272bf752dfe982c202cb8b6cf411a1bc949f5035b2c1062468e40632b2061ac611c771d35567dd5970b013ff2090f8") +set(qtcoap_HASH "ce51ea39b7946b85cacddd3ebfe3a92615f31b032a779b799113c1e97aecdd3906e4fdc066296b0c0a369f4a023df4c951cc18dd47d2713e173118f2bd055cff") +set(qtopcua_HASH "ac11aab0f9333a4b666c9c523f5d74140bd52e236ed14cfce3dbfc030516b1cc654761048a7fd9e4238a9f1e0e47a72c6f2f8e98173f27042c6cdbb348c8d6d9") +set(qtimageformats_HASH "174bddd49dac507b7a2c9f1e1f7b384bff9ac515891ee49fd72acfa944b503cf5bd26acf388203e7d14b1f147b07ccbc2da992f71d51b7a18151245efc53a3a2") +set(qtmqtt_HASH "1934405a8e6b7188ce710e89eaf7ae00f1e1516b803b773ec95b962368a8da3967bac29dfe2a4377a76d0f8b9bf47599f566d7130eff311f38af2041d0c40a88") +set(qtnetworkauth_HASH "8f9f25883534af6ce7029a6c96501de3e944c8c6c3021f185c3a932653b4e4c40b3a0f8bc210d3ee175b690721a99b3d42de2f6fa9d1dbd1b730abf22fc48455") +set(qt3d_HASH "8316fbe5a39bc5113da4759e195a55c57d8340021a39576939c0a4a604f47b4edb3c0206f914d4a3177ff09471d1f3475ffc4c2fa935ed8d98a166e310bc78b4") +set(qtactiveqt_HASH "d49c16f4e055bcf389c719ae0e33a6ae0ef54f2433211f14864774c3694f82361783d18db6996b6f5abd52f5ac7f791b0eab015c946ceaa3ddfb9ef6abf64f19") +set(qtdatavis3d_HASH "a5d0cf5c223a5baa69dc7fc59b131eb3b971dc3701d20e81bf7e86ccb6e8f4d20a82079e514d1269091fa014896167d52912e3940210fd546a8a55439c75509a") +set(qtdeviceutilities_HASH "b32222c52169832a30a1d6bf0b19e5adc15bc9b1c7c12e4613ea73eba73b00528969f8a87830d0a9bf61663547ff263e2e0d6e5f4bc37b8624c3f96d9cbc51b6") +set(qtlottie_HASH "c663b830210359bd738a3ab2ae84d956646c249e199acac194c1ec725b3eb1acb2392eef0a9b252e8ece0adad104932d4f7207903e49ec041287618d3a6f9894") +set(qtscxml_HASH "c0138fc338b2d12fb4bcbba2c852b44e4257c56850f22af46d452871fb9bd9465bd824d86cd7e7772ef62b8ed48515790b496e1e873aa335deae8e25789cb4d0") +set(qtvirtualkeyboard_HASH "a128c8210eec799d81c76b20e32e3c09ccb345d822b5c59b1fbf0960a1e2bec50c43140d86aaae9419a1fc514fc3e14bd283f612bf9133676db1a21e7217f528") +set(qtcharts_HASH "84b372c8b52aea580b2b9727775753345affa80b73e0be843e65f7331bb809187d7183d93fdaf543197860210bc4e006f3a707663a160cf8ae05b37871abac7e") +set(qtconnectivity_HASH "5508f3fc57679a4f986f430dcd19c5da15af663a677d27c9cc6aba81629f4a6e1954be31c5d2a44ba22366d7731ff105d2eaa3a0565b3b02baea0f498c547733") +set(qtpositioning_HASH "8899b4bf8096211fca37f7a7855ae2c6f79d770602105d76a98b580ad8e2f2f55096095bd7f935f6f9ac36e23135e7594cf3c2e5b760c979560a108d43d57784") +set(qtlocation_HASH "c7cbd76b6b8b7d09387c7da0e6630959ae66f0c8af2cd26b255e86ec36c6efeec59e4af7b34faa05f2fa035d4dd075d13a8dd0bccaefac48d391b4fa786769c0") +set(qtmultimedia_HASH "2f001888b44274583dcd5bc6f467cf18efbb1a711f29d6baf354071199772ee49d835922f2fa0e9770898d42decddf04b379d8f05d1dfd923c5f9d58e3c7fcd8") +set(qtremoteobjects_HASH "5845afc5ea4894fa788ce07a89348bd5027c0cceca65dce99a6bf437b396c71f25e8e7374401c8d10fd88be2303766c6df29b62e826f4d5ba38971a042dd7b06") +set(qtsensors_HASH "88e9277aefdc609bda881cb836dfdc04d29a32a4e09998d67e2ebe7ec6f94aff508fb39c2b624f00bcc85ddccd61bb5ed3ffcc953dd28d00ef559d50e6104ae4") +set(qtserialbus_HASH "b0ce725382c15048913204e6173dd899af6f8233ff3a098f497dea6a3d9d2cd436ad7944165398fba59f92098f7e38e7c3c5efa47a7ffeec2bf3a464ae9d4539") +set(qtserialport_HASH "343537aedd9c84dd5d6889d45babff181d7ef05927fd9cfdbb9389066f8860e2522bc059ca2c5c9af4c88bca255e0fc40b5eea84b93c970123a94afc803a638d") +set(qtwebchannel_HASH "156d3d1f7e1a0b0df8c103db010cd8e40717e6fcf27dd20c27ca22900ae377a8da8bc86a9ec1d65765defb68032469415c345a571e9a3dcbc3919603972d01d6") +set(qtwebengine_HASH "01e8988c76ff40ca5e38f76e90791d7ef708c29f2e9f8e83ca8604b6335fbecdee71473678a63633ec1edec85088256b20e56a618ca95748ccbe1e7b9673c298") +set(qtwebsockets_HASH "7453c6657e9885393d57df3ebaf9d3ad12237b5fb848ac3547cc6c6ed607562d58564667a7fd10133d4cdb94151aa5c21660e33c7f48f01a4061001a47f85b60") +set(qtwebview_HASH "af16c85d76e55e3c39c747995b3c46354efe5f5a3e111df36f9b169ab8fe3ac878cfe223ee47aef9aa8bc302c7383fc9b1f9682c63034e42def3714b28a0aabf") +set(qtinterfaceframework_REF "373322fc654e875cb56828de554dfdda96e9fb4e") +set(qtapplicationmanager_HASH "7d404ac3f98d29004009d87996779a0c5c86b976e864257cd3a9018d84db8bc07bcedc74f0b15443f90b487d2229fdb7b80d1ae082b0fc8dea30f682b58cea1a") +set(qtlanguageserver_HASH "8b55a3558de28d6c2c61bf52e8f10d1a67cc6890fdd3846db99f6c766fd22fef1793687b88b146f5a64971d60eef4357409b893c91310d1b9abec883ab35c2bc") +set(qthttpserver_HASH "4e99164e285ed4e8ae64a4af2c717fc22a7b5934ac5a78fe3adbb04e29109d1294e9917aa089b9cb9e5492bdf7fad4888c837374c2fef691ea7294bccbe7b01a") +set(qtquick3dphysics_HASH "e8948f84e337bc4c496ba67f047c809ece8d74a3d2af388227c902b765a1d2969f86be2ebaaa89f271c4b73d2cf5151a4c488ff7dc4f4a965d5f6a4de052784a") +set(qtspeech_HASH "6434ccf743604bf4ac4bc31b26c7dbc7f765ec95174f0d9047bec822292f85e6b21ace825b52ce60bd388d9c333d427b206209f78c612782701567bb7d271e6d") +set(qtgrpc_HASH "488c7e6a20cd9c267b44923c317e545e71543f68153228a4fee1fa9c0a2f6d3e212db9482962999bb80e87313a1a851b787759852089f17dca8add7040627c55") +set(qtquickeffectmaker_HASH "cdcee80a0bf7347ef9b63acc277ce6ef134128ba56f247008803d9444a9e0713e23205ed0f9ecf2b7752d82183acb471a2589c8b0ec914259a22395f94755bfa") +set(qtgraphs_HASH "c1803e68e065fc4ed7de68e65f5dc86a0b926768779c0de57a7f4af46506f019c27d47095f87eb1516011868262d6654817c478e130739477658a3dbcef2fb35") + + +# Keep for beta/rc +#set(qttools_qlitehtml_REF bd70f93ce41443a6a90a269531393f575685283e) +#set(qtwebengine_chromium_REF 0b138dc30d0aec7930c76a2595065629948ad9f7) diff --git a/vcpkg/ports/qtbase/cmake/qt_port_details.cmake b/vcpkg/ports/qtbase/cmake/qt_port_details.cmake new file mode 100644 index 000000000000..e1f263d57fdf --- /dev/null +++ b/vcpkg/ports/qtbase/cmake/qt_port_details.cmake @@ -0,0 +1,183 @@ +### Steps to update the qt6 ports +## 1. Change QT_VERSION below to the new version +## 2. Set QT_UPDATE_VERSION to 1 +## 3. Add any new Qt modules to QT_PORTS +## 4. Run a build of `qtbase` +## 5. Fix any intermediate failures by adding the module into QT_FROM_GITHUB, QT_FROM_GITHUB_BRANCH, or QT_FROM_QT_GIT as appropriate +## 6. The build should fail with "Done downloading version and emitting hashes." This will have changed out the vcpkg.json versions of the qt ports and rewritten qt_port_data.cmake +## 7. Set QT_UPDATE_VERSION back to 0 + +set(QT_VERSION 6.8.3) +set(QT_DEV_BRANCH 0) + +set(QT_UPDATE_VERSION 0) + +if(PORT MATCHES "(qtquickcontrols2)") + set(VCPKG_POLICY_EMPTY_PACKAGE enabled) + return() +endif() + +### Setting up the git tag. + +set(QT_PORTS qt + qtbase + qttools + qtdeclarative + qtsvg + qt5compat + qtshadertools + qtquicktimeline + qtquick3d + qttranslations + qtwayland + qtdoc + qtcoap + qtopcua + qtimageformats + qtmqtt + qtnetworkauth + qt3d) + # qtquickcontrols2 -> moved into qtdeclarative +if(QT_VERSION VERSION_GREATER_EQUAL 6.1) + list(APPEND QT_PORTS + ## New in 6.1 + qtactiveqt + qtdatavis3d + qtdeviceutilities + qtlottie + qtscxml + qtvirtualkeyboard + qtcharts) +endif() +if(QT_VERSION VERSION_GREATER_EQUAL 6.2) + list(APPEND QT_PORTS + ## New in 6.2 + qtconnectivity + qtpositioning + qtlocation # back in 6.5 as tech preview + qtmultimedia + qtremoteobjects + qtsensors + qtserialbus + qtserialport + qtwebchannel + qtwebengine + qtwebsockets + qtwebview) +endif() +if(QT_VERSION VERSION_GREATER_EQUAL 6.2.2) + list(APPEND QT_PORTS + ## New in 6.2.2 + qtinterfaceframework + qtapplicationmanager) +endif() +if(QT_VERSION VERSION_GREATER_EQUAL 6.3.0) + list(APPEND QT_PORTS + ## New in 6.3.0 + qtlanguageserver) +endif() +if(QT_VERSION VERSION_GREATER_EQUAL 6.4.0) + list(APPEND QT_PORTS + ## New in 6.4.0 + qthttpserver + qtquick3dphysics + qtspeech) +endif() +if(QT_VERSION VERSION_GREATER_EQUAL 6.5.0) + list(APPEND QT_PORTS + ## New in 6.5.0 + qtgrpc + qtquickeffectmaker + ) +endif() +if(QT_VERSION VERSION_GREATER_EQUAL 6.6.0) + list(APPEND QT_PORTS + ## New in 6.6.0 + qtgraphs + #qtvncserver # only commercial + #qtinsighttracker + ) +endif() +#qtinsighttracker +#qtvncserver +#qtgraphs + +# 1. By default, modules come from the official release +# 2. These modules are mirrored to github and have tags matching the release +set(QT_FROM_GITHUB qtcoap qtopcua qtmqtt qtapplicationmanager) +# 3. These modules are mirrored to github and have branches matching the release +set(QT_FROM_GITHUB_BRANCH qtdeviceutilities) +# 4. These modules are not mirrored to github and not part of the release +set(QT_FROM_QT_GIT qtinterfaceframework) +# For beta releases uncomment the next two lines and comment the lines with QT_FROM_GITHUB, QT_FROM_GITHUB_BRANCH, QT_FROM_QT_GIT +#set(QT_FROM_QT_GIT ${QT_PORTS}) +#list(POP_FRONT QT_FROM_QT_GIT) + +function(qt_get_url_filename qt_port out_urls out_filename) + if("${qt_port}" IN_LIST QT_FROM_GITHUB) + set(urls "https://github.com/qt/${qt_port}/archive/v${QT_VERSION}.tar.gz") + set(filename "qt-${qt_port}-v${QT_VERSION}.tar.gz") + elseif("${qt_port}" IN_LIST QT_FROM_GITHUB_BRANCH) + set(urls "https://github.com/qt/${qt_port}/archive/${QT_VERSION}.tar.gz") + set(filename "qt-${qt_port}-${QT_VERSION}.tar.gz") + else() + string(SUBSTRING "${QT_VERSION}" 0 3 qt_major_minor) + + if(NOT QT_DEV_BRANCH) + set(branch_subpath "archive") + else() + set(branch_subpath "development_releases") + endif() + + set(filename "${qt_port}-everywhere-src-${QT_VERSION}.tar.xz") + set(mirrors + "https://download.qt.io/" + "https://mirrors.ocf.berkeley.edu/qt/" + ) + set(url_subpath "${branch_subpath}/qt/${qt_major_minor}/${QT_VERSION}/submodules/${filename}") + list(TRANSFORM mirrors APPEND "${url_subpath}" OUTPUT_VARIABLE urls) + endif() + set(${out_urls} ${urls} PARENT_SCOPE) + set(${out_filename} "${filename}" PARENT_SCOPE) +endfunction() + +if(QT_UPDATE_VERSION) + if(NOT PORT STREQUAL "qtbase") + message(FATAL_ERROR "QT_UPDATE_VERSION must be used from the root 'qtbase' package") + endif() + set(VCPKG_USE_HEAD_VERSION 1) + set(msg "" CACHE INTERNAL "") + foreach(qt_port IN LISTS QT_PORTS) + set(port_json "${CMAKE_CURRENT_LIST_DIR}/../../${qt_port}/vcpkg.json") + file(READ "${port_json}" _control_contents) + string(REGEX REPLACE "\"version(-(string|semver))?\": [^\n]+\n" "\"version\": \"${QT_VERSION}\",\n" _control_contents "${_control_contents}") + string(REGEX REPLACE "\"port-version\": [^\n]+\n" "" _control_contents "${_control_contents}") + file(WRITE "${port_json}" "${_control_contents}") + if(qt_port STREQUAL "qt") + continue() + endif() + if("${qt_port}" IN_LIST QT_FROM_QT_GIT) + vcpkg_find_acquire_program(GIT) + execute_process( + COMMAND "${GIT}" ls-remote -t "https://code.qt.io/cgit/qt/${qt_port}.git" "v${QT_VERSION}" + OUTPUT_VARIABLE out + ) + string(SUBSTRING "${out}" 0 40 tag_sha) + string(APPEND msg "set(${qt_port}_REF ${tag_sha})\n") + else() + qt_get_url_filename("${qt_port}" urls filename) + vcpkg_download_distfile(archive + URLS ${urls} + FILENAME "${filename}" + SKIP_SHA512 + ) + file(SHA512 "${archive}" hash) + string(APPEND msg "set(${qt_port}_HASH \"${hash}\")\n") + endif() + endforeach() + message("${msg}") + file(WRITE "${CMAKE_CURRENT_LIST_DIR}/qt_port_data_new.cmake" "${msg}") + message(FATAL_ERROR "Done downloading version and emitting hashes.") +endif() + +include("${CMAKE_CURRENT_LIST_DIR}/qt_port_data.cmake") diff --git a/vcpkg/ports/qtbase/config_install.patch b/vcpkg/ports/qtbase/config_install.patch new file mode 100644 index 000000000000..fdfc703301d2 --- /dev/null +++ b/vcpkg/ports/qtbase/config_install.patch @@ -0,0 +1,13 @@ +diff --git a/cmake/QtBuildPathsHelpers.cmake b/cmake/QtBuildPathsHelpers.cmake +index bd186c28b..edee52e8b 100644 +--- a/cmake/QtBuildPathsHelpers.cmake ++++ b/cmake/QtBuildPathsHelpers.cmake +@@ -100,7 +100,7 @@ function(qt_internal_set_up_global_paths) + if(QT_CONFIG_INSTALL_DIR) + string(APPEND QT_CONFIG_INSTALL_DIR "/") + endif() +- string(APPEND QT_CONFIG_INSTALL_DIR ${__config_path_part}) ++ string(APPEND QT_CONFIG_INSTALL_DIR "share") + + set(QT_BUILD_DIR "${QT_BUILD_DIR}" PARENT_SCOPE) + set(QT_INSTALL_DIR "${QT_INSTALL_DIR}" PARENT_SCOPE) diff --git a/vcpkg/ports/qtbase/dont_force_cmakecache_latest.patch b/vcpkg/ports/qtbase/dont_force_cmakecache_latest.patch new file mode 100644 index 000000000000..752cefe6d2b8 --- /dev/null +++ b/vcpkg/ports/qtbase/dont_force_cmakecache_latest.patch @@ -0,0 +1,13 @@ +diff --git a/cmake/QtPostProcessHelpers.cmake b/cmake/QtPostProcessHelpers.cmake +index 4f8106dfa..bec5c402e 100644 +--- a/cmake/QtPostProcessHelpers.cmake ++++ b/cmake/QtPostProcessHelpers.cmake +@@ -414,7 +414,7 @@ function(qt_generate_install_prefixes out_var) + + foreach(var ${vars}) + get_property(docstring CACHE "${var}" PROPERTY HELPSTRING) +- string(APPEND content "set(${var} \"${${var}}\" CACHE STRING \"${docstring}\" FORCE)\n") ++ string(APPEND content "set(${var} \"${${var}}\" CACHE STRING \"${docstring}\")\n") + endforeach() + + set(${out_var} "${content}" PARENT_SCOPE) diff --git a/vcpkg/ports/qtbase/env.patch b/vcpkg/ports/qtbase/env.patch new file mode 100644 index 000000000000..6a371675927a --- /dev/null +++ b/vcpkg/ports/qtbase/env.patch @@ -0,0 +1,16 @@ +diff --git a/cmake/QtTestHelpers.cmake b/cmake/QtTestHelpers.cmake +index 279ab07dd..951fd3d36 100644 +--- a/cmake/QtTestHelpers.cmake ++++ b/cmake/QtTestHelpers.cmake +@@ -653,9 +653,9 @@ function(qt_internal_collect_command_environment out_path out_plugin_path) + # The regular CMAKE_INSTALL_PREFIX can be different for example when building standalone tests. + # Any given CMAKE_INSTALL_PREFIX takes priority over qt_relocatable_install_prefix for the + # PATH environment variable. +- set(install_prefixes "${CMAKE_INSTALL_PREFIX}") ++ set(install_prefixes "${CMAKE_INSTALL_PREFIX}$<$:/debug>") + if(QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX) +- list(APPEND install_prefixes "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}") ++ list(APPEND install_prefixes "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}$<$:/debug>") + endif() + + file(TO_NATIVE_PATH "${CMAKE_CURRENT_BINARY_DIR}" test_env_path) diff --git a/vcpkg/ports/qtbase/fix-host-aliasing.patch b/vcpkg/ports/qtbase/fix-host-aliasing.patch new file mode 100644 index 000000000000..1823a351d963 --- /dev/null +++ b/vcpkg/ports/qtbase/fix-host-aliasing.patch @@ -0,0 +1,17 @@ +diff --git a/cmake/QtTargetHelpers.cmake b/cmake/QtTargetHelpers.cmake +index 180ec33..a03e3b1 100644 +--- a/cmake/QtTargetHelpers.cmake ++++ b/cmake/QtTargetHelpers.cmake +@@ -281,10 +281,10 @@ function(qt_internal_add_target_aliases target) + set_target_properties("${target}" PROPERTIES _qt_versionfull_alias "${versionfull_alias}") + + get_target_property(type "${target}" TYPE) +- if (type STREQUAL EXECUTABLE) ++ if (type STREQUAL EXECUTABLE AND NOT TARGET "${versionfull_alias}") + add_executable("${versionless_alias}" ALIAS "${target}") + add_executable("${versionfull_alias}" ALIAS "${target}") +- else() ++ elseif(NOT type STREQUAL EXECUTABLE) + add_library("${versionless_alias}" ALIAS "${target}") + add_library("${versionfull_alias}" ALIAS "${target}") + endif() diff --git a/vcpkg/ports/qtbase/fix-link-lib-discovery.patch b/vcpkg/ports/qtbase/fix-link-lib-discovery.patch new file mode 100644 index 000000000000..339d2549069c --- /dev/null +++ b/vcpkg/ports/qtbase/fix-link-lib-discovery.patch @@ -0,0 +1,12 @@ +diff --git a/cmake/QtPriHelpers.cmake b/cmake/QtPriHelpers.cmake +index b6f1242..eaa4d65 100644 +--- a/cmake/QtPriHelpers.cmake ++++ b/cmake/QtPriHelpers.cmake +@@ -37,6 +37,7 @@ function(qt_generate_qmake_libraries_pri_content module_name output_root_dir out + get_target_property(lib_target_type ${lib_target} TYPE) + if(lib_target_type MATCHES "^(INTERFACE|UNKNOWN)_LIBRARY") + get_target_property(iface_libs ${lib_target} INTERFACE_LINK_LIBRARIES) ++ string(REGEX REPLACE [[\$]+)>]] "\\1" iface_libs "${iface_libs}") + if(iface_libs) + list(PREPEND lib_targets ${iface_libs}) + endif() diff --git a/vcpkg/ports/qtbase/fix_cmake_build.patch b/vcpkg/ports/qtbase/fix_cmake_build.patch new file mode 100644 index 000000000000..65410e3fc708 --- /dev/null +++ b/vcpkg/ports/qtbase/fix_cmake_build.patch @@ -0,0 +1,15 @@ +diff --git a/cmake/QtBuildInternalsExtra.cmake.in b/cmake/QtBuildInternalsExtra.cmake.in +index ffc9d90f8..0b3a7d59e 100644 +--- a/cmake/QtBuildInternalsExtra.cmake.in ++++ b/cmake/QtBuildInternalsExtra.cmake.in +@@ -51,8 +51,8 @@ endif() + set(QT_WILL_INSTALL @QT_WILL_INSTALL@ CACHE BOOL + "Boolean indicating if doing a Qt prefix build (vs non-prefix build)." FORCE) + +-set(QT_SOURCE_TREE "@QT_SOURCE_TREE@" CACHE PATH +-"A path to the source tree of the previously configured QtBase project." FORCE) ++# set(QT_SOURCE_TREE "@QT_SOURCE_TREE@" CACHE PATH ++# "A path to the source tree of the previously configured QtBase project." FORCE) + + # Propagate decision of building tests and examples to other repositories. + set(QT_BUILD_TESTS @QT_BUILD_TESTS@ CACHE BOOL "Build the testing tree.") diff --git a/vcpkg/ports/qtbase/fix_deploy_windows.patch b/vcpkg/ports/qtbase/fix_deploy_windows.patch new file mode 100644 index 000000000000..2d2f46ff0cdf --- /dev/null +++ b/vcpkg/ports/qtbase/fix_deploy_windows.patch @@ -0,0 +1,26 @@ +diff --git a/src/corelib/Qt6CoreMacros.cmake b/src/corelib/Qt6CoreMacros.cmake +index 8a0d07feac..0e6a720c20 100644 +--- a/src/corelib/Qt6CoreMacros.cmake ++++ b/src/corelib/Qt6CoreMacros.cmake +@@ -2977,17 +2977,19 @@ function(_qt_internal_setup_deploy_support) + if(CMAKE_HOST_WIN32) ++ if(CMAKE_CROSSCOMPILING AND NOT CMAKE_BUILD_TYPE STREQUAL "Debug") +- if(CMAKE_CROSSCOMPILING) + set(qt_paths_ext ".bat") ++ elseif(CMAKE_BUILD_TYPE STREQUAL "Debug") ++ set(qt_paths_ext ".debug.bat") + else() + set(qt_paths_ext ".exe") + endif() + else() + set(qt_paths_ext "") + endif() + + + + set(target_qtpaths_path "") +- set(qtpaths_prefix "${QT6_INSTALL_PREFIX}/${QT6_INSTALL_BINS}") ++ set(qtpaths_prefix "${QT6_INSTALL_PREFIX}/tools/Qt6/bin") + get_property(qt_major_version TARGET "${target}" PROPERTY INTERFACE_QT_MAJOR_VERSION) + if(qt_major_version) + set(target_qtpaths_with_major_version_path diff --git a/vcpkg/ports/qtbase/fix_egl.patch b/vcpkg/ports/qtbase/fix_egl.patch new file mode 100644 index 000000000000..7868310687cd --- /dev/null +++ b/vcpkg/ports/qtbase/fix_egl.patch @@ -0,0 +1,12 @@ +diff --git a/cmake/3rdparty/extra-cmake-modules/find-modules/FindEGL.cmake b/cmake/3rdparty/extra-cmake-modules/find-modules/FindEGL.cmake +index eafbc1ff9..dd4068838 100644 +--- a/cmake/3rdparty/extra-cmake-modules/find-modules/FindEGL.cmake ++++ b/cmake/3rdparty/extra-cmake-modules/find-modules/FindEGL.cmake +@@ -82,6 +82,7 @@ find_path(EGL_INCLUDE_DIR + find_library(EGL_LIBRARY + NAMES + EGL ++ libEGL # required to find angle on windows within vcpkg. + HINTS + ${PKG_EGL_LIBRARY_DIRS} + ) diff --git a/vcpkg/ports/qtbase/fix_egl_2.patch b/vcpkg/ports/qtbase/fix_egl_2.patch new file mode 100644 index 000000000000..78b1c360fc00 --- /dev/null +++ b/vcpkg/ports/qtbase/fix_egl_2.patch @@ -0,0 +1,13 @@ +diff --git a/cmake/3rdparty/extra-cmake-modules/find-modules/FindEGL.cmake b/cmake/3rdparty/extra-cmake-modules/find-modules/FindEGL.cmake +index db48f79b9..4b1686132 100644 +--- a/cmake/3rdparty/extra-cmake-modules/find-modules/FindEGL.cmake ++++ b/cmake/3rdparty/extra-cmake-modules/find-modules/FindEGL.cmake +@@ -116,7 +116,7 @@ if(EGL_INCLUDE_DIR) + unset(_EGL_version_lines) + endif() + +-cmake_push_check_state(RESET) ++cmake_push_check_state() # To be able to fix the compile check in vcpkg-cmake-wrapper + list(APPEND CMAKE_REQUIRED_LIBRARIES "${EGL_LIBRARY}") + list(APPEND CMAKE_REQUIRED_INCLUDES "${EGL_INCLUDE_DIR}") + list(APPEND CMAKE_REQUIRED_DEFINITIONS "${EGL_DEFINITIONS}") diff --git a/vcpkg/ports/qtbase/harfbuzz.patch b/vcpkg/ports/qtbase/harfbuzz.patch new file mode 100644 index 000000000000..a2f8e74249c3 --- /dev/null +++ b/vcpkg/ports/qtbase/harfbuzz.patch @@ -0,0 +1,13 @@ +diff --git a/cmake/FindWrapSystemHarfbuzz.cmake b/cmake/FindWrapSystemHarfbuzz.cmake +index 3cb44aa76..9bf0d7165 100644 +--- a/cmake/FindWrapSystemHarfbuzz.cmake ++++ b/cmake/FindWrapSystemHarfbuzz.cmake +@@ -6,7 +6,7 @@ if(TARGET WrapSystemHarfbuzz::WrapSystemHarfbuzz) + endif() + set(WrapSystemHarfbuzz_REQUIRED_VARS __harfbuzz_found) + +-find_package(harfbuzz ${${CMAKE_FIND_PACKAGE_NAME}_FIND_VERSION} QUIET) ++find_package(harfbuzz QUIET) # VCPKG is missing the version file for harfbuzz. + + # Gentoo has some buggy version of a harfbuzz Config file. Check if include paths are valid. + set(__harfbuzz_target_name "harfbuzz::harfbuzz") diff --git a/vcpkg/ports/qtbase/installed_dir.patch b/vcpkg/ports/qtbase/installed_dir.patch new file mode 100644 index 000000000000..918673141598 --- /dev/null +++ b/vcpkg/ports/qtbase/installed_dir.patch @@ -0,0 +1,15 @@ +diff --git a/cmake/qt.toolchain.cmake.in b/cmake/qt.toolchain.cmake.in +index 6e37ae02..e7e84468 100644 +--- a/cmake/qt.toolchain.cmake.in ++++ b/cmake/qt.toolchain.cmake.in +@@ -65,6 +65,10 @@ get_filename_component(QT_TOOLCHAIN_RELOCATABLE_INSTALL_PREFIX + # one level higher is what we're looking for. + get_filename_component(QT_TOOLCHAIN_RELOCATABLE_CMAKE_DIR "${CMAKE_CURRENT_LIST_DIR}/.." ABSOLUTE) + ++get_filename_component(vcpkg_installed_dir ++ ${CMAKE_CURRENT_LIST_DIR}/../../../ ++ ABSOLUTE) ++ + # REROOT_PATH_ISSUE_MARKER + # There's a subdirectory check in cmake's cmFindCommon::RerootPaths() function, that doesn't handle + # the case of CMAKE_PREFIX_PATH == CMAKE_FIND_ROOT_PATH for a particular pair of entries. diff --git a/vcpkg/ports/qtbase/macdeployqt-symlinks.patch b/vcpkg/ports/qtbase/macdeployqt-symlinks.patch new file mode 100644 index 000000000000..ce6fe71f6421 --- /dev/null +++ b/vcpkg/ports/qtbase/macdeployqt-symlinks.patch @@ -0,0 +1,33 @@ +diff --git a/src/tools/macdeployqt/shared/shared.cpp b/src/tools/macdeployqt/shared/shared.cpp +index 6ff269b..caffd44 100644 +--- a/src/tools/macdeployqt/shared/shared.cpp ++++ b/src/tools/macdeployqt/shared/shared.cpp +@@ -1,4 +1,5 @@ + // Copyright (C) 2016 The Qt Company Ltd. ++ + // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + #include + #include +@@ -85,7 +86,21 @@ + } + } + +- if (QFile::copy(from, to)) { ++ QFileInfo fromFileInfo(from); ++ ++ if (fromFileInfo.isSymLink()) { ++ const QString fromSymLinkTarget = fromFileInfo.absoluteDir().relativeFilePath(fromFileInfo.symLinkTarget()); ++ if (QFile::link(fromSymLinkTarget, to)) { ++ return copyFilePrintStatus(fromFileInfo.absoluteDir().absoluteFilePath(fromSymLinkTarget), QFileInfo(to).absoluteDir().absoluteFilePath(fromSymLinkTarget)); ++ } ++ else { ++ LogError() << "symlink copy failed from" << from; ++ LogError() << " to" << to; ++ return false; ++ } ++ ++ } ++ else if (QFile::copy(from, to)) { + QFile dest(to); + dest.setPermissions(dest.permissions() | QFile::WriteOwner | QFile::WriteUser); + LogNormal() << " copied:" << from; diff --git a/vcpkg/ports/qtbase/portfile.cmake b/vcpkg/ports/qtbase/portfile.cmake new file mode 100644 index 000000000000..f3548a4f24af --- /dev/null +++ b/vcpkg/ports/qtbase/portfile.cmake @@ -0,0 +1,599 @@ +# Reminder for myself and everybody else: +# Qt cross module dependency information within the Qt respository is wrong and/or incomplete. +# Always check the toplevel CMakeLists.txt for the find_package call and search for linkage against the Qt:: targets +# Often enough certain (bigger) dependencies are only used to build examples and/or tests. +# As such getting the correct dependency information relevant for vcpkg requires a manual search/check +set(QT_IS_LATEST ON) + +## All above goes into the qt_port_hashes in the future +include("${CMAKE_CURRENT_LIST_DIR}/cmake/qt_install_submodule.cmake") + +set(${PORT}_PATCHES + allow_outside_prefix.patch + config_install.patch + fix_cmake_build.patch + harfbuzz.patch + fix_egl.patch + fix_egl_2.patch + installed_dir.patch + GLIB2-static.patch # alternative is to force pkg-config + clang-cl_source_location.patch + clang-cl_QGADGET_fix.diff + fix-host-aliasing.patch + fix_deploy_windows.patch + fix-link-lib-discovery.patch + macdeployqt-symlinks.patch +) + +if(VCPKG_TARGET_IS_WINDOWS AND NOT VCPKG_TARGET_IS_MINGW) + list(APPEND ${PORT}_PATCHES env.patch) +endif() + +if("shared-mime-info" IN_LIST FEATURES) + list(APPEND ${PORT}_PATCHES use-shared-mime-info.patch) +endif() + +list(APPEND ${PORT}_PATCHES + dont_force_cmakecache_latest.patch + ) + +if(VCPKG_TARGET_IS_WINDOWS AND NOT "doubleconversion" IN_LIST FEATURES) + message(FATAL_ERROR "${PORT} requires feature doubleconversion on windows!" ) +endif() + +# Feature like glib depend on pkg-config +vcpkg_find_acquire_program(PKGCONFIG) +set(ENV{PKG_CONFIG} "${PKGCONFIG}") + +if(VCPKG_TARGET_IS_LINUX) + message(WARNING "qtbase currently requires packages from the system package manager. " + "They can be installed on Ubuntu systems via sudo apt-get install " + "'^libxcb.*-dev' libx11-xcb-dev libglu1-mesa-dev libxrender-dev libxi-dev libxkbcommon-dev " + "libxkbcommon-x11-dev libegl1-mesa-dev.") +endif() + +# Features can be found via searching for qt_feature in all configure.cmake files in the source: +# The files also contain information about the Platform for which it is searched +# Always use FEATURE_ in vcpkg_cmake_configure +# (using QT_FEATURE_X overrides Qts condition check for the feature.) +# Theoretically there is a feature for every widget to enable/disable it but that is way to much for vcpkg + +set(input_vars doubleconversion freetype harfbuzz libb2 jpeg libmd4c png sql-sqlite) +set(INPUT_OPTIONS) +foreach(_input IN LISTS input_vars) + if(_input MATCHES "(png|jpeg)" ) + list(APPEND INPUT_OPTIONS -DINPUT_lib${_input}:STRING=) + elseif(_input MATCHES "(sql-sqlite)") # Not yet used by the cmake build + else() + list(APPEND INPUT_OPTIONS -DINPUT_${_input}:STRING=) + endif() + if("${_input}" IN_LIST FEATURES) + string(APPEND INPUT_OPTIONS system) + elseif(_input STREQUAL "libb2" AND NOT VCPKG_TARGET_IS_WINDOWS) + string(APPEND INPUT_OPTIONS system) + elseif(_input STREQUAL "libmd4c") + string(APPEND INPUT_OPTIONS qt) # libmd4c is not yet in VCPKG (but required by qtdeclarative) + else() + string(APPEND INPUT_OPTIONS no) + endif() +endforeach() + +# General features: + +vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS +FEATURES + "appstore-compliant" FEATURE_appstore_compliant + "zstd" FEATURE_zstd + "framework" FEATURE_framework + "concurrent" FEATURE_concurrent + "concurrent" FEATURE_future + "dbus" FEATURE_dbus + "gui" FEATURE_gui + "thread" FEATURE_thread + "network" FEATURE_network + "sql" FEATURE_sql + "widgets" FEATURE_widgets + #"xml" FEATURE_xml # Required to build moc + "testlib" FEATURE_testlib + "zstd" CMAKE_REQUIRE_FIND_PACKAGE_zstd + ${require_features} +INVERTED_FEATURES + "zstd" CMAKE_DISABLE_FIND_PACKAGE_ZSTD + "dbus" CMAKE_DISABLE_FIND_PACKAGE_WrapDBus1 + ) + +list(APPEND FEATURE_OPTIONS -DCMAKE_DISABLE_FIND_PACKAGE_Libudev:BOOL=ON) +list(APPEND FEATURE_OPTIONS -DFEATURE_xml:BOOL=ON) + +if("dbus" IN_LIST FEATURES AND VCPKG_TARGET_IS_LINUX) + list(APPEND FEATURE_OPTIONS -DINPUT_dbus=linked) +elseif("dbus" IN_LIST FEATURES) + list(APPEND FEATURE_OPTIONS -DINPUT_dbus=runtime) +else() + list(APPEND FEATURE_OPTIONS -DINPUT_dbus=no) +endif() + +if(VCPKG_QT_NAMESPACE) + list(APPEND FEATURE_OPTIONS "-DQT_NAMESPACE:STRING=${VCPKG_QT_NAMESPACE}") +endif() + +# Corelib features: +vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_CORE_OPTIONS +FEATURES + "doubleconversion" FEATURE_doubleconversion + "glib" FEATURE_glib + "icu" FEATURE_icu + "pcre2" FEATURE_pcre2 + #"icu" CMAKE_REQUIRE_FIND_PACKAGE_ICU + #"glib" CMAKE_REQUIRE_FIND_PACKAGE_GLIB2 +INVERTED_FEATURES + #"doubleconversion" CMAKE_DISABLE_FIND_PACKAGE_WrapDoubleConversion # Required + #"pcre2" CMAKE_DISABLE_FIND_PACKAGE_WrapSystemPCRE2 # Bug in qt cannot be deactivated + "icu" CMAKE_DISABLE_FIND_PACKAGE_ICU + "glib" CMAKE_DISABLE_FIND_PACKAGE_GLIB2 + ) + +list(APPEND FEATURE_CORE_OPTIONS -DCMAKE_DISABLE_FIND_PACKAGE_LTTngUST:BOOL=ON) +list(APPEND FEATURE_CORE_OPTIONS -DCMAKE_DISABLE_FIND_PACKAGE_PPS:BOOL=ON) +list(APPEND FEATURE_CORE_OPTIONS -DCMAKE_DISABLE_FIND_PACKAGE_Slog2:BOOL=ON) +list(APPEND FEATURE_CORE_OPTIONS -DCMAKE_DISABLE_FIND_PACKAGE_Libsystemd:BOOL=ON) +list(APPEND FEATURE_CORE_OPTIONS -DCMAKE_DISABLE_FIND_PACKAGE_WrapBacktrace:BOOL=ON) +#list(APPEND FEATURE_CORE_OPTIONS -DCMAKE_DISABLE_FIND_PACKAGE_WrapAtomic:BOOL=ON) # Cannot be disabled on x64 platforms +#list(APPEND FEATURE_CORE_OPTIONS -DCMAKE_DISABLE_FIND_PACKAGE_WrapRt:BOOL=ON) # Cannot be disabled on osx + +# Network features: + vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_NET_OPTIONS + FEATURES + "openssl" FEATURE_openssl + "brotli" FEATURE_brotli + "securetransport" FEATURE_securetransport + "dnslookup" FEATURE_dnslookup + #"brotli" CMAKE_REQUIRE_FIND_PACKAGE_WrapBrotli + #"openssl" CMAKE_REQUIRE_FIND_PACKAGE_WrapOpenSSL + INVERTED_FEATURES + "brotli" CMAKE_DISABLE_FIND_PACKAGE_WrapBrotli + "openssl" CMAKE_DISABLE_FIND_PACKAGE_WrapOpenSSL + "dnslookup" CMAKE_DISABLE_FIND_PACKAGE_WrapResolve + ) + +if("openssl" IN_LIST FEATURES) + list(APPEND FEATURE_NET_OPTIONS -DINPUT_openssl=linked) +else() + list(APPEND FEATURE_NET_OPTIONS -DINPUT_openssl=no) +endif() + +if ("dnslookup" IN_LIST FEATURES AND NOT VCPKG_TARGET_IS_ANDROID AND NOT VCPKG_TARGET_IS_WINDOWS) + list(APPEND FEATURE_NET_OPTIONS -DFEATURE_libresolv:BOOL=ON) +endif() + +list(APPEND FEATURE_NET_OPTIONS -DCMAKE_DISABLE_FIND_PACKAGE_Libproxy:BOOL=ON) +list(APPEND FEATURE_NET_OPTIONS -DCMAKE_DISABLE_FIND_PACKAGE_GSSAPI:BOOL=ON) + +# Gui features: +vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_GUI_OPTIONS + FEATURES + "freetype" FEATURE_freetype # required on windows + "harfbuzz" FEATURE_harfbuzz + "fontconfig" FEATURE_fontconfig # NOT WINDOWS + "jpeg" FEATURE_jpeg + "png" FEATURE_png + "opengl" FEATURE_opengl + "xlib" FEATURE_xlib + "xkb" FEATURE_xkbcommon + "xcb" FEATURE_xcb + "xcb-xlib" FEATURE_xcb_xlib + "xkbcommon-x11" FEATURE_xkbcommon_x11 + "xrender" FEATURE_xrender # requires FEATURE_xcb_native_painting; otherwise disabled. + "xrender" FEATURE_xcb_native_painting # experimental + "gles2" FEATURE_opengles2 + "gles3" FEATURE_opengles3 + #Cannot be required since Qt will look in CONFIG mode first but is controlled via CMAKE_DISABLE_FIND_PACKAGE_Vulkan below + #"vulkan" CMAKE_REQUIRE_FIND_PACKAGE_WrapVulkanHeaders + "egl" FEATURE_egl + #"fontconfig" CMAKE_REQUIRE_FIND_PACKAGE_Fontconfig + #"harfbuzz" CMAKE_REQUIRE_FIND_PACKAGE_WrapSystemHarfbuzz + #"jpeg" CMAKE_REQUIRE_FIND_PACKAGE_JPEG + #"png" CMAKE_REQUIRE_FIND_PACKAGE_PNG + #"xlib" CMAKE_REQUIRE_FIND_PACKAGE_X11 + #"xkb" CMAKE_REQUIRE_FIND_PACKAGE_XKB + #"xcb" CMAKE_REQUIRE_FIND_PACKAGE_XCB + #"xcb-xlib" CMAKE_REQUIRE_FIND_PACKAGE_X11_XCB + #"xkbcommon-x11" CMAKE_REQUIRE_FIND_PACKAGE_XKB_COMMON_X11 + #"xrender" CMAKE_REQUIRE_FIND_PACKAGE_XRender + INVERTED_FEATURES + "vulkan" CMAKE_DISABLE_FIND_PACKAGE_Vulkan + "opengl" CMAKE_DISABLE_FIND_PACKAGE_WrapOpenGL + "egl" CMAKE_DISABLE_FIND_PACKAGE_EGL + "gles2" CMAKE_DISABLE_FIND_PACKAGE_GLESv2 + "gles3" CMAKE_DISABLE_FIND_PACKAGE_GLESv3 + "fontconfig" CMAKE_DISABLE_FIND_PACKAGE_Fontconfig + #"freetype" CMAKE_DISABLE_FIND_PACKAGE_WrapSystemFreetype # Bug in qt cannot be deactivated + "harfbuzz" CMAKE_DISABLE_FIND_PACKAGE_WrapSystemHarfbuzz + "jpeg" CMAKE_DISABLE_FIND_PACKAGE_JPEG + #"png" CMAKE_DISABLE_FIND_PACKAGE_PNG # Unable to disable if Freetype requires it + "xlib" CMAKE_DISABLE_FIND_PACKAGE_X11 + "xkb" CMAKE_DISABLE_FIND_PACKAGE_XKB + "xcb" CMAKE_DISABLE_FIND_PACKAGE_XCB + "xcb-xlib" CMAKE_DISABLE_FIND_PACKAGE_X11_XCB + "xkbcommon-x11" CMAKE_DISABLE_FIND_PACKAGE_XKB_COMMON_X11 + "xrender" CMAKE_DISABLE_FIND_PACKAGE_XRender + # There are more X features but I am unsure how to safely disable them! Most of them seem to be found automaticall with find_package(X11) + ) + +if("gles2" IN_LIST FEATURES) + list(APPEND FEATURE_GUI_OPTIONS -DINPUT_opengl='es2') + list(APPEND FEATURE_GUI_OPTIONS -DFEATURE_opengl_desktop=OFF) +endif() + +if(NOT "opengl" IN_LIST FEATURES AND NOT "gles2" IN_LIST FEATURES) + list(APPEND FEATURE_GUI_OPTIONS -DINPUT_opengl='no') + list(APPEND FEATURE_GUI_OPTIONS -DFEATURE_opengl_desktop=OFF) + list(APPEND FEATURE_GUI_OPTIONS -DFEATURE_opengl_dynamic=OFF) +endif() + +if("xcb" IN_LIST FEATURES) + list(APPEND FEATURE_GUI_OPTIONS -DINPUT_xcb=yes) +else() + list(APPEND FEATURE_GUI_OPTIONS -DINPUT_xcb=no) +endif() +if("xkb" IN_LIST FEATURES) + list(APPEND FEATURE_GUI_OPTIONS -DINPUT_xkbcommon=yes) +else() + list(APPEND FEATURE_GUI_OPTIONS -DINPUT_xkbcommon=no) +endif() + +# Disable OpenGL ES 3.1 and 3.2 +list(APPEND FEATURE_GUI_OPTIONS -DFEATURE_opengles31:BOOL=OFF) +list(APPEND FEATURE_GUI_OPTIONS -DFEATURE_opengles32:BOOL=OFF) + +list(APPEND FEATURE_GUI_OPTIONS -DCMAKE_DISABLE_FIND_PACKAGE_ATSPI2:BOOL=ON) +list(APPEND FEATURE_GUI_OPTIONS -DCMAKE_DISABLE_FIND_PACKAGE_DirectFB:BOOL=ON) +list(APPEND FEATURE_GUI_OPTIONS -DCMAKE_DISABLE_FIND_PACKAGE_Libdrm:BOOL=ON) +list(APPEND FEATURE_GUI_OPTIONS -DCMAKE_DISABLE_FIND_PACKAGE_gbm:BOOL=ON) +list(APPEND FEATURE_GUI_OPTIONS -DCMAKE_DISABLE_FIND_PACKAGE_Libinput:BOOL=ON) +list(APPEND FEATURE_GUI_OPTIONS -DCMAKE_DISABLE_FIND_PACKAGE_Mtdev:BOOL=ON) +list(APPEND FEATURE_GUI_OPTIONS -DCMAKE_DISABLE_FIND_PACKAGE_Tslib:BOOL=ON) +# sql-drivers features: + +vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_SQLDRIVERS_OPTIONS + FEATURES + "sql-sqlite" FEATURE_system_sqlite + "sql-odbc" FEATURE_sql_odbc + "sql-mysql" FEATURE_sql_mysql + "sql-oci" FEATURE_sql_oci + #"sql-psql" CMAKE_REQUIRE_FIND_PACKAGE_PostgreSQL + #"sql-sqlite" CMAKE_REQUIRE_FIND_PACKAGE_SQLite3 + INVERTED_FEATURES + "sql-psql" CMAKE_DISABLE_FIND_PACKAGE_PostgreSQL + "sql-sqlite" CMAKE_DISABLE_FIND_PACKAGE_SQLite3 + "sql-odbc" CMAKE_DISABLE_FIND_PACKAGE_ODBC + "sql-mysql" CMAKE_DISABLE_FIND_PACKAGE_MySQL + "sql-oci" CMAKE_DISABLE_FIND_PACKAGE_Oracle + ) + +set(DB_LIST DB2 Interbase Mimer) +foreach(_db IN LISTS DB_LIST) + list(APPEND FEATURE_SQLDRIVERS_OPTIONS -DCMAKE_DISABLE_FIND_PACKAGE_${_db}:BOOL=ON) +endforeach() + +# printsupport features: +vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_PRINTSUPPORT_OPTIONS + FEATURES + "cups" FEATURE_cups + INVERTED_FEATURES + "cups" CMAKE_DISABLE_FIND_PACKAGE_Cups +) + + +vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_WIDGETS_OPTIONS + FEATURES + "gtk3" FEATURE_gtk3 + INVERTED_FEATURES + "gtk3" CMAKE_DISABLE_FIND_PACKAGE_GTK3 +) + +set(TOOL_NAMES + androiddeployqt + androidtestrunner + cmake_automoc_parser + moc + qdbuscpp2xml + qdbusxml2cpp + qlalr + qmake + qmake6 + qvkgen + rcc + tracegen + uic + qtpaths + qtpaths6 + windeployqt + windeployqt6 + macdeployqt + macdeployqt6 + androiddeployqt6 + syncqt + tracepointgen + ) + +qt_install_submodule(PATCHES ${${PORT}_PATCHES} + TOOL_NAMES ${TOOL_NAMES} + CONFIGURE_OPTIONS + #--trace-expand + ${FEATURE_OPTIONS} + ${FEATURE_CORE_OPTIONS} + ${FEATURE_NET_OPTIONS} + ${FEATURE_GUI_OPTIONS} + ${FEATURE_SQLDRIVERS_OPTIONS} + ${FEATURE_PRINTSUPPORT_OPTIONS} + ${FEATURE_WIDGETS_OPTIONS} + ${INPUT_OPTIONS} + -DQT_USE_BUNDLED_BundledFreetype:BOOL=FALSE + -DQT_USE_BUNDLED_BundledHarfbuzz:BOOL=FALSE + -DQT_USE_BUNDLED_BundledLibpng:BOOL=FALSE + -DQT_USE_BUNDLED_BundledPcre2:BOOL=FALSE + -DINPUT_bundled_xcb_xinput:STRING=no + -DFEATURE_force_debug_info:BOOL=ON + -DFEATURE_relocatable:BOOL=ON + -DQT_AUTODETECT_ANDROID:BOOL=ON # Use vcpkg toolchain as is + CONFIGURE_OPTIONS_RELEASE + CONFIGURE_OPTIONS_DEBUG + -DFEATURE_debug:BOOL=ON + CONFIGURE_OPTIONS_MAYBE_UNUSED + FEATURE_appstore_compliant # only used for android/ios + QT_AUTODETECT_ANDROID + ) + +# Install CMake helper scripts +file(COPY + "${CMAKE_CURRENT_LIST_DIR}/cmake/" + DESTINATION + "${CURRENT_PACKAGES_DIR}/share/${PORT}" + ) + +file(CONFIGURE OUTPUT "${CURRENT_PACKAGES_DIR}/share/${PORT}/port_status.cmake" CONTENT "set(qtbase_with_icu ${FEATURE_icu})\n") + +set(other_files qt-cmake + qt-cmake-create + qt-cmake-private + qt-cmake-standalone-test + qt-configure-module + qt-internal-configure-tests + qt-cmake-create + qt-internal-configure-examples + qt-internal-configure-tests + qmake + qmake6 + qtpaths + qtpaths6 +) + +if(CMAKE_HOST_WIN32) + set(script_suffix ".bat") +else() + set(script_suffix "") +endif() +list(TRANSFORM other_files APPEND "${script_suffix}") + +list(APPEND other_files + android_cmakelist_patcher.sh + android_emulator_launcher.sh + ensure_pro_file.cmake + qt-android-runner.py + qt-cmake-private-install.cmake + qt-testrunner.py + qt-wasmtestrunner.py + sanitizer-testrunner.py + syncqt.pl + target_qt.conf +) + +foreach(_config debug release) + if(_config MATCHES "debug") + set(path_suffix debug/) + else() + set(path_suffix) + endif() + if(NOT EXISTS "${CURRENT_PACKAGES_DIR}/${path_suffix}bin") + continue() + endif() + file(MAKE_DIRECTORY "${CURRENT_PACKAGES_DIR}/tools/Qt6/bin/${path_suffix}") + foreach(other_file IN LISTS other_files) + if(EXISTS "${CURRENT_PACKAGES_DIR}/${path_suffix}bin/${other_file}") + set(target_file "${CURRENT_PACKAGES_DIR}/tools/Qt6/bin/${path_suffix}${other_file}") + file(RENAME "${CURRENT_PACKAGES_DIR}/${path_suffix}bin/${other_file}" "${target_file}") + file(READ "${target_file}" _contents) + if(_config MATCHES "debug") + string(REPLACE "..\\share\\" "..\\..\\..\\..\\share\\" _contents "${_contents}") + string(REPLACE "../share/" "../../../../share/" _contents "${_contents}") + else() + string(REPLACE "..\\share\\" "..\\..\\..\\share\\" _contents "${_contents}") + string(REPLACE "../share/" "../../../share/" _contents "${_contents}") + endif() + string(REGEX REPLACE "set cmake_path=[^\n]+\n" "set cmake_path=cmake\n" _contents "${_contents}") + string(REGEX REPLACE "original_cmake_path=[^\n]+\n" "original_cmake_path=does-not-exist\n" _contents "${_contents}") + file(WRITE "${target_file}" "${_contents}") + endif() + endforeach() +endforeach() +if(VCPKG_CROSSCOMPILING AND NOT CMAKE_HOST_WIN32) + foreach(name IN ITEMS qmake qmake6 qtpaths qtpaths6) + vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/tools/Qt6/bin/${name}" "${CURRENT_HOST_INSTALLED_DIR}/" "\"\$script_dir_path\"/../../../../${HOST_TRIPLET}/") + endforeach() +endif() + +# Fixup qt.toolchain.cmake +set(qttoolchain "${CURRENT_PACKAGES_DIR}/share/Qt6/qt.toolchain.cmake") +file(READ "${qttoolchain}" toolchain_contents) +string(REGEX REPLACE "set\\\(__qt_initially_configured_toolchain_file [^\\\n]+\\\n" "" toolchain_contents "${toolchain_contents}") +string(REGEX REPLACE "set\\\(__qt_chainload_toolchain_file [^\\\n]+\\\n" "set(__qt_chainload_toolchain_file \"\${VCPKG_CHAINLOAD_TOOLCHAIN_FILE}\")" toolchain_contents "${toolchain_contents}") +string(REGEX REPLACE "set\\\(VCPKG_CHAINLOAD_TOOLCHAIN_FILE [^\\\n]+\\\n" "" toolchain_contents "${toolchain_contents}") +string(REGEX REPLACE "set\\\(__qt_initial_c_compiler [^\\\n]+\\\n" "" toolchain_contents "${toolchain_contents}") +string(REGEX REPLACE "set\\\(__qt_initial_cxx_compiler [^\\\n]+\\\n" "" toolchain_contents "${toolchain_contents}") +string(REPLACE "${CURRENT_HOST_INSTALLED_DIR}" "\${vcpkg_installed_dir}/${HOST_TRIPLET}" toolchain_contents "${toolchain_contents}") +file(WRITE "${qttoolchain}" "${toolchain_contents}") + +if(VCPKG_LIBRARY_LINKAGE STREQUAL "static" OR NOT VCPKG_TARGET_IS_WINDOWS) + if(VCPKG_CROSSCOMPILING) + file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/bin/qmake" "${CURRENT_PACKAGES_DIR}/debug/bin/qmake") # qmake has been moved so this is the qmake helper script + endif() + file(GLOB_RECURSE _bin_files "${CURRENT_PACKAGES_DIR}/bin/*") + if(NOT _bin_files) # Only clean if empty otherwise let vcpkg throw and error. + file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/bin/" "${CURRENT_PACKAGES_DIR}/debug/bin/") + else() + message(STATUS "Files in '/bin':${_bin_files}") + endif() +endif() + +file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/share/Qt6/QtBuildInternals") + +if(NOT VCPKG_TARGET_IS_OSX) + file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/share/Qt6/macos") +endif() +if(NOT VCPKG_TARGET_IS_IOS) + file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/share/Qt6/ios") +endif() + +file(RELATIVE_PATH installed_to_host "${CURRENT_INSTALLED_DIR}" "${CURRENT_HOST_INSTALLED_DIR}") +file(RELATIVE_PATH host_to_installed "${CURRENT_HOST_INSTALLED_DIR}" "${CURRENT_INSTALLED_DIR}") +if(installed_to_host) + string(APPEND installed_to_host "/") + string(APPEND host_to_installed "/") +endif() +set(_file "${CMAKE_CURRENT_LIST_DIR}/qt.conf.in") +set(REL_PATH "") +set(REL_HOST_TO_DATA "\${CURRENT_INSTALLED_DIR}/") +configure_file("${_file}" "${CURRENT_PACKAGES_DIR}/tools/Qt6/qt_release.conf" @ONLY) # For vcpkg-qmake +set(BACKUP_CURRENT_INSTALLED_DIR "${CURRENT_INSTALLED_DIR}") +set(BACKUP_CURRENT_HOST_INSTALLED_DIR "${CURRENT_HOST_INSTALLED_DIR}") +set(CURRENT_INSTALLED_DIR "./../../../") +set(CURRENT_HOST_INSTALLED_DIR "${CURRENT_INSTALLED_DIR}${installed_to_host}") + +## Configure installed qt.conf +set(REL_HOST_TO_DATA "${host_to_installed}") +configure_file("${_file}" "${CURRENT_PACKAGES_DIR}/tools/Qt6/bin/qt.conf") +set(REL_PATH debug/) +configure_file("${_file}" "${CURRENT_PACKAGES_DIR}/tools/Qt6/bin/qt.debug.conf") + +set(CURRENT_INSTALLED_DIR "${BACKUP_CURRENT_INSTALLED_DIR}") +set(CURRENT_HOST_INSTALLED_DIR "${BACKUP_CURRENT_HOST_INSTALLED_DIR}") +set(REL_HOST_TO_DATA "\${CURRENT_INSTALLED_DIR}/") +configure_file("${_file}" "${CURRENT_PACKAGES_DIR}/tools/Qt6/qt_debug.conf" @ONLY) # For vcpkg-qmake + +set(target_qt_conf "${CURRENT_PACKAGES_DIR}/tools/Qt6/bin/target_qt.conf") +if(EXISTS "${target_qt_conf}") + file(READ "${target_qt_conf}" qt_conf_contents) + string(REGEX REPLACE "Prefix=[^\n]+" "Prefix=./../../../" qt_conf_contents ${qt_conf_contents}) + string(REGEX REPLACE "HostData=[^\n]+" "HostData=./../${TARGET_TRIPLET}/share/Qt6" qt_conf_contents ${qt_conf_contents}) + string(REGEX REPLACE "HostPrefix=[^\n]+" "HostPrefix=./../../../../${_HOST_TRIPLET}" qt_conf_contents ${qt_conf_contents}) + file(WRITE "${target_qt_conf}" "${qt_conf_contents}") + if(NOT VCPKG_BUILD_TYPE) + set(target_qt_conf_debug "${CURRENT_PACKAGES_DIR}/tools/Qt6/target_qt_debug.conf") + configure_file("${target_qt_conf}" "${target_qt_conf_debug}" COPYONLY) + file(READ "${target_qt_conf_debug}" qt_conf_contents) + string(REGEX REPLACE "=(bin|lib|Qt6/plugins|Qt6/qml)" "=debug/\\1" qt_conf_contents ${qt_conf_contents}) + file(WRITE "${target_qt_conf_debug}" "${qt_conf_contents}") + + configure_file("${CURRENT_PACKAGES_DIR}/tools/Qt6/bin/qmake${script_suffix}" "${CURRENT_PACKAGES_DIR}/tools/Qt6/bin/qmake.debug${script_suffix}" COPYONLY) + vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/tools/Qt6/bin/qmake.debug${script_suffix}" "target_qt.conf" "target_qt_debug.conf") + endif() +endif() + +if(VCPKG_TARGET_IS_ANDROID) + vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/share/Qt6Core/Qt6AndroidMacros.cmake" + [[ set(cmake_dir "${prefix_path}/${${export_namespace_upper}_INSTALL_LIBS}/cmake")]] + [[ set(cmake_dir "${prefix_path}/share")]] + ) +endif() + +if(VCPKG_TARGET_IS_EMSCRIPTEN) + vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/share/Qt6Core/Qt6WasmMacros.cmake" "_qt_test_emscripten_version()" "") # this is missing a include(QtPublicWasmToolchainHelpers) +endif() + +if(VCPKG_TARGET_IS_WINDOWS) + set(_DLL_FILES brotlicommon brotlidec bz2 freetype harfbuzz libpng16) + set(DLLS_TO_COPY "") + foreach(_file IN LISTS _DLL_FILES) + if(EXISTS "${CURRENT_INSTALLED_DIR}/bin/${_file}.dll") + list(APPEND DLLS_TO_COPY "${CURRENT_INSTALLED_DIR}/bin/${_file}.dll") + endif() + endforeach() + file(COPY ${DLLS_TO_COPY} DESTINATION "${CURRENT_PACKAGES_DIR}/tools/Qt6/bin") +endif() + +set(hostinfofile "${CURRENT_PACKAGES_DIR}/share/Qt6HostInfo/Qt6HostInfoConfig.cmake") +file(READ "${hostinfofile}" _contents) +string(REPLACE [[set(QT6_HOST_INFO_LIBEXECDIR "bin")]] [[set(QT6_HOST_INFO_LIBEXECDIR "tools/Qt6/bin")]] _contents "${_contents}") +string(REPLACE [[set(QT6_HOST_INFO_BINDIR "bin")]] [[set(QT6_HOST_INFO_BINDIR "tools/Qt6/bin")]] _contents "${_contents}") +file(WRITE "${hostinfofile}" "${_contents}") + +if(NOT VCPKG_CROSSCOMPILING OR EXISTS "${CURRENT_PACKAGES_DIR}/share/Qt6CoreTools/Qt6CoreToolsAdditionalTargetInfo.cmake") + vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/share/Qt6CoreTools/Qt6CoreToolsAdditionalTargetInfo.cmake" + "CMAKE_CURRENT_LIST_DIR}/../../bin/syncqt" + "CMAKE_CURRENT_LIST_DIR}/../../tools/Qt6/bin/syncqt" + IGNORE_UNCHANGED) +endif() + +set(configfile "${CURRENT_PACKAGES_DIR}/share/Qt6CoreTools/Qt6CoreToolsTargets-debug.cmake") +if(EXISTS "${configfile}") + file(READ "${configfile}" _contents) + if(EXISTS "${CURRENT_PACKAGES_DIR}/tools/Qt6/bin/qmake.exe") + file(INSTALL "${CMAKE_CURRENT_LIST_DIR}/qmake.debug.bat" DESTINATION "${CURRENT_PACKAGES_DIR}/tools/Qt6/bin") + string(REPLACE [[ "${_IMPORT_PREFIX}/tools/Qt6/bin/qmake.exe"]] [[ "${_IMPORT_PREFIX}/tools/Qt6/bin/qmake.debug.bat"]] _contents "${_contents}") + endif() + if(EXISTS "${CURRENT_PACKAGES_DIR}/tools/Qt6/bin/qtpaths.exe") + file(INSTALL "${CMAKE_CURRENT_LIST_DIR}/qtpaths.debug.bat" DESTINATION "${CURRENT_PACKAGES_DIR}/tools/Qt6/bin") + string(REPLACE [[ "${_IMPORT_PREFIX}/tools/Qt6/bin/qtpaths.exe"]] [[ "${_IMPORT_PREFIX}/tools/Qt6/bin/qtpaths.debug.bat"]] _contents "${_contents}") + endif() + if(EXISTS "${CURRENT_PACKAGES_DIR}/tools/Qt6/bin/windeployqt.exe") + file(INSTALL "${CMAKE_CURRENT_LIST_DIR}/windeployqt.debug.bat" DESTINATION "${CURRENT_PACKAGES_DIR}/tools/Qt6/bin") + string(REPLACE [[ "${_IMPORT_PREFIX}/tools/Qt6/bin/windeployqt.exe"]] [[ "${_IMPORT_PREFIX}/tools/Qt6/bin/windeployqt.debug.bat"]] _contents "${_contents}") + endif() + file(WRITE "${configfile}" "${_contents}") +endif() + +if(VCPKG_CROSSCOMPILING) + vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/share/Qt6/Qt6Dependencies.cmake" "${CURRENT_HOST_INSTALLED_DIR}" "\${CMAKE_CURRENT_LIST_DIR}/../../../${HOST_TRIPLET}") +endif() + +function(remove_original_cmake_path file) + file(READ "${file}" _contents) + string(REGEX REPLACE "original_cmake_path=[^\n]*" "original_cmake_path=''" _contents "${_contents}") + file(WRITE "${file}" "${_contents}") +endfunction() + +if(NOT VCPKG_TARGET_IS_WINDOWS AND NOT CMAKE_HOST_WIN32) + foreach(file "qt-cmake${script_suffix}" "qt-cmake-private${script_suffix}") + remove_original_cmake_path("${CURRENT_PACKAGES_DIR}/tools/Qt6/bin/${file}") + if(NOT VCPKG_BUILD_TYPE) + remove_original_cmake_path("${CURRENT_PACKAGES_DIR}/tools/Qt6/bin/debug/${file}") + endif() + endforeach() +endif() + +if(VCPKG_TARGET_IS_WINDOWS) + # dlls owned but not automatically installed by qtbase + # this is required to avoid ownership troubles in downstream qt modules + set(qtbase_owned_dlls + double-conversion.dll + icudt74.dll + icuin74.dll + icuuc74.dll + libcrypto-3-${VCPKG_TARGET_ARCHITECTURE}.dll + libcrypto-3.dll # for x86 + pcre2-16.dll + zlib1.dll + zstd.dll + ) + if("dbus" IN_LIST FEATURES) + list(APPEND qtbase_owned_dlls dbus-1-3.dll) + endif() + list(TRANSFORM qtbase_owned_dlls PREPEND "${CURRENT_INSTALLED_DIR}/bin/") + foreach(dll IN LISTS qtbase_owned_dlls) + if(NOT EXISTS "${dll}") # Need to remove non-existant dlls since dependencies could have been build statically + list(REMOVE_ITEM qtbase_owned_dlls "${dll}") + endif() + endforeach() + file(COPY ${qtbase_owned_dlls} DESTINATION "${CURRENT_PACKAGES_DIR}/tools/Qt6/bin") +endif() diff --git a/vcpkg/ports/qtbase/qmake.debug.bat b/vcpkg/ports/qtbase/qmake.debug.bat new file mode 100644 index 000000000000..a7ed903a342f --- /dev/null +++ b/vcpkg/ports/qtbase/qmake.debug.bat @@ -0,0 +1,2 @@ +@echo off +"%0\..\qmake.exe" -qtconf "%0\..\qt.debug.conf" %* diff --git a/vcpkg/ports/qtbase/qt.conf.in b/vcpkg/ports/qtbase/qt.conf.in new file mode 100644 index 000000000000..8e76b8f6d343 --- /dev/null +++ b/vcpkg/ports/qtbase/qt.conf.in @@ -0,0 +1,31 @@ +[DevicePaths] +Prefix=${CURRENT_INSTALLED_DIR} +Headers=include/@QT6_DIRECTORY_PREFIX@ +Libraries=@REL_PATH@lib +Plugins=@REL_PATH@@QT6_DIRECTORY_PREFIX@plugins +Qml2Imports=@REL_PATH@@QT6_DIRECTORY_PREFIX@qml +Documentation=doc/@QT6_DIRECTORY_PREFIX@ +Binaries=@REL_PATH@bin +LibraryExecutables=tools/Qt6/bin +ArchData=share/Qt6 +Data=share/Qt6 +Translations=translations/@QT6_DIRECTORY_PREFIX@ +Examples=share/examples/@QT6_DIRECTORY_PREFIX@ +[Paths] +Prefix=${CURRENT_INSTALLED_DIR} +Headers=include/@QT6_DIRECTORY_PREFIX@ +Libraries=@REL_PATH@lib +Plugins=@REL_PATH@@QT6_DIRECTORY_PREFIX@plugins +Qml2Imports=@REL_PATH@@QT6_DIRECTORY_PREFIX@qml +Documentation=doc/@QT6_DIRECTORY_PREFIX@ +Binaries=@REL_PATH@bin +LibraryExecutables=tools/Qt6/bin +ArchData=share/Qt6 +Data=share/Qt6 +Translations=translations/@QT6_DIRECTORY_PREFIX@ +Examples=share/examples/@QT6_DIRECTORY_PREFIX@ +HostPrefix=${CURRENT_HOST_INSTALLED_DIR} +HostData=@REL_HOST_TO_DATA@share/Qt6 +HostBinaries=@REL_PATH@bin +HostLibraries=@REL_PATH@lib +HostLibraryExecutables=tools/Qt6/bin diff --git a/vcpkg/ports/qtbase/qtpaths.debug.bat b/vcpkg/ports/qtbase/qtpaths.debug.bat new file mode 100644 index 000000000000..4fef8e754ebe --- /dev/null +++ b/vcpkg/ports/qtbase/qtpaths.debug.bat @@ -0,0 +1,2 @@ +@echo off +"%0\..\qtpaths.exe" --qtconf "%0\..\qt.debug.conf" %* diff --git a/vcpkg/ports/qtbase/use-shared-mime-info.patch b/vcpkg/ports/qtbase/use-shared-mime-info.patch new file mode 100644 index 000000000000..3bd2724f1883 --- /dev/null +++ b/vcpkg/ports/qtbase/use-shared-mime-info.patch @@ -0,0 +1,31 @@ + src/corelib/mimetypes/mimetypes_resources.cmake | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/corelib/mimetypes/mimetypes_resources.cmake b/src/corelib/mimetypes/mimetypes_resources.cmake +index 1bec50e4..d4d54763 100644 +--- a/src/corelib/mimetypes/mimetypes_resources.cmake ++++ b/src/corelib/mimetypes/mimetypes_resources.cmake +@@ -7,17 +7,17 @@ + # file with the same information + + set(corelib_mimetypes_resource_file +- "${CMAKE_CURRENT_LIST_DIR}/3rdparty/tika-mimetypes.xml" ++ "${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/share/mime/packages/freedesktop.org.xml" + ) + + function(corelib_add_mimetypes_resources target) + set(source_file "${corelib_mimetypes_resource_file}") + set_source_files_properties("${source_file}" +- PROPERTIES QT_RESOURCE_ALIAS "tika-mimetypes.xml" ++ PROPERTIES QT_RESOURCE_ALIAS "freedesktop.org.xml" + ) + qt_internal_add_resource(${target} "mimetypes" + PREFIX +- "/qt-project.org/qmime/tika/packages" ++ "/qt-project.org/qmime/packages" + FILES + "${source_file}" + ) +-- +2.34.1 + diff --git a/vcpkg/ports/qtbase/vcpkg.json b/vcpkg/ports/qtbase/vcpkg.json new file mode 100644 index 000000000000..9837650b777d --- /dev/null +++ b/vcpkg/ports/qtbase/vcpkg.json @@ -0,0 +1,594 @@ +{ + "name": "qtbase", + "version": "6.8.3", + "port-version": 3, + "description": "Qt Base (Core, Gui, Widgets, Network, ...)", + "homepage": "https://www.qt.io/", + "license": null, + "supports": "!uwp", + "dependencies": [ + { + "name": "libb2", + "platform": "!windows" + }, + { + "name": "pcre2", + "default-features": false + }, + { + "name": "qtbase", + "host": true, + "default-features": false + }, + { + "name": "qtbase", + "default-features": false, + "features": [ + "doubleconversion" + ] + }, + { + "name": "qtbase", + "default-features": false, + "features": [ + "cups", + "thread" + ], + "platform": "osx" + }, + { + "name": "qtbase", + "default-features": false, + "features": [ + "concurrent", + "thread" + ], + "platform": "android" + }, + { + "name": "qtbase", + "default-features": false, + "features": [ + "pcre2" + ], + "platform": "windows & static" + }, + { + "name": "vcpkg-cmake", + "host": true + }, + { + "name": "vcpkg-cmake-config", + "host": true + }, + "zlib" + ], + "default-features": [ + { + "name": "appstore-compliant", + "platform": "uwp" + }, + "brotli", + "concurrent", + { + "name": "dbus", + "platform": "!(static & windows) & !android" + }, + "dnslookup", + "doubleconversion", + { + "name": "egl", + "platform": "linux" + }, + { + "name": "egl", + "platform": "android" + }, + { + "name": "fontconfig", + "platform": "linux" + }, + "freetype", + { + "name": "gles2", + "platform": "android" + }, + "gui", + "harfbuzz", + "icu", + "jpeg", + "network", + { + "name": "opengl", + "platform": "!ios" + }, + { + "name": "openssl", + "platform": "!ios" + }, + "pcre2", + "png", + { + "name": "securetransport", + "platform": "ios" + }, + "sql", + "sql-psql", + "sql-sqlite", + "testlib", + "thread", + "widgets", + { + "name": "xcb", + "platform": "linux" + }, + { + "name": "xcb-xlib", + "platform": "linux" + }, + { + "name": "xrender", + "platform": "linux" + }, + "zstd" + ], + "features": { + "appstore-compliant": { + "description": "Disable code that is not allowed in platform app stores. This is on by default for platforms which require distribution through an app store by default, in particular Android, iOS, tvOS, and watchOS." + }, + "brotli": { + "description": "Support for downloading and decompressing resources compressed with Brotli through QNetworkAccessManager.", + "dependencies": [ + "brotli", + { + "name": "qtbase", + "default-features": false, + "features": [ + "network" + ] + } + ] + }, + "concurrent": { + "description": "Provides a high-level multi-threading API. Qt Concurrent", + "dependencies": [ + { + "name": "qtbase", + "default-features": false, + "features": [ + "thread" + ] + } + ] + }, + "cups": { + "description": "Provides support for the Common Unix Printing System.", + "supports": "linux | osx" + }, + "dbus": { + "description": "Qt D-Bus", + "dependencies": [ + { + "name": "dbus", + "default-features": false + }, + { + "name": "qtbase", + "host": true, + "default-features": false, + "features": [ + "dbus" + ] + }, + { + "name": "qtbase", + "default-features": false, + "features": [ + "thread" + ] + } + ] + }, + "dnslookup": { + "description": "Enable DNS lookup support", + "dependencies": [ + { + "name": "qtbase", + "default-features": false, + "features": [ + "network", + "thread" + ] + } + ] + }, + "doubleconversion": { + "description": "Enable double conversion support", + "dependencies": [ + "double-conversion" + ] + }, + "egl": { + "description": "EGL", + "supports": "android | linux", + "dependencies": [ + "egl" + ] + }, + "fontconfig": { + "description": "Use fontconfig", + "supports": "!osx & !windows", + "dependencies": [ + "fontconfig", + { + "name": "qtbase", + "default-features": false, + "features": [ + "freetype", + "gui" + ] + } + ] + }, + "framework": { + "description": "MAC framework build", + "supports": "osx & !static" + }, + "freetype": { + "description": "Supports the FreeType 2 font engine (and its supported font formats).", + "dependencies": [ + { + "name": "freetype", + "default-features": false + } + ] + }, + "gles2": { + "description": "OpenGL ES 2.0", + "supports": "!windows & !osx", + "dependencies": [ + { + "name": "qtbase", + "default-features": false, + "features": [ + "gui" + ] + } + ] + }, + "gles3": { + "description": "OpenGL ES 3.0", + "supports": "!windows & !osx", + "dependencies": [ + { + "name": "qtbase", + "default-features": false, + "features": [ + "gles2" + ] + } + ] + }, + "glib": { + "description": "GLib", + "dependencies": [ + "glib" + ] + }, + "gtk3": { + "description": "GTK3 platform theme plugin", + "supports": "linux", + "dependencies": [ + "gtk3", + { + "name": "qtbase", + "default-features": false, + "features": [ + "glib" + ] + } + ] + }, + "gui": { + "description": "Qt Gui", + "dependencies": [ + { + "name": "opengl", + "platform": "!ios" + }, + { + "name": "qtbase", + "default-features": false, + "features": [ + "freetype" + ] + }, + { + "name": "qtbase", + "default-features": false, + "features": [ + "opengl" + ], + "platform": "osx" + }, + { + "name": "qtbase", + "default-features": false, + "features": [ + "egl", + "gles2", + "opengl" + ], + "platform": "android" + }, + { + "name": "qtbase", + "default-features": false, + "features": [ + "thread" + ], + "platform": "windows" + } + ] + }, + "harfbuzz": { + "description": "Use harfbuzz", + "dependencies": [ + "harfbuzz", + { + "name": "qtbase", + "default-features": false, + "features": [ + "gui" + ] + } + ] + }, + "icu": { + "description": "Enable ICU support", + "dependencies": [ + "icu" + ] + }, + "jpeg": { + "description": "Enable JPEG", + "dependencies": [ + "libjpeg-turbo", + { + "name": "qtbase", + "default-features": false, + "features": [ + "gui" + ] + } + ] + }, + "network": { + "description": "Qt Network" + }, + "opengl": { + "description": "OpenGL", + "dependencies": [ + "opengl", + { + "name": "qtbase", + "default-features": false, + "features": [ + "gui" + ] + } + ] + }, + "openssl": { + "description": "Enable OpenSSL", + "dependencies": [ + "openssl", + { + "name": "qtbase", + "default-features": false, + "features": [ + "network" + ] + } + ] + }, + "pcre2": { + "description": "Enable PCRE2 support", + "dependencies": [ + { + "name": "pcre2", + "default-features": false + } + ] + }, + "png": { + "description": "Enable PNG", + "dependencies": [ + "libpng", + { + "name": "qtbase", + "default-features": false, + "features": [ + "gui" + ] + } + ] + }, + "securetransport": { + "description": "Enable Secure Transport", + "supports": "ios | osx" + }, + "shared-mime-info": { + "description": "Use GPL licensed shared-mime-info port from freedesktop.org", + "dependencies": [ + "shared-mime-info" + ] + }, + "sql": { + "description": "Qt Sql", + "dependencies": [ + { + "name": "qtbase", + "default-features": false, + "features": [ + "concurrent" + ] + } + ] + }, + "sql-mysql": { + "description": "Enable SQL Driver MySQL", + "dependencies": [ + "libmysql", + { + "name": "qtbase", + "default-features": false, + "features": [ + "sql" + ] + } + ] + }, + "sql-oci": { + "description": "Enable SQL Driver Oracle OCI", + "dependencies": [ + "ocilib", + { + "name": "qtbase", + "default-features": false, + "features": [ + "sql" + ] + } + ] + }, + "sql-odbc": { + "description": "Enable SQL Driver odbc", + "dependencies": [ + { + "name": "qtbase", + "default-features": false, + "features": [ + "sql" + ] + }, + { + "name": "unixodbc", + "platform": "!windows" + } + ] + }, + "sql-psql": { + "description": "Enable SQL Driver psql", + "dependencies": [ + "libpq", + { + "name": "qtbase", + "default-features": false, + "features": [ + "sql" + ] + } + ] + }, + "sql-sqlite": { + "description": "Enable SQL Driver sqlite", + "dependencies": [ + { + "name": "qtbase", + "default-features": false, + "features": [ + "sql" + ] + }, + "sqlite3" + ] + }, + "testlib": { + "description": "Qt Testlib" + }, + "thread": { + "description": "Thread support; provides QThread and related classes." + }, + "vulkan": { + "description": "Enable Vulkan support", + "dependencies": [ + "vulkan" + ] + }, + "widgets": { + "description": "Qt Widgets", + "dependencies": [ + { + "name": "qtbase", + "default-features": false, + "features": [ + "gui" + ] + } + ] + }, + "xcb": { + "description": "XCB", + "dependencies": [ + { + "name": "qtbase", + "default-features": false, + "features": [ + "concurrent", + "xkbcommon-x11", + "xlib" + ] + } + ] + }, + "xcb-xlib": { + "description": "xcb-xlib", + "dependencies": [ + { + "name": "qtbase", + "default-features": false, + "features": [ + "xlib" + ] + } + ] + }, + "xkb": { + "description": "XKB" + }, + "xkbcommon-x11": { + "description": "xkbcommon_x11", + "dependencies": [ + { + "name": "qtbase", + "default-features": false, + "features": [ + "xkb" + ] + } + ] + }, + "xlib": { + "description": "XLib" + }, + "xrender": { + "description": "XRender for native painting", + "dependencies": [ + { + "name": "qtbase", + "default-features": false, + "features": [ + "xcb" + ] + } + ] + }, + "zstd": { + "description": "Zstandard support", + "dependencies": [ + "zstd" + ] + } + } +} diff --git a/vcpkg/ports/qtbase/windeployqt.debug.bat b/vcpkg/ports/qtbase/windeployqt.debug.bat new file mode 100644 index 000000000000..234bb4383512 --- /dev/null +++ b/vcpkg/ports/qtbase/windeployqt.debug.bat @@ -0,0 +1,10 @@ +@echo off +setlocal enabledelayedexpansion +set mypath=%~dp0 +set mypath=%mypath:~0,-1% +set BAKCD=!CD! +cd /D "%mypath%\..\..\..\debug\bin" +set PATH=!CD!;%PATH% +cd /D "%BAKCD%" +"%mypath%\windeployqt6.exe" --qtpaths "%mypath%\qtpaths.debug.bat" %* +endlocal diff --git a/vcpkg/vcpkg.json b/vcpkg/vcpkg.json index 600ba5b4ccbb..3bece9166077 100644 --- a/vcpkg/vcpkg.json +++ b/vcpkg/vcpkg.json @@ -2,13 +2,13 @@ "vcpkg-configuration": { "default-registry": { "kind": "git", - "baseline": "a9eee3b18df395dbb8be71a31bd78ea441056e42", + "baseline": "f75c836a67777a86a2c1116a28b179827f028b66", "repository": "https://github.com/microsoft/vcpkg" }, "registries": [ { "kind": "git", - "baseline": "461f91ec1125bb2c20aaa28d7456dfd83dbc3eec", + "baseline": "bceab4650d942b31b8d13e484b4096e85546e697", "repository": "https://github.com/open-vcpkg/python-registry", "packages": [ "python3", @@ -33,6 +33,7 @@ "description": "QGIS is a free, open source, cross platform (lin/win/mac) geographical information system (GIS)", "homepage": "https://qgis.org", "dependencies": [ + "duckdb", { "name": "exiv2", "features": [ @@ -43,9 +44,12 @@ { "name": "gdal", "features": [ + "arrow-adbc", "freexl", "kea", - "poppler" + "parquet", + "poppler", + "tools" ] }, "geos", @@ -73,9 +77,16 @@ "ossl" ] }, - "qtbase", + { + "name": "qtbase", + "features": [ + "sql-odbc" + ] + }, + "qtdeclarative", "qtkeychain-qt6", "qtlocation", + "qtquickcontrols2", "qtsvg", "qttools", "zlib" @@ -98,6 +109,7 @@ }, "py-autopep8", "py-dateutil", + "py-duckdb", "py-isort", "py-jinja2", "py-lxml", @@ -105,8 +117,18 @@ "py-numpy", "py-owslib", "py-pip", + "py-psycopg", "py-psycopg2", - "py-pyqt6", + "py-pydantic", + { + "name": "py-pyqt6", + "features": [ + "qt3d", + "qt5compat", + "qtcharts", + "qtdeclarative" + ] + }, "py-pytz", "py-pyyaml", "py-qscintilla", @@ -129,11 +151,10 @@ "opencl" ] }, - "quick": { - "description": "Build the QGIS quick components for mobile interfaces", + "oracle": { + "description": "Build with oracle support", "dependencies": [ - "qtdeclarative", - "qtquickcontrols2" + "oracle-instantclient" ] }, "server": {