├── .clang-format ├── .editorconfig ├── .github └── workflows │ └── build.yml ├── .gitignore ├── .gitmodules ├── .nvmrc ├── .prettierignore ├── .prettierrc.json ├── .vscode ├── c_cpp_properties.json └── settings.json ├── CMakeLists.txt ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── build ├── actions │ ├── clean.ts │ ├── compile.ts │ ├── install.ts │ ├── lib │ │ ├── BuildType.ts │ │ └── QgisJsOptions.ts │ ├── libs.ts │ └── size.ts ├── scripts │ ├── clean.sh │ ├── compile.sh │ └── install.sh ├── vcpkg-ports │ ├── gdal │ │ ├── avoid-getrlimit-warnings.patch │ │ ├── cmake-project-include.cmake │ │ ├── find-link-libraries.patch │ │ ├── fix-gdal-target-interfaces.patch │ │ ├── fix-simd-cpu-features.patch │ │ ├── libkml.patch │ │ ├── portfile.cmake │ │ ├── usage │ │ ├── vcpkg-cmake-wrapper.cmake │ │ ├── vcpkg.json │ │ └── vsicurl-fetch-api.diff │ ├── qca │ │ ├── 0001-fix-path-for-vcpkg.patch │ │ ├── 0002-fix-build-error.patch │ │ ├── 0003-Define-NOMINMAX-for-botan-plugin-with-MSVC.patch │ │ ├── mk-ca-bundle.pl │ │ ├── portfile.cmake │ │ └── vcpkg.json │ ├── qgis-qt6 │ │ ├── 02-exclude-wfs-provider.patch │ │ ├── 03-fix-missing-QTimeZone.patch │ │ ├── 04-fix-missing-QCryptographicHash.patch │ │ ├── 06-GDAL-no-QThread-sleep.patch │ │ ├── 07-fix-QgsArcGisRestQueryUtils-includes.patch │ │ ├── 08-skip-QgsExpression-initFunctionHelp.patch │ │ ├── 09-fix-QgsExpression-Functions.patch │ │ ├── 10-exclude-qgscoordinatereferencesystem_legacy.patch │ │ ├── 11-disable-openedFileLimit.patch │ │ ├── 12-disable-wcs-provider.patch │ │ ├── 13-no-LinguistTools-dep.patch │ │ ├── 14-disable-map_crs_projection.patch │ │ ├── bigobj.patch │ │ ├── crssync.patch │ │ ├── disable-auth-manager.patch │ │ ├── exiv2-0.28.patch │ │ ├── fix-settings-tree.patch │ │ ├── fix-ssl-network-access-manager.patch │ │ ├── gdal.patch │ │ ├── keychain.patch │ │ ├── no-exiv.patch │ │ ├── no-tcp-udp-sensors.patch │ │ ├── no-user-agent-override.patch │ │ ├── portfile.cmake │ │ ├── qt6positioning.patch │ │ └── vcpkg.json │ ├── qtbase │ │ ├── GLIB2-static.patch │ │ ├── allow_outside_prefix.patch │ │ ├── clang-cl_QGADGET_fix.diff │ │ ├── clang-cl_source_location.patch │ │ ├── cmake │ │ │ ├── qt_install_copyright.cmake │ │ │ ├── qt_install_submodule.cmake │ │ │ ├── qt_port_data.cmake │ │ │ └── qt_port_details.cmake │ │ ├── config_install.patch │ │ ├── dont_force_cmakecache_latest.patch │ │ ├── env.patch │ │ ├── fix-host-aliasing.patch │ │ ├── fix_cmake_build.patch │ │ ├── fix_cmake_build_type.patch │ │ ├── fix_egl.patch │ │ ├── fix_egl_2.patch │ │ ├── harfbuzz.patch │ │ ├── installed_dir.patch │ │ ├── patches │ │ │ ├── 0001-CVE-2023-51714-qtbase-6.6.diff │ │ │ └── 0002-CVE-2023-51714-qtbase-6.6.diff │ │ ├── portfile.cmake │ │ ├── qmake.debug.bat │ │ ├── qt.conf.in │ │ ├── qtpaths.debug.bat │ │ ├── vcpkg.json │ │ └── windeployqt.debug.bat │ └── qtkeychain-qt6 │ │ ├── dbus-fix-config.patch │ │ ├── dbus-fix.patch │ │ ├── portfile.cmake │ │ └── vcpkg.json ├── vcpkg-toolchains │ └── qgis-js.cmake ├── vcpkg-triplets │ └── wasm32-emscripten-qt-threads.cmake └── vite │ ├── CrossOriginIsolationPlugin.ts │ ├── DirectoryListingPlugin.ts │ └── QgisRuntimePlugin.ts ├── docs ├── architecture.md ├── bundling.md ├── ci.md ├── compatibility.md ├── debugging.md ├── examples │ ├── qgis-js-example-api │ │ ├── index.html │ │ ├── main.js │ │ ├── package.json │ │ └── vite.config.js │ └── qgis-js-example-ol │ │ ├── index.html │ │ ├── main.js │ │ ├── package.json │ │ ├── style.css │ │ └── vite.config.js ├── performance.md └── profiling.md ├── package.json ├── packages ├── qgis-js-ol │ ├── README.md │ ├── package.json │ ├── src │ │ ├── QgisCanvasDataSource.ts │ │ ├── QgisJobDataSource.ts │ │ ├── QgisXYZDataSource.ts │ │ └── index.ts │ ├── tsconfig.json │ └── vite.config.ts ├── qgis-js-utils │ ├── README.md │ ├── package.json │ ├── src │ │ ├── fs │ │ │ ├── FileSystem.ts │ │ │ ├── GithubProject.ts │ │ │ ├── LocalProject.ts │ │ │ ├── Project.ts │ │ │ ├── RemoteProject.ts │ │ │ └── index.ts │ │ └── index.ts │ ├── tsconfig.json │ └── vite.config.ts └── qgis-js │ ├── README.md │ ├── package.json │ ├── src │ ├── QgisApiAdapter.ts │ ├── emscripten.ts │ ├── index.ts │ ├── loader.ts │ └── runtime.ts │ ├── tsconfig.json │ └── vite.config.ts ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── qgis-js.ts ├── sites ├── dev │ ├── index.html │ ├── package.json │ ├── public │ │ ├── projects │ │ │ └── village │ │ │ │ ├── buildings.dbf │ │ │ │ ├── buildings.prj │ │ │ │ ├── buildings.qpj │ │ │ │ ├── buildings.shp │ │ │ │ ├── buildings.shx │ │ │ │ ├── project.qgs │ │ │ │ └── rgb.tif │ │ └── qgis-icon128.svg │ ├── src │ │ ├── demo.css │ │ ├── index.ts │ │ ├── js.ts │ │ ├── layers.ts │ │ └── ol.ts │ ├── tsconfig.json │ └── vite.config.ts └── performance │ ├── .gitignore │ ├── index.html │ ├── package.json │ ├── playwright.config.ts │ ├── report.html │ ├── src │ └── index.ts │ ├── tests │ └── performance.spec.ts │ ├── tsconfig.json │ └── vite.config.ts ├── src ├── api │ ├── QgisApi.cpp │ ├── QgisApi.ts │ └── QgisModel.ts ├── model │ ├── MapLayer.hpp │ ├── MapLayer.ts │ ├── PointXY.hpp │ ├── PointXY.ts │ ├── QgsMapRendererJob.hpp │ ├── QgsMapRendererJob.ts │ ├── QgsMapRendererParallelJob.hpp │ ├── QgsMapRendererParallelJob.ts │ ├── QgsMapRendererQImageJob.hpp │ ├── QgsMapRendererQImageJob.ts │ ├── Rectangle.hpp │ └── Rectangle.ts └── qgis-js.cpp ├── tsconfig.json └── vcpkg.json /.clang-format: -------------------------------------------------------------------------------- 1 | #see https://clang.llvm.org/docs/ClangFormatStyleOptions.html 2 | Language: Cpp 3 | ColumnLimit: 100 4 | ContinuationIndentWidth: 2 5 | UseTab: Never 6 | IndentWidth: 2 7 | TabWidth: 2 8 | IndentCaseLabels: true 9 | IncludeBlocks: Preserve 10 | SortIncludes: true 11 | SortUsingDeclarations: false 12 | AlignConsecutiveMacros: false 13 | AlignEscapedNewlines: DontAlign 14 | AlignAfterOpenBracket: AlwaysBreak 15 | AlignOperands: false 16 | AlignTrailingComments: false 17 | BinPackArguments: false 18 | BinPackParameters: false 19 | SpacesInContainerLiterals: false 20 | Cpp11BracedListStyle: true 21 | AllowShortFunctionsOnASingleLine: Empty 22 | AllowShortIfStatementsOnASingleLine: Always 23 | FixNamespaceComments: false 24 | ReflowComments: false 25 | NamespaceIndentation: All 26 | BreakStringLiterals: false 27 | ConstructorInitializerIndentWidth: 2 28 | SpaceBeforeCtorInitializerColon: true 29 | BreakBeforeInheritanceComma: false 30 | BreakInheritanceList: AfterColon 31 | BreakConstructorInitializersBeforeComma: false 32 | BreakConstructorInitializers: AfterColon 33 | ConstructorInitializerAllOnOneLineOrOnePerLine: true 34 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | workflow_dispatch 5 | # push: 6 | # branches: 7 | # - main 8 | # pull_request: 9 | # branches: 10 | # - main 11 | 12 | permissions: 13 | contents: read 14 | pages: write 15 | id-token: write 16 | 17 | concurrency: 18 | group: "pages" 19 | cancel-in-progress: true 20 | 21 | jobs: 22 | build-qgis-js: 23 | environment: 24 | name: github-pages 25 | url: ${{ steps.deployment.outputs.page_url }} 26 | runs-on: ubuntu-20.04 27 | steps: 28 | - uses: actions/checkout@v4 29 | - name: Set Swap Space 30 | if: ${{ !env.ACT }} 31 | uses: pierotofy/set-swap-space@master 32 | with: 33 | swap-size-gb: 8 34 | - name: Update apt cache 35 | run: >- 36 | sudo apt-get update 37 | - name: Install system dependencies 38 | run: >- 39 | sudo apt-get install -y 40 | ninja-build 41 | pkg-config 42 | flex 43 | bison 44 | - name: Free Disk Space (Ubuntu) 45 | if: ${{ !env.ACT }} 46 | uses: jlumbroso/free-disk-space@main 47 | with: 48 | tool-cache: false 49 | swap-storage: false 50 | - name: Setup node from package.json 51 | uses: actions/setup-node@v4 52 | with: 53 | node-version-file: "package.json" 54 | - uses: pnpm/action-setup@v2 55 | - name: Install dependencies 56 | run: pnpm install 57 | - name: Compile qgis-js 58 | run: pnpm run compile:release 59 | - name: Save logs on failure 60 | if: ${{ failure() }} 61 | uses: actions/upload-artifact@v3 62 | with: 63 | name: vcpkg-buildtrees-logs 64 | path: build/vcpkg/buildtrees/**/*.log 65 | - name: Build qgis-js packages 66 | run: pnpm run build 67 | - uses: actions/upload-artifact@v3 68 | with: 69 | name: "package-qgis-js" 70 | path: | 71 | packages/qgis-js/package.json 72 | packages/qgis-js/README.md 73 | packages/qgis-js/dist/**/* 74 | - uses: actions/upload-artifact@v3 75 | with: 76 | name: "package-qgis-js-utils" 77 | path: | 78 | packages/qgis-js-utils/package.json 79 | packages/qgis-js-utils/README.md 80 | packages/qgis-js-utils/dist/**/* 81 | - uses: actions/upload-artifact@v3 82 | with: 83 | name: "package-qgis-js-ol" 84 | path: | 85 | packages/qgis-js-ol/package.json 86 | packages/qgis-js-ol/README.md 87 | packages/qgis-js-ol/dist/**/* 88 | - name: Build site 89 | run: pnpm run dev:build 90 | - name: Setup Pages 91 | uses: actions/configure-pages@v3 92 | - name: Upload artifact 93 | uses: actions/upload-pages-artifact@v1 94 | with: 95 | path: "./sites/dev/dist" 96 | - name: Deploy to GitHub Pages 97 | id: deployment 98 | uses: actions/deploy-pages@v1 99 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | package-lock.json 2 | CMakeLists.txt.user 3 | build/wasm 4 | node_modules 5 | dist 6 | packages/*/dist 7 | packages/*/etc 8 | bin/act 9 | docs/api 10 | .DS_Store 11 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "build/vcpkg"] 2 | path = build/vcpkg 3 | url = https://github.com/microsoft/vcpkg.git 4 | [submodule "build/emsdk"] 5 | path = build/emsdk 6 | url = https://github.com/emscripten-core/emsdk.git 7 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v22.14.0 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | public 2 | dist 3 | node_modules 4 | build/wasm 5 | build/emsdk 6 | build/vcpkg 7 | build/vcpkg-ports 8 | build/vcpkg-toolchains 9 | build/vcpkg-triplets 10 | build/qt-patches 11 | pnpm-lock.yaml 12 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "Linux", 5 | "includePath": [ 6 | "${workspaceFolder}/build/wasm/vcpkg_installed/wasm32-emscripten-qt-threads/include", 7 | "${workspaceFolder}/build/wasm/vcpkg_installed/wasm32-emscripten-qt-threads/include/qgis", 8 | "${workspaceFolder}/build/emsdk/upstream/emscripten/system/include" 9 | ], 10 | "defines": [], 11 | "compilerPath": "/usr/bin/gcc", 12 | "cStandard": "c11", 13 | "cppStandard": "c++17", 14 | "intelliSenseMode": "clang-x64" 15 | } 16 | ], 17 | "version": 4 18 | } 19 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "workbench.editor.enablePreview": false, 3 | "editor.tabSize": 2, 4 | "editor.formatOnSave": true, 5 | "files.insertFinalNewline": true, 6 | "files.associations": { 7 | "**/package.json": "json", 8 | "**/*.json": "jsonc", 9 | "**/*.svg": "xml", 10 | "**/*.cpp": "cpp", 11 | "**/*.hpp": "cpp", 12 | "functional": "cpp" 13 | }, 14 | "terminal.integrated.env.linux": { 15 | "PATH": "${workspaceRoot}/build/emsdk:${workspaceRoot}/build/emsdk/upstream/emscripten:${workspaceRoot}/build/emsdk/upstream/bin:${workspaceRoot}/build/vcpkg:${env:PATH}" 16 | }, 17 | "search.exclude": { 18 | "build/emsdk": true, 19 | "build/vcpkg": true, 20 | "docs/api": true, 21 | "*/*/node_modules": true, 22 | "*/*/dist": true, 23 | "*/*/temp": true, 24 | "*/*/.vitepress/dist": true 25 | }, 26 | "typescript.tsdk": "node_modules/typescript/lib", 27 | "C_Cpp.autoAddFileAssociations": false, 28 | "C_Cpp.clang_format_path": "${workspaceRoot}/node_modules/clang-format/bin/linux_x64/clang-format", 29 | "cmake.cmakePath": "${workspaceFolder}/build/vcpkg/downloads/tools/cmake-3.27.1-linux/cmake-3.27.1-linux-x86_64/bin/cmake", 30 | "cmake.environment": { 31 | "VCPKG_BINARY_SOURCES": "clear" 32 | }, 33 | "cmake.configureSettings": { 34 | "CMAKE_TOOLCHAIN_FILE": "${workspaceFolder}/build/vcpkg/scripts/buildsystems/vcpkg.cmake", 35 | "VCPKG_CHAINLOAD_TOOLCHAIN_FILE": "${workspaceFolder}/build/vcpkg-toolchains/qgis-js.cmake", 36 | "VCPKG_TARGET_TRIPLET": "wasm32-emscripten-qt-threads", 37 | "VCPKG_OVERLAY_TRIPLETS": "${workspaceFolder}/build/vcpkg-triplets", 38 | "VCPKG_OVERLAY_PORTS": "${workspaceFolder}/build/vcpkg-ports" 39 | }, 40 | "cmake.buildDirectory": "${workspaceFolder}/build/wasm", 41 | "cmake.emscriptenSearchDirs": ["build/emsdk/upstream/emscripten"], 42 | "prettier.configPath": ".prettierrc.json", 43 | "prettier.documentSelectors": [ 44 | "**/*.{js,cjs,json,ts,vue,html,css,svg,yaml,md,webmanifest,clang-format,npmrc}" 45 | ], 46 | "clang-format.executable": "${workspaceRoot}/node_modules/clang-format/bin/linux_x64/clang-format" 47 | } 48 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to qgis-js 2 | 3 | Thank you for considering contributing to qgis-js! We welcome all contributions, big or small 🙏 4 | 5 | ## QGIS Code of Conduct 6 | 7 | Please note that for this project the [QGIS Code of Conduct](https://qgis.org/en/site/getinvolved/governance/codeofconduct/codeofconduct.html) also applies. 8 | 9 | ## Getting Started 10 | 11 | To get started with contributing, please follow these steps: 12 | 13 | 1. Fork the repository and clone it to your local machine. 14 | 2. See the [README](../README.md) for instructions on how to build the project. 15 | 3. Make your changes and test them locally. 16 | 4. Submit a pull request with your changes. 17 | 18 | ## Code Style 19 | 20 | Please follow the existing code style when making changes. We use [Prettier](https://prettier.io/) and [ClangFormat](https://clang.llvm.org/docs/ClangFormat.html) to enforce consitent code style, so please make sure your changes pass the linter by running `npm run lint`. 21 | 22 | ## Reporting Bugs 23 | 24 | If you find a bug, please open an issue on the [issue tracker](https://github.com/qgis/qgis-js/issues) with a detailed description of the problem and steps to reproduce it. 25 | 26 | ## Contact 27 | 28 | If you have any questions or concerns, please reach out as follows: 29 | 30 | - [qgis-js issues](https://github.com/qgis/qgis-js/issues) 31 | - [qgis-js discussions](https://github.com/qgis/qgis-js/discussions) 32 | - [QGIS Developers mailing list](https://lists.osgeo.org/mailman/listinfo/qgis-developer) 33 | 34 | > For general questions about QGIS, have a look at the [Get Involved in the QGIS Community](https://qgis.org/en/site/getinvolved/index.html) site 35 | -------------------------------------------------------------------------------- /build/actions/clean.ts: -------------------------------------------------------------------------------- 1 | import { CommandLineAction } from "@rushstack/ts-command-line"; 2 | 3 | import { QgisJsOptions } from "./lib/QgisJsOptions"; 4 | 5 | import "zx/globals"; 6 | 7 | export class CleanAction extends CommandLineAction { 8 | private _options: QgisJsOptions; 9 | 10 | public constructor(options: QgisJsOptions) { 11 | super({ 12 | actionName: "clean", 13 | summary: "Clean qgis-js build tree", 14 | documentation: `Cleans emsdk, vcpkg and the qgis-js build tree in "build/wasm".`, 15 | }); 16 | this._options = options; 17 | } 18 | 19 | protected onExecute(): Promise { 20 | return new Promise(async (resolve) => { 21 | const v = this._options.verbose; 22 | $.verbose = this._options.verbose; 23 | 24 | if (v) console.log(`- cleaning build/emsdk`); 25 | await $`(cd build/emsdk && git clean -xfd)`; 26 | 27 | if (v) console.log(`\n- cleaning build/vcpkg`); 28 | await $`(cd build/vcpkg && git clean -xfd)`; 29 | 30 | if (v) console.log(`\n- cleaning build/wasm`); 31 | await $`(rm -rf build/wasm && mkdir build/wasm)`; 32 | 33 | if (v) console.log(`\n`); 34 | resolve(); 35 | }); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /build/actions/compile.ts: -------------------------------------------------------------------------------- 1 | import { dirname, join } from "path"; 2 | import { fileURLToPath } from "url"; 3 | 4 | import { 5 | CommandLineAction, 6 | CommandLineChoiceParameter, 7 | CommandLineFlagParameter, 8 | } from "@rushstack/ts-command-line"; 9 | 10 | import { BuildType } from "./lib/BuildType"; 11 | import { QgisJsOptions } from "./lib/QgisJsOptions"; 12 | 13 | import "zx/globals"; 14 | 15 | const CMakeCacheFile = "build/wasm/CMakeCache.txt"; 16 | 17 | export class CompileAction extends CommandLineAction { 18 | private _options: QgisJsOptions; 19 | 20 | private _buildType!: CommandLineChoiceParameter; 21 | private _debug!: CommandLineFlagParameter; 22 | 23 | public constructor(options: QgisJsOptions) { 24 | super({ 25 | actionName: "compile", 26 | summary: "Compiles qgis-js", 27 | documentation: 28 | "Uses emsdk, vcpkg and CMake to configure and build qgis-js.", 29 | }); 30 | this._options = options; 31 | } 32 | 33 | protected onDefineParameters(): void { 34 | this._debug = this.defineFlagParameter({ 35 | parameterLongName: "--debug", 36 | parameterShortName: "-d", 37 | description: 38 | "Prints debug information during build (and runs the compilation single threaded)", 39 | }); 40 | 41 | this._buildType = this.defineChoiceParameter({ 42 | parameterLongName: "--builde-type", 43 | parameterShortName: "-t", 44 | description: "Specify the CMake build type", 45 | alternatives: ["Dev", "Release", "Debug"], 46 | environmentVariable: "QGIS_JS_BUILD_TYPE", 47 | defaultValue: "Dev" as BuildType, 48 | }); 49 | } 50 | 51 | protected onExecute(): Promise { 52 | return new Promise(async (resolve, reject) => { 53 | const v = this._options.verbose; 54 | $.verbose = true; 55 | 56 | const repo = join(dirname(fileURLToPath(import.meta.url)), "../.."); 57 | 58 | const buildType = (this._buildType.value || "Dev") as BuildType; 59 | const debug = this._debug.value || false; 60 | 61 | if (v) console.log("Build Type:", buildType); 62 | 63 | // check if CMakeCache.txt needs to be regenerated 64 | if (fs.existsSync(CMakeCacheFile)) { 65 | if (v) 66 | console.log( 67 | `"${CMakeCacheFile}" exists, checking if it has to be regenerated`, 68 | ); 69 | const lastBuild = await lastBuildType(); 70 | if (lastBuild === buildType) { 71 | if (v) 72 | console.log( 73 | `Build type has not changed, skipping regenerating of ${CMakeCacheFile}`, 74 | ); 75 | } else { 76 | if (v) 77 | console.log( 78 | `Build type has changed, regenerating ${CMakeCacheFile}`, 79 | ); 80 | await $`rm ${CMakeCacheFile}`; 81 | 82 | if (v) 83 | console.log(`Build type has changed, removing build artifacts`); 84 | const artifacts = await glob(["build/wasm/{qt*,qgis-js*}"]); 85 | if (artifacts.length > 0) await $`rm ${artifacts}`; 86 | } 87 | } else { 88 | if (v) console.log(`"${CMakeCacheFile}" does not exist`); 89 | } 90 | 91 | // set environment variables for CMake 92 | process.env.VCPKG_BINARY_SOURCES = "clear"; 93 | if (debug) { 94 | process.env.VERBOSE = "1"; 95 | process.env.EMCC_DEBUG = "1"; 96 | } 97 | 98 | // if vcpkg has installed its own cmake, use that, otherwise use the system cmake 99 | const cmake = 100 | await $`find . -iwholename './build/vcpkg/downloads/tools/cmake-*/*/bin/cmake' | grep bin/cmake || echo cmake`; 101 | 102 | // configure and build vcpgk dependencies 103 | try { 104 | await $`${cmake} \ 105 | -S . \ 106 | -B build/wasm \ 107 | -G Ninja \ 108 | -DCMAKE_TOOLCHAIN_FILE=${repo}/build/vcpkg/scripts/buildsystems/vcpkg.cmake \ 109 | -DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=${repo}/build/vcpkg-toolchains/qgis-js.cmake \ 110 | -DVCPKG_OVERLAY_TRIPLETS=./build/vcpkg-triplets \ 111 | -DVCPKG_OVERLAY_PORTS=./build/vcpkg-ports \ 112 | -DVCPKG_TARGET_TRIPLET=wasm32-emscripten-qt-threads \ 113 | -DCMAKE_BUILD_TYPE=${buildType !== "Dev" ? buildType : ""}`; 114 | 115 | // build 116 | await $`${cmake} --build build/wasm`; 117 | } catch (error) { 118 | reject(error); 119 | return; 120 | } 121 | 122 | resolve(); 123 | }); 124 | } 125 | } 126 | 127 | async function lastBuildType(): Promise { 128 | const CMakeCacheFileContents = fs.readFileSync(CMakeCacheFile, "utf-8"); 129 | if (!CMakeCacheFileContents || CMakeCacheFileContents.length === 0) 130 | return undefined; 131 | const match = CMakeCacheFileContents.match(/CMAKE_BUILD_TYPE:STRING=(\w+)/); 132 | return (match ? match[1] : "Dev") as BuildType; 133 | } 134 | -------------------------------------------------------------------------------- /build/actions/install.ts: -------------------------------------------------------------------------------- 1 | import { CommandLineAction } from "@rushstack/ts-command-line"; 2 | 3 | import { QgisJsOptions } from "./lib/QgisJsOptions"; 4 | 5 | import "zx/globals"; 6 | 7 | export class InstallAction extends CommandLineAction { 8 | private _options: QgisJsOptions; 9 | 10 | public constructor(options: QgisJsOptions) { 11 | super({ 12 | actionName: "install", 13 | summary: "Installs tools and downloads dependency sources", 14 | documentation: `Installs emsdk and vcpkg and then downlaods the source code of all ports with vcpkg.`, 15 | }); 16 | this._options = options; 17 | } 18 | 19 | protected onExecute(): Promise { 20 | return new Promise(async (resolve) => { 21 | const v = this._options.verbose; 22 | $.verbose = true; 23 | 24 | if (v) console.log(`- installing emsdk`); 25 | // ensure git submodule is initialized 26 | await $`git submodule update --init build/emsdk`; 27 | // read engine "emsdk" from package.json 28 | const emsdkVersion = JSON.parse(fs.readFileSync("package.json", "utf-8")) 29 | .engines.emsdk; 30 | if (!emsdkVersion || emsdkVersion === "") 31 | throw new Error(`"emsdk" version not found in package.json`); 32 | await $`(cd build/emsdk && ./emsdk install ${emsdkVersion} && ./emsdk activate ${emsdkVersion})`; 33 | 34 | if (v) console.log(`\n- installing vcpkg`); 35 | // ensure git submodule is initialized 36 | await $`git submodule update --init build/vcpkg`; 37 | // bootstrap vcpkg 38 | await $`./build/vcpkg/bootstrap-vcpkg.sh -disableMetrics`; 39 | 40 | if (v) console.log(`\n- running vcpkg install`); 41 | await $`./build/vcpkg/vcpkg install \ 42 | --x-install-root=build/wasm/vcpkg_installed \ 43 | --only-downloads \ 44 | --overlay-triplets=build/vcpkg-triplets \ 45 | --overlay-ports=build/vcpkg-ports \ 46 | --triplet wasm32-emscripten-qt-threads`; 47 | 48 | if (v) console.log(`\n`); 49 | resolve(); 50 | }); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /build/actions/lib/BuildType.ts: -------------------------------------------------------------------------------- 1 | export type BuildType = "Dev" | "Release" | "Debug"; 2 | -------------------------------------------------------------------------------- /build/actions/lib/QgisJsOptions.ts: -------------------------------------------------------------------------------- 1 | export interface QgisJsOptions { 2 | verbose: boolean; 3 | } 4 | -------------------------------------------------------------------------------- /build/scripts/clean.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -eo pipefail 3 | 4 | (cd build/emsdk; git clean -xfd) 5 | 6 | (cd build/vcpkg; git clean -xfd) 7 | 8 | rm -rf build/wasm && mkdir build/wasm 9 | -------------------------------------------------------------------------------- /build/scripts/compile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -eo pipefail 3 | 4 | # if vcpkg has installed its own cmake, use that, otherwise use the system cmake 5 | $(find . -iwholename './build/vcpkg/downloads/tools/cmake-*/*/bin/cmake' | grep bin/cmake || echo cmake) \ 6 | -S . \ 7 | -B build/wasm \ 8 | -G Ninja \ 9 | -DCMAKE_TOOLCHAIN_FILE=$PWD/build/vcpkg/scripts/buildsystems/vcpkg.cmake \ 10 | -DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=$PWD/build/vcpkg-toolchains/qgis-js.cmake \ 11 | -DVCPKG_OVERLAY_TRIPLETS=./build/vcpkg-triplets \ 12 | -DVCPKG_OVERLAY_PORTS=./build/vcpkg-ports \ 13 | -DVCPKG_TARGET_TRIPLET=wasm32-emscripten-qt-threads \ 14 | -DCMAKE_BUILD_TYPE= 15 | 16 | $(echo ./build/vcpkg/downloads/tools/cmake-*/*/bin/cmake) \ 17 | --build build/wasm 18 | -------------------------------------------------------------------------------- /build/scripts/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -eo pipefail 3 | 4 | git submodule update --init build/emsdk 5 | build/emsdk/emsdk install 3.1.59; 6 | build/emsdk/emsdk activate 3.1.59; 7 | 8 | git submodule update --init build/vcpkg 9 | ./build/vcpkg/bootstrap-vcpkg.sh -disableMetrics 10 | 11 | ./build/vcpkg/vcpkg install \ 12 | --x-install-root=build/wasm/vcpkg_installed \ 13 | --only-downloads \ 14 | --overlay-triplets=build/vcpkg-triplets \ 15 | --overlay-ports=build/vcpkg-ports \ 16 | --triplet wasm32-emscripten-qt-threads 17 | -------------------------------------------------------------------------------- /build/vcpkg-ports/gdal/avoid-getrlimit-warnings.patch: -------------------------------------------------------------------------------- 1 | diff --git a/port/cpl_vsisimple.cpp b/port/cpl_vsisimple.cpp 2 | index 61d807bfc9..e613ae9e09 100644 3 | --- a/port/cpl_vsisimple.cpp 4 | +++ b/port/cpl_vsisimple.cpp 5 | @@ -1596,7 +1596,7 @@ GIntBig CPLGetUsablePhysicalRAM(void) 6 | if (nRAM > INT_MAX) 7 | nRAM = INT_MAX; 8 | #endif 9 | -#if HAVE_GETRLIMIT 10 | +#if HAVE_GETRLIMIT && !defined(EMSCRIPTEN) 11 | struct rlimit sLimit; 12 | #if HAVE_RLIMIT_AS 13 | const int res = RLIMIT_AS; 14 | -------------------------------------------------------------------------------- /build/vcpkg-ports/gdal/cmake-project-include.cmake: -------------------------------------------------------------------------------- 1 | if(GDAL_USE_WEBP) 2 | find_package(WebP CONFIG REQUIRED) 3 | add_library(WEBP::WebP ALIAS WebP::webp) 4 | set(GDAL_CHECK_PACKAGE_WebP_NAMES WebP CACHE INTERNAL "vcpkg") 5 | set(GDAL_CHECK_PACKAGE_WebP_TARGETS WebP::webp CACHE INTERNAL "vcpkg") 6 | endif() 7 | -------------------------------------------------------------------------------- /build/vcpkg-ports/gdal/fix-gdal-target-interfaces.patch: -------------------------------------------------------------------------------- 1 | diff --git a/cmake/helpers/GdalDriverHelper.cmake b/cmake/helpers/GdalDriverHelper.cmake 2 | index 838f0fd..380e20d 100644 3 | --- a/cmake/helpers/GdalDriverHelper.cmake 4 | +++ b/cmake/helpers/GdalDriverHelper.cmake 5 | @@ -248,6 +248,10 @@ function(gdal_target_interfaces _TARGET) 6 | if (_res) 7 | target_compile_options(${_TARGET} PRIVATE ${_res}) 8 | endif () 9 | + get_property(_res TARGET ${_LIB} PROPERTY INTERFACE_LINK_LIBRARIES) 10 | + if (_res) 11 | + gdal_target_interfaces(${_TARGET} ${_res}) 12 | + endif () 13 | endif () 14 | endforeach () 15 | endfunction() 16 | -------------------------------------------------------------------------------- /build/vcpkg-ports/gdal/fix-simd-cpu-features.patch: -------------------------------------------------------------------------------- 1 | diff --git a/CMakeLists.txt b/CMakeLists.txt 2 | index 7fe1a41b81..17bfb87517 100644 3 | --- a/CMakeLists.txt 4 | +++ b/CMakeLists.txt 5 | @@ -93,22 +93,22 @@ if ("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "(x86|AMD64)") 6 | endif () 7 | endif () 8 | 9 | - check_compiler_machine_option(flag AVX) 10 | - if (NOT ${flag} STREQUAL "") 11 | - set(HAVE_AVX_AT_COMPILE_TIME 1) 12 | - add_definitions(-DHAVE_AVX_AT_COMPILE_TIME) 13 | - if (NOT ${flag} STREQUAL " ") 14 | - set(GDAL_AVX_FLAG ${flag}) 15 | - endif () 16 | - endif () 17 | + #check_compiler_machine_option(flag AVX) 18 | + #if (NOT ${flag} STREQUAL "") 19 | + # set(HAVE_AVX_AT_COMPILE_TIME 1) 20 | + # add_definitions(-DHAVE_AVX_AT_COMPILE_TIME) 21 | + # if (NOT ${flag} STREQUAL " ") 22 | + # set(GDAL_AVX_FLAG ${flag}) 23 | + # endif () 24 | + #endif () 25 | 26 | - check_compiler_machine_option(flag AVX2) 27 | - if (NOT ${flag} STREQUAL "") 28 | - set(HAVE_AVX2_AT_COMPILE_TIME 1) 29 | - if (NOT ${flag} STREQUAL " ") 30 | - set(GDAL_AVX2_FLAG ${flag}) 31 | - endif () 32 | - endif () 33 | + #check_compiler_machine_option(flag AVX2) 34 | + #if (NOT ${flag} STREQUAL "") 35 | + # set(HAVE_AVX2_AT_COMPILE_TIME 1) 36 | + # if (NOT ${flag} STREQUAL " ") 37 | + # set(GDAL_AVX2_FLAG ${flag}) 38 | + # endif () 39 | + #endif () 40 | 41 | endif () 42 | # 43 | diff --git a/port/cpl_cpu_features.h b/port/cpl_cpu_features.h 44 | index 4e83411147..53ad5b8fac 100644 45 | --- a/port/cpl_cpu_features.h 46 | +++ b/port/cpl_cpu_features.h 47 | @@ -35,7 +35,7 @@ 48 | //! @cond Doxygen_Suppress 49 | 50 | #ifdef HAVE_SSE_AT_COMPILE_TIME 51 | -#if (defined(_M_X64) || defined(__x86_64)) 52 | +#if (defined(EMSCRIPTEN)) 53 | #define HAVE_INLINE_SSE 54 | static bool inline CPLHaveRuntimeSSE() 55 | { 56 | @@ -47,7 +47,7 @@ bool CPLHaveRuntimeSSE(); 57 | #endif 58 | 59 | #ifdef HAVE_SSSE3_AT_COMPILE_TIME 60 | -#if __SSSE3__ 61 | +#if (defined(EMSCRIPTEN)) 62 | #define HAVE_INLINE_SSSE3 63 | static bool inline CPLHaveRuntimeSSSE3() 64 | { 65 | @@ -71,11 +71,11 @@ bool CPLHaveRuntimeSSSE3(); 66 | #endif 67 | 68 | #ifdef HAVE_AVX_AT_COMPILE_TIME 69 | -#if __AVX__ 70 | +#if (defined(EMSCRIPTEN)) 71 | #define HAVE_INLINE_AVX 72 | static bool inline CPLHaveRuntimeAVX() 73 | { 74 | - return true; 75 | + return false; 76 | } 77 | #elif defined(__GNUC__) 78 | extern bool bCPLHasAVX; 79 | -------------------------------------------------------------------------------- /build/vcpkg-ports/gdal/libkml.patch: -------------------------------------------------------------------------------- 1 | diff --git a/cmake/modules/packages/FindLibKML.cmake b/cmake/modules/packages/FindLibKML.cmake 2 | index 9418247..589b83d 100644 3 | --- a/cmake/modules/packages/FindLibKML.cmake 4 | +++ b/cmake/modules/packages/FindLibKML.cmake 5 | @@ -56,6 +56,8 @@ find_library(LIBKML_BASE_LIBRARY 6 | HINTS ${PC_LIBKML_LIBRARY_DIRS} ) 7 | mark_as_advanced(LIBKML_BASE_LIBRARY) 8 | 9 | +cmake_policy(PUSH) 10 | +cmake_policy(SET CMP0057 NEW) 11 | set(libkml_known_components DOM CONVENIENCE ENGINE REGIONATOR) 12 | foreach(_comp IN LISTS libkml_known_components) 13 | if(${_comp} IN_LIST LibKML_FIND_COMPONENTS) 14 | @@ -99,21 +101,20 @@ find_package_handle_standard_args(LibKML 15 | if(LIBKML_FOUND) 16 | set(LIBKML_INCLUDE_DIRS "${LIBKML_INCLUDE_DIR}") 17 | set(LIBKML_LIBRARIES "${LIBKML_BASE_LIBRARY}") 18 | + find_package(LibKML CONFIG REQUIRED) 19 | if(NOT TARGET LIBKML::LibKML) 20 | - add_library(LIBKML::LibKML UNKNOWN IMPORTED) 21 | + add_library(LIBKML::LibKML INTERFACE IMPORTED) 22 | set_target_properties(LIBKML::LibKML PROPERTIES 23 | - INTERFACE_INCLUDE_DIRECTORIES "${LIBKML_INCLUDE_DIR}" 24 | - IMPORTED_LINK_INTERFACE_LANGUAGES "C++" 25 | - IMPORTED_LOCATION "${LIBKML_BASE_LIBRARY}") 26 | + INTERFACE_LINK_LIBRARIES kmlbase) 27 | endif() 28 | foreach(_comp IN LISTS libkml_known_components) 29 | if(${_comp} IN_LIST LibKML_FIND_COMPONENTS) 30 | + string(TOLOWER ${_comp} _name) 31 | list(APPEND LIBKML_LIBRARIES "${LIBKML_${_comp}_LIBRARY}") 32 | if(NOT TARGET LIBKML::${_comp}) 33 | - add_library(LIBKML::${_comp} UNKNOWN IMPORTED) 34 | + add_library(LIBKML::${_comp} INTERFACE IMPORTED) 35 | set_target_properties(LIBKML::${_comp} PROPERTIES 36 | - IMPORTED_LINK_INTERFACE_LANGUAGES "C++" 37 | - IMPORTED_LOCATION "${LIBKML_${_comp}_LIBRARY}") 38 | + INTERFACE_LINK_LIBRARIES kml${_name}) 39 | endif() 40 | endif() 41 | endforeach() 42 | @@ -129,3 +130,4 @@ if(LIBKML_FOUND) 43 | endif() 44 | endforeach() 45 | endif() 46 | +cmake_policy(POP) 47 | -------------------------------------------------------------------------------- /build/vcpkg-ports/gdal/usage: -------------------------------------------------------------------------------- 1 | The package GDAL provides CMake targets: 2 | 3 | find_package(GDAL CONFIG REQUIRED) 4 | target_link_libraries(main PRIVATE GDAL::GDAL) 5 | -------------------------------------------------------------------------------- /build/vcpkg-ports/gdal/vcpkg-cmake-wrapper.cmake: -------------------------------------------------------------------------------- 1 | cmake_policy(PUSH) 2 | cmake_policy(SET CMP0012 NEW) 3 | cmake_policy(SET CMP0054 NEW) 4 | 5 | list(REMOVE_ITEM ARGS "NO_MODULE" "CONFIG" "MODULE") 6 | list(APPEND ARGS "CONFIG") 7 | # The current port version should satisfy GDAL 3.0 ... 3.5 8 | list(GET ARGS 1 vcpkg_gdal_maybe_version) 9 | if(vcpkg_gdal_maybe_version MATCHES "(^3\$|^3[.][0-5])") 10 | list(REMOVE_AT ARGS "1") 11 | endif() 12 | unset(vcpkg_gdal_maybe_version) 13 | _find_package(${ARGS} CONFIG) 14 | if(GDAL_FOUND) 15 | get_filename_component(vcpkg_gdal_prefix "${CMAKE_CURRENT_LIST_DIR}/../.." ABSOLUTE) 16 | set(GDAL_INCLUDE_DIR "${vcpkg_gdal_prefix}/include" CACHE INTERNAL "") 17 | set(GDAL_INCLUDE_DIRS "${GDAL_INCLUDE_DIR}") 18 | set(GDAL_LIBRARY GDAL::GDAL CACHE INTERNAL "") 19 | set(GDAL_LIBRARIES "${GDAL_LIBRARY}") 20 | unset(vcpkg_gdal_prefix) 21 | endif() 22 | 23 | cmake_policy(POP) 24 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qca/0001-fix-path-for-vcpkg.patch: -------------------------------------------------------------------------------- 1 | diff --git "a/CMakeLists.txt" "b/CMakeLists.txt" 2 | index 1f84c2c9e..f72ee9d8d 100644 3 | --- "a/CMakeLists.txt" 4 | +++ "b/CMakeLists.txt" 5 | @@ -58,6 +58,7 @@ set(QCA_SUFFIX "qt5") 6 | if(NOT BUILD_SHARED_LIBS OR QT_IS_STATIC) 7 | set(STATIC_PLUGINS ON) 8 | add_definitions(-DQT_STATICPLUGIN) 9 | + add_definitions(-DQCA_STATIC) 10 | set(PLUGIN_TYPE "STATIC") 11 | else() 12 | set(PLUGIN_TYPE "MODULE") 13 | @@ -266,10 +267,17 @@ if(DEVELOPER_MODE) 14 | add_definitions(-DDEVELOPER_MODE) 15 | 16 | # To prefer plugins from build tree when run qca from build tree 17 | - file(WRITE ${CMAKE_BINARY_DIR}/bin/qt.conf 18 | -"[Paths] 19 | -Plugins=${CMAKE_BINARY_DIR}/lib/${QCA_LIB_NAME} 20 | -") 21 | + if(NOT BUILD_SHARED_LIBS OR QT_IS_STATIC) 22 | + file(WRITE ${CMAKE_BINARY_DIR}/bin/qt.conf 23 | + "[Paths] 24 | + Plugins=${CMAKE_BINARY_DIR}/lib/${QCA_LIB_NAME} 25 | + ") 26 | + else() 27 | + file(WRITE ${CMAKE_BINARY_DIR}/bin/qt.conf 28 | + "[Paths] 29 | + Plugins=${CMAKE_BINARY_DIR}/bin/${QCA_LIB_NAME} 30 | + ") 31 | + endif() 32 | endif() 33 | 34 | if (APPLE) 35 | @@ -309,7 +317,7 @@ else() 36 | set( qca_CERTSTORE "${CMAKE_CURRENT_SOURCE_DIR}/certs/rootcerts.pem") 37 | # note that INSTALL_FILES targets are relative to the current installation prefix... 38 | if(NOT DEVELOPER_MODE) 39 | - install(FILES "${qca_CERTSTORE}" DESTINATION "${QCA_PREFIX_INSTALL_DIR}/certs") 40 | + install(FILES "${qca_CERTSTORE}" DESTINATION "${QCA_PREFIX_INSTALL_DIR}/share/qca/certs") 41 | endif() 42 | endif() 43 | message(STATUS "certstore path: " ${qca_CERTSTORE}) 44 | @@ -390,10 +398,10 @@ endif() 45 | include(CMakePackageConfigHelpers) 46 | configure_package_config_file( 47 | "${CMAKE_CURRENT_SOURCE_DIR}/QcaConfig.cmake.in" 48 | - "${CMAKE_CURRENT_BINARY_DIR}/lib/cmake/${QCA_CONFIG_NAME_BASE}/${QCA_CONFIG_NAME_BASE}Config.cmake" 49 | - INSTALL_DESTINATION ${QCA_LIBRARY_INSTALL_DIR}/cmake/${QCA_CONFIG_NAME_BASE} 50 | + "${CMAKE_BINARY_DIR}/share/qca/cmake/${QCA_CONFIG_NAME_BASE}Config.cmake" 51 | + INSTALL_DESTINATION ${CMAKE_BINARY_DIR}/share/qca/cmake 52 | ) 53 | -write_basic_config_version_file("${CMAKE_CURRENT_BINARY_DIR}/lib/cmake/${QCA_CONFIG_NAME_BASE}/${QCA_CONFIG_NAME_BASE}ConfigVersion.cmake" VERSION ${QCA_LIB_VERSION_STRING} COMPATIBILITY AnyNewerVersion) 54 | +write_basic_config_version_file("${CMAKE_BINARY_DIR}/share/qca/cmake/${QCA_CONFIG_NAME_BASE}ConfigVersion.cmake" VERSION ${QCA_LIB_VERSION_STRING} COMPATIBILITY AnyNewerVersion) 55 | 56 | if(NOT DEVELOPER_MODE) 57 | 58 | @@ -461,10 +469,10 @@ if(NOT DEVELOPER_MODE) 59 | endif() 60 | endif() 61 | 62 | - install(EXPORT ${QCA_CONFIG_NAME_BASE}Targets DESTINATION ${QCA_LIBRARY_INSTALL_DIR}/cmake/${QCA_CONFIG_NAME_BASE} FILE ${QCA_CONFIG_NAME_BASE}Targets.cmake) 63 | + install(EXPORT ${QCA_CONFIG_NAME_BASE}Targets DESTINATION ${QCA_PREFIX_INSTALL_DIR}/share/qca/cmake FILE ${QCA_CONFIG_NAME_BASE}Targets.cmake) 64 | install(FILES 65 | - "${CMAKE_CURRENT_BINARY_DIR}/lib/cmake/${QCA_CONFIG_NAME_BASE}/${QCA_CONFIG_NAME_BASE}Config.cmake" 66 | - "${CMAKE_CURRENT_BINARY_DIR}/lib/cmake/${QCA_CONFIG_NAME_BASE}/${QCA_CONFIG_NAME_BASE}ConfigVersion.cmake" 67 | - DESTINATION ${QCA_LIBRARY_INSTALL_DIR}/cmake/${QCA_CONFIG_NAME_BASE} 68 | + "${CMAKE_BINARY_DIR}/share/qca/cmake/${QCA_CONFIG_NAME_BASE}Config.cmake" 69 | + "${CMAKE_BINARY_DIR}/share/qca/cmake/${QCA_CONFIG_NAME_BASE}ConfigVersion.cmake" 70 | + DESTINATION ${QCA_PREFIX_INSTALL_DIR}/share/qca/cmake 71 | ) 72 | endif() 73 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qca/0002-fix-build-error.patch: -------------------------------------------------------------------------------- 1 | From 8d67288a3dde7e535ff747715f96f98282a3bf67 Mon Sep 17 00:00:00 2001 2 | From: Matthias Kuhn 3 | Date: Fri, 3 Dec 2021 15:17:25 +0100 4 | Subject: [PATCH] Ifdef codecs 5 | 6 | --- 7 | cmake/modules/QcaMacro.cmake | 9 --------- 8 | plugins/qca-ossl/qca-ossl.cpp | 6 ++++++ 9 | 2 files changed, 6 insertions(+), 9 deletions(-) 10 | 11 | diff --git a/cmake/modules/QcaMacro.cmake b/cmake/modules/QcaMacro.cmake 12 | index 80af6e84..ba86310d 100644 13 | --- a/cmake/modules/QcaMacro.cmake 14 | +++ b/cmake/modules/QcaMacro.cmake 15 | @@ -65,10 +65,6 @@ macro(add_qca_test TARGET DESCRIPTION) 16 | endmacro(add_qca_test) 17 | 18 | macro(install_pdb TARGET INSTALL_PATH) 19 | - if(MSVC) 20 | - install(FILES $ DESTINATION ${INSTALL_PATH} CONFIGURATIONS Debug) 21 | - install(FILES $ DESTINATION ${INSTALL_PATH} CONFIGURATIONS RelWithDebInfo) 22 | - endif() 23 | endmacro(install_pdb) 24 | 25 | macro(normalize_path PATH) 26 | 27 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qca/0003-Define-NOMINMAX-for-botan-plugin-with-MSVC.patch: -------------------------------------------------------------------------------- 1 | From f32f5ae8b8b49653bfff87f2f882862bcaa8c3f1 Mon Sep 17 00:00:00 2001 2 | From: =?UTF-8?q?=D9=85=D9=87=D8=AF=D9=8A=20=D8=B4=D9=8A=D9=86=D9=88=D9=86?= 3 | =?UTF-8?q?=20=28Mehdi=20Chinoune=29?= 4 | Date: Mon, 20 Mar 2023 16:21:18 +0100 5 | Subject: [PATCH] Define NOMINMAX to fix building qca-botan plugin with MSVC 6 | 7 | --- 8 | plugins/qca-botan/CMakeLists.txt | 4 ++++ 9 | 1 file changed, 4 insertions(+) 10 | 11 | diff --git a/plugins/qca-botan/CMakeLists.txt b/plugins/qca-botan/CMakeLists.txt 12 | index 11c0d20..9b8b978 100644 13 | --- a/plugins/qca-botan/CMakeLists.txt 14 | +++ b/plugins/qca-botan/CMakeLists.txt 15 | @@ -11,6 +11,10 @@ if(BOTAN_FOUND) 16 | set(QCA_BOTAN_SOURCES qca-botan.cpp) 17 | add_library(qca-botan ${PLUGIN_TYPE} ${QCA_BOTAN_SOURCES}) 18 | 19 | + if(MSVC) 20 | + target_compile_definitions(qca-botan PRIVATE NOMINMAX) 21 | + endif() 22 | + 23 | if(APPLE AND ${PLUGIN_TYPE} STREQUAL "MODULE") 24 | set_property(TARGET qca-botan PROPERTY SUFFIX ".dylib") 25 | endif() 26 | -- 27 | 2.40.0.windows.1 28 | 29 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qca/portfile.cmake: -------------------------------------------------------------------------------- 1 | # This portfile adds the Qt Cryptographic Arcitecture 2 | # Changes to the original build: 3 | # No -qt5 suffix, which is recommended just for Linux 4 | # Output directories according to vcpkg 5 | # Updated certstore. See certstore.pem in the output dirs 6 | # 7 | vcpkg_find_acquire_program(PERL) 8 | get_filename_component(PERL_EXE_PATH ${PERL} DIRECTORY) 9 | vcpkg_add_to_path("${PERL_EXE_PATH}") 10 | 11 | vcpkg_from_github( 12 | OUT_SOURCE_PATH SOURCE_PATH 13 | REPO KDE/qca 14 | REF "v${VERSION}" 15 | SHA512 de06173aaea32aac19a24510b5dbb4bb79681217eb1e4256de36db9f7158ad485fa450ffba5e13c12a0425866923b54f9b4d6164d0eaf659fdf40e458f5ee017 16 | PATCHES 17 | 0001-fix-path-for-vcpkg.patch 18 | 0002-fix-build-error.patch 19 | 0003-Define-NOMINMAX-for-botan-plugin-with-MSVC.patch 20 | ) 21 | 22 | vcpkg_find_acquire_program(PKGCONFIG) 23 | 24 | if(VCPKG_LIBRARY_LINKAGE STREQUAL "dynamic") 25 | set(QCA_FEATURE_INSTALL_DIR_DEBUG ${CURRENT_PACKAGES_DIR}/debug/bin/Qca) 26 | set(QCA_FEATURE_INSTALL_DIR_RELEASE ${CURRENT_PACKAGES_DIR}/bin/Qca) 27 | else() 28 | set(QCA_FEATURE_INSTALL_DIR_DEBUG ${CURRENT_PACKAGES_DIR}/debug/lib/Qca) 29 | set(QCA_FEATURE_INSTALL_DIR_RELEASE ${CURRENT_PACKAGES_DIR}/lib/Qca) 30 | endif() 31 | 32 | # According to: 33 | # https://www.openssl.org/docs/faq.html#USER16 34 | # it is up to developers or admins to maintain CAs. 35 | # So we do it here: 36 | message(STATUS "Importing certstore") 37 | file(REMOVE "${SOURCE_PATH}/certs/rootcerts.pem") 38 | 39 | # Using file(DOWNLOAD) to use https 40 | file(DOWNLOAD https://raw.githubusercontent.com/mozilla/gecko-dev/master/security/nss/lib/ckfw/builtins/certdata.txt 41 | "${CURRENT_BUILDTREES_DIR}/cert/certdata.txt" 42 | TLS_VERIFY ON 43 | ) 44 | vcpkg_execute_required_process( 45 | COMMAND "${PERL}" "${CMAKE_CURRENT_LIST_DIR}/mk-ca-bundle.pl" -n "${SOURCE_PATH}/certs/rootcerts.pem" 46 | WORKING_DIRECTORY "${CURRENT_BUILDTREES_DIR}/cert" 47 | LOGNAME ca-bundle 48 | ) 49 | message(STATUS "Importing certstore done") 50 | 51 | set(PLUGINS logger softstore wincrypto) 52 | if("botan" IN_LIST FEATURES) 53 | list(APPEND PLUGINS botan) 54 | endif() 55 | if ("gnupg" IN_LIST FEATURES) 56 | list(APPEND PLUGINS gnupg) 57 | endif() 58 | if ("ossl" IN_LIST FEATURES) 59 | list(APPEND PLUGINS ossl) 60 | endif() 61 | 62 | # Configure and build 63 | vcpkg_cmake_configure( 64 | SOURCE_PATH "${SOURCE_PATH}" 65 | OPTIONS 66 | -DUSE_RELATIVE_PATHS=ON 67 | "-DBUILD_PLUGINS=${PLUGINS}" 68 | -DBUILD_TESTS=OFF 69 | -DBUILD_TOOLS=OFF 70 | -DBUILD_WITH_QT6=ON 71 | -DQCA_SUFFIX=OFF 72 | -DQCA_FEATURE_INSTALL_DIR=share/qca/mkspecs/features 73 | -DOSX_FRAMEWORK=OFF 74 | "-DPKG_CONFIG_EXECUTABLE=${PKGCONFIG}" 75 | OPTIONS_DEBUG 76 | -DQCA_PLUGINS_INSTALL_DIR=${QCA_FEATURE_INSTALL_DIR_DEBUG} 77 | OPTIONS_RELEASE 78 | -DQCA_PLUGINS_INSTALL_DIR=${QCA_FEATURE_INSTALL_DIR_RELEASE} 79 | ) 80 | 81 | vcpkg_cmake_install() 82 | 83 | vcpkg_cmake_config_fixup(CONFIG_PATH share/qca/cmake) 84 | file(READ "${CURRENT_PACKAGES_DIR}/share/${PORT}/QcaConfig.cmake" QCA_CONFIG_FILE) 85 | string(REGEX REPLACE "PACKAGE_PREFIX_DIR \"(.*)\" ABSOLUTE" 86 | [[PACKAGE_PREFIX_DIR "${CMAKE_CURRENT_LIST_DIR}/../../" ABSOLUTE]] 87 | QCA_CONFIG_FILE "${QCA_CONFIG_FILE}" 88 | ) 89 | file(WRITE "${CURRENT_PACKAGES_DIR}/share/${PORT}/QcaConfig.cmake" "${QCA_CONFIG_FILE}") 90 | 91 | # Remove unneeded dirs 92 | file(REMOVE_RECURSE 93 | "${CURRENT_BUILDTREES_DIR}/share/man" 94 | "${CURRENT_PACKAGES_DIR}/share/man" 95 | "${CURRENT_PACKAGES_DIR}/debug/include" 96 | "${CURRENT_PACKAGES_DIR}/debug/share" 97 | ) 98 | 99 | vcpkg_fixup_pkgconfig() 100 | 101 | # Handle copyright 102 | vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/COPYING") 103 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qca/vcpkg.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "qca", 3 | "version": "2.3.7", 4 | "description": "Qt Cryptographic Architecture (QCA).", 5 | "homepage": "https://userbase.kde.org/QCA", 6 | "dependencies": [ 7 | { 8 | "name": "qt5compat", 9 | "default-features": false 10 | }, 11 | { 12 | "name": "qtbase", 13 | "default-features": false 14 | }, 15 | { 16 | "name": "vcpkg-cmake", 17 | "host": true 18 | }, 19 | { 20 | "name": "vcpkg-cmake-config", 21 | "host": true 22 | } 23 | ], 24 | "default-features": [ 25 | "botan" 26 | ], 27 | "features": { 28 | "botan": { 29 | "description": "Build with botan", 30 | "dependencies": [ 31 | "botan" 32 | ] 33 | }, 34 | "gnupg": { 35 | "description": "Build with gnupg" 36 | }, 37 | "ossl": { 38 | "description": "Build with openssl", 39 | "dependencies": [ 40 | "openssl" 41 | ] 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qgis-qt6/03-fix-missing-QTimeZone.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/core/gps/qgsgpslogger.cpp b/src/core/gps/qgsgpslogger.cpp 2 | index b4dd8ad7e3..3eecc19dd1 100644 3 | --- a/src/core/gps/qgsgpslogger.cpp 4 | +++ b/src/core/gps/qgsgpslogger.cpp 5 | @@ -479,11 +479,13 @@ QDateTime QgsGpsLogger::lastTimestamp() const 6 | if ( mTimeStampSpec == Qt::TimeSpec::TimeZone ) 7 | { 8 | // Get timezone from the combo 9 | +#if 0 10 | const QTimeZone destTz( mTimeZone.toUtf8() ); 11 | if ( destTz.isValid() ) 12 | { 13 | time = time.toTimeZone( destTz ); 14 | } 15 | +#endif 16 | } 17 | else if ( mTimeStampSpec == Qt::TimeSpec::LocalTime ) 18 | { 19 | diff --git a/src/core/layout/qgslayoutexporter.cpp b/src/core/layout/qgslayoutexporter.cpp 20 | index b758190970..d3c48339e7 100644 21 | --- a/src/core/layout/qgslayoutexporter.cpp 22 | +++ b/src/core/layout/qgslayoutexporter.cpp 23 | @@ -1653,6 +1653,7 @@ bool QgsLayoutExporter::georeferenceOutputPrivate( const QString &file, QgsLayou 24 | if ( creationDateTime.isValid() ) 25 | { 26 | creationDateString = QStringLiteral( "D:%1" ).arg( mLayout->project()->metadata().creationDateTime().toString( QStringLiteral( "yyyyMMddHHmmss" ) ) ); 27 | +#if 0 28 | if ( creationDateTime.timeZone().isValid() ) 29 | { 30 | int offsetFromUtc = creationDateTime.timeZone().offsetFromUtc( creationDateTime ); 31 | @@ -1662,6 +1663,7 @@ bool QgsLayoutExporter::georeferenceOutputPrivate( const QString &file, QgsLayou 32 | int offsetMins = ( offsetFromUtc % 3600 ) / 60; 33 | creationDateString += QStringLiteral( "%1'%2'" ).arg( offsetHours ).arg( offsetMins ); 34 | } 35 | +#endif 36 | } 37 | GDALSetMetadataItem( outputDS.get(), "CREATION_DATE", creationDateString.toUtf8().constData(), nullptr ); 38 | 39 | diff --git a/src/core/maprenderer/qgsmaprenderertask.cpp b/src/core/maprenderer/qgsmaprenderertask.cpp 40 | index eb5d87641d..33e759f3ff 100644 41 | --- a/src/core/maprenderer/qgsmaprenderertask.cpp 42 | +++ b/src/core/maprenderer/qgsmaprenderertask.cpp 43 | @@ -329,6 +329,7 @@ bool QgsMapRendererTask::run() 44 | if ( creationDateTime.isValid() ) 45 | { 46 | creationDateString = QStringLiteral( "D:%1" ).arg( mGeoPdfExportDetails.creationDateTime.toString( QStringLiteral( "yyyyMMddHHmmss" ) ) ); 47 | +#if 0 48 | if ( creationDateTime.timeZone().isValid() ) 49 | { 50 | int offsetFromUtc = creationDateTime.timeZone().offsetFromUtc( creationDateTime ); 51 | @@ -338,6 +339,7 @@ bool QgsMapRendererTask::run() 52 | const int offsetMins = ( offsetFromUtc % 3600 ) / 60; 53 | creationDateString += QStringLiteral( "%1'%2'" ).arg( offsetHours ).arg( offsetMins ); 54 | } 55 | +#endif 56 | } 57 | GDALSetMetadataItem( outputDS.get(), "CREATION_DATE", creationDateString.toUtf8().constData(), nullptr ); 58 | 59 | diff --git a/src/core/qgsabstractgeopdfexporter.cpp b/src/core/qgsabstractgeopdfexporter.cpp 60 | index 6700bd157c..fa9936b19d 100644 61 | --- a/src/core/qgsabstractgeopdfexporter.cpp 62 | +++ b/src/core/qgsabstractgeopdfexporter.cpp 63 | @@ -231,6 +231,7 @@ QString QgsAbstractGeoPdfExporter::createCompositionXml( const QList 7 | #include 8 | #include 9 | +#include 10 | +#include 11 | 12 | QVariantMap QgsArcGisRestQueryUtils::getServiceInfo( const QString &baseurl, const QString &authcfg, QString &errorTitle, QString &errorText, const QgsHttpHeaders &requestHeaders ) 13 | { 14 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qgis-qt6/08-skip-QgsExpression-initFunctionHelp.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt 2 | index 02dce34c30..da37472f57 100644 3 | --- a/src/core/CMakeLists.txt 4 | +++ b/src/core/CMakeLists.txt 5 | @@ -927,7 +927,7 @@ set(QGIS_CORE_SRCS 6 | vectortile/qgsvtpkvectortiledataprovider.cpp 7 | vectortile/qgsxyzvectortiledataprovider.cpp 8 | 9 | - ${CMAKE_CURRENT_BINARY_DIR}/qgsexpression_texts.cpp 10 | + # ${CMAKE_CURRENT_BINARY_DIR}/qgsexpression_texts.cpp 11 | 12 | qgsuserprofile.cpp 13 | qgsuserprofilemanager.cpp 14 | @@ -947,18 +947,18 @@ else () 15 | include_directories(${Poly2Tri_INCLUDE_DIR}) 16 | endif () 17 | 18 | -file(GLOB JSON_HELP_FILES "${CMAKE_SOURCE_DIR}/resources/function_help/json/*") 19 | -if(CMAKE_VERSION VERSION_LESS "3.18" AND NOT USING_NINJA) 20 | - string(REPLACE "$" "$$" JSON_HELP_FILES "${JSON_HELP_FILES}") 21 | -endif() 22 | -string(REPLACE "\(" "\\(" JSON_HELP_FILES "${JSON_HELP_FILES}") 23 | -string(REPLACE "\)" "\\)" JSON_HELP_FILES "${JSON_HELP_FILES}") 24 | -add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/qgsexpression_texts.cpp 25 | - COMMAND ${Python_EXECUTABLE} ${CMAKE_SOURCE_DIR}/scripts/process_function_template.py ${CMAKE_CURRENT_BINARY_DIR}/qgsexpression_texts.cpp.temp 26 | - COMMAND ${CMAKE_COMMAND} -DSRC=${CMAKE_CURRENT_BINARY_DIR}/qgsexpression_texts.cpp.temp -DDST=${CMAKE_CURRENT_BINARY_DIR}/qgsexpression_texts.cpp -P ${CMAKE_SOURCE_DIR}/cmake/CopyIfChanged.cmake 27 | - DEPENDS ${JSON_HELP_FILES} 28 | - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} 29 | -) 30 | +# file(GLOB JSON_HELP_FILES "${CMAKE_SOURCE_DIR}/resources/function_help/json/*") 31 | +# if(CMAKE_VERSION VERSION_LESS "3.18" AND NOT USING_NINJA) 32 | +# string(REPLACE "$" "$$" JSON_HELP_FILES "${JSON_HELP_FILES}") 33 | +# endif() 34 | +# string(REPLACE "\(" "\\(" JSON_HELP_FILES "${JSON_HELP_FILES}") 35 | +# string(REPLACE "\)" "\\)" JSON_HELP_FILES "${JSON_HELP_FILES}") 36 | +# add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/qgsexpression_texts.cpp 37 | +# COMMAND ${Python_EXECUTABLE} ${CMAKE_SOURCE_DIR}/scripts/process_function_template.py ${CMAKE_CURRENT_BINARY_DIR}/qgsexpression_texts.cpp.temp 38 | +# COMMAND ${CMAKE_COMMAND} -DSRC=${CMAKE_CURRENT_BINARY_DIR}/qgsexpression_texts.cpp.temp -DDST=${CMAKE_CURRENT_BINARY_DIR}/qgsexpression_texts.cpp -P ${CMAKE_SOURCE_DIR}/cmake/CopyIfChanged.cmake 39 | +# DEPENDS ${JSON_HELP_FILES} 40 | +# WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} 41 | +# ) 42 | 43 | if(ENABLE_MODELTEST) 44 | set(MODELTEST_SRCS 45 | @@ -2006,19 +2006,19 @@ if (HAVE_OPENCL) 46 | ) 47 | endif() 48 | 49 | -if(MSVC) 50 | - set_source_files_properties( 51 | - ${CMAKE_CURRENT_BINARY_DIR}/qgsexpression_texts.cpp 52 | - ${CMAKE_CURRENT_BINARY_DIR}/qgis_core_autogen/mocs_compilation.cpp 53 | - proj/qgscoordinatereferencesystem.cpp 54 | - PROPERTIES COMPILE_FLAGS "/bigobj" 55 | - ) 56 | -else() 57 | - if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" AND (CMAKE_BUILD_TYPE MATCHES Release OR CMAKE_BUILD_TYPE MATCHES RelWithDebInfo)) 58 | - set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/qgsexpression_texts.cpp PROPERTIES COMPILE_FLAGS "-O1") 59 | - set_source_files_properties(proj/qgscoordinatereferencesystem.cpp PROPERTIES COMPILE_FLAGS "-mllvm -inline-threshold=128") 60 | - endif() 61 | -endif() 62 | +# if(MSVC) 63 | +# set_source_files_properties( 64 | +# ${CMAKE_CURRENT_BINARY_DIR}/qgsexpression_texts.cpp 65 | +# ${CMAKE_CURRENT_BINARY_DIR}/qgis_core_autogen/mocs_compilation.cpp 66 | +# proj/qgscoordinatereferencesystem.cpp 67 | +# PROPERTIES COMPILE_FLAGS "/bigobj" 68 | +# ) 69 | +# else() 70 | +# if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" AND (CMAKE_BUILD_TYPE MATCHES Release OR CMAKE_BUILD_TYPE MATCHES RelWithDebInfo)) 71 | +# set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/qgsexpression_texts.cpp PROPERTIES COMPILE_FLAGS "-O1") 72 | +# set_source_files_properties(proj/qgscoordinatereferencesystem.cpp PROPERTIES COMPILE_FLAGS "-mllvm -inline-threshold=128") 73 | +# endif() 74 | +# endif() 75 | 76 | # Generate cpp+header file from .proto file using "protoc" tool (to support MVT encoding of vector tiles) 77 | protobuf_generate_cpp(VECTOR_TILE_PROTO_SRCS VECTOR_TILE_PROTO_HDRS vectortile/vector_tile.proto) 78 | diff --git a/src/core/expression/qgsexpression.cpp b/src/core/expression/qgsexpression.cpp 79 | index bdcb37cff7..401cc9010b 100644 80 | --- a/src/core/expression/qgsexpression.cpp 81 | +++ b/src/core/expression/qgsexpression.cpp 82 | @@ -29,6 +29,11 @@ 83 | 84 | #include 85 | 86 | +void QgsExpression::initFunctionHelp() 87 | +{ 88 | + // dummy function to prevent initialization of function help (too large cpp file) 89 | +} 90 | + 91 | // from parser 92 | extern QgsExpressionNode *parseExpression( const QString &str, QString &parserErrorMsg, QList &parserErrors ); 93 | 94 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qgis-qt6/09-fix-QgsExpression-Functions.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt 2 | index 02dce34c302..3bca83c548d 100644 3 | --- a/src/core/CMakeLists.txt 4 | +++ b/src/core/CMakeLists.txt 5 | @@ -2172,6 +2172,10 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}) 6 | 7 | add_library(qgis_core ${LIBRARY_TYPE} ${QGIS_CORE_SRCS} ${QGIS_CORE_HDRS} ${QGIS_CORE_PRIVATE_HDRS} ${IMAGE_RCCS}) 8 | 9 | +# fix "local count too large" when compiling qgsexpressionfunction.cpp with emscripten with Debug build type 10 | +# (see https://github.com/emscripten-core/emscripten/issues/19346) 11 | +set_source_files_properties(expression/qgsexpressionfunction.cpp PROPERTIES COMPILE_FLAGS "-O1") 12 | + 13 | 14 | # require c++17 15 | target_compile_features(qgis_core PRIVATE cxx_std_17) 16 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qgis-qt6/10-exclude-qgscoordinatereferencesystem_legacy.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt 2 | index f061ace19c..84746cbd3f 100644 3 | --- a/src/core/CMakeLists.txt 4 | +++ b/src/core/CMakeLists.txt 5 | @@ -1942,7 +1942,7 @@ set(QGIS_CORE_PRIVATE_HDRS 6 | proj/qgscoordinatereferencesystem_p.h 7 | proj/qgscoordinatetransformcontext_p.h 8 | proj/qgscoordinatetransform_p.h 9 | - proj/qgscoordinatereferencesystem_legacy_p.h 10 | + # proj/qgscoordinatereferencesystem_legacy_p.h 11 | 12 | providers/ogr/qgscplerrorhandler_p.h 13 | 14 | diff --git a/src/core/proj/qgscoordinatereferencesystem.cpp b/src/core/proj/qgscoordinatereferencesystem.cpp 15 | index 80e92071ce..f54cc20a6d 100644 16 | --- a/src/core/proj/qgscoordinatereferencesystem.cpp 17 | +++ b/src/core/proj/qgscoordinatereferencesystem.cpp 18 | @@ -18,7 +18,9 @@ 19 | #include "qgscoordinatereferencesystem.h" 20 | #include "qgscoordinatereferencesystem_p.h" 21 | 22 | -#include "qgscoordinatereferencesystem_legacy_p.h" 23 | +// #include "qgscoordinatereferencesystem_legacy_p.h" 24 | +const QMap< QString, QString > sAuthIdToQgisSrsIdMap; 25 | + 26 | #include "qgscoordinatereferencesystemregistry.h" 27 | #include "qgsreadwritelocker.h" 28 | 29 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qgis-qt6/11-disable-openedFileLimit.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/core/qgsfileutils.cpp b/src/core/qgsfileutils.cpp 2 | index e1da9c823c..59fcddbdad 100644 3 | --- a/src/core/qgsfileutils.cpp 4 | +++ b/src/core/qgsfileutils.cpp 5 | @@ -471,7 +471,7 @@ bool QgsFileUtils::renameDataset( const QString &oldPath, const QString &newPath 6 | 7 | int QgsFileUtils::openedFileLimit() 8 | { 9 | -#ifdef Q_OS_UNIX 10 | +#if defined(Q_OS_UNIX) && !defined(EMSCRIPTEN) 11 | struct rlimit rescLimit; 12 | if ( getrlimit( RLIMIT_NOFILE, &rescLimit ) == 0 ) 13 | { 14 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qgis-qt6/12-disable-wcs-provider.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/core/providers/qgsproviderregistry.cpp b/src/core/providers/qgsproviderregistry.cpp 2 | index 1713af97baa..e7c3bb4ef45 100644 3 | --- a/src/core/providers/qgsproviderregistry.cpp 4 | +++ b/src/core/providers/qgsproviderregistry.cpp 5 | @@ -52,7 +52,7 @@ 6 | 7 | #ifdef HAVE_STATIC_PROVIDERS 8 | #include "qgswmsprovider.h" 9 | -#include "qgswcsprovider.h" 10 | +// #include "qgswcsprovider.h" 11 | #include "qgsdelimitedtextprovider.h" 12 | #include "qgsafsprovider.h" 13 | #include "qgsamsprovider.h" 14 | @@ -228,7 +228,7 @@ void QgsProviderRegistry::init() 15 | 16 | #ifdef HAVE_STATIC_PROVIDERS 17 | mProviders[ QgsWmsProvider::providerKey() ] = new QgsWmsProviderMetadata(); 18 | - mProviders[ QgsWcsProvider::providerKey() ] = new QgsWcsProviderMetadata(); 19 | + // mProviders[ QgsWcsProvider::providerKey() ] = new QgsWcsProviderMetadata(); 20 | mProviders[ QgsDelimitedTextProvider::providerKey() ] = new QgsDelimitedTextProviderMetadata(); 21 | mProviders[ QgsAfsProvider::providerKey() ] = new QgsAfsProviderMetadata(); 22 | mProviders[ QgsAmsProvider::providerKey() ] = new QgsAmsProviderMetadata(); 23 | diff --git a/src/providers/CMakeLists.txt b/src/providers/CMakeLists.txt 24 | index 2fbe41cd4e5..1e3ed189c31 100644 25 | --- a/src/providers/CMakeLists.txt 26 | +++ b/src/providers/CMakeLists.txt 27 | @@ -4,7 +4,7 @@ set (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${QGIS_OUTPUT_DIRECTORY}/${QGIS_PLUGIN_SUBDI 28 | 29 | # providers with implemented both static and dynamic building 30 | add_subdirectory(wms) 31 | -add_subdirectory(wcs) 32 | +#add_subdirectory(wcs) 33 | add_subdirectory(delimitedtext) 34 | add_subdirectory(arcgisrest) 35 | 36 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qgis-qt6/13-no-LinguistTools-dep.patch: -------------------------------------------------------------------------------- 1 | diff --git a/i18n/CMakeLists.txt b/i18n/CMakeLists.txt 2 | index 752a951d41b..3c2673c209d 100644 3 | --- a/i18n/CMakeLists.txt 4 | +++ b/i18n/CMakeLists.txt 5 | @@ -1,5 +1,5 @@ 6 | -find_package(${QT_VERSION_BASE} COMPONENTS LinguistTools REQUIRED) 7 | -set(QT_LRELEASE_EXECUTABLE ${QT_VERSION_BASE}::lrelease) 8 | +find_package(${QT_VERSION_BASE} COMPONENTS LinguistTools) 9 | +option(QT_LRELEASE_EXECUTABLE "QT_LRELEASE_EXECUTABLE" ${QT_VERSION_BASE}::lrelease) 10 | 11 | macro(ADD_TRANSLATION_FILES _sources ) 12 | foreach (_current_FILE ${ARGN}) 13 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qgis-qt6/14-disable-map_crs_projection.patch: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------- 2 | # Disable "map_crs_projection" expression 3 | # ----------------------------------------------------- 4 | # 5 | # Dirty quick fix: 6 | # map_crs_projection cases a proj_create which will block the main thread for a notable amount of time 7 | # 8 | # 9 | diff --git a/src/core/expression/qgsexpressioncontextutils.cpp b/src/core/expression/qgsexpressioncontextutils.cpp 10 | index 966ece1160a..354a2058cba 100644 11 | --- a/src/core/expression/qgsexpressioncontextutils.cpp 12 | +++ b/src/core/expression/qgsexpressioncontextutils.cpp 13 | @@ -487,7 +487,7 @@ QgsExpressionContextScope *QgsExpressionContextUtils::mapSettingsScope( const Qg 14 | scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_units" ), QgsUnitTypes::toString( mapSettings.mapUnits() ), true ) ); 15 | scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_crs_description" ), mapSettings.destinationCrs().description(), true ) ); 16 | scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_crs_acronym" ), mapSettings.destinationCrs().projectionAcronym(), true ) ); 17 | - scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_crs_projection" ), mapSettings.destinationCrs().operation().description(), true ) ); 18 | + // scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_crs_projection" ), mapSettings.destinationCrs().operation().description(), true ) ); 19 | scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_crs_ellipsoid" ), mapSettings.destinationCrs().ellipsoidAcronym(), true ) ); 20 | scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_crs_proj4" ), mapSettings.destinationCrs().toProj(), true ) ); 21 | scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_crs_wkt" ), mapSettings.destinationCrs().toWkt( QgsCoordinateReferenceSystem::WKT_PREFERRED ), true ) ); 22 | diff --git a/src/core/layout/qgslayoutitemmap.cpp b/src/core/layout/qgslayoutitemmap.cpp 23 | index f29c618c81f..bc71249b91c 100644 24 | --- a/src/core/layout/qgslayoutitemmap.cpp 25 | +++ b/src/core/layout/qgslayoutitemmap.cpp 26 | @@ -1784,7 +1784,7 @@ QgsExpressionContext QgsLayoutItemMap::createExpressionContext() const 27 | scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_crs_description" ), mapCrs.description(), true ) ); 28 | scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_units" ), QgsUnitTypes::toString( mapCrs.mapUnits() ), true ) ); 29 | scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_crs_acronym" ), mapCrs.projectionAcronym(), true ) ); 30 | - scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_crs_projection" ), mapCrs.operation().description(), true ) ); 31 | + // scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_crs_projection" ), mapCrs.operation().description(), true ) ); 32 | scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_crs_ellipsoid" ), mapCrs.ellipsoidAcronym(), true ) ); 33 | scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_crs_proj4" ), mapCrs.toProj(), true ) ); 34 | scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_crs_wkt" ), mapCrs.toWkt( QgsCoordinateReferenceSystem::WKT_PREFERRED ), true ) ); 35 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qgis-qt6/bigobj.patch: -------------------------------------------------------------------------------- 1 | diff --git a/CMakeLists.txt b/CMakeLists.txt 2 | index 9d48e77a31..e360e29e42 100644 3 | --- a/CMakeLists.txt 4 | +++ b/CMakeLists.txt 5 | @@ -694,6 +694,7 @@ if(MSVC) 6 | set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") 7 | # disable macros that offend std::numeric_limits::min()/max() 8 | add_definitions(-DNOMINMAX) 9 | + add_definitions(/bigobj) 10 | endif() 11 | 12 | # Prevent build when Qt api deprecated before this Qt version is used: 13 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qgis-qt6/crssync.patch: -------------------------------------------------------------------------------- 1 | From ee182628c01881cc3f39e86e4b00cfc41127bd19 Mon Sep 17 00:00:00 2001 2 | From: Matthias Kuhn 3 | Date: Mon, 18 Oct 2021 12:07:06 +0200 4 | Subject: [PATCH] No crssync on Android 5 | 6 | --- 7 | src/CMakeLists.txt | 4 +- 8 | 1 file changed, 3 insertion(+), 1 deletion(-) 9 | 10 | diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt 11 | index f7f32a998f..6338b1e539 100644 12 | --- a/src/CMakeLists.txt 13 | +++ b/src/CMakeLists.txt 14 | @@ -16,7 +16,9 @@ endif() 15 | 16 | add_subdirectory(providers) 17 | 18 | -add_subdirectory(crssync) 19 | +if (NOT FORCE_STATIC_LIBS) 20 | + add_subdirectory(crssync) 21 | +endif() 22 | 23 | if (WITH_CRASH_HANDLER) 24 | add_subdirectory(crashhandler) 25 | -- 26 | 2.31.1 27 | 28 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qgis-qt6/exiv2-0.28.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/core/raster/qgsexiftools.cpp b/src/core/raster/qgsexiftools.cpp 2 | index 7fa2709845..97cfc5dc5a 100644 3 | --- a/src/core/raster/qgsexiftools.cpp 4 | +++ b/src/core/raster/qgsexiftools.cpp 5 | @@ -66,7 +66,7 @@ QVariant decodeXmpData( const QString &key, Exiv2::XmpData::const_iterator &it ) 6 | case Exiv2::signedLong: 7 | case Exiv2::unsignedLongLong: 8 | case Exiv2::signedLongLong: 9 | - val = QVariant::fromValue( it->toLong() ); 10 | + val = QVariant::fromValue( it->toInt64() ); 11 | break; 12 | 13 | case Exiv2::tiffDouble: 14 | @@ -80,7 +80,7 @@ QVariant decodeXmpData( const QString &key, Exiv2::XmpData::const_iterator &it ) 15 | case Exiv2::signedByte: 16 | case Exiv2::tiffIfd: 17 | case Exiv2::tiffIfd8: 18 | - val = QVariant::fromValue( static_cast< int >( it->toLong() ) ); 19 | + val = QVariant::fromValue( static_cast< int >( it->toInt64() ) ); 20 | break; 21 | 22 | case Exiv2::date: 23 | @@ -182,7 +182,7 @@ QVariant decodeExifData( const QString &key, Exiv2::ExifData::const_iterator &it 24 | case Exiv2::signedLong: 25 | case Exiv2::unsignedLongLong: 26 | case Exiv2::signedLongLong: 27 | - val = QVariant::fromValue( it->toLong() ); 28 | + val = QVariant::fromValue( it->toInt64() ); 29 | break; 30 | 31 | case Exiv2::tiffDouble: 32 | @@ -196,7 +196,7 @@ QVariant decodeExifData( const QString &key, Exiv2::ExifData::const_iterator &it 33 | case Exiv2::signedByte: 34 | case Exiv2::tiffIfd: 35 | case Exiv2::tiffIfd8: 36 | - val = QVariant::fromValue( static_cast< int >( it->toLong() ) ); 37 | + val = QVariant::fromValue( static_cast< int >( it->toInt64() ) ); 38 | break; 39 | 40 | case Exiv2::date: 41 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qgis-qt6/fix-ssl-network-access-manager.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/core/network/qgsnetworkaccessmanager.cpp b/src/core/network/qgsnetworkaccessmanager.cpp 2 | index bec4ff2300..7f1fdc423a 100644 3 | --- a/src/core/network/qgsnetworkaccessmanager.cpp 4 | +++ b/src/core/network/qgsnetworkaccessmanager.cpp 5 | @@ -455,6 +455,7 @@ void QgsNetworkAccessManager::afterSslErrorHandled( QNetworkReply *reply ) 6 | emit sslErrorsHandled( reply ); 7 | } 8 | } 9 | +#endif 10 | 11 | void QgsNetworkAccessManager::afterAuthRequestHandled( QNetworkReply *reply ) 12 | { 13 | @@ -495,6 +496,7 @@ int QgsNetworkAccessManager::getRequestId( QNetworkReply *reply ) 14 | return reply->property( "requestId" ).toInt(); 15 | } 16 | 17 | +#ifndef QT_NO_SSL 18 | void QgsNetworkAccessManager::handleSslErrors( QNetworkReply *reply, const QList &errors ) 19 | { 20 | mSslErrorHandler->handleSslErrors( reply, errors ); 21 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qgis-qt6/gdal.patch: -------------------------------------------------------------------------------- 1 | From 1e4d3489a8a84d3003af6e1690234746c667f31f Mon Sep 17 00:00:00 2001 2 | From: Matthias Kuhn 3 | Date: Wed, 28 Jul 2021 09:54:01 +0200 4 | Subject: [PATCH] Link to all gdal deps 5 | 6 | --- 7 | CMakeLists.txt | 2 ++ 8 | 1 file changed, 2 insertions(+) 9 | 10 | diff --git a/CMakeLists.txt b/CMakeLists.txt 11 | index 7a41b0d1e2..1141d6815a 100644 12 | --- a/CMakeLists.txt 13 | +++ b/CMakeLists.txt 14 | @@ -354,6 +354,8 @@ if(WITH_CORE) 15 | find_package(Proj) 16 | find_package(GEOS) 17 | find_package(GDAL) 18 | + # Make sure we link to all gdal dependencies 19 | + set(GDAL_LIBRARY ${GDAL_LIBRARIES}) 20 | find_package(Expat REQUIRED) 21 | find_package(Spatialindex REQUIRED) 22 | find_package(LibZip REQUIRED) 23 | -- 24 | 2.31.1 25 | 26 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qgis-qt6/keychain.patch: -------------------------------------------------------------------------------- 1 | From 7adf95ea43874f006ff3e1ae39a3aea05184e2d5 Mon Sep 17 00:00:00 2001 2 | From: Matthias Kuhn 3 | Date: Wed, 28 Jul 2021 07:28:28 +0200 4 | Subject: [PATCH] Qt5Keychain 5 | 6 | --- 7 | CMakeLists.txt | 5 ++++- 8 | 1 file changed, 4 insertions(+), 1 deletion(-) 9 | 10 | diff --git a/CMakeLists.txt b/CMakeLists.txt 11 | index b8d9287728..7a41b0d1e2 100644 12 | --- a/CMakeLists.txt 13 | +++ b/CMakeLists.txt 14 | @@ -490,7 +490,10 @@ if(WITH_CORE) 15 | endif() 16 | 17 | # Password helper 18 | - find_package(QtKeychain REQUIRED) 19 | + find_package(Qt6Keychain REQUIRED) 20 | + set(QTKEYCHAIN_INCLUDE_DIR ${QTKEYCHAIN_INCLUDE_DIRS}/qt6keychain) 21 | + set(QTKEYCHAIN_LIBRARY ${QTKEYCHAIN_LIBRARIES}) 22 | + set(QTKEYCHAIN_FOUND ${Qt6Keychain_FOUND}) 23 | # Master password hash and authentication encryption 24 | find_package(QCA REQUIRED) 25 | # Check for runtime dependency of qca-ossl plugin 26 | -- 27 | 2.31.1 28 | 29 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qgis-qt6/no-exiv.patch: -------------------------------------------------------------------------------- 1 | diff --git a/CMakeLists.txt b/CMakeLists.txt 2 | index eefb398762..d73533eb8d 100644 3 | --- a/CMakeLists.txt 4 | +++ b/CMakeLists.txt 5 | @@ -371,7 +371,7 @@ if(WITH_CORE) 6 | find_package(ZLIB REQUIRED) # for decompression of vector tiles in MBTiles file 7 | message(STATUS "Found zlib: ${ZLIB_LIBRARIES}") 8 | 9 | - find_package(EXIV2 REQUIRED) 10 | + #find_package(EXIV2 REQUIRED) 11 | 12 | # optional 13 | if (WITH_POSTGRESQL) 14 | diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt 15 | index 02dce34c30..4c61296690 100644 16 | --- a/src/core/CMakeLists.txt 17 | +++ b/src/core/CMakeLists.txt 18 | @@ -700,7 +700,7 @@ set(QGIS_CORE_SRCS 19 | raster/qgscolorrampshader.cpp 20 | raster/qgscontrastenhancement.cpp 21 | raster/qgscontrastenhancementfunction.cpp 22 | - raster/qgsexiftools.cpp 23 | + #raster/qgsexiftools.cpp 24 | raster/qgslinearminmaxenhancement.cpp 25 | raster/qgslinearminmaxenhancementwithclip.cpp 26 | raster/qgsraster.cpp 27 | @@ -1771,7 +1771,7 @@ set(QGIS_CORE_HDRS 28 | raster/qgscontrastenhancement.h 29 | raster/qgscontrastenhancementfunction.h 30 | raster/qgscubicrasterresampler.h 31 | - raster/qgsexiftools.h 32 | + #raster/qgsexiftools.h 33 | raster/qgshillshaderenderer.h 34 | raster/qgshuesaturationfilter.h 35 | raster/qgslinearminmaxenhancement.h 36 | @@ -2206,7 +2206,7 @@ target_include_directories(qgis_core SYSTEM PUBLIC 37 | ${${QT_VERSION_BASE}SerialPort_INCLUDE_DIRS} 38 | ${Protobuf_INCLUDE_DIRS} 39 | ${ZLIB_INCLUDE_DIRS} 40 | - ${EXIV2_INCLUDE_DIR} 41 | + #${EXIV2_INCLUDE_DIR} 42 | ) 43 | 44 | if (WITH_SPATIALITE) 45 | @@ -2377,7 +2377,7 @@ target_link_libraries(qgis_core 46 | ${LIBZIP_LIBRARY} 47 | ${Protobuf_LITE_LIBRARY} 48 | ${ZLIB_LIBRARIES} 49 | - ${EXIV2_LIBRARY} 50 | + #${EXIV2_LIBRARY} 51 | ) 52 | if (NOT IOS) 53 | target_link_libraries(qgis_core ${QT_VERSION_BASE}::PrintSupport) 54 | diff --git a/src/core/expression/qgsexpressionfunction.cpp b/src/core/expression/qgsexpressionfunction.cpp 55 | index 57a3aa8753..b0ac23730d 100644 56 | --- a/src/core/expression/qgsexpressionfunction.cpp 57 | +++ b/src/core/expression/qgsexpressionfunction.cpp 58 | @@ -21,7 +21,7 @@ 59 | #include "qgsexpressionfunction.h" 60 | #include "qgsexpressionutils.h" 61 | #include "qgsexpressionnodeimpl.h" 62 | -#include "qgsexiftools.h" 63 | +//#include "qgsexiftools.h" 64 | #include "qgsfeaturerequest.h" 65 | #include "qgsgeos.h" 66 | #include "qgsstringutils.h" 67 | @@ -2883,6 +2883,7 @@ static QVariant fcnDateTimeFromEpoch( const QVariantList &values, const QgsExpre 68 | return QVariant( QDateTime::fromMSecsSinceEpoch( millisecs_since_epoch ) ); 69 | } 70 | 71 | +#if 0 72 | static QVariant fcnExif( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction * ) 73 | { 74 | const QString filepath = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent ); 75 | @@ -2906,6 +2907,7 @@ static QVariant fcnExifGeoTag( const QVariantList &values, const QgsExpressionCo 76 | bool ok; 77 | return QVariant::fromValue( QgsGeometry( new QgsPoint( QgsExifTools::getGeoTag( filepath, ok ) ) ) ); 78 | } 79 | +#endif 80 | 81 | #define ENSURE_GEOM_TYPE(f, g, geomtype) \ 82 | if ( !(f).hasGeometry() ) \ 83 | @@ -8333,10 +8335,12 @@ const QList &QgsExpression::Functions() 84 | << new QgsStaticExpressionFunction( QStringLiteral( "file_size" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "path" ) ), 85 | fcnFileSize, QStringLiteral( "Files and Paths" ) ) 86 | 87 | +#if 0 88 | << new QgsStaticExpressionFunction( QStringLiteral( "exif" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "path" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "tag" ), true ), 89 | fcnExif, QStringLiteral( "Files and Paths" ) ) 90 | << new QgsStaticExpressionFunction( QStringLiteral( "exif_geotag" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "path" ) ), 91 | fcnExifGeoTag, QStringLiteral( "GeometryGroup" ) ) 92 | +#endif 93 | 94 | // hash 95 | << new QgsStaticExpressionFunction( QStringLiteral( "hash" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "string" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "method" ) ), 96 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qgis-qt6/no-tcp-udp-sensors.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt 2 | index 02dce34c30..e6eece9174 100644 3 | --- a/src/core/CMakeLists.txt 4 | +++ b/src/core/CMakeLists.txt 5 | @@ -340,7 +340,7 @@ set(QGIS_CORE_SRCS 6 | sensor/qgssensormanager.cpp 7 | sensor/qgssensorregistry.cpp 8 | sensor/qgsabstractsensor.cpp 9 | - sensor/qgsiodevicesensor.cpp 10 | + #sensor/qgsiodevicesensor.cpp 11 | 12 | fromencodedcomponenthelper.cpp 13 | qgis.cpp 14 | diff --git a/src/core/sensor/qgssensorregistry.cpp b/src/core/sensor/qgssensorregistry.cpp 15 | index b9196be833..8551418a8a 100644 16 | --- a/src/core/sensor/qgssensorregistry.cpp 17 | +++ b/src/core/sensor/qgssensorregistry.cpp 18 | @@ -17,7 +17,7 @@ 19 | #include "qgsconfig.h" 20 | 21 | #include "qgssensorregistry.h" 22 | -#include "qgsiodevicesensor.h" 23 | +//#include "qgsiodevicesensor.h" 24 | #include "qgsproject.h" 25 | #include "qgssensormanager.h" 26 | 27 | @@ -36,8 +36,10 @@ bool QgsSensorRegistry::populate() 28 | if ( !mMetadata.isEmpty() ) 29 | return false; 30 | 31 | +#if 0 32 | addSensorType( new QgsSensorMetadata( QLatin1String( "tcp_socket" ), QObject::tr( "TCP socket sensor" ), QgsTcpSocketSensor::create ) ); 33 | addSensorType( new QgsSensorMetadata( QLatin1String( "udp_socket" ), QObject::tr( "UDP socket sensor" ), QgsUdpSocketSensor::create ) ); 34 | +#endif 35 | #if defined( HAVE_QTSERIALPORT ) 36 | addSensorType( new QgsSensorMetadata( QLatin1String( "serial_port" ), QObject::tr( "Serial port sensor" ), QgsSerialPortSensor::create ) ); 37 | #endif 38 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qgis-qt6/no-user-agent-override.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/core/network/qgsnetworkaccessmanager.cpp b/src/core/network/qgsnetworkaccessmanager.cpp 2 | index bec4ff2300..41763db2f4 100644 3 | --- a/src/core/network/qgsnetworkaccessmanager.cpp 4 | +++ b/src/core/network/qgsnetworkaccessmanager.cpp 5 | @@ -298,11 +298,13 @@ QNetworkReply *QgsNetworkAccessManager::createRequest( QNetworkAccessManager::Op 6 | 7 | QNetworkRequest *pReq( const_cast< QNetworkRequest * >( &req ) ); // hack user agent 8 | 9 | +#ifndef EMSCRIPTEN 10 | QString userAgent = s.value( QStringLiteral( "/qgis/networkAndProxy/userAgent" ), "Mozilla/5.0" ).toString(); 11 | if ( !userAgent.isEmpty() ) 12 | userAgent += ' '; 13 | userAgent += QStringLiteral( "QGIS/%1/%2" ).arg( Qgis::versionInt() ).arg( QSysInfo::prettyProductName() ); 14 | pReq->setRawHeader( "User-Agent", userAgent.toLatin1() ); 15 | +#endif 16 | 17 | #ifndef QT_NO_SSL 18 | const bool ishttps = pReq->url().scheme().compare( QLatin1String( "https" ), Qt::CaseInsensitive ) == 0; 19 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qgis-qt6/portfile.cmake: -------------------------------------------------------------------------------- 1 | set(QGIS_REF final-3_32_1) 2 | set(QGIS_SHA512 37a8f92739e0ed1df1e8bc1b81b513d275b25d6afeb5d612c3e4cd51123deee29406b3347b863d06d1f6055fac0dd3e032d81ddda19f21e845ddb113c0724974) 3 | 4 | vcpkg_from_github( 5 | OUT_SOURCE_PATH SOURCE_PATH 6 | REPO qgis/QGIS 7 | REF ${QGIS_REF} 8 | SHA512 ${QGIS_SHA512} 9 | PATCHES 10 | gdal.patch 11 | keychain.patch 12 | crssync.patch 13 | bigobj.patch 14 | # wasm-specific 15 | qt6positioning.patch 16 | no-tcp-udp-sensors.patch 17 | exiv2-0.28.patch 18 | no-exiv.patch 19 | fix-settings-tree.patch 20 | fix-ssl-network-access-manager.patch 21 | disable-auth-manager.patch 22 | no-user-agent-override.patch 23 | 02-exclude-wfs-provider.patch 24 | 03-fix-missing-QTimeZone.patch 25 | 04-fix-missing-QCryptographicHash.patch 26 | 06-GDAL-no-QThread-sleep.patch 27 | 07-fix-QgsArcGisRestQueryUtils-includes.patch 28 | 08-skip-QgsExpression-initFunctionHelp.patch 29 | 09-fix-QgsExpression-Functions.patch 30 | 10-exclude-qgscoordinatereferencesystem_legacy.patch 31 | 11-disable-openedFileLimit.patch 32 | 12-disable-wcs-provider.patch 33 | 13-no-LinguistTools-dep.patch 34 | 14-disable-map_crs_projection.patch 35 | ) 36 | 37 | file(REMOVE ${SOURCE_PATH}/cmake/FindQtKeychain.cmake) 38 | file(REMOVE ${SOURCE_PATH}/cmake/FindGDAL.cmake) 39 | file(REMOVE ${SOURCE_PATH}/cmake/FindGEOS.cmake) 40 | file(REMOVE ${SOURCE_PATH}/cmake/FindEXIV2.cmake) 41 | file(REMOVE ${SOURCE_PATH}/cmake/FindExpat.cmake) 42 | file(REMOVE ${SOURCE_PATH}/cmake/FindIconv.cmake) 43 | 44 | vcpkg_find_acquire_program(FLEX) 45 | vcpkg_find_acquire_program(BISON) 46 | vcpkg_find_acquire_program(PYTHON3) 47 | get_filename_component(PYTHON3_PATH ${PYTHON3} DIRECTORY) 48 | vcpkg_add_to_path(${PYTHON3_PATH}) 49 | vcpkg_add_to_path(${PYTHON3_PATH}/Scripts) 50 | set(PYTHON_EXECUTABLE ${PYTHON3}) 51 | 52 | list(APPEND QGIS_OPTIONS -DFORCE_STATIC_LIBS:BOOL=ON) 53 | list(APPEND QGIS_OPTIONS -DBUILD_WITH_QT6:BOOL=ON) 54 | 55 | list(APPEND QGIS_OPTIONS -DENABLE_TESTS:BOOL=OFF) 56 | list(APPEND QGIS_OPTIONS -DWITH_QTWEBKIT:BOOL=OFF) 57 | list(APPEND QGIS_OPTIONS -DWITH_GRASS7:BOOL=OFF) 58 | list(APPEND QGIS_OPTIONS -DUSE_OPENCL:BOOL=OFF) 59 | list(APPEND QGIS_OPTIONS -DWITH_BINDINGS:BOOL=OFF) 60 | list(APPEND QGIS_OPTIONS -DWITH_GUI:BOOL=OFF) 61 | list(APPEND QGIS_OPTIONS -DWITH_DESKTOP:BOOL=OFF) 62 | list(APPEND QGIS_OPTIONS -DWITH_CUSTOM_WIDGETS:BOOL=OFF) 63 | list(APPEND QGIS_OPTIONS -DWITH_SERVER:BOOL=OFF) 64 | list(APPEND QGIS_OPTIONS -DWITH_QGIS_PROCESS:BOOL=OFF) 65 | list(APPEND QGIS_OPTIONS -DWITH_PDAL:BOOL=OFF) 66 | list(APPEND QGIS_OPTIONS -DWITH_EPT:BOOL=OFF) 67 | list(APPEND QGIS_OPTIONS -DWITH_3D:BOOL=OFF) 68 | list(APPEND QGIS_OPTIONS -DWITH_COPC=OFF) 69 | list(APPEND QGIS_OPTIONS -DWITH_ANALYSIS=OFF) 70 | list(APPEND QGIS_OPTIONS -DENABLE_TESTS=OFF) 71 | list(APPEND QGIS_OPTIONS -DWITH_GUI=OFF) 72 | list(APPEND QGIS_OPTIONS -DWITH_APIDOC=OFF) 73 | list(APPEND QGIS_OPTIONS -DWITH_ASTYLE=OFF) 74 | list(APPEND QGIS_OPTIONS -DWITH_QUICK:BOOL=OFF) 75 | list(APPEND QGIS_OPTIONS -DQGIS_MACAPP_FRAMEWORK=FALSE) 76 | list(APPEND QGIS_OPTIONS -DWITH_QTSERIALPORT=FALSE) 77 | 78 | # WASM 79 | list(APPEND QGIS_OPTIONS -DWITH_POSTGRESQL:BOOL=FALSE) 80 | list(APPEND QGIS_OPTIONS -DWITH_SPATIALITE:BOOL=FALSE) 81 | list(APPEND QGIS_OPTIONS -DWITH_AUTH:BOOL=FALSE) 82 | 83 | list(APPEND QGIS_OPTIONS -DQT_LRELEASE_EXECUTABLE=${CURRENT_HOST_INSTALLED_DIR}/tools/Qt6/bin/lrelease) 84 | 85 | # QGIS likes to install auth and providers to different locations on each platform 86 | # let's keep things clean and tidy and put them at a predictable location 87 | list(APPEND QGIS_OPTIONS -DQGIS_PLUGIN_SUBDIR=lib) 88 | 89 | # By default QGIS installs includes into "include" on Windows and into "include/qgis" everywhere else 90 | # let's keep things clean and tidy and put them at a predictable location 91 | list(APPEND QGIS_OPTIONS -DQGIS_INCLUDE_SUBDIR=include/qgis) 92 | 93 | list(APPEND QGIS_OPTIONS -DWITH_INTERNAL_POLY2TRI=ON) 94 | 95 | vcpkg_configure_cmake( 96 | SOURCE_PATH ${SOURCE_PATH} 97 | #PREFER_NINJA 98 | OPTIONS ${QGIS_OPTIONS} 99 | OPTIONS_DEBUG ${QGIS_OPTIONS_DEBUG} 100 | OPTIONS_RELEASE ${QGIS_OPTIONS_RELEASE} 101 | ) 102 | 103 | vcpkg_install_cmake() 104 | 105 | 106 | file(GLOB QGIS_CMAKE_PATH ${CURRENT_PACKAGES_DIR}/*.cmake) 107 | if(QGIS_CMAKE_PATH) 108 | file(COPY ${QGIS_CMAKE_PATH} DESTINATION ${CURRENT_PACKAGES_DIR}/share/cmake/${PORT}) 109 | file(REMOVE_RECURSE ${QGIS_CMAKE_PATH}) 110 | endif() 111 | 112 | file(GLOB QGIS_CMAKE_PATH_DEBUG ${CURRENT_PACKAGES_DIR}/debug/*.cmake) 113 | if( QGIS_CMAKE_PATH_DEBUG ) 114 | file(REMOVE_RECURSE ${QGIS_CMAKE_PATH_DEBUG}) 115 | endif() 116 | 117 | file(REMOVE_RECURSE 118 | ${CURRENT_PACKAGES_DIR}/debug/include 119 | ) 120 | file(REMOVE_RECURSE # Added for debug porpose 121 | ${CURRENT_PACKAGES_DIR}/debug/share 122 | ) 123 | 124 | # Handle copyright 125 | file(INSTALL ${SOURCE_PATH}/COPYING DESTINATION ${CURRENT_PACKAGES_DIR}/share/${PORT} RENAME copyright) 126 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qgis-qt6/qt6positioning.patch: -------------------------------------------------------------------------------- 1 | diff --git a/CMakeLists.txt b/CMakeLists.txt 2 | --- CMakeLists.txt 3 | +++ CMakeLists.txt 4 | @@ -468,7 +468,7 @@ 5 | set (HAVE_QTSERIALPORT TRUE) 6 | endif() 7 | 8 | - find_package(${QT_VERSION_BASE} COMPONENTS Core Gui Widgets Network Xml Svg Concurrent Test Sql Positioning REQUIRED) 9 | + find_package(${QT_VERSION_BASE} COMPONENTS Core Gui Widgets Network Xml Svg Concurrent Test Sql REQUIRED) 10 | if (BUILD_WITH_QT6) 11 | find_package(${QT_VERSION_BASE} COMPONENTS Core5Compat REQUIRED) 12 | endif() 13 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qgis-qt6/vcpkg.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "qgis-qt6", 3 | "version": "3.32.1", 4 | "port-version": 1, 5 | "homepage": "https://qgis.org", 6 | "description": "QGIS is a free, open source, cross platform (lin/win/mac) geographical information system (GIS)", 7 | "dependencies": [ 8 | "expat", 9 | "zlib", 10 | "libspatialindex", 11 | { 12 | "name": "sqlite3", 13 | "default-features": false 14 | }, 15 | "exiv2", 16 | "protobuf", 17 | { 18 | "name": "proj", 19 | "default-features": false 20 | }, 21 | "geos", 22 | { 23 | "name": "gdal", 24 | "default-features": false 25 | }, 26 | 27 | { 28 | "name": "qtbase", 29 | "default-features": false, 30 | "features": [ 31 | "concurrent", 32 | "gui", 33 | "jpeg", 34 | "network", 35 | "png", 36 | "widgets", 37 | "sql", 38 | "sql-sqlite" 39 | ] 40 | }, 41 | { 42 | "name": "qtsvg", 43 | "default-features": false 44 | }, 45 | 46 | { 47 | "name": "qttools", 48 | "default-features": false, 49 | "features": [ 50 | "linguist" 51 | ] 52 | }, 53 | { 54 | "name": "qttools", 55 | "host": true, 56 | "default-features": false, 57 | "features": [ 58 | "linguist" 59 | ] 60 | }, 61 | 62 | { 63 | "name": "qca", 64 | "default-features": false 65 | }, 66 | "qtkeychain-qt6", 67 | { 68 | "name": "vcpkg-cmake", 69 | "host": true 70 | }, 71 | { 72 | "name": "vcpkg-cmake-config", 73 | "host": true 74 | } 75 | ] 76 | } 77 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qtbase/GLIB2-static.patch: -------------------------------------------------------------------------------- 1 | diff --git a/cmake/3rdparty/extra-cmake-modules/find-modules/FindGLIB2.cmake b/cmake/3rdparty/extra-cmake-modules/find-modules/FindGLIB2.cmake 2 | index 24a194c..91c8e41 100644 3 | --- a/cmake/3rdparty/extra-cmake-modules/find-modules/FindGLIB2.cmake 4 | +++ b/cmake/3rdparty/extra-cmake-modules/find-modules/FindGLIB2.cmake 5 | @@ -95,6 +95,18 @@ find_library(GLIB2_GIO_LIBRARIES 6 | HINTS ${PC_GIO_LIBDIR} 7 | ) 8 | 9 | +pkg_check_modules(PC_GMODULE QUIET gmodule-2.0) 10 | + 11 | +find_path(GLIB2_GMODULE_INCLUDE_DIRS 12 | + NAMES gmodule.h 13 | + HINTS ${PC_GMODULE} 14 | + PATH_SUFFIXES glib-2.0) 15 | + 16 | +find_library(GLIB2_GMODULE_LIBRARIES 17 | + NAMES gmodule-2.0 18 | + HINTS ${PC_GMODULE} 19 | +) 20 | + 21 | # search the glibconfig.h include dir under the same root where the library is found 22 | get_filename_component(glib2LibDir "${GLIB2_LIBRARIES}" PATH) 23 | 24 | @@ -126,6 +138,11 @@ if(GLIB2_GIO_LIBRARIES AND GLIB2_GIO_INCLUDE_DIRS) 25 | set(GLIB2_GIO_FOUND TRUE) 26 | endif() 27 | 28 | +if(GLIB2_GMODULE_LIBRARIES AND GLIB2_GMODULE_INCLUDE_DIRS) 29 | + set(GLIB2_GMODULE_FOUND TRUE) 30 | +endif() 31 | + 32 | + 33 | include(FindPackageHandleStandardArgs) 34 | find_package_handle_standard_args(GLIB2 35 | REQUIRED_VARS GLIB2_LIBRARIES GTHREAD2_LIBRARIES GLIB2_INCLUDE_DIRS 36 | @@ -137,6 +154,16 @@ if(GLIB2_FOUND AND NOT TARGET GLIB2::GLIB2) 37 | IMPORTED_LOCATION "${GLIB2_LIBRARIES}" 38 | INTERFACE_LINK_LIBRARIES "${GTHREAD2_LIBRARIES}" 39 | INTERFACE_INCLUDE_DIRECTORIES "${GLIB2_INCLUDE_DIRS}") 40 | + #vcpkg specific 41 | + pkg_check_modules(PC_PCRE2_8BIT QUIET libpcre2-8) 42 | + find_library(PCRE2_8BIT_LIBRARIES 43 | + NAMES pcre2-8 44 | + HINTS ${PC_PCRE2_8BIT} 45 | + ) 46 | + target_link_libraries(GLIB2::GLIB2 INTERFACE ${PCRE2_8BIT_LIBRARIES}) 47 | + find_package(Iconv) 48 | + find_package(Intl) 49 | + target_link_libraries(GLIB2::GLIB2 INTERFACE Intl::Intl Iconv::Iconv) 50 | endif() 51 | 52 | if(GLIB2_GOBJECT_FOUND AND NOT TARGET GLIB2::GOBJECT) 53 | @@ -153,12 +180,21 @@ if(GLIB2_GIO_FOUND AND NOT TARGET GLIB2::GIO) 54 | INTERFACE_INCLUDE_DIRECTORIES "${GLIB2_GIO_INCLUDE_DIRS}") 55 | endif() 56 | 57 | +if(GLIB2_GMODULE_FOUND AND NOT TARGET GLIB2::GMODULE) 58 | + add_library(GLIB2::GMODULE UNKNOWN IMPORTED) 59 | + set_target_properties(GLIB2::GMODULE PROPERTIES 60 | + IMPORTED_LOCATION "${GLIB2_GMODULE_LIBRARIES}" 61 | + INTERFACE_INCLUDE_DIRECTORIES "${GLIB2_GMODULE_INCLUDE_DIRS}") 62 | +endif() 63 | + 64 | + 65 | mark_as_advanced(GLIB2_INCLUDE_DIRS GLIB2_INCLUDE_DIR 66 | GLIB2_LIBRARIES GLIB2_LIBRARY 67 | GLIB2_GOBJECT_INCLUDE_DIRS GLIB2_GOBJECT_INCLUDE_DIR 68 | GLIB2_GOBJECT_LIBRARIES GLIB2_GOBJECT_LIBRARY 69 | GLIB2_GIO_INCLUDE_DIRS GLIB2_GIO_INCLUDE_DIR 70 | - GLIB2_GIO_LIBRARIES GLIB2_GIO_LIBRARY) 71 | + GLIB2_GIO_LIBRARIES GLIB2_GIO_LIBRARY 72 | + GLIB2_GMODULE_LIBRARIES GLIB2_GMODULE_INCLUDE_DIRS) 73 | 74 | include(FeatureSummary) 75 | set_package_properties(GLIB2 PROPERTIES 76 | diff --git a/src/corelib/configure.cmake b/src/corelib/configure.cmake 77 | index 7d52f48..2b1b221 100644 78 | --- a/src/corelib/configure.cmake 79 | +++ b/src/corelib/configure.cmake 80 | @@ -25,7 +25,7 @@ endif() 81 | qt_find_package(WrapSystemDoubleConversion 82 | PROVIDED_TARGETS WrapSystemDoubleConversion::WrapSystemDoubleConversion 83 | MODULE_NAME core QMAKE_LIB doubleconversion) 84 | -qt_find_package(GLIB2 PROVIDED_TARGETS GLIB2::GLIB2 MODULE_NAME core QMAKE_LIB glib) 85 | +qt_find_package(GLIB2 PROVIDED_TARGETS GLIB2::GLIB2 MODULE MODULE_NAME core QMAKE_LIB glib) 86 | qt_find_package(ICU 50.1 COMPONENTS i18n uc data PROVIDED_TARGETS ICU::i18n ICU::uc ICU::data 87 | MODULE_NAME core QMAKE_LIB icu) 88 | 89 | diff --git a/src/network/configure.cmake b/src/network/configure.cmake 90 | index aef7f15..21b0c1d 100644 91 | --- a/src/network/configure.cmake 92 | +++ b/src/network/configure.cmake 93 | @@ -10,8 +10,8 @@ 94 | qt_find_package(WrapBrotli PROVIDED_TARGETS WrapBrotli::WrapBrotliDec MODULE_NAME network QMAKE_LIB brotli) 95 | qt_find_package(Libproxy PROVIDED_TARGETS PkgConfig::Libproxy MODULE_NAME network QMAKE_LIB libproxy) 96 | qt_find_package(GSSAPI PROVIDED_TARGETS GSSAPI::GSSAPI MODULE_NAME network QMAKE_LIB gssapi) 97 | -qt_find_package(GLIB2 OPTIONAL_COMPONENTS GOBJECT PROVIDED_TARGETS GLIB2::GOBJECT MODULE_NAME core QMAKE_LIB gobject) 98 | -qt_find_package(GLIB2 OPTIONAL_COMPONENTS GIO PROVIDED_TARGETS GLIB2::GIO MODULE_NAME core QMAKE_LIB gio) 99 | +qt_find_package(GLIB2 OPTIONAL_COMPONENTS GOBJECT PROVIDED_TARGETS GLIB2::GOBJECT MODULE MODULE_NAME core QMAKE_LIB gobject) 100 | +qt_find_package(GLIB2 OPTIONAL_COMPONENTS GIO PROVIDED_TARGETS GLIB2::GIO MODULE MODULE_NAME core QMAKE_LIB gio) 101 | qt_find_package(WrapResolv PROVIDED_TARGETS WrapResolv::WrapResolv MODULE_NAME network QMAKE_LIB libresolv) 102 | 103 | #### Tests 104 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qtbase/allow_outside_prefix.patch: -------------------------------------------------------------------------------- 1 | diff --git a/cmake/QtBuild.cmake b/cmake/QtBuild.cmake 2 | index bd186c28b..2c1994d2e 100644 3 | --- a/cmake/QtBuild.cmake 4 | +++ b/cmake/QtBuild.cmake 5 | @@ -28,11 +28,13 @@ function(qt_configure_process_path name default docstring) 6 | elseif(rel_path MATCHES "^\.\./") 7 | # INSTALL_SYSCONFDIR is allowed to be outside the prefix. 8 | if(NOT name STREQUAL "INSTALL_SYSCONFDIR") 9 | - message(FATAL_ERROR 10 | - "Path component '${name}' is outside computed install prefix: ${rel_path} ") 11 | - return() 12 | + #message(FATAL_ERROR 13 | + # "Path component '${name}' is outside computed install prefix: ${rel_path} ") 14 | + #return() 15 | + set("${name}" "${rel_path}" CACHE STRING "${docstring}" FORCE) 16 | + else() 17 | + set("${name}" "${${name}}" CACHE STRING "${docstring}" FORCE) 18 | endif() 19 | - set("${name}" "${${name}}" CACHE STRING "${docstring}" FORCE) 20 | else() 21 | set("${name}" "${rel_path}" CACHE STRING "${docstring}" FORCE) 22 | endif() 23 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qtbase/clang-cl_QGADGET_fix.diff: -------------------------------------------------------------------------------- 1 | diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h 2 | index e40cd85..ba68a01 100644 3 | --- a/src/corelib/kernel/qmetatype.h 4 | +++ b/src/corelib/kernel/qmetatype.h 5 | @@ -18,6 +18,7 @@ 6 | #endif 7 | #include 8 | 9 | +#include 10 | #include 11 | #include 12 | #include 13 | @@ -826,7 +829,13 @@ 14 | struct IsGadgetHelper { enum { IsRealGadget = false, IsGadgetOrDerivedFrom = false }; }; 15 | 16 | template 17 | +#if defined(__clang__) && (__clang_major__ > 11) 18 | + // Clang does not reject T::QtGadgetHelper as ambiguous if a class inherits from two QGADGETS 19 | + // but is not a QGADGET itself 20 | + struct IsGadgetHelper> 21 | +#else 22 | struct IsGadgetHelper 23 | +#endif 24 | { 25 | template 26 | static char checkType(void (X::*)()); 27 | @@ -841,7 +850,11 @@ 28 | struct IsPointerToGadgetHelper { enum { IsRealGadget = false, IsGadgetOrDerivedFrom = false }; }; 29 | 30 | template 31 | +#if defined(__clang__) && (__clang_major__ > 11) 32 | + struct IsPointerToGadgetHelper> 33 | +#else 34 | struct IsPointerToGadgetHelper 35 | +#endif 36 | { 37 | using BaseType = T; 38 | template 39 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qtbase/clang-cl_source_location.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/corelib/kernel/qproperty.h b/src/corelib/kernel/qproperty.h 2 | index 823b2057b..4a8cd4fa8 100644 3 | --- a/src/corelib/kernel/qproperty.h 4 | +++ b/src/corelib/kernel/qproperty.h 5 | @@ -16,8 +16,8 @@ 6 | 7 | #include 8 | 9 | -#if __has_include() && __cplusplus >= 202002L && !defined(Q_QDOC) 10 | +#if __has_include() && __cplusplus >= 202002L && !defined(Q_QDOC) && ( (defined(__cpp_consteval) && defined(_MSC_VER)) || !defined(_MSC_VER) ) 11 | #include 12 | #if defined(__cpp_lib_source_location) 13 | #define QT_SOURCE_LOCATION_NAMESPACE std 14 | #define QT_PROPERTY_COLLECT_BINDING_LOCATION 15 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qtbase/cmake/qt_install_copyright.cmake: -------------------------------------------------------------------------------- 1 | include_guard(GLOBAL) 2 | 3 | #Could probably be the beginning of a vcpkg_install_copyright? 4 | function(qt_install_copyright SOURCE_PATH) 5 | #Find the relevant license file and install it 6 | if(EXISTS "${SOURCE_PATH}/LICENSE.LGPLv3") 7 | set(LICENSE_PATH "${SOURCE_PATH}/LICENSE.LGPLv3") 8 | elseif(EXISTS "${SOURCE_PATH}/LICENSE.LGPL3") 9 | set(LICENSE_PATH "${SOURCE_PATH}/LICENSE.LGPL3") 10 | elseif(EXISTS "${SOURCE_PATH}/LICENSE.GPLv3") 11 | set(LICENSE_PATH "${SOURCE_PATH}/LICENSE.GPLv3") 12 | elseif(EXISTS "${SOURCE_PATH}/LICENSE.GPL3") 13 | set(LICENSE_PATH "${SOURCE_PATH}/LICENSE.GPL3") 14 | elseif(EXISTS "${SOURCE_PATH}/LICENSE.GPL3-EXCEPT") 15 | set(LICENSE_PATH "${SOURCE_PATH}/LICENSE.GPL3-EXCEPT") 16 | elseif(EXISTS "${SOURCE_PATH}/LICENSE.FDL") 17 | set(LICENSE_PATH "${SOURCE_PATH}/LICENSE.FDL") 18 | endif() 19 | if(LICENSE_PATH) 20 | file(INSTALL "${LICENSE_PATH}" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}" RENAME copyright) 21 | elseif(EXISTS "${SOURCE_PATH}/LICENSES") 22 | file(GLOB LICENSES "${SOURCE_PATH}/LICENSES/*") 23 | vcpkg_install_copyright(FILE_LIST ${LICENSES}) 24 | else() 25 | message(WARNING "No license/copyright file found!") 26 | endif() 27 | endfunction() 28 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qtbase/config_install.patch: -------------------------------------------------------------------------------- 1 | diff --git a/cmake/QtBuild.cmake b/cmake/QtBuild.cmake 2 | index bd186c28b..edee52e8b 100644 3 | --- a/cmake/QtBuild.cmake 4 | +++ b/cmake/QtBuild.cmake 5 | @@ -194,7 +194,7 @@ function(qt_internal_set_up_global_paths) 6 | if(QT_CONFIG_INSTALL_DIR) 7 | string(APPEND QT_CONFIG_INSTALL_DIR "/") 8 | endif() 9 | - string(APPEND QT_CONFIG_INSTALL_DIR ${__config_path_part}) 10 | + string(APPEND QT_CONFIG_INSTALL_DIR "share") 11 | 12 | set(QT_BUILD_DIR "${QT_BUILD_DIR}" PARENT_SCOPE) 13 | set(QT_INSTALL_DIR "${QT_INSTALL_DIR}" PARENT_SCOPE) 14 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qtbase/dont_force_cmakecache_latest.patch: -------------------------------------------------------------------------------- 1 | diff --git a/cmake/QtPostProcessHelpers.cmake b/cmake/QtPostProcessHelpers.cmake 2 | index 4f8106dfa..bec5c402e 100644 3 | --- a/cmake/QtPostProcessHelpers.cmake 4 | +++ b/cmake/QtPostProcessHelpers.cmake 5 | @@ -414,7 +414,7 @@ function(qt_generate_install_prefixes out_var) 6 | 7 | foreach(var ${vars}) 8 | get_property(docstring CACHE "${var}" PROPERTY HELPSTRING) 9 | - string(APPEND content "set(${var} \"${${var}}\" CACHE STRING \"${docstring}\" FORCE)\n") 10 | + string(APPEND content "set(${var} \"${${var}}\" CACHE STRING \"${docstring}\")\n") 11 | endforeach() 12 | 13 | set(${out_var} "${content}" PARENT_SCOPE) 14 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qtbase/env.patch: -------------------------------------------------------------------------------- 1 | diff --git a/cmake/QtTestHelpers.cmake b/cmake/QtTestHelpers.cmake 2 | index 279ab07dd..951fd3d36 100644 3 | --- a/cmake/QtTestHelpers.cmake 4 | +++ b/cmake/QtTestHelpers.cmake 5 | @@ -653,9 +653,9 @@ function(qt_internal_collect_command_environment out_path out_plugin_path) 6 | # The regular CMAKE_INSTALL_PREFIX can be different for example when building standalone tests. 7 | # Any given CMAKE_INSTALL_PREFIX takes priority over qt_relocatable_install_prefix for the 8 | # PATH environment variable. 9 | - set(install_prefixes "${CMAKE_INSTALL_PREFIX}") 10 | + set(install_prefixes "${CMAKE_INSTALL_PREFIX}$<$:/debug>") 11 | if(QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX) 12 | - list(APPEND install_prefixes "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}") 13 | + list(APPEND install_prefixes "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}$<$:/debug>") 14 | endif() 15 | 16 | file(TO_NATIVE_PATH "${CMAKE_CURRENT_BINARY_DIR}" test_env_path) 17 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qtbase/fix-host-aliasing.patch: -------------------------------------------------------------------------------- 1 | diff --git a/cmake/QtTargetHelpers.cmake b/cmake/QtTargetHelpers.cmake 2 | index 180ec33..a03e3b1 100644 3 | --- a/cmake/QtTargetHelpers.cmake 4 | +++ b/cmake/QtTargetHelpers.cmake 5 | @@ -281,10 +281,10 @@ function(qt_internal_add_target_aliases target) 6 | set_target_properties("${target}" PROPERTIES _qt_versionfull_alias "${versionfull_alias}") 7 | 8 | get_target_property(type "${target}" TYPE) 9 | - if (type STREQUAL EXECUTABLE) 10 | + if (type STREQUAL EXECUTABLE AND NOT TARGET "${versionfull_alias}") 11 | add_executable("${versionless_alias}" ALIAS "${target}") 12 | add_executable("${versionfull_alias}" ALIAS "${target}") 13 | - else() 14 | + elseif(NOT type STREQUAL EXECUTABLE) 15 | add_library("${versionless_alias}" ALIAS "${target}") 16 | add_library("${versionfull_alias}" ALIAS "${target}") 17 | endif() 18 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qtbase/fix_cmake_build.patch: -------------------------------------------------------------------------------- 1 | diff --git a/cmake/QtBuildInternalsExtra.cmake.in b/cmake/QtBuildInternalsExtra.cmake.in 2 | index ffc9d90f8..0b3a7d59e 100644 3 | --- a/cmake/QtBuildInternalsExtra.cmake.in 4 | +++ b/cmake/QtBuildInternalsExtra.cmake.in 5 | @@ -51,8 +51,8 @@ endif() 6 | set(QT_WILL_INSTALL @QT_WILL_INSTALL@ CACHE BOOL 7 | "Boolean indicating if doing a Qt prefix build (vs non-prefix build)." FORCE) 8 | 9 | -set(QT_SOURCE_TREE "@QT_SOURCE_TREE@" CACHE PATH 10 | -"A path to the source tree of the previously configured QtBase project." FORCE) 11 | +# set(QT_SOURCE_TREE "@QT_SOURCE_TREE@" CACHE PATH 12 | +# "A path to the source tree of the previously configured QtBase project." FORCE) 13 | 14 | # Propagate decision of building tests and examples to other repositories. 15 | set(QT_BUILD_TESTS @QT_BUILD_TESTS@ CACHE BOOL "Build the testing tree.") 16 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qtbase/fix_cmake_build_type.patch: -------------------------------------------------------------------------------- 1 | diff --git a/cmake/QtBuildInternalsExtra.cmake.in b/cmake/QtBuildInternalsExtra.cmake.in 2 | index 21c40f2..c212148 100644 3 | --- a/cmake/QtBuildInternalsExtra.cmake.in 4 | +++ b/cmake/QtBuildInternalsExtra.cmake.in 5 | @@ -162,6 +162,7 @@ function(qt_internal_force_set_cmake_build_type_conditionally value) 6 | # STREQUAL check needs to be expanded variables because an undefined var is not equal to an 7 | # empty defined var. 8 | if("${CMAKE_BUILD_TYPE}" STREQUAL "${CMAKE_BUILD_TYPE_INIT}" 9 | + AND NOT DEFINED CACHE{CMAKE_BUILD_TYPE} 10 | AND NOT __qt_toolchain_cmake_build_type_before_project_call 11 | AND NOT QT_NO_FORCE_SET_CMAKE_BUILD_TYPE 12 | AND NOT __qt_internal_extras_is_multi_config) 13 | diff --git a/cmake/QtSetup.cmake b/cmake/QtSetup.cmake 14 | index 762299f..f104479 100644 15 | --- a/cmake/QtSetup.cmake 16 | +++ b/cmake/QtSetup.cmake 17 | @@ -56,6 +56,7 @@ get_property(QT_GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CON 18 | # See also qt_internal_force_set_cmake_build_type_conditionally which is used 19 | # to set the build type when building other repos or tests. 20 | if("${CMAKE_BUILD_TYPE}" STREQUAL "${CMAKE_BUILD_TYPE_INIT}" 21 | + AND NOT DEFINED CACHE{CMAKE_BUILD_TYPE} 22 | AND NOT __qt_auto_detect_cmake_build_type_before_project_call 23 | AND NOT __qt_build_internals_cmake_build_type 24 | AND NOT CMAKE_CONFIGURATION_TYPES) 25 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qtbase/fix_egl.patch: -------------------------------------------------------------------------------- 1 | diff --git a/cmake/3rdparty/extra-cmake-modules/find-modules/FindEGL.cmake b/cmake/3rdparty/extra-cmake-modules/find-modules/FindEGL.cmake 2 | index eafbc1ff9..dd4068838 100644 3 | --- a/cmake/3rdparty/extra-cmake-modules/find-modules/FindEGL.cmake 4 | +++ b/cmake/3rdparty/extra-cmake-modules/find-modules/FindEGL.cmake 5 | @@ -82,6 +82,7 @@ find_path(EGL_INCLUDE_DIR 6 | find_library(EGL_LIBRARY 7 | NAMES 8 | EGL 9 | + libEGL # required to find angle on windows within vcpkg. 10 | HINTS 11 | ${PKG_EGL_LIBRARY_DIRS} 12 | ) 13 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qtbase/fix_egl_2.patch: -------------------------------------------------------------------------------- 1 | diff --git a/cmake/3rdparty/extra-cmake-modules/find-modules/FindEGL.cmake b/cmake/3rdparty/extra-cmake-modules/find-modules/FindEGL.cmake 2 | index db48f79b9..4b1686132 100644 3 | --- a/cmake/3rdparty/extra-cmake-modules/find-modules/FindEGL.cmake 4 | +++ b/cmake/3rdparty/extra-cmake-modules/find-modules/FindEGL.cmake 5 | @@ -116,7 +116,7 @@ if(EGL_INCLUDE_DIR) 6 | unset(_EGL_version_lines) 7 | endif() 8 | 9 | -cmake_push_check_state(RESET) 10 | +cmake_push_check_state() # To be able to fix the compile check in vcpkg-cmake-wrapper 11 | list(APPEND CMAKE_REQUIRED_LIBRARIES "${EGL_LIBRARY}") 12 | list(APPEND CMAKE_REQUIRED_INCLUDES "${EGL_INCLUDE_DIR}") 13 | list(APPEND CMAKE_REQUIRED_DEFINITIONS "${EGL_DEFINITIONS}") 14 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qtbase/harfbuzz.patch: -------------------------------------------------------------------------------- 1 | diff --git a/cmake/FindWrapSystemHarfbuzz.cmake b/cmake/FindWrapSystemHarfbuzz.cmake 2 | index 3cb44aa76..9bf0d7165 100644 3 | --- a/cmake/FindWrapSystemHarfbuzz.cmake 4 | +++ b/cmake/FindWrapSystemHarfbuzz.cmake 5 | @@ -6,7 +6,7 @@ if(TARGET WrapSystemHarfbuzz::WrapSystemHarfbuzz) 6 | endif() 7 | set(WrapSystemHarfbuzz_REQUIRED_VARS __harfbuzz_found) 8 | 9 | -find_package(harfbuzz ${${CMAKE_FIND_PACKAGE_NAME}_FIND_VERSION} QUIET) 10 | +find_package(harfbuzz QUIET) # VCPKG is missing the version file for harfbuzz. 11 | 12 | # Gentoo has some buggy version of a harfbuzz Config file. Check if include paths are valid. 13 | set(__harfbuzz_target_name "harfbuzz::harfbuzz") 14 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qtbase/installed_dir.patch: -------------------------------------------------------------------------------- 1 | diff --git a/cmake/qt.toolchain.cmake.in b/cmake/qt.toolchain.cmake.in 2 | index 6e37ae02..e7e84468 100644 3 | --- a/cmake/qt.toolchain.cmake.in 4 | +++ b/cmake/qt.toolchain.cmake.in 5 | @@ -65,6 +65,10 @@ get_filename_component(QT_TOOLCHAIN_RELOCATABLE_INSTALL_PREFIX 6 | # one level higher is what we're looking for. 7 | get_filename_component(QT_TOOLCHAIN_RELOCATABLE_CMAKE_DIR "${CMAKE_CURRENT_LIST_DIR}/.." ABSOLUTE) 8 | 9 | +get_filename_component(vcpkg_installed_dir 10 | + ${CMAKE_CURRENT_LIST_DIR}/../../../ 11 | + ABSOLUTE) 12 | + 13 | # REROOT_PATH_ISSUE_MARKER 14 | # There's a subdirectory check in cmake's cmFindCommon::RerootPaths() function, that doesn't handle 15 | # the case of CMAKE_PREFIX_PATH == CMAKE_FIND_ROOT_PATH for a particular pair of entries. 16 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qtbase/patches/0001-CVE-2023-51714-qtbase-6.6.diff: -------------------------------------------------------------------------------- 1 | From 13c16b756900fe524f6d9534e8a07aa003c05e0c Mon Sep 17 00:00:00 2001 2 | From: Marc Mutz 3 | Date: Tue, 12 Dec 2023 20:51:56 +0100 4 | Subject: [PATCH] HPack: fix a Yoda Condition 5 | 6 | Putting the variable on the LHS of a relational operation makes the 7 | expression easier to read. In this case, we find that the whole 8 | expression is nonsensical as an overflow protection, because if 9 | name.size() + value.size() overflows, the result will exactly _not_ 10 | be > max() - 32, because UB will have happened. 11 | 12 | To be fixed in a follow-up commit. 13 | 14 | As a drive-by, add parentheses around the RHS. 15 | 16 | Pick-to: 6.5 6.2 5.15 17 | Change-Id: I35ce598884c37c51b74756b3bd2734b9aad63c09 18 | Reviewed-by: Allan Sandfeld Jensen 19 | (cherry picked from commit 658607a34ead214fbacbc2cca44915655c318ea9) 20 | Reviewed-by: Qt Cherry-pick Bot 21 | (cherry picked from commit 4f7efd41740107f90960116700e3134f5e433867) 22 | --- 23 | 24 | diff --git a/src/network/access/http2/hpacktable.cpp b/src/network/access/http2/hpacktable.cpp 25 | index 74a09a2..c8c5d09 100644 26 | --- a/src/network/access/http2/hpacktable.cpp 27 | +++ b/src/network/access/http2/hpacktable.cpp 28 | @@ -27,7 +27,7 @@ 29 | // 32 octets of overhead." 30 | 31 | const unsigned sum = unsigned(name.size() + value.size()); 32 | - if (std::numeric_limits::max() - 32 < sum) 33 | + if (sum > (std::numeric_limits::max() - 32)) 34 | return HeaderSize(); 35 | return HeaderSize(true, quint32(sum + 32)); 36 | } 37 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qtbase/patches/0002-CVE-2023-51714-qtbase-6.6.diff: -------------------------------------------------------------------------------- 1 | From 811b9eef6d08d929af8708adbf2a5effb0eb62d7 Mon Sep 17 00:00:00 2001 2 | From: Marc Mutz 3 | Date: Tue, 12 Dec 2023 22:08:07 +0100 4 | Subject: [PATCH] HPack: fix incorrect integer overflow check 5 | 6 | This code never worked: 7 | 8 | For the comparison with max() - 32 to trigger, on 32-bit platforms (or 9 | Qt 5) signed interger overflow would have had to happen in the 10 | addition of the two sizes. The compiler can therefore remove the 11 | overflow check as dead code. 12 | 13 | On Qt 6 and 64-bit platforms, the signed integer addition would be 14 | very unlikely to overflow, but the following truncation to uint32 15 | would yield the correct result only in a narrow 32-value window just 16 | below UINT_MAX, if even that. 17 | 18 | Fix by using the proper tool, qAddOverflow. 19 | 20 | Pick-to: 6.5 6.2 5.15 21 | Change-Id: I7599f2e75ff7f488077b0c60b81022591005661c 22 | Reviewed-by: Allan Sandfeld Jensen 23 | (cherry picked from commit ee5da1f2eaf8932aeca02ffea6e4c618585e29e3) 24 | Reviewed-by: Qt Cherry-pick Bot 25 | (cherry picked from commit debeb8878da2dc706ead04b6072ecbe7e5313860) 26 | Reviewed-by: Thiago Macieira 27 | Reviewed-by: Marc Mutz 28 | --- 29 | 30 | diff --git a/src/network/access/http2/hpacktable.cpp b/src/network/access/http2/hpacktable.cpp 31 | index c8c5d09..2c728b3 100644 32 | --- a/src/network/access/http2/hpacktable.cpp 33 | +++ b/src/network/access/http2/hpacktable.cpp 34 | @@ -26,7 +26,9 @@ 35 | // for counting the number of references to the name and value would have 36 | // 32 octets of overhead." 37 | 38 | - const unsigned sum = unsigned(name.size() + value.size()); 39 | + size_t sum; 40 | + if (qAddOverflow(size_t(name.size()), size_t(value.size()), &sum)) 41 | + return HeaderSize(); 42 | if (sum > (std::numeric_limits::max() - 32)) 43 | return HeaderSize(); 44 | return HeaderSize(true, quint32(sum + 32)); 45 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qtbase/qmake.debug.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | "%0\..\qmake.exe" -qtconf "%0\..\qt.debug.conf" %* 3 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qtbase/qt.conf.in: -------------------------------------------------------------------------------- 1 | [DevicePaths] 2 | Prefix=${CURRENT_INSTALLED_DIR} 3 | Headers=include/@QT6_DIRECTORY_PREFIX@ 4 | Libraries=@REL_PATH@lib 5 | Plugins=@REL_PATH@@QT6_DIRECTORY_PREFIX@plugins 6 | Qml2Imports=@REL_PATH@@QT6_DIRECTORY_PREFIX@qml 7 | Documentation=doc/@QT6_DIRECTORY_PREFIX@ 8 | Binaries=@REL_PATH@bin 9 | LibraryExecutables=tools/Qt6/bin 10 | ArchData=share/Qt6 11 | Data=share/Qt6 12 | Translations=translations/@QT6_DIRECTORY_PREFIX@ 13 | Examples=share/examples/@QT6_DIRECTORY_PREFIX@ 14 | [Paths] 15 | Prefix=${CURRENT_INSTALLED_DIR} 16 | Headers=include/@QT6_DIRECTORY_PREFIX@ 17 | Libraries=@REL_PATH@lib 18 | Plugins=@REL_PATH@@QT6_DIRECTORY_PREFIX@plugins 19 | Qml2Imports=@REL_PATH@@QT6_DIRECTORY_PREFIX@qml 20 | Documentation=doc/@QT6_DIRECTORY_PREFIX@ 21 | Binaries=@REL_PATH@bin 22 | LibraryExecutables=tools/Qt6/bin 23 | ArchData=share/Qt6 24 | Data=share/Qt6 25 | Translations=translations/@QT6_DIRECTORY_PREFIX@ 26 | Examples=share/examples/@QT6_DIRECTORY_PREFIX@ 27 | HostPrefix=${CURRENT_HOST_INSTALLED_DIR} 28 | HostData=@REL_HOST_TO_DATA@share/Qt6 29 | HostBinaries=@REL_PATH@bin 30 | HostLibraries=@REL_PATH@lib 31 | HostLibraryExecutables=tools/Qt6/bin 32 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qtbase/qtpaths.debug.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | "%0\..\qtpaths.exe" --qtconf "%0\..\qt.debug.conf" %* 3 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qtbase/windeployqt.debug.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | setlocal enabledelayedexpansion 3 | set mypath=%~dp0 4 | set mypath=%mypath:~0,-1% 5 | set BAKCD=!CD! 6 | cd /D %mypath%\..\..\..\debug\bin 7 | set PATH=!CD!;%PATH% 8 | cd %BAKCD% 9 | "%mypath%\windeployqt6.exe" --qtpaths "%mypath%\qtpaths.debug.bat" %* 10 | endlocal 11 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qtkeychain-qt6/dbus-fix-config.patch: -------------------------------------------------------------------------------- 1 | diff --git a/QtKeychainConfig.cmake.in b/QtKeychainConfig.cmake.in 2 | --- QtKeychainConfig.cmake.in 3 | +++ QtKeychainConfig.cmake.in 4 | @@ -14,7 +14,7 @@ 5 | 6 | find_dependency(Qt@QTKEYCHAIN_VERSION_INFIX@Core) 7 | 8 | -if(UNIX AND NOT APPLE AND NOT ANDROID) 9 | +if(UNIX AND NOT APPLE AND NOT ANDROID AND NOT EMSCRIPTEN) 10 | find_dependency(Qt@QTKEYCHAIN_VERSION_INFIX@DBus) 11 | endif() 12 | 13 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qtkeychain-qt6/dbus-fix.patch: -------------------------------------------------------------------------------- 1 | diff --git a/CMakeLists.txt b/CMakeLists.txt 2 | --- CMakeLists.txt 3 | +++ CMakeLists.txt 4 | @@ -65,7 +65,7 @@ 5 | set(QTANDROIDEXTRAS_LIBRARIES ${Qt5AndroidExtras_LIBRARIES}) 6 | endif() 7 | 8 | - if(UNIX AND NOT APPLE AND NOT ANDROID AND NOT HAIKU) 9 | + if(UNIX AND NOT APPLE AND NOT ANDROID AND NOT HAIKU AND NOT EMSCRIPTEN) 10 | find_package(Qt5 COMPONENTS DBus REQUIRED) 11 | include_directories(${Qt5DBus_INCLUDE_DIRS}) 12 | set(QTDBUS_LIBRARIES ${Qt5DBus_LIBRARIES}) 13 | @@ -95,7 +95,7 @@ 14 | set(QTKEYCHAIN_VERSION_INFIX 6) 15 | 16 | 17 | - if(UNIX AND NOT APPLE AND NOT ANDROID AND NOT HAIKU) 18 | + if(UNIX AND NOT APPLE AND NOT ANDROID AND NOT HAIKU AND NOT EMSCRIPTEN) 19 | find_package(Qt6 COMPONENTS DBus REQUIRED) 20 | include_directories(${Qt6DBus_INCLUDE_DIRS}) 21 | set(QTDBUS_LIBRARIES ${Qt6DBus_LIBRARIES}) 22 | @@ -168,7 +168,7 @@ 23 | list(APPEND qtkeychain_LIBRARIES ${BE_LIBRARY}) 24 | endif() 25 | 26 | -if(UNIX AND NOT APPLE AND NOT ANDROID AND NOT HAIKU) 27 | +if(UNIX AND NOT APPLE AND NOT ANDROID AND NOT HAIKU AND NOT EMSCRIPTEN) 28 | option(LIBSECRET_SUPPORT "Build with libsecret support" ON) 29 | 30 | if(LIBSECRET_SUPPORT) 31 | @@ -305,7 +305,7 @@ 32 | PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/Qt${QTKEYCHAIN_VERSION_INFIX}KeychainConfigVersion.cmake" 33 | SOVERSION ${QTKEYCHAIN_VERSION}) 34 | 35 | -if(UNIX AND NOT APPLE AND NOT ANDROID AND NOT HAIKU) 36 | +if(UNIX AND NOT APPLE AND NOT ANDROID AND NOT HAIKU AND NOT EMSCRIPTEN) 37 | set(PRI_EXTRA_DEPS "dbus") 38 | endif() 39 | ecm_generate_pri_file(BASE_NAME Qt${QTKEYCHAIN_VERSION_INFIX}Keychain 40 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qtkeychain-qt6/portfile.cmake: -------------------------------------------------------------------------------- 1 | message(WARNING "qtkeychain is a third-party extension to Qt and is not affiliated with The Qt Company") 2 | 3 | vcpkg_from_github( 4 | OUT_SOURCE_PATH SOURCE_PATH 5 | REPO frankosterfeld/qtkeychain 6 | REF v0.14.0 7 | SHA512 65118198d82f284c1bb914964657e62fccb81050359071b44530574c73c673913d22b5de17cc30e9099feca06ece556bb9329350f017ce331e845ba074d1f078 8 | HEAD_REF master 9 | PATCHES 10 | dbus-fix.patch 11 | dbus-fix-config.patch 12 | ) 13 | 14 | # Opportunity to build without dependency on qt5-tools/qt5-declarative 15 | set(BUILD_TRANSLATIONS OFF) 16 | if("translations" IN_LIST FEATURES) 17 | set(BUILD_TRANSLATIONS ON) 18 | endif() 19 | 20 | vcpkg_cmake_configure( 21 | DISABLE_PARALLEL_CONFIGURE 22 | SOURCE_PATH ${SOURCE_PATH} 23 | OPTIONS 24 | -DBUILD_WITH_QT6=ON 25 | -DBUILD_TEST_APPLICATION=OFF 26 | -DBUILD_TRANSLATIONS=${BUILD_TRANSLATIONS} 27 | -DBUILD_TOOLS=OFF 28 | -DWITH_nss_PLUGIN=OFF 29 | -DWITH_pkcs11_PLUGIN=OFF 30 | ) 31 | 32 | vcpkg_cmake_install() 33 | vcpkg_copy_pdbs() 34 | vcpkg_cmake_config_fixup(CONFIG_PATH lib/cmake/Qt6Keychain PACKAGE_NAME Qt6Keychain) 35 | 36 | # Remove unneeded dirs 37 | file(REMOVE_RECURSE 38 | "${CURRENT_PACKAGES_DIR}/debug/include" 39 | "${CURRENT_PACKAGES_DIR}/debug/share" 40 | ) 41 | 42 | # Handle copyright 43 | file(INSTALL "${SOURCE_PATH}/COPYING" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}" RENAME copyright) 44 | -------------------------------------------------------------------------------- /build/vcpkg-ports/qtkeychain-qt6/vcpkg.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "qtkeychain-qt6", 3 | "version": "0.14.0", 4 | "port-version": 0, 5 | "description": "(Unaffiliated with Qt) Platform-independent Qt5 API for storing passwords securely", 6 | "homepage": "https://github.com/frankosterfeld/qtkeychain", 7 | "license": "BSD-3-Clause", 8 | "dependencies": [ 9 | { 10 | "name": "qt5compat", 11 | "default-features": false 12 | }, 13 | { 14 | "name": "qtbase", 15 | "default-features": false 16 | }, 17 | { 18 | "name": "vcpkg-cmake", 19 | "host": true 20 | }, 21 | { 22 | "name": "vcpkg-cmake-config", 23 | "host": true 24 | } 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /build/vcpkg-toolchains/qgis-js.cmake: -------------------------------------------------------------------------------- 1 | 2 | message(STATUS "Using 'qgis-js' toolchain") 3 | 4 | # use/derrive EMSDK and EMSCRIPTEN_ROOT to locate EMSCRIPTEN_TOOLCHAIN_FILE 5 | if(NOT DEFINED ENV{EMSDK}) 6 | get_filename_component(QGIS_JS_BUILD_EMSDK 7 | "${CMAKE_CURRENT_LIST_DIR}/../emsdk" 8 | ABSOLUTE) 9 | set(ENV{EMSDK} ${QGIS_JS_BUILD_EMSDK}) 10 | endif() 11 | if(NOT EMSCRIPTEN_ROOT) 12 | if(NOT DEFINED ENV{EMSDK}) 13 | message(FATAL_ERROR "emsdk not found") 14 | endif() 15 | set(EMSCRIPTEN_ROOT "$ENV{EMSDK}/upstream/emscripten") 16 | endif() 17 | if(NOT DEFINED ENV{EMSCRIPTEN_ROOT}) 18 | set(ENV{EMSCRIPTEN_ROOT} ${EMSCRIPTEN_ROOT}) 19 | endif() 20 | set(EMSCRIPTEN_TOOLCHAIN_FILE ${EMSCRIPTEN_ROOT}/cmake/Modules/Platform/Emscripten.cmake) 21 | if(NOT EXISTS ${EMSCRIPTEN_TOOLCHAIN_FILE}) 22 | message(FATAL_ERROR "Emscripten.cmake toolchain file not found") 23 | endif() 24 | 25 | # determine QT_TOOLCHAIN_FILE path 26 | get_filename_component(VCPKG_ROOT_DIR ${CMAKE_TOOLCHAIN_FILE} DIRECTORY) 27 | get_filename_component(VCPKG_ROOT_DIR ${VCPKG_ROOT_DIR} DIRECTORY) 28 | get_filename_component(VCPKG_BUILDTREE_PATH "${VCPKG_ROOT_DIR}/../buildtrees" ABSOLUTE) 29 | # TODO: is it ok to assume -rel? 30 | set("QT_TOOLCHAIN_FILE" ${VCPKG_BUILDTREE_PATH}/qtbase/${VCPKG_TARGET_TRIPLET}-rel/lib/cmake/Qt6/qt.toolchain.cmake ) 31 | 32 | # setup vcpkg chainload toolchain file 33 | if(EXISTS ${QT_TOOLCHAIN_FILE}) 34 | # during "compile" the qt.toolchain.cmake is used, and the EMSCRIPTEN_TOOLCHAIN_FILE is chainloaded by it 35 | set(QT_CHAINLOAD_TOOLCHAIN_FILE ${EMSCRIPTEN_TOOLCHAIN_FILE}) 36 | include(${QT_TOOLCHAIN_FILE}) 37 | message(STATUS "CMake toolchains: vcpkg.cmake -> qgis-js.cmake -> qt.toolchain.cmake -> Emscripten.cmake") 38 | else() 39 | # during "install" Qt6_DIR has not to be set, EMSCRIPTEN_TOOLCHAIN_FILE will used directly by vcpkg 40 | set(VCPKG_CHAINLOAD_TOOLCHAIN_FILE ${EMSCRIPTEN_TOOLCHAIN_FILE}) 41 | message(STATUS "CMake toolchains: vcpkg.cmake -> qgis-js.cmake -> Emscripten.cmake") 42 | endif() 43 | 44 | # flags that have to be set across all ports and qgis-js itself 45 | set(QGIS_JS_FLAGS "-pthread -fwasm-exceptions -msimd128") 46 | 47 | set(CMAKE_C_FLAGS_INIT "${CMAKE_C_FLAGS_INIT} ${QGIS_JS_FLAGS}") 48 | set(CMAKE_CXX_FLAGS_INIT "${CMAKE_CXX_FLAGS_INIT} ${QGIS_JS_FLAGS}") 49 | -------------------------------------------------------------------------------- /build/vcpkg-triplets/wasm32-emscripten-qt-threads.cmake: -------------------------------------------------------------------------------- 1 | message(STATUS "Using 'wasm32-emscripten-qt-threads' triplet") 2 | 3 | set(VCPKG_TARGET_ARCHITECTURE wasm32) 4 | set(VCPKG_CRT_LINKAGE dynamic) 5 | set(VCPKG_LIBRARY_LINKAGE static) 6 | set(VCPKG_CMAKE_SYSTEM_NAME Emscripten) 7 | 8 | # to avoid building both debug and release of all libs uncomment the following line 9 | # set(VCPKG_BUILD_TYPE "release") 10 | 11 | set(VCPKG_ENV_PASSTHROUGH_UNTRACKED EMSDK EMSCRIPTEN EMSCRIPTEN_ROOT PATH) 12 | 13 | # this needs to be present for vcpkg installs, but also the same VCPKG_CHAINLOAD_TOOLCHAIN_FILE 14 | # needs to be present when running CMake so that the project gets it 15 | get_filename_component(QGISJS_TOOLCHAIN_FILE 16 | "${CMAKE_CURRENT_LIST_DIR}/../vcpkg-toolchains/qgis-js.cmake" 17 | ABSOLUTE) 18 | set(VCPKG_CHAINLOAD_TOOLCHAIN_FILE ${QGISJS_TOOLCHAIN_FILE}) 19 | 20 | set(VCPKG_ENV_PASSTHROUGH_UNTRACKED EMSDK EMSCRIPTEN EMSCRIPTEN_ROOT PATH) 21 | 22 | -------------------------------------------------------------------------------- /build/vite/CrossOriginIsolationPlugin.ts: -------------------------------------------------------------------------------- 1 | import type { Plugin } from "vite"; 2 | 3 | export const CrossOriginIsolationResponseHeaders = { 4 | "Cross-Origin-Opener-Policy": "same-origin", 5 | "Cross-Origin-Embedder-Policy": "require-corp", 6 | }; 7 | 8 | /** 9 | * A Vite plugin that adds Cross-Origin Isolation headers to the server responses. 10 | */ 11 | export default function CrossOriginIsolationPlugin(): Plugin { 12 | return { 13 | name: "CrossOriginIsolationPlugin", 14 | configureServer(server) { 15 | server.middlewares.use((_req, res, next) => { 16 | Object.entries(CrossOriginIsolationResponseHeaders).forEach( 17 | ([key, value]) => { 18 | res.setHeader(key, value); 19 | }, 20 | ); 21 | next(); 22 | }); 23 | }, 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /build/vite/DirectoryListingPlugin.ts: -------------------------------------------------------------------------------- 1 | import { File, Folder } from "../../packages/qgis-js-utils"; 2 | 3 | import type { Plugin, ResolvedConfig } from "vite"; 4 | 5 | import { basename, resolve, join } from "path"; 6 | import { readdir } from "fs/promises"; 7 | import { Dirent } from "fs"; 8 | 9 | const FILTER_LIST = [".DS_Store", ".git", ".gitignore", ".env"]; 10 | const DIRECTORY_LISTING_FILENAME = "directory-listing.json"; 11 | 12 | let config: ResolvedConfig; 13 | 14 | export default function DirectoryListingPlugin( 15 | directories: string | string[], 16 | ): Plugin { 17 | const directoriesToList = 18 | typeof directories === "string" ? [directories] : directories; 19 | for (const directory of directoriesToList) { 20 | if (!directory.startsWith("public/")) { 21 | throw new Error( 22 | `DirectoryListingPlugin: Directory ${directory} is not in the public folder`, 23 | ); 24 | } 25 | } 26 | return { 27 | name: "DirectoryListingPlugin", 28 | configResolved(_config) { 29 | config = _config; 30 | }, 31 | configureServer(server) { 32 | const dirs = directoriesToList.map( 33 | (directory) => 34 | config.base + 35 | directory.replace(/^public\//, "") + 36 | `/${DIRECTORY_LISTING_FILENAME}`, 37 | ); 38 | server.middlewares.use(async (req, res, next) => { 39 | if (req.url && dirs.includes(req.url)) { 40 | let dir = req.url; 41 | // remove potential base from start of the url 42 | if (dir.startsWith(config.base)) { 43 | dir = dir.slice(config.base.length); 44 | } 45 | // remove filename from url at the end 46 | dir = dir.slice(0, -`/${DIRECTORY_LISTING_FILENAME}`.length); 47 | 48 | const dirParts = dir.split("/"); 49 | const dirBase = dirParts.slice(0, -1).join("/"); 50 | const dirName = dirParts[dirParts.length - 1]; 51 | 52 | const drectoryListing = await createDirectoryListing( 53 | join(process.cwd(), "public", dirBase), 54 | dirName, 55 | ".", 56 | ); 57 | res.setHeader("Content-Type", "application/json"); 58 | res.end(JSON.stringify(drectoryListing, null, 2)); 59 | } else { 60 | next(); 61 | } 62 | }); 63 | }, 64 | async generateBundle() { 65 | for (const dir of directoriesToList.map((directory) => 66 | directory.replace(/^public\//, ""), 67 | )) { 68 | const drectoryListing = await createDirectoryListing( 69 | join(process.cwd(), "public"), 70 | dir, 71 | ".", 72 | ); 73 | this.emitFile({ 74 | type: "asset", 75 | fileName: dir + `/${DIRECTORY_LISTING_FILENAME}`, 76 | source: JSON.stringify(drectoryListing, null, 2), 77 | }); 78 | } 79 | }, 80 | }; 81 | } 82 | 83 | async function readFolder(folder: string): Promise { 84 | return await readdir(folder, { withFileTypes: true }); 85 | } 86 | 87 | async function createDirectoryListing( 88 | root: string, 89 | base: string, 90 | directory: string, 91 | ) { 92 | const directoryListing = await readFolder(join(root, base, directory)); 93 | return directoryListing 94 | .filter((dirent) => dirent.isFile || dirent.isDirectory) 95 | .filter((dirent) => !FILTER_LIST.includes(dirent.name)) 96 | .reduce( 97 | async (currentFolderPromise, entry: Dirent) => { 98 | const currentFolder = (await currentFolderPromise) as Folder; 99 | if (entry.isDirectory()) { 100 | currentFolder.entries.push( 101 | await createDirectoryListing( 102 | root, 103 | join(base, directory), 104 | entry.name, 105 | ), 106 | ); 107 | } else { 108 | currentFolder.entries.push({ 109 | name: entry.name, 110 | path: join(currentFolder.path, entry.name), 111 | type: "File", 112 | } as File); 113 | } 114 | return currentFolder; 115 | }, 116 | Promise.resolve({ 117 | name: basename(resolve(join(base, directory))), 118 | path: join(base, directory), 119 | type: "Folder", 120 | entries: [], 121 | } as Folder), 122 | ); 123 | } 124 | -------------------------------------------------------------------------------- /build/vite/QgisRuntimePlugin.ts: -------------------------------------------------------------------------------- 1 | import { join, resolve, basename } from "path"; 2 | import { existsSync, readFileSync } from "fs"; 3 | import { dirname } from "path"; 4 | import { fileURLToPath } from "url"; 5 | 6 | import { CrossOriginIsolationResponseHeaders } from "./CrossOriginIsolationPlugin"; 7 | 8 | import type { Plugin, ResolvedConfig } from "vite"; 9 | 10 | const __dirname = dirname(fileURLToPath(import.meta.url)); 11 | 12 | const RUNTIME_JS = "js"; 13 | const RUNTIME_WASM = "wasm"; 14 | const RUNTIME_WASM_MAP = "wasm.map"; 15 | const RUNTIME_WASM_DEBUG = "wasm.debug.wasm"; 16 | const RUNTIME_DATA = "data"; 17 | 18 | export const BASE_DIR = "wasm"; 19 | 20 | export interface Runtime { 21 | name: string; 22 | outputDir: string; 23 | } 24 | 25 | function patchEmccJs(content: string): string { 26 | // prevent setting of read-only property "stack" in Firefox 27 | // (will throw an error in strict mode) 28 | const search = `e.stack = arr.join("\\n");`; 29 | return content.replaceAll( 30 | search, 31 | `if (! (navigator.userAgent.indexOf("Firefox") !== -1)) { ${search} }`, 32 | ); 33 | } 34 | 35 | export default function QgisRuntimePlugin(_runtime: Runtime | null): Plugin { 36 | let runtime: Runtime; 37 | if (_runtime === null) { 38 | throw new Error("QgisRuntimePlugin: No runtime specified"); 39 | } else { 40 | runtime = _runtime; 41 | } 42 | 43 | let config: ResolvedConfig; 44 | let runtimeDir = () => `${config.build.assetsDir}/${BASE_DIR}`; 45 | 46 | const repoRoot = resolve(__dirname, "../.."); 47 | 48 | function file(ending: string) { 49 | return `${runtime.name}.${ending}`; 50 | } 51 | 52 | const fileRuntimeJs = file(RUNTIME_JS); 53 | const fileRuntimeWasm = file(RUNTIME_WASM); 54 | const fileRuntimeWasmMap = file(RUNTIME_WASM_MAP); 55 | const fileRuntimeWasmDebug = file(RUNTIME_WASM_DEBUG); 56 | const fileRuntimeData = file(RUNTIME_DATA); 57 | 58 | const filesRuntime = [ 59 | fileRuntimeJs, 60 | fileRuntimeWasmMap, 61 | fileRuntimeWasmDebug, 62 | fileRuntimeWasm, 63 | fileRuntimeData, 64 | ]; 65 | 66 | return { 67 | name: "QgisRuntimePlugin", 68 | enforce: "pre", 69 | configResolved(_config) { 70 | config = _config; 71 | }, 72 | configureServer(server) { 73 | const filesRuntimeDir = runtimeDir(); 74 | const runtimeFiles = filesRuntime.map( 75 | (id) => 76 | `${config.base}${filesRuntimeDir ? filesRuntimeDir + "/" : ""}${id}`, 77 | ); 78 | server.middlewares.use((req, res, next) => { 79 | if ( 80 | req.url && 81 | runtimeFiles.some((runtimefile) => runtimefile === req.url) 82 | ) { 83 | const filePath = join(repoRoot, runtime.outputDir, basename(req.url)); 84 | if (existsSync(filePath)) { 85 | const raw = readFileSync(filePath); 86 | res.statusCode = 200; 87 | Object.entries(CrossOriginIsolationResponseHeaders).forEach( 88 | ([key, value]) => { 89 | res.setHeader(key, value); 90 | }, 91 | ); 92 | if ( 93 | filePath.endsWith("." + RUNTIME_WASM) || 94 | filePath.endsWith("." + RUNTIME_DATA) 95 | ) { 96 | if (filePath.endsWith("." + RUNTIME_WASM)) { 97 | res.setHeader("Content-Type", "application/wasm"); 98 | } 99 | res.end(raw); 100 | } else if (filePath.endsWith("." + RUNTIME_JS)) { 101 | const content = raw.toString(); 102 | res.setHeader("Content-Type", "application/javascript"); 103 | res.end(patchEmccJs(content)); 104 | } else if (filePath.endsWith("." + RUNTIME_WASM_MAP)) { 105 | const content = raw.toString(); 106 | res.setHeader("Content-Type", "application/json"); 107 | res.end(content); 108 | } 109 | } else { 110 | console.log("404", filePath); 111 | res.statusCode = 404; 112 | res.end(); 113 | } 114 | } else { 115 | next(); 116 | } 117 | }); 118 | }, 119 | generateBundle() { 120 | filesRuntime.forEach((id) => { 121 | const filesRuntimeDir = runtimeDir(); 122 | const filePath = join(repoRoot, runtime.outputDir, id); 123 | if (existsSync(filePath)) { 124 | const raw = readFileSync(filePath); 125 | 126 | let source = raw as Uint8Array; 127 | 128 | if (filePath.endsWith("." + RUNTIME_JS)) { 129 | const encoder = new TextEncoder(); 130 | const content = patchEmccJs(raw.toString()); 131 | source = encoder.encode(content); 132 | } 133 | 134 | this.emitFile({ 135 | fileName: `${filesRuntimeDir ? filesRuntimeDir + "/" : ""}${id}`, 136 | type: "asset", 137 | source, 138 | }); 139 | } 140 | }); 141 | }, 142 | }; 143 | } 144 | -------------------------------------------------------------------------------- /docs/architecture.md: -------------------------------------------------------------------------------- 1 | # Architecture 2 | 3 | ## qgis-js Repository 4 | 5 | ## qgis-js Build 6 | 7 | ## qgis-js Runtime 8 | -------------------------------------------------------------------------------- /docs/bundling.md: -------------------------------------------------------------------------------- 1 | # Bundling 2 | 3 | qgis-js consists of two parts: The runtime generated by Emscripten and the TypeScript/JavaScript API, that can be seen as a wrapper around the runtime. The wrapper can be imported, used and bundled (e.g. tree-shaked) like any other JavaScript library. But it is important that the runtime is not modified and served as is. 4 | 5 | See the [`qgis-js` Package `README.md`](../packages/qgis-js/README.md) for more information about the files involved. Everything inside `assets/wasm` is part of the runtime. 6 | 7 | To not confuse any downstream bundler, the runtime is [dynamically loaded](../packages/qgis-js/src/loader.ts) in a way that it will not be processed. Therefore **it is up to the end user to include the runtime files in the final build**. 8 | 9 | ### Explicitly specifying the runtime location 10 | 11 | The runtime location can be specified with the `prefix` configuration option. This is useful when the runtime is not in the same directory as the main script or served from a different server (e.g. a CDN). 12 | 13 | ```js 14 | const { api } = await qgis({ 15 | prefix: "/path/to/runtime/assets", 16 | }); 17 | ``` 18 | 19 | ## Examples 20 | 21 | ### qgis-js with [Vite](https://vitejs.dev/) 22 | 23 | One can use the [vite-plugin-static-copy](https://github.com/sapphi-red/vite-plugin-static-copy). 24 | 25 | For an example see the [`vite.config.ts`](./examples/qgis-js-example-ol/vite.config.js) in the [qgis-js-example-ol](./examples/qgis-js-example-ol) project and note that the COOP/COEP headers have to be set after the plugin (see [`compatibility.md`](./compatibility.md) for more information). 26 | 27 | ### qgis.js with [Webpack](https://webpack.js.org/) 28 | 29 | With Webpack one can use the [copy-webpack-plugin](https://www.npmjs.com/package/copy-webpack-plugin). 30 | 31 | Note that the COOP/COEP headers have to be set in the `webpack.config.js` (see [`compatibility.md`](./compatibility.md) for more information). 32 | 33 | ### Using qgis-js from a CDN 34 | 35 | An example of how to use qgis-js from a CDN (e.g. [jsDelivr](https://www.jsdelivr.com/)): 36 | 37 | ```html 38 | 39 | 40 | 41 | qgis-js 42 | 43 | 44 | 56 | 57 | 58 | ``` 59 | 60 | Note that the main script has to be explicitly loaded with `qgis-js/dist/qgis.js` (Or a prefix pointing to `qgis-js/dist/assets/wasm` has to be set ([see above](#explicitly-specifying-the-runtime-location))). 61 | 62 | And also ensure that the HTML document has the correct COOP/COEP headers set (see [`compatibility.md`](./compatibility.md) for more information). 63 | -------------------------------------------------------------------------------- /docs/ci.md: -------------------------------------------------------------------------------- 1 | # CI/CD 2 | -------------------------------------------------------------------------------- /docs/compatibility.md: -------------------------------------------------------------------------------- 1 | # Compatibility 2 | 3 | ## Features 4 | 5 | qgis-js uses the following features which have to be supported by the JavaScript/WebAssembly runtime: 6 | 7 | - ES modules with [dynamic imports](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#dynamic_imports) 8 | - [SharedArrayBuffer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer) 9 | - [WebAssembly](https://developer.mozilla.org/en-US/docs/WebAssembly) 10 | - [WebAssembly Threads](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer) 11 | - [WebAssembly Exception Handling](https://developer.mozilla.org/en-US/docs/WebAssembly/Exception_handling) 12 | 13 | ## COOP/COEP 14 | 15 | In order to use SharedArrayBuffer a secure cross-origin context is required. This means that the [Cross-Origin-Opener-Policy (COOP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cross-Origin-Opener-Policy) and [Cross-Origin-Embedder-Policy (COEP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cross-Origin-Embedder-Policy) headers have to be set by the server. 16 | 17 | Alternativley one can use [coi-serviceworker](https://github.com/gzuidhof/coi-serviceworker) to set the headers through a service worker. This makes it possible to use qgis-js for example on GitHub pages. 18 | 19 | ## Supported Browsers 20 | 21 | The [features listed above are supported by the following browsers](https://caniuse.com/es6-module-dynamic-import,wasm,sharedarraybuffer,mdn-javascript_builtins_webassembly_exception,webworkers): 22 | 23 | - **Chromium based browsers (>= 95)** 24 | 25 | - **Firefox (>= 100)** 26 | 27 | - Safari (15.2, yet to be tested!) 28 | 29 | ### Mobile Browsers 30 | 31 | > 🚧 At the moment we don't support mobile browsers 32 | 33 | ## Supported JavaScript Runtimes 34 | 35 | > 🚧 At the moment only browsers are supported 36 | -------------------------------------------------------------------------------- /docs/debugging.md: -------------------------------------------------------------------------------- 1 | # Debugging 2 | 3 | ## Setup 4 | 5 | - Make sure that you have compiled qgis-js with the [`Debug` build type](../README.md#build-types) 6 | 7 | - DWARF debug info is only supported in Chromium based browsers (Chrome, Edge, Brave, ...) 8 | 9 | - Make sure that you have enabled the "Experimental WebAssembly features" flag in your browser (see [Debugging WebAssembly with modern tools](https://developer.chrome.com/blog/wasm-debugging-2020/)) 10 | 11 | - Install the [C/C++ DevTools Support (DWARF)](https://chrome.google.com/webstore/detail/pdcpmagijalfljmkmjngeonclgbbannb) extension 12 | 13 | ## Links 14 | 15 | - [Debugging WebAssembly with modern tools](https://developer.chrome.com/blog/wasm-debugging-2020/), Chrome for Developers Blog, 2020 16 | 17 | - [Debugging WebAssembly Faster](https://developer.chrome.com/blog/faster-wasm-debugging/), Chrome for Developers Blog, 2022 18 | 19 | - [WASM Debugging with Emscripten and VSCode](https://floooh.github.io/2023/11/11/emscripten-ide.html), 20 | The Brain Dump, 2023 21 | -------------------------------------------------------------------------------- /docs/examples/qgis-js-example-api/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | qgis-js-example-api 6 | 7 | 14 | 15 | 16 |

📐 Using the qgis-js API example

17 |

Open the Console to see the result 🤓

18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /docs/examples/qgis-js-example-api/main.js: -------------------------------------------------------------------------------- 1 | const QGIS_JS_DIST = window.location.pathname + "node_modules/qgis-js/dist"; 2 | 3 | // loading the qgis-js library 4 | const { qgis, QGIS_JS_VERSION } = await import(QGIS_JS_DIST + "/qgis.js"); 5 | console.log(`qgis-js (v${QGIS_JS_VERSION})`); 6 | 7 | // booting the qgis-js runtime 8 | console.log(`- loading qgis-js`); 9 | const { api } = await qgis({ 10 | prefix: QGIS_JS_DIST + "/assets/wasm", 11 | }); 12 | console.log(`- qgis-js ready`); 13 | 14 | // qgis-js API example 15 | console.log(`- creating a rectangle`); 16 | const rect = new api.Rectangle(1, 2, 3, 4); 17 | console.log("-> " + printRect(rect)); 18 | 19 | console.log(`- scaling the rectangle`); 20 | rect.scale(5); 21 | console.log("-> " + printRect(rect)); 22 | 23 | console.log(`- getting the center of the rectangle`); 24 | const center = rect.center(); 25 | console.log(`-> Point: x: ${center.x}, y: ${center.y}`); 26 | 27 | function printRect(rect) { 28 | return `Rectangle: xMaximum: ${rect.xMaximum}, xMinimum: ${rect.xMinimum}, yMaximum: ${rect.yMaximum}, yMinimum: ${rect.yMinimum}`; 29 | } 30 | -------------------------------------------------------------------------------- /docs/examples/qgis-js-example-api/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "qgis-js-example-api", 3 | "private": true, 4 | "type": "module", 5 | "scripts": { 6 | "start": "vite preview --outDir ." 7 | }, 8 | "dependencies": { 9 | "qgis-js": "0.0.5" 10 | }, 11 | "devDependencies": { 12 | "vite": "^6.2.2" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /docs/examples/qgis-js-example-api/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | 3 | export default defineConfig({ 4 | preview: { 5 | headers: { 6 | "Cross-Origin-Opener-Policy": "same-origin", 7 | "Cross-Origin-Embedder-Policy": "require-corp", 8 | }, 9 | }, 10 | }); 11 | -------------------------------------------------------------------------------- /docs/examples/qgis-js-example-ol/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | qgis-js-example-ol 6 | 7 | 8 | 9 | 10 |

🗺️ Minimal OpenLayers example

11 |
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/examples/qgis-js-example-ol/main.js: -------------------------------------------------------------------------------- 1 | import { qgis } from "qgis-js"; 2 | 3 | import { QgisCanvasDataSource } from "@qgis-js/ol"; 4 | 5 | import { Map, View } from "ol"; 6 | 7 | import ImageLayer from "ol/layer/Image"; 8 | import Projection from "ol/proj/Projection.js"; 9 | 10 | // start the qgis-js runtime 11 | const { api, fs } = await qgis({ 12 | prefix: "/assets/wasm", 13 | }); 14 | 15 | // prepare the upload directory 16 | const uploadDir = "/upload"; 17 | fs.mkdir(uploadDir); 18 | 19 | // fetch demo project and upload it to the runtime 20 | const source = 21 | "https://raw.githubusercontent.com/boardend/qgis-js-projects/main/demo/World%20GPKG"; 22 | const files = ["project.qgz", "world_map.gpkg"]; 23 | for (const file of files) { 24 | const url = `${source}/${file}`; 25 | const response = await fetch(url); 26 | const blob = await response.blob(); 27 | const buffer = await blob.arrayBuffer(); 28 | fs.writeFile(`${uploadDir}/${file}`, new Uint8Array(buffer)); 29 | } 30 | 31 | // load the uploaded project 32 | api.loadProject(`${uploadDir}/${files[0]}`); 33 | 34 | // create the ol map with the projection from the project 35 | const projection = new Projection({ 36 | code: api.srid(), 37 | units: "m", 38 | }); 39 | 40 | function createQgisLayer() { 41 | return new ImageLayer({ 42 | source: new QgisCanvasDataSource(api, { 43 | projection, 44 | }), 45 | }); 46 | } 47 | 48 | const map = new Map({ 49 | target: "map", 50 | layers: [createQgisLayer()], 51 | view: new View({ 52 | center: [0, 0], 53 | zoom: 2, 54 | projection, 55 | }), 56 | }); 57 | 58 | // create a dropdown with all map themes 59 | const mapThemes = api.mapThemes(); 60 | if (mapThemes.length > 0) { 61 | const themeContainer = document.createElement("div"); 62 | themeContainer.style.marginTop = "1em"; 63 | document.body.appendChild(themeContainer); 64 | 65 | themeContainer.appendChild(document.createTextNode("Map theme: ")); 66 | 67 | const select = document.createElement("select"); 68 | select.addEventListener("change", () => { 69 | if (select.value) { 70 | api.setMapTheme(select.value); 71 | map.getLayers().clear(); 72 | map.addLayer(createQgisLayer()); 73 | } 74 | }); 75 | themeContainer.appendChild(select); 76 | 77 | const currentTheme = api.getMapTheme(); 78 | 79 | const option = document.createElement("option"); 80 | option.value = ""; 81 | option.text = ""; 82 | if (!currentTheme) { 83 | option.selected = true; 84 | } 85 | select.appendChild(option); 86 | 87 | for (const theme of api.mapThemes()) { 88 | const option = document.createElement("option"); 89 | option.value = theme; 90 | option.text = theme; 91 | if (theme === currentTheme) { 92 | option.selected = true; 93 | } 94 | select.appendChild(option); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /docs/examples/qgis-js-example-ol/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "qgis-js-example-ol", 3 | "private": true, 4 | "type": "module", 5 | "scripts": { 6 | "start": "vite dev", 7 | "build": "vite build", 8 | "preview": "vite preview" 9 | }, 10 | "dependencies": { 11 | "ol": "^9.2.4", 12 | "@qgis-js/ol": "0.0.5", 13 | "qgis-js": "0.0.5" 14 | }, 15 | "devDependencies": { 16 | "vite": "^6.2.2", 17 | "vite-plugin-static-copy": "^2.3.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /docs/examples/qgis-js-example-ol/style.css: -------------------------------------------------------------------------------- 1 | @import "node_modules/ol/ol.css"; 2 | 3 | body { 4 | font-family: sans-serif; 5 | margin: 1em; 6 | padding: 1em; 7 | } 8 | #map { 9 | width: 800px; 10 | height: 600px; 11 | border: 1px solid grey; 12 | } 13 | -------------------------------------------------------------------------------- /docs/examples/qgis-js-example-ol/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | 3 | import { viteStaticCopy } from "vite-plugin-static-copy"; 4 | 5 | const headers = { 6 | "Cross-Origin-Opener-Policy": "same-origin", 7 | "Cross-Origin-Embedder-Policy": "require-corp", 8 | }; 9 | 10 | export default defineConfig({ 11 | build: { 12 | target: "esnext", 13 | }, 14 | plugins: [ 15 | { 16 | name: "headers-after-static-copy", 17 | configureServer(server) { 18 | server.middlewares.use((_req, res, next) => { 19 | Object.entries(headers).forEach(([key, value]) => { 20 | res.setHeader(key, value); 21 | }); 22 | next(); 23 | }); 24 | }, 25 | }, 26 | viteStaticCopy({ 27 | silent: true, 28 | targets: [ 29 | { 30 | src: "node_modules/qgis-js/dist/assets/wasm/**", 31 | dest: "assets/wasm", 32 | }, 33 | ], 34 | }), 35 | ], 36 | preview: { 37 | headers, 38 | }, 39 | }); 40 | -------------------------------------------------------------------------------- /docs/profiling.md: -------------------------------------------------------------------------------- 1 | # Profiling 2 | 3 | ## qgis-js Performance Measurement Tool 4 | 5 | The [qgis-js Performance Measurement Tool](../sites/performance/) can be used to measure the performance of the qgis-js application in a reproducible way: 6 | 7 | ``` 8 | cd sites/performance 9 | npm run dev 10 | ``` 11 | 12 | 1. Boot the runtime 13 | 2. Load a project 14 | 3. Render a first dummy frame 15 | 4. Start the performance test 16 | 17 | ## Browsers 18 | 19 | ### Chrome 20 | 21 | The Performance tab of the Chrome DevTools can be used to profile the performance of the qgis-js application. See the [official documentation](https://developer.chrome.com/docs/devtools/evaluate-performance/) for more information. 22 | 23 | ![Firefox Profiler](https://developer.chrome.com/static/docs/devtools/performance/image/the-results-the-profile-5d830d01508e2_2880.png) 24 | 25 | - 💡 In order to get useful results (e.g. function names in the `.wasm` module), the [build type](../README.md#build-types) has to be set to `Dev` or `Debug` 26 | - ⚠️ Note that the `Debug` build type is significantly slower than the `Dev` build type 27 | 28 | ### Firefox 29 | 30 | The [Firefox Profiler⁩](https://profiler.firefox.com/) can be used to profile the performance of the qgis-js application. 31 | 32 | ![Firefox Profiler](https://profiler.firefox.com/b45b29da558efa211628.jpg) 33 | 34 | - 💡 In order to get useful results (e.g. function names in the `.wasm` module), the [build type](../README.md#build-types) has to be set to `Dev` or `Debug` 35 | - ⚠️ Note that the `Debug` build type is significantly slower than the `Dev` build type 36 | 37 | ## Emscripten 38 | 39 | - Emscripten provies a [profiling guide](https://emscripten.org/docs/optimizing/Optimizing-Code.html#profiling) and some embeddable tools to profile the application: 40 | - `--cpuprofiler` 41 | - `--memoryprofiler` 42 | - `--threadprofiler` 43 | 44 | ## QGIS profiling 45 | 46 | - It would be nice to extend the qgis-js API in order to retrieve profiling information from the QGIS core 47 | - ⚠️ This is not yet implemented 48 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "version": "0.0.5", 4 | "license": "GPL-2.0-or-later", 5 | "homepage": "https://qgis.github.io/qgis-js/", 6 | "repository": "github:qgis/qgis-js", 7 | "bugs": { 8 | "url": "https://github.com/qgis/qgis-js/issues" 9 | }, 10 | "packageManager": "pnpm@10.6.5", 11 | "engines": { 12 | "node": "22.14.0", 13 | "pnpm": "10.6.5", 14 | "emsdk": "3.1.59", 15 | "vcpkg": "2024.02.14", 16 | "qt": "6.6.1", 17 | "qgis": "3.32.1" 18 | }, 19 | "type": "module", 20 | "scripts": { 21 | "postinstall": "./qgis-js.ts -v install", 22 | "update": "pnpm update --ignore-scripts", 23 | "clean": "./qgis-js.ts -v clean", 24 | "compile": "pnpm run compile:dev", 25 | "compile:dev": "./qgis-js.ts compile", 26 | "compile:debug": "./qgis-js.ts compile -t Debug", 27 | "compile:release": "./qgis-js.ts compile -t Release", 28 | "build": "pnpm -r --filter=./packages/** run build", 29 | "dev": "pnpm --filter @qgis-js/dev dev", 30 | "dev:build": "pnpm --filter @qgis-js/dev build", 31 | "dev:preview": "npm run dev:build && pnpm --filter @qgis-js/dev preview", 32 | "site": "vite dev", 33 | "deploy": "pnpm -r --filter=./sites/** run deploy", 34 | "publish": "pnpm publish -r --filter=./packages/qgis-js** --access=public", 35 | "lint": "npm run lint:prettier && npm run lint:clang-format", 36 | "lint:prettier": "npx prettier . --write", 37 | "lint:pretty-quick": "pretty-quick --staged", 38 | "lint:clang-format": "clang-format -i \"--glob=src/**/*.{cpp,hpp}\"" 39 | }, 40 | "devDependencies": { 41 | "pnpm": "10.6.5", 42 | "vite": "6.2.2", 43 | "vite-node": "3.0.9", 44 | "zx": "8.4.1", 45 | "@rushstack/ts-command-line": "4.23.6", 46 | "ts-markdown": "1.2.0", 47 | "@microsoft/api-extractor": "7.52.1", 48 | "@microsoft/api-documenter": "7.26.17", 49 | "prettier": "3.5.3", 50 | "pretty-quick": "4.1.1", 51 | "clang-format": "1.8.0" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /packages/qgis-js-ol/README.md: -------------------------------------------------------------------------------- 1 | # @qgis-js/ol 2 | 3 | **OpenLayers sources for [qgis-js](https://github.com/qgis/qgis-js)** 4 | 5 | [qgis-js Repository](https://github.com/qgis/qgis-js) | [qgis-js Website](https://qgis.github.io/qgis-js) | ["`@qgis-js/ol`" package source](https://github.com/qgis/qgis-js/tree/main/packages/qgis-js-ol) 6 | 7 | [![@qgis-js/ol on npm](https://img.shields.io/npm/v/@qgis-js/ol)](https://www.npmjs.com/package/@qgis-js/ol) 8 | 9 | > ⚠️🧪 **Work in progress**! Currently this project is in public beta 10 | 11 | ## Prerequisites 12 | 13 | - This package requires **[OpenLayers](https://openlayers.org) `>=8`** to be installed as a peer dependency 14 | 15 | - The [qgis-js](https://www.npmjs.com/package/@qgis-js/ol) package is also required as a direct dependency of this package 16 | 17 | - An instance of the qgis-js runtime has to be created at runtime and its API must be passed to the OpenLayers source constructor 18 | 19 | ## Installation 20 | 21 | ```bash 22 | npm install -S @qgis-js/ol 23 | ``` 24 | 25 | ## Usage 26 | 27 | ### QgisCanvasDataSource 28 | 29 | [OpenLayers](https://openlayers.org) source for rendering a single tile with the size and pixel ratio of the ol map canvas. This is useful for rendering in the projection of the QGIS project, both in the OpenLayers view and in the qgis-js runtime. 30 | 31 | > See [QgisCanvasDataSource.ts](https://github.com/qgis/qgis-js/blob/main/packages/qgis-js-ol/src/QgisCanvasDataSource.ts) for the implementation. 32 | 33 | ### QgisXYZDataSource 34 | 35 | [OpenLayers](https://openlayers.org) source to render a QGIS project in the common Web Mercator projection (EPSG:3857) addressed with the xyz tile scheme. This makes it convenient to mix the QGIS layer with other layer sources provided by OpenLayers. 36 | 37 | > See [QgisXYZDataSource.ts](https://github.com/qgis/qgis-js/blob/main/packages/qgis-js-ol/src/QgisXYZDataSource.ts) for the implementation. 38 | 39 | ## Versioning 40 | 41 | This package uses [SemVer](http://semver.org/) for versioning. For the versions available, see the [tags on this repository](https://github.com/qgis/qgis-js/tags). 42 | 43 | ## License 44 | 45 | [GNU General Public License v2.0](https://github.com/qgis/qgis-js/blob/main/LICENSE) 46 | -------------------------------------------------------------------------------- /packages/qgis-js-ol/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@qgis-js/ol", 3 | "version": "0.0.5", 4 | "description": "OpenLayers sources for qgis-js", 5 | "license": "GPL-2.0-or-later", 6 | "homepage": "https://qgis.github.io/qgis-js/", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/qgis/qgis-js", 10 | "directory": "packages/qgis-js-ol" 11 | }, 12 | "bugs": { 13 | "url": "https://github.com/qgis/qgis-js/issues" 14 | }, 15 | "type": "module", 16 | "main": "dist/qgis-js-ol.js", 17 | "types": "dist/qgis-js-ol.d.ts", 18 | "files": [ 19 | "dist/**/*" 20 | ], 21 | "scripts": { 22 | "build": "vite build" 23 | }, 24 | "dependencies": { 25 | "qgis-js": "workspace:*" 26 | }, 27 | "peerDependencies": { 28 | "ol": "^10.4.0" 29 | }, 30 | "devDependencies": { 31 | "@types/node": "^22.13.11", 32 | "typescript": "5.8.2", 33 | "vite": "6.2.2", 34 | "vite-plugin-dts": "4.5.3" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/qgis-js-ol/src/QgisCanvasDataSource.ts: -------------------------------------------------------------------------------- 1 | import type { QgisApi } from "qgis-js"; 2 | 3 | import ImageSource, { Options } from "ol/source/Image"; 4 | import { getWidth, getHeight } from "ol/extent"; 5 | 6 | export interface QgisCanvasDataSourceOptions extends Options { 7 | renderFunction?: QgisCanvasRenderFunction; 8 | } 9 | 10 | export type QgisCanvasRenderFunction = ( 11 | api: QgisApi, 12 | srid: string, 13 | xMin: number, 14 | yMin: number, 15 | xMax: number, 16 | yMax: number, 17 | width: number, 18 | height: number, 19 | pixelRatio: number, 20 | ) => Promise; 21 | 22 | export class QgisCanvasDataSource extends ImageSource { 23 | protected api: QgisApi; 24 | 25 | protected static DEFAULT_RENDERFUNCTION: QgisCanvasRenderFunction = ( 26 | api: QgisApi, 27 | srid: string, 28 | xMin: number, 29 | yMin: number, 30 | xMax: number, 31 | yMax: number, 32 | width: number, 33 | height: number, 34 | pixelRatio: number, 35 | ) => { 36 | return api.renderImage( 37 | srid, 38 | new api.Rectangle(xMin, yMin, xMax, yMax), 39 | width, 40 | height, 41 | pixelRatio, 42 | ); 43 | }; 44 | 45 | protected renderFunction: QgisCanvasRenderFunction | undefined; 46 | 47 | protected getrenderFunction(): QgisCanvasRenderFunction { 48 | return this.renderFunction || QgisCanvasDataSource.DEFAULT_RENDERFUNCTION; 49 | } 50 | 51 | constructor(api: QgisApi, options: QgisCanvasDataSourceOptions = {}) { 52 | super({ 53 | loader: (extent, resolution, requestPixelRatio) => { 54 | return new Promise(async (resolve) => { 55 | // note: requestPixelRatio is managed by ol and will not change on zoom 56 | const pixelRatio = requestPixelRatio || window?.devicePixelRatio || 1; 57 | const imageResolution = resolution / pixelRatio; 58 | const width = Math.round(getWidth(extent) / imageResolution); 59 | const height = Math.round(getHeight(extent) / imageResolution); 60 | 61 | const renderFunction = this.getrenderFunction(); 62 | const imageData = await renderFunction( 63 | this.api, 64 | this.getProjection()?.getCode() || "EPSG:3857", 65 | extent[0], 66 | extent[1], 67 | extent[2], 68 | extent[3], 69 | width, 70 | height, 71 | pixelRatio, 72 | ); 73 | 74 | resolve(createImageBitmap(imageData)); 75 | }); 76 | }, 77 | ...options, 78 | }); 79 | 80 | this.api = api; 81 | this.renderFunction = options.renderFunction; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /packages/qgis-js-ol/src/QgisXYZDataSource.ts: -------------------------------------------------------------------------------- 1 | import type { QgisApi } from "qgis-js"; 2 | 3 | import XYZ, { Options } from "ol/source/XYZ"; 4 | 5 | import { createCanvasContext2D } from "ol/dom"; 6 | import { toSize } from "ol/size"; 7 | 8 | import type { TileCoord } from "ol/tilecoord"; 9 | import ImageTile from "ol/ImageTile"; 10 | 11 | export interface QgisXYZDataSourceOptions extends Options { 12 | extentBufferFactor?: number | (() => number); 13 | renderFunction?: QgisXYZRenderFunction; 14 | debug?: boolean; 15 | } 16 | 17 | export type QgisXYZRenderFunction = ( 18 | api: QgisApi, 19 | tileCoord: TileCoord, 20 | tileSize: number, 21 | pixelRatio: number, 22 | extentBufferFactor: number, 23 | ) => Promise; 24 | 25 | export class QgisXYZDataSource extends XYZ { 26 | protected api: QgisApi; 27 | 28 | protected static DEFAULT_RENDERFUNCTION: QgisXYZRenderFunction = ( 29 | api: QgisApi, 30 | tileCoord: TileCoord, 31 | tileSize: number, 32 | devicePixelRatio: number, 33 | extentBufferFactor: number, 34 | ) => { 35 | return api.renderXYZTile( 36 | tileCoord[1], 37 | tileCoord[2], 38 | tileCoord[0], 39 | tileSize, 40 | devicePixelRatio, 41 | extentBufferFactor, 42 | ); 43 | }; 44 | 45 | protected renderFunction: QgisXYZRenderFunction | undefined; 46 | 47 | protected getrenderFunction(): QgisXYZRenderFunction { 48 | return this.renderFunction || QgisXYZDataSource.DEFAULT_RENDERFUNCTION; 49 | } 50 | 51 | protected static DEFAULT_EXTENTBUFFERFACTOR = 0; 52 | 53 | protected extentBufferFactor: number | number | (() => number) | undefined; 54 | 55 | protected getextentBufferFactor(): number { 56 | return typeof this.extentBufferFactor === "function" 57 | ? this.extentBufferFactor() 58 | : this.extentBufferFactor || QgisXYZDataSource.DEFAULT_EXTENTBUFFERFACTOR; 59 | } 60 | 61 | constructor(api: QgisApi, options: QgisXYZDataSourceOptions = {}) { 62 | super({ 63 | tileUrlFunction: (tileCoord, pixelRatio) => { 64 | const tileSize = ( 65 | toSize(this.tileGrid!.getTileSize(tileCoord[0])) as [number, number] 66 | )[0]; 67 | return `${tileSize * (pixelRatio || 1)}`; 68 | }, 69 | tileLoadFunction: async (tile, text) => { 70 | const renderFunction = this.getrenderFunction(); 71 | if (this.tileGrid && renderFunction) { 72 | console.assert(tile instanceof ImageTile); 73 | const imageTile = tile as ImageTile; 74 | 75 | const tileSize = parseInt(text); 76 | const pixelRatio = Math.round(tileSize / 256); 77 | 78 | const context = createCanvasContext2D(tileSize, tileSize); 79 | 80 | const imageData = await renderFunction( 81 | this.api, 82 | tile.getTileCoord(), 83 | tileSize, 84 | pixelRatio, 85 | this.getextentBufferFactor(), 86 | ); 87 | context.putImageData(imageData, 0, 0); 88 | 89 | if (options.debug) { 90 | context.strokeStyle = "grey"; 91 | context.strokeRect(0.5, 0.5, tileSize + 0.5, tileSize + 0.5); 92 | 93 | context.fillStyle = "darkgrey"; 94 | context.strokeStyle = "black"; 95 | context.textAlign = "center"; 96 | context.textBaseline = "middle"; 97 | context.font = "20px sans-serif"; 98 | context.lineWidth = 2; 99 | context.strokeText(text, tileSize / 2, tileSize / 2, tileSize); 100 | context.fillText(text, tileSize / 2, tileSize / 2, tileSize); 101 | } 102 | 103 | imageTile.setImage(context.canvas); 104 | } 105 | }, 106 | ...options, 107 | }); 108 | 109 | this.api = api; 110 | this.renderFunction = options.renderFunction; 111 | this.extentBufferFactor = options.extentBufferFactor; 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /packages/qgis-js-ol/src/index.ts: -------------------------------------------------------------------------------- 1 | export { QgisCanvasDataSource } from "./QgisCanvasDataSource"; 2 | export { QgisXYZDataSource } from "./QgisXYZDataSource"; 3 | export { QgisJobDataSource } from "./QgisJobDataSource"; 4 | -------------------------------------------------------------------------------- /packages/qgis-js-ol/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/qgis-js-ol/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { resolve } from "path"; 2 | import { defineConfig } from "vite"; 3 | 4 | import dts from "vite-plugin-dts"; 5 | 6 | export default defineConfig({ 7 | plugins: [ 8 | dts({ 9 | rollupTypes: true, 10 | entryRoot: "src", 11 | }), 12 | ], 13 | build: { 14 | lib: { 15 | entry: [resolve(__dirname, "src/index.ts")], 16 | name: "qgis-js-ol", 17 | formats: ["es"], 18 | fileName: "qgis-js-ol", 19 | }, 20 | rollupOptions: { 21 | external: ["qgis-js", "ol", new RegExp("^ol/*")], 22 | }, 23 | }, 24 | }); 25 | -------------------------------------------------------------------------------- /packages/qgis-js-utils/README.md: -------------------------------------------------------------------------------- 1 | # @qgis-js/utils 2 | 3 | **Utilities to integrate [qgis-js](https://github.com/qgis/qgis-js) into web applications** 4 | 5 | [qgis-js Repository](https://github.com/qgis/qgis-js) | [qgis-js Website](https://qgis.github.io/qgis-js) | ["`@qgis-js/utils`" package source](https://github.com/qgis/qgis-js/tree/main/packages/qgis-js-ol) 6 | 7 | [![@qgis-js/utils on npm](https://img.shields.io/npm/v/@qgis-js/utils)](https://www.npmjs.com/package/@qgis-js/utils) 8 | 9 | > ⚠️🧪 **Work in progress**! Currently this project is in public beta 10 | 11 | ## Installation 12 | 13 | ```bash 14 | npm install -S @qgis-js/utils 15 | ``` 16 | 17 | ## Usage 18 | 19 | ### `useProjects` 20 | 21 | Provides an abstraction to load QGIS projects from various sources. 22 | 23 | ```js 24 | import { qgis } from "qgis-js"; 25 | import { useProjects } from "@qgis-js/utils"; 26 | 27 | const { api, fs } = await qgis(); 28 | const { 29 | openProject, 30 | loadLocalProject, 31 | loadGithubProjects, 32 | loadRemoteProjects, 33 | } = useProjects(fs, (projectPath: string) => { 34 | api.loadProject(projectPath); 35 | }); 36 | ``` 37 | 38 | The following project sources are supported: 39 | 40 | #### LocalProject 41 | 42 | Loads QGIS projects from the user's file system with the [File System API](https://developer.mozilla.org/en-US/docs/Web/API/File_System_API) 43 | 44 | ```js 45 | await openProject(await loadLocalProject()); 46 | ``` 47 | 48 | #### GithubProject 49 | 50 | Loads QGIS projects from a GitHub repository with the [GitHub API](https://docs.github.com/en/rest) 51 | 52 | #### RemoteProject 53 | 54 | Fetches QGIS projects from a remote server with the [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) 55 | 56 | - If `loadRemoteProjects` is invoked with a string as, it is assumed to be the URL of a JSON file with the following structure: 57 | 58 | ```json 59 | { 60 | "name": "projects", 61 | "path": "projects", 62 | "type": "Folder", 63 | "entries": [ 64 | { 65 | "name": "village", 66 | "path": "projects/village", 67 | "type": "Folder", 68 | "entries": [ 69 | { 70 | "name": "project.qgs", 71 | "path": "projects/village/project.qgs", 72 | "type": "File" 73 | }, 74 | { 75 | "name": "rgb.tif", 76 | "path": "projects/village/rgb.tif", 77 | "type": "File" 78 | } 79 | ] 80 | } 81 | ] 82 | } 83 | ``` 84 | 85 | - Otherwise a `Folder` object can also be passed directly to `loadRemoteProjects`, see [FileSystem.ts](./src/fs/FileSystem.ts) 86 | 87 | ## Versioning 88 | 89 | This package uses [SemVer](http://semver.org/) for versioning. For the versions available, see the [tags on this repository](https://github.com/qgis/qgis-js/tags). 90 | 91 | ## License 92 | 93 | [GNU General Public License v2.0](https://github.com/qgis/qgis-js/blob/main/LICENSE) 94 | -------------------------------------------------------------------------------- /packages/qgis-js-utils/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@qgis-js/utils", 3 | "version": "0.0.5", 4 | "description": "Utilities to integrate qgis-js into web applications", 5 | "license": "GPL-2.0-or-later", 6 | "homepage": "https://qgis.github.io/qgis-js/", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/qgis/qgis-js", 10 | "directory": "packages/qgis-js-utils" 11 | }, 12 | "bugs": { 13 | "url": "https://github.com/qgis/qgis-js/issues" 14 | }, 15 | "type": "module", 16 | "main": "dist/qgis-js-utils.js", 17 | "types": "dist/qgis-js-utils.d.ts", 18 | "files": [ 19 | "dist/**/*" 20 | ], 21 | "scripts": { 22 | "build": "vite build" 23 | }, 24 | "dependencies": { 25 | "@types/emscripten": "1.40.0", 26 | "browser-fs-access": "0.35.0", 27 | "qgis-js": "workspace:*" 28 | }, 29 | "devDependencies": { 30 | "@types/node": "^22.13.11", 31 | "typescript": "5.8.2", 32 | "vite": "6.2.2", 33 | "vite-plugin-dts": "4.5.3" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /packages/qgis-js-utils/src/fs/FileSystem.ts: -------------------------------------------------------------------------------- 1 | export type FileSystemEntryType = "File" | "Folder"; 2 | 3 | export interface FileSystemEntry { 4 | name: string; 5 | path: string; 6 | type: FileSystemEntryType; 7 | } 8 | 9 | export interface File extends FileSystemEntry {} 10 | 11 | export interface Folder extends FileSystemEntry { 12 | entries: FolderEntries; 13 | } 14 | 15 | export type FolderEntries = Array; 16 | 17 | /** 18 | * Flattens the "Folder" hierarchy and returns an array of folder paths. 19 | * 20 | * @param entries - The entries of the root folder. 21 | * @param basePath - The base path of the root folder. 22 | * @returns An array of folder paths. 23 | */ 24 | export function flatFolders( 25 | entries: Folder["entries"], 26 | basePath: string, 27 | ): string[] { 28 | return entries.reduce((acc, entry) => { 29 | if (entry.type === "Folder") { 30 | return acc.concat([ 31 | basePath + "/" + entry.name, 32 | ...flatFolders((entry as Folder).entries, basePath + "/" + entry.name), 33 | ]); 34 | } else { 35 | return acc; 36 | } 37 | }, []); 38 | } 39 | 40 | /** 41 | * Flattens the files in a "Folder" hierarchy and returns an array of file paths. 42 | * 43 | * @param entries - The entries of the root folder. 44 | * @param basePath - The base path of the root folder. 45 | * @returns An array of file paths. 46 | */ 47 | export function flatFiles( 48 | entries: Folder["entries"], 49 | basePath: string, 50 | ): string[] { 51 | return entries.reduce((acc, entry) => { 52 | if (entry.type === "Folder") { 53 | return acc.concat( 54 | flatFiles((entry as Folder).entries, basePath + "/" + entry.name), 55 | ); 56 | } else { 57 | return acc.concat(basePath + "/" + entry.name); 58 | } 59 | }, []); 60 | } 61 | -------------------------------------------------------------------------------- /packages/qgis-js-utils/src/fs/LocalProject.ts: -------------------------------------------------------------------------------- 1 | import type { EmscriptenFS } from "qgis-js"; 2 | 3 | import { Project, PROJECTS_UPLOAD_DIR } from "./Project"; 4 | 5 | import { 6 | directoryOpen, 7 | FileWithDirectoryAndFileHandle, 8 | } from "browser-fs-access"; 9 | 10 | export type LocalEntries = Array; 11 | 12 | export { directoryOpen as openLocalDirectory }; 13 | 14 | export class LocalProject extends Project { 15 | protected entries: LocalEntries; 16 | 17 | constructor(FS: EmscriptenFS, entries: LocalEntries) { 18 | super(FS, "Local"); 19 | 20 | this.entries = entries; 21 | 22 | const possibleNames = entries 23 | .map((e) => e.webkitRelativePath) 24 | .filter((p) => p && p.length > 0 && p.includes("/")) 25 | .map((p) => p.split("/", 1)[0]); 26 | 27 | if (possibleNames.length < 1) { 28 | throw new Error("Could not determine project name"); 29 | } 30 | // just use the first possible name as final project name 31 | this.name = possibleNames[0]; 32 | } 33 | 34 | getDirectories(): string[] { 35 | const subFoldersToCreate = new Set(); 36 | subFoldersToCreate.add(this.name); 37 | for (const entry of this.entries) { 38 | const path = (entry as FileWithDirectoryAndFileHandle).webkitRelativePath; 39 | subFoldersToCreate.add(path.substring(0, path.lastIndexOf("/"))); 40 | } 41 | return Array.from(subFoldersToCreate); 42 | } 43 | 44 | getFiles(): string[] { 45 | return this.entries.map((e) => e.webkitRelativePath); 46 | } 47 | 48 | async uploadProject(): Promise { 49 | // ensure directories exist 50 | this.ensureDirectories(); 51 | // write files to the runtime FS 52 | for (const file of this.entries) { 53 | this.FS.writeFile( 54 | PROJECTS_UPLOAD_DIR + "/" + file.webkitRelativePath, 55 | new Uint8Array(await file.arrayBuffer()), 56 | ); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /packages/qgis-js-utils/src/fs/Project.ts: -------------------------------------------------------------------------------- 1 | import type { EmscriptenFS } from "qgis-js"; 2 | 3 | export type ProjectType = "Remote" | "Local" | "Github"; 4 | 5 | export const PROJECTS_UPLOAD_DIR = "/upload/projects"; 6 | 7 | export abstract class Project { 8 | protected FS; 9 | type: ProjectType; 10 | name!: string; 11 | 12 | constructor(FS: EmscriptenFS, type: ProjectType) { 13 | this.FS = FS; 14 | this.type = type; 15 | } 16 | 17 | abstract getDirectories(): string[]; 18 | abstract getFiles(): string[]; 19 | 20 | abstract uploadProject(): Promise; 21 | 22 | isValid(): boolean { 23 | return this.getFiles().length > 0 && this.getProjectFile() !== undefined; 24 | } 25 | 26 | getProjectFile(): string | undefined { 27 | const candidates = this.getFiles().filter( 28 | (f) => f.endsWith(".qgs") || f.endsWith(".qgz"), 29 | ); 30 | if (candidates.length == 1) { 31 | return candidates[0]; 32 | } else if (candidates.length > 1) { 33 | console.warn("Found multiple project file candiates"); 34 | return candidates[0]; 35 | } else { 36 | return undefined; 37 | } 38 | } 39 | 40 | getDirectoriesToCreate(): string[] { 41 | const directories = new Set(); 42 | for (const directory of this.getDirectories()) { 43 | let direcotryDirs = directory.split("/"); 44 | for (let i = 0; i < direcotryDirs.length; i++) { 45 | const dirToCreate = direcotryDirs.slice(0, i + 1).join("/"); 46 | directories.add(dirToCreate); 47 | } 48 | } 49 | return Array.from(directories).sort(); 50 | } 51 | 52 | ensureDirectories() { 53 | // create directories in the runtime FS (if not already existing) 54 | for (const directory of this.getDirectoriesToCreate()) { 55 | const dirToCreate = PROJECTS_UPLOAD_DIR + "/" + directory; 56 | // @ts-ignore (FS by @types/emscripten is missing the analyzePath method...) 57 | const node = this.FS.analyzePath(dirToCreate, false); 58 | // @ts-ignore 59 | if (!node || !node.exists) { 60 | this.FS.mkdir(dirToCreate); 61 | } 62 | } 63 | } 64 | 65 | isProjectUploaded() { 66 | return this.FS.readdir(PROJECTS_UPLOAD_DIR).includes(this.name); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /packages/qgis-js-utils/src/fs/RemoteProject.ts: -------------------------------------------------------------------------------- 1 | import type { EmscriptenFS } from "qgis-js"; 2 | 3 | import { Project, PROJECTS_UPLOAD_DIR } from "./Project"; 4 | 5 | import { Folder, flatFolders, flatFiles } from "./FileSystem"; 6 | 7 | export class RemoteProject extends Project { 8 | protected folder: Folder; 9 | protected path: string; 10 | 11 | private baseUrl: URL; 12 | 13 | constructor(FS: EmscriptenFS, basePath: string, projectFolder: Folder) { 14 | super(FS, "Remote"); 15 | 16 | this.baseUrl = new URL(basePath); 17 | this.folder = projectFolder; 18 | 19 | const bsaeFolder = this.baseUrl.pathname.split("/").pop(); 20 | 21 | this.name = projectFolder.name; 22 | this.path = projectFolder.path.replace(new RegExp(`^${bsaeFolder}\/`), ""); 23 | } 24 | 25 | getDirectories(): string[] { 26 | return [this.path, ...flatFolders(this.folder.entries, this.path)]; 27 | } 28 | 29 | getFiles(): string[] { 30 | return flatFiles(this.folder.entries, this.path); 31 | } 32 | 33 | async uploadProject() { 34 | // download all files in parallel 35 | const downloads = Object.fromEntries( 36 | this.getFiles().map((file) => { 37 | return [ 38 | file, 39 | new Promise((resolve, _reject) => { 40 | const remoteUrl = new URL(`${this.baseUrl.href}/${file}`); 41 | fetch(remoteUrl).then((response) => 42 | response.arrayBuffer().then((buffer) => { 43 | resolve(buffer); 44 | }), 45 | ); 46 | }), 47 | ]; 48 | }), 49 | ); 50 | // wait for all responses 51 | await Promise.all([Object.values(downloads)]); 52 | // ensure directories exist 53 | this.ensureDirectories(); 54 | // write files to the runtime FS 55 | for (const file of this.getFiles()) { 56 | const data = new Uint8Array(await downloads[file]); 57 | this.FS.writeFile(PROJECTS_UPLOAD_DIR + "/" + file, data); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /packages/qgis-js-utils/src/fs/index.ts: -------------------------------------------------------------------------------- 1 | import type { EmscriptenFS } from "qgis-js"; 2 | 3 | import { Folder } from "./FileSystem"; 4 | 5 | import { PROJECTS_UPLOAD_DIR, Project } from "./Project"; 6 | import { LocalEntries, LocalProject, openLocalDirectory } from "./LocalProject"; 7 | import { RemoteProject } from "./RemoteProject"; 8 | import { 9 | GithubProject, 10 | fetchGithubDirectory, 11 | fetchGithubTreeFiles, 12 | mapFilesToFolder, 13 | } from "./GithubProject"; 14 | 15 | export function useProjects( 16 | fs: EmscriptenFS, 17 | onProjectLoaded: (projectFile: string) => void, 18 | ) { 19 | // ensure PROJECTS_UPLOAD_DIR (and its parent dirs) exist 20 | let projectUploadDirs = PROJECTS_UPLOAD_DIR.split("/"); 21 | for (let i = 1; i < projectUploadDirs.length; i++) { 22 | fs.mkdir(projectUploadDirs.slice(0, i + 1).join("/")); 23 | } 24 | 25 | const openProject = async (project: Project | Promise) => { 26 | if (!project) { 27 | return; 28 | } else { 29 | if (project instanceof Promise) { 30 | project = await project; 31 | } 32 | 33 | if (!project.isValid()) { 34 | throw new Error(`Project "${project.name}" is not valid`); 35 | } 36 | if (!project.isProjectUploaded()) { 37 | await project.uploadProject(); 38 | } 39 | loadProject(project); 40 | } 41 | }; 42 | 43 | const loadProject = (project: Project) => { 44 | const projectFile = PROJECTS_UPLOAD_DIR + "/" + project.getProjectFile(); 45 | onProjectLoaded(projectFile); 46 | }; 47 | 48 | const loadLocalProject = () => 49 | new Promise(async (resolve, reject) => { 50 | try { 51 | const entries: LocalEntries = (await openLocalDirectory({ 52 | recursive: true, 53 | mode: "read", 54 | })) as LocalEntries; //TODO: This cast is probably not working when "fs-browser-fs-access" is using the fallback implementation 55 | const localProject = new LocalProject(fs, entries); 56 | resolve(localProject); 57 | } catch (error) { 58 | reject(error); 59 | } 60 | }); 61 | 62 | const loadRemoteProjects = ( 63 | remoteProjects: string = "./projects/directory-listing.json", 64 | ) => 65 | new Promise(async (resolve, reject) => { 66 | try { 67 | const url = new URL(remoteProjects as string, window.location.href); 68 | const basePath = url.href.split("/").slice(0, -1).join("/"); 69 | 70 | const remoteProjectsResponse = await fetch(remoteProjects); 71 | const remoteProjectsResponseJson = await remoteProjectsResponse.json(); 72 | 73 | const remoteFolder = remoteProjectsResponseJson as Folder; 74 | if (!remoteFolder.type || remoteFolder.type !== "Folder") { 75 | reject(new Error("Remote projects response seems not a folder")); 76 | return; 77 | } 78 | 79 | resolve( 80 | remoteFolder.entries 81 | .filter((entry) => entry.type === "Folder") 82 | .map((entry) => new RemoteProject(fs, basePath, entry as Folder)), 83 | ); 84 | } catch (error) { 85 | reject(error); 86 | } 87 | }); 88 | 89 | const loadGithubProjects = ( 90 | owner: string, 91 | repo: string, 92 | path: string = "/", 93 | branch: string = "main", 94 | ) => 95 | new Promise<{ [key: string]: () => Promise }>( 96 | async (resolve, reject) => { 97 | try { 98 | const projects = await fetchGithubDirectory( 99 | owner, 100 | repo, 101 | path, 102 | branch, 103 | ); 104 | // check if the response got an error message 105 | if (!(projects instanceof Array)) { 106 | console.warn(projects); 107 | resolve({}); 108 | return; 109 | } else { 110 | resolve( 111 | Object.fromEntries( 112 | projects 113 | .filter((entry) => entry.type === "dir") 114 | .map((entry) => { 115 | return [ 116 | entry.name, 117 | () => { 118 | return new Promise(async (resolve) => { 119 | const files = await fetchGithubTreeFiles( 120 | owner, 121 | repo, 122 | entry.sha, 123 | ); 124 | resolve( 125 | new GithubProject( 126 | fs, 127 | mapFilesToFolder(entry.name, entry.path, files), 128 | owner, 129 | repo, 130 | branch, 131 | ), 132 | ); 133 | }); 134 | }, 135 | ]; 136 | }), 137 | ), 138 | ); 139 | } 140 | } catch (error) { 141 | reject(error); 142 | } 143 | }, 144 | ); 145 | 146 | return { 147 | openProject, 148 | loadLocalProject, 149 | loadRemoteProjects, 150 | loadGithubProjects, 151 | }; 152 | } 153 | -------------------------------------------------------------------------------- /packages/qgis-js-utils/src/index.ts: -------------------------------------------------------------------------------- 1 | export { useProjects } from "./fs"; 2 | 3 | export type { Project } from "./fs/Project"; 4 | export type { FileSystemEntry, File, Folder } from "./fs/FileSystem"; 5 | -------------------------------------------------------------------------------- /packages/qgis-js-utils/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/qgis-js-utils/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { resolve } from "path"; 2 | import { defineConfig } from "vite"; 3 | 4 | import dts from "vite-plugin-dts"; 5 | 6 | export default defineConfig({ 7 | plugins: [ 8 | dts({ 9 | rollupTypes: true, 10 | entryRoot: "src", 11 | }), 12 | ], 13 | build: { 14 | lib: { 15 | entry: [resolve(__dirname, "src/index.ts")], 16 | name: "qgis-js-utils", 17 | formats: ["es"], 18 | fileName: "qgis-js-utils", 19 | }, 20 | rollupOptions: { 21 | external: ["qgis-js", "public/projects"], 22 | }, 23 | }, 24 | }); 25 | -------------------------------------------------------------------------------- /packages/qgis-js/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "qgis-js", 3 | "version": "0.0.5", 4 | "description": "QGIS core ported to WebAssembly to run it on the web platform", 5 | "license": "GPL-2.0-or-later", 6 | "homepage": "https://qgis.github.io/qgis-js/", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/qgis/qgis-js", 10 | "directory": "packages/qgis-js" 11 | }, 12 | "bugs": { 13 | "url": "https://github.com/qgis/qgis-js/issues" 14 | }, 15 | "type": "module", 16 | "main": "dist/qgis.js", 17 | "types": "dist/qgis.d.ts", 18 | "files": [ 19 | "dist/**/*" 20 | ], 21 | "scripts": { 22 | "build": "vite build" 23 | }, 24 | "dependencies": { 25 | "@types/emscripten": "1.40.0", 26 | "p-limit": "6.2.0" 27 | }, 28 | "devDependencies": { 29 | "@types/node": "^22.13.11", 30 | "typescript": "5.8.2", 31 | "vite": "6.2.2", 32 | "vite-plugin-dts": "4.5.3" 33 | }, 34 | "keywords": [ 35 | "qgis", 36 | "qgisjs", 37 | "qgis-js", 38 | "qgiswasm", 39 | "qgis-wasm", 40 | "webassembly", 41 | "wasm", 42 | "geo", 43 | "geospatial" 44 | ] 45 | } 46 | -------------------------------------------------------------------------------- /packages/qgis-js/src/QgisApiAdapter.ts: -------------------------------------------------------------------------------- 1 | import { 2 | InternalQgisApi, 3 | QgisApi, 4 | QgisApiAdapter, 5 | } from "../../../src/api/QgisApi"; 6 | import { MapLayer, Rectangle } from "../../../src/api/QgisModel"; 7 | 8 | import { threadPoolSize } from "./runtime"; 9 | 10 | import pLimit from "p-limit"; 11 | import type { LimitFunction } from "p-limit"; 12 | 13 | export class QgisApiAdapterImplementation implements QgisApiAdapter { 14 | private readonly _api: InternalQgisApi; 15 | private readonly _threadPoolSize: number; 16 | private readonly _limit: LimitFunction; 17 | 18 | constructor(api: InternalQgisApi) { 19 | this._api = api; 20 | this._threadPoolSize = threadPoolSize(); 21 | this._limit = pLimit(this._threadPoolSize); 22 | } 23 | 24 | protected runLimited(fn: () => Promise): Promise { 25 | return this._limit(fn); 26 | } 27 | 28 | renderImage( 29 | srid: string, 30 | extent: Rectangle, 31 | width: number, 32 | height: number, 33 | pixelRatio: number = window?.devicePixelRatio || 1, 34 | ): Promise { 35 | return this.runLimited(() => { 36 | return new Promise((resolve) => { 37 | this._api.renderImage( 38 | srid, 39 | extent, 40 | width, 41 | height, 42 | pixelRatio, 43 | (tileData) => { 44 | const data = new Uint8ClampedArray(tileData); 45 | const imageData = new ImageData(data, width, height); 46 | resolve(imageData); 47 | }, 48 | ); 49 | }); 50 | }); 51 | } 52 | renderXYZTile( 53 | x: number, 54 | y: number, 55 | z: number, 56 | tileSize: number = 256, 57 | pixelRatio: number = window?.devicePixelRatio || 1, 58 | extentBuffer: number = 0, 59 | ): Promise { 60 | return this.runLimited(() => { 61 | return new Promise((resolve) => { 62 | this._api.renderXYZTile( 63 | x, 64 | y, 65 | z, 66 | tileSize, 67 | pixelRatio, 68 | extentBuffer, 69 | (tileData) => { 70 | const data = new Uint8ClampedArray(tileData); 71 | const imageData = new ImageData(data, tileSize, tileSize); 72 | resolve(imageData); 73 | }, 74 | ); 75 | }); 76 | }); 77 | } 78 | 79 | mapLayers(): readonly MapLayer[] { 80 | const mapLayersRaw = this._api.mapLayers(); 81 | const result = new Array(mapLayersRaw.size()); 82 | for (let i = 0; i < mapLayersRaw.size(); i++) { 83 | result[i] = mapLayersRaw.get(i); 84 | } 85 | return result; 86 | } 87 | 88 | mapThemes(): readonly string[] { 89 | const mapLayersRaw = this._api.mapThemes(); 90 | const result = new Array(mapLayersRaw.size()); 91 | for (let i = 0; i < mapLayersRaw.size(); i++) { 92 | result[i] = mapLayersRaw.get(i); 93 | } 94 | return result; 95 | } 96 | } 97 | 98 | export function getQgisApiProxy(api: InternalQgisApi): QgisApi { 99 | const adapter = new QgisApiAdapterImplementation(api); 100 | 101 | return new Proxy( 102 | // @ts-ignore 103 | {}, 104 | { 105 | has(_target, property) { 106 | return property in adapter || property in api; 107 | }, 108 | get(_target, property) { 109 | if (property in adapter) { 110 | // @ts-ignore 111 | return adapter[property]; 112 | } else if (property in api) { 113 | // @ts-ignore 114 | return api[property]; 115 | } 116 | }, 117 | }, 118 | ); 119 | } 120 | -------------------------------------------------------------------------------- /packages/qgis-js/src/emscripten.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | /** 4 | * Extension of a EmscriptenModule that adds additional properties 5 | */ 6 | export interface EmscriptenRuntimeModule extends EmscriptenModule { 7 | [x: string]: any; 8 | } 9 | 10 | /** 11 | * Emscripten file system 12 | * 13 | * {@link https://emscripten.org/docs/api_reference/Filesystem-API.html} 14 | */ 15 | export type EmscriptenFS = typeof FS; 16 | -------------------------------------------------------------------------------- /packages/qgis-js/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * The version of qgis-js. 3 | */ 4 | export const QGIS_JS_VERSION: string = 5 | //@ts-ignore (will be defined by vite) 6 | __QGIS_JS_VERSION; 7 | 8 | export type { 9 | QgisApi, 10 | QgisApiAdapter, 11 | CommonQgisApi, 12 | InternalQgisApi, 13 | } from "../../../src/api/QgisApi"; 14 | 15 | export type { EmscriptenFS } from "./emscripten"; 16 | 17 | export type { PointXY, Rectangle } from "../../../src/api/QgisModel"; 18 | 19 | export { qgis } from "./loader"; 20 | -------------------------------------------------------------------------------- /packages/qgis-js/src/loader.ts: -------------------------------------------------------------------------------- 1 | import { getQgisApiProxy } from "./QgisApiAdapter"; 2 | 3 | import { threadPoolSize } from "./runtime"; 4 | import type { 5 | QgisRuntime, 6 | QgisRuntimeConfig, 7 | QgisRuntimeModule, 8 | } from "./runtime"; 9 | 10 | import type { EmscriptenRuntimeModule } from "./emscripten"; 11 | 12 | /** 13 | * Emscripten module configuration 14 | */ 15 | interface QtAppConfig {} 16 | 17 | /** 18 | * Interface for a Emscripten module that creates a Qt app instance. 19 | */ 20 | interface QtRuntimeFactory { 21 | createQtAppInstance(config: QtAppConfig): Promise; 22 | } 23 | 24 | /** 25 | * Loads the QtRuntimeFactory Emscripten module with the given prefix. 26 | * 27 | * @param mainScriptPath - The import path of the main script 28 | * @returns A promise that resolves with the QtRuntimeFactory module. 29 | */ 30 | function loadModule(mainScriptPath: string): Promise { 31 | return new Promise(async (resolve, reject) => { 32 | try { 33 | // hack to import es module without vite knowing about it 34 | const createQtAppInstance = ( 35 | await new Function(`return import("${mainScriptPath}")`)() 36 | ).default; 37 | resolve({ 38 | createQtAppInstance, 39 | }); 40 | } catch (error) { 41 | reject(error); 42 | } 43 | }); 44 | } 45 | 46 | /** 47 | * Load and initialize a new qgis-js runtime. 48 | * 49 | * @param config The {@link QgisRuntimeConfig} that will be taken into account during loading and initialization. 50 | * @returns A promise that resolves to a {@link QgisRuntime}. 51 | */ 52 | export async function qgis( 53 | config: QgisRuntimeConfig = {}, 54 | ): Promise { 55 | return new Promise(async (resolve, reject) => { 56 | let prefix: string | undefined = undefined; 57 | if (config.prefix) { 58 | prefix = config.prefix; 59 | } else { 60 | const url = import.meta.url; 61 | if (/.*\/src\/loader\.[ts|js]\?*[^/]*$/.test(url)) { 62 | console.warn( 63 | [ 64 | `qgis-js loader is running in development mode and no "prefix" seems to be configured.`, 65 | ` - Consider adding the QgisRuntimePlugin when bundling with Vite.`, 66 | ` - For more information see: https://github.com/qgis/qgis-js/blob/main/docs/bundling.md`, 67 | ].join("\n"), 68 | ); 69 | if (typeof window !== "undefined") { 70 | prefix = new URL("assets/wasm", window.location.href).pathname; 71 | } 72 | } else { 73 | prefix = new URL("assets/wasm", import.meta.url).href; 74 | } 75 | } 76 | 77 | if (!prefix) { 78 | prefix = "assets/wasm"; 79 | } else { 80 | prefix = prefix.replace(/\/$/, ""); // ensure no trailing slash 81 | } 82 | 83 | let qtRuntimeFactory: QtRuntimeFactory | undefined = undefined; 84 | try { 85 | const mainScriptPath = `${prefix}/qgis-js.js`; 86 | qtRuntimeFactory = await loadModule(mainScriptPath); 87 | } catch (error) { 88 | reject( 89 | new Error(`Unable to load the qgis-js.js script`, { cause: error }), 90 | ); 91 | return; 92 | } 93 | 94 | const { createQtAppInstance } = qtRuntimeFactory!; 95 | 96 | let canvas: HTMLDivElement | undefined = undefined; 97 | if (typeof document !== "undefined") { 98 | canvas = document?.querySelector("#screen") as HTMLDivElement; 99 | } 100 | 101 | const runtimePromise = createQtAppInstance({ 102 | locateFile: (path: string) => `${prefix}/` + path, 103 | preRun: [ 104 | function (module: any) { 105 | module.qtContainerElements = canvas ? [canvas] : []; 106 | module.qtFontDpi = 96; 107 | module.qgisJsMaxThreads = threadPoolSize(); 108 | }, 109 | ], 110 | postRun: [ 111 | async function () { 112 | const runtime = await runtimePromise; 113 | resolve({ 114 | api: getQgisApiProxy(runtime), 115 | module: runtime as EmscriptenRuntimeModule, 116 | fs: runtime.FS, 117 | }); 118 | }, 119 | ], 120 | ...(config.onStatus ? { setStatus: config.onStatus } : {}), 121 | }); 122 | }); 123 | } 124 | -------------------------------------------------------------------------------- /packages/qgis-js/src/runtime.ts: -------------------------------------------------------------------------------- 1 | import { EmscriptenRuntimeModule, EmscriptenFS } from "./emscripten"; 2 | 3 | import { QgisApi, InternalQgisApi } from "../../../src/api/QgisApi"; 4 | 5 | /** 6 | * Qt emscripten runtime module that exposes the QgisInternalApi 7 | */ 8 | export interface QgisRuntimeModule 9 | extends EmscriptenRuntimeModule, 10 | InternalQgisApi {} 11 | 12 | /** 13 | * Boot configuration options for the QGIS runtime. 14 | */ 15 | export interface QgisRuntimeConfig { 16 | /** 17 | * The prefix to use for the {@link EmscriptenRuntimeModule} path. 18 | */ 19 | prefix?: string; 20 | /** 21 | * A callback function that will be called when the runtime status changes. 22 | */ 23 | onStatus?: (status: string) => void; 24 | } 25 | 26 | /** 27 | * Wraps the {@link EmscriptenRuntimeModule} and exposes the {@link QgisApi} and {@link EmscriptenFS} 28 | */ 29 | export interface QgisRuntime { 30 | api: QgisApi; 31 | module: EmscriptenRuntimeModule; 32 | fs: EmscriptenFS; 33 | } 34 | 35 | /** 36 | * Returns the thread pool size based on the hardware concurrency of the user's device. 37 | * The thread pool size is capped between a minium of 4 and a maximum 16 threads. 38 | * 39 | * @privateRemarks This needs to be in sync with PTHREAD_POOL_SIZE in CMakeLists.txt 40 | * 41 | * @returns The thread pool size of the qgis-js runtime 42 | */ 43 | export function threadPoolSize() { 44 | const MINIMAL_THREAD_POOL_SIZE = 4; 45 | const MAXIMAL_THREAD_POOL_SIZE = 16; 46 | return Math.min( 47 | Math.max( 48 | navigator?.hardwareConcurrency || MINIMAL_THREAD_POOL_SIZE, 49 | MINIMAL_THREAD_POOL_SIZE, 50 | ), 51 | MAXIMAL_THREAD_POOL_SIZE, 52 | ); 53 | } 54 | -------------------------------------------------------------------------------- /packages/qgis-js/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/qgis-js/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { resolve } from "path"; 2 | import { defineConfig } from "vite"; 3 | 4 | import QgisRuntimePlugin from "../../build/vite/QgisRuntimePlugin"; 5 | 6 | import dts from "vite-plugin-dts"; 7 | 8 | import packageJson from "./package.json"; 9 | 10 | export default defineConfig({ 11 | define: { 12 | __QGIS_JS_VERSION: JSON.stringify(packageJson.version), 13 | }, 14 | plugins: [ 15 | QgisRuntimePlugin({ 16 | name: "qgis-js", 17 | outputDir: "build/wasm", 18 | }), 19 | dts({ 20 | copyDtsFiles: true, 21 | 22 | staticImport: true, 23 | // insertTypesEntry: true, 24 | compilerOptions: { 25 | declarationMap: true, 26 | }, 27 | 28 | rollupTypes: true, 29 | entryRoot: "src", 30 | rollupConfig: { 31 | docModel: { 32 | enabled: true, 33 | apiJsonFilePath: "/etc/.api.json", 34 | }, 35 | }, 36 | async afterBuild() { 37 | // remove empty export statement 38 | const fs = await import("fs"); 39 | const path = await import("path"); 40 | const dtsFile = path.join(__dirname, "dist", "qgis.d.ts"); 41 | let content = fs.readFileSync(dtsFile, "utf-8"); 42 | content = content.replace("export { }", ""); 43 | 44 | // format file with prettier 45 | const prettier = await import("prettier"); 46 | const prettierConfig = await prettier.resolveConfig( 47 | path.join(__dirname, "../..", ".prettierrc.json"), 48 | ); 49 | 50 | content = await prettier.format(content, { 51 | ...prettierConfig, 52 | parser: "typescript", 53 | }); 54 | 55 | fs.writeFileSync(dtsFile, content); 56 | return; 57 | }, 58 | }), 59 | ], 60 | build: { 61 | lib: { 62 | entry: [resolve(__dirname, "src/index.ts")], 63 | name: "qgis-js", 64 | formats: ["es"], 65 | fileName: "qgis", 66 | }, 67 | }, 68 | }); 69 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - packages/* 3 | - sites/* 4 | onlyBuiltDependencies: 5 | - esbuild 6 | -------------------------------------------------------------------------------- /qgis-js.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env -S node_modules/.bin/vite-node --script 2 | 3 | /* 4 | * qgis-js CLI 5 | * 6 | * Will help you to build qgis-js and generate its documentation. 7 | * 8 | * Run "qgis-js --help" for more information. 9 | */ 10 | 11 | import { CommandLineParser } from "@rushstack/ts-command-line"; 12 | 13 | import { CleanAction } from "./build/actions/clean"; 14 | import { InstallAction } from "./build/actions/install"; 15 | import { CompileAction } from "./build/actions/compile"; 16 | import { LibsAction } from "./build/actions/libs"; 17 | import { SizeAction } from "./build/actions/size"; 18 | 19 | import { QgisJsOptions } from "./build/actions/lib/QgisJsOptions"; 20 | 21 | const options: QgisJsOptions = {} as QgisJsOptions; 22 | 23 | export class QgisJsCommandLine extends CommandLineParser { 24 | public constructor() { 25 | super({ 26 | toolFilename: "qgis-js", 27 | toolDescription: 'The "qgis-js" build tool.', 28 | }); 29 | this.addAction(new CleanAction(options)); 30 | this.addAction(new InstallAction(options)); 31 | this.addAction(new CompileAction(options)); 32 | this.addAction(new LibsAction(options)); 33 | this.addAction(new SizeAction(options)); 34 | } 35 | 36 | protected onDefineParameters(): void { 37 | this.defineFlagParameter({ 38 | parameterLongName: "--verbose", 39 | parameterShortName: "-v", 40 | description: "Show extra logging detail", 41 | }); 42 | } 43 | 44 | protected onExecute(): Promise { 45 | options.verbose = this.getFlagParameter("--verbose")?.value || false; 46 | 47 | process.env.FORCE_COLOR = "1"; 48 | 49 | return super.onExecute(); 50 | } 51 | } 52 | 53 | const qgisjs = new QgisJsCommandLine(); 54 | qgisjs.execute(); 55 | -------------------------------------------------------------------------------- /sites/dev/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@qgis-js/dev", 3 | "version": "0.0.5", 4 | "private": true, 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite dev", 8 | "build": "vite build", 9 | "preview": "vite preview", 10 | "deploy": "npm run build && npm run deploy:upload", 11 | "deploy:upload": "rsync --recursive --delete-before dist/ tux@zrhwpk.asuscomm.com:/data/https-portal/vhosts/qgis-js.dev.schmuki.io" 12 | }, 13 | "dependencies": { 14 | "@qgis-js/ol": "workspace:*", 15 | "@qgis-js/utils": "workspace:*", 16 | "qgis-js": "workspace:*" 17 | }, 18 | "devDependencies": { 19 | "coi-serviceworker": "0.1.7", 20 | "ol": "^10.4.0", 21 | "typescript": "5.8.2", 22 | "vite": "6.2.2", 23 | "vite-plugin-static-copy": "2.3.0" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /sites/dev/public/projects/village/buildings.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qgis/qgis-js/f297b1601cc4062d71057ef8f274d71c0cddc91e/sites/dev/public/projects/village/buildings.dbf -------------------------------------------------------------------------------- /sites/dev/public/projects/village/buildings.prj: -------------------------------------------------------------------------------- 1 | PROJCS["OSGB_1936_British_National_Grid",GEOGCS["GCS_OSGB 1936",DATUM["D_OSGB_1936",SPHEROID["Airy_1830",6377563.396,299.3249646]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",49],PARAMETER["central_meridian",-2],PARAMETER["scale_factor",0.9996012717],PARAMETER["false_easting",400000],PARAMETER["false_northing",-100000],UNIT["Meter",1]] -------------------------------------------------------------------------------- /sites/dev/public/projects/village/buildings.qpj: -------------------------------------------------------------------------------- 1 | PROJCS["OSGB 1936 / British National Grid",GEOGCS["OSGB 1936",DATUM["OSGB_1936",SPHEROID["Airy 1830",6377563.396,299.3249646,AUTHORITY["EPSG","7001"]],TOWGS84[446.448,-125.157,542.06,0.15,0.247,0.842,-20.489],AUTHORITY["EPSG","6277"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4277"]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",49],PARAMETER["central_meridian",-2],PARAMETER["scale_factor",0.9996012717],PARAMETER["false_easting",400000],PARAMETER["false_northing",-100000],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["Easting",EAST],AXIS["Northing",NORTH],AUTHORITY["EPSG","27700"]] 2 | -------------------------------------------------------------------------------- /sites/dev/public/projects/village/buildings.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qgis/qgis-js/f297b1601cc4062d71057ef8f274d71c0cddc91e/sites/dev/public/projects/village/buildings.shp -------------------------------------------------------------------------------- /sites/dev/public/projects/village/buildings.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qgis/qgis-js/f297b1601cc4062d71057ef8f274d71c0cddc91e/sites/dev/public/projects/village/buildings.shx -------------------------------------------------------------------------------- /sites/dev/public/projects/village/rgb.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qgis/qgis-js/f297b1601cc4062d71057ef8f274d71c0cddc91e/sites/dev/public/projects/village/rgb.tif -------------------------------------------------------------------------------- /sites/dev/public/qgis-icon128.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /sites/dev/src/js.ts: -------------------------------------------------------------------------------- 1 | import { QgisApi } from "qgis-js"; 2 | 3 | import type { Rectangle } from "qgis-js"; 4 | 5 | const mapScaleFactor = 1.5; 6 | const mapMoveFactor = 0.1; 7 | 8 | export function jsDemo( 9 | canvas: HTMLCanvasElement, 10 | api: QgisApi, 11 | ): { update: () => void; render: () => void } { 12 | let lastExtent: Rectangle | null = null; 13 | 14 | // ensure pixel perfect rendering 15 | // see https://web.dev/articles/device-pixel-content-box 16 | const observer = new ResizeObserver((entries) => { 17 | const entry = entries.find((entry) => entry.target === canvas); 18 | if (entry) { 19 | canvas.width = entry.devicePixelContentBoxSize[0].inlineSize; 20 | canvas.height = entry.devicePixelContentBoxSize[0].blockSize; 21 | } 22 | renderMap(); 23 | }); 24 | observer.observe(canvas, { box: "device-pixel-content-box" }); 25 | 26 | async function renderMap() { 27 | var devicePixelRatio = window.devicePixelRatio || 1; 28 | var cssRect = canvas.getBoundingClientRect(); 29 | const imageWidth = cssRect.width * devicePixelRatio; 30 | const imageHeight = cssRect.height * devicePixelRatio; 31 | 32 | if (imageWidth && imageHeight) { 33 | const image = await api.renderImage( 34 | api.srid(), 35 | lastExtent!, 36 | imageWidth, 37 | imageHeight, 38 | window.devicePixelRatio, 39 | ); 40 | 41 | const context = canvas.getContext("2d"); 42 | canvas.width = imageWidth; 43 | canvas.height = imageHeight; 44 | context!.scale(devicePixelRatio, devicePixelRatio); 45 | context!.putImageData(image, 0, 0); 46 | } 47 | } 48 | 49 | document.getElementById("zoomin")!.onclick = function () { 50 | lastExtent!.scale(1 / mapScaleFactor); 51 | renderMap(); 52 | }; 53 | document.getElementById("zoomout")!.onclick = function () { 54 | lastExtent!.scale(mapScaleFactor); 55 | renderMap(); 56 | }; 57 | document.getElementById("panleft")!.onclick = function () { 58 | lastExtent!.move( 59 | (lastExtent!.xMaximum - lastExtent!.xMinimum) * mapMoveFactor, 60 | 0, 61 | ); 62 | renderMap(); 63 | }; 64 | document.getElementById("panright")!.onclick = function () { 65 | lastExtent!.move( 66 | -(lastExtent!.xMaximum - lastExtent!.xMinimum) * mapMoveFactor, 67 | 0, 68 | ); 69 | renderMap(); 70 | }; 71 | document.getElementById("panup")!.onclick = function () { 72 | lastExtent!.move( 73 | 0, 74 | -(lastExtent!.yMaximum - lastExtent!.yMinimum) * mapMoveFactor, 75 | ); 76 | renderMap(); 77 | }; 78 | document.getElementById("pandown")!.onclick = function () { 79 | lastExtent!.move( 80 | 0, 81 | (lastExtent!.yMaximum - lastExtent!.yMinimum) * mapMoveFactor, 82 | ); 83 | renderMap(); 84 | }; 85 | 86 | function onStart() { 87 | lastExtent = api.fullExtent(); 88 | renderMap(); 89 | } 90 | 91 | onStart(); 92 | 93 | return { 94 | update: () => { 95 | onStart(); 96 | }, 97 | render: () => { 98 | renderMap(); 99 | }, 100 | }; 101 | } 102 | -------------------------------------------------------------------------------- /sites/dev/src/layers.ts: -------------------------------------------------------------------------------- 1 | import { QgisApi } from "qgis-js"; 2 | 3 | export function layersControl( 4 | target: HTMLDivElement, 5 | api: QgisApi, 6 | redraw: () => void = () => {}, 7 | ): () => void { 8 | const update = () => { 9 | target.innerHTML = ""; 10 | 11 | const layerContainer = document.createElement("div"); 12 | layerContainer.className = "layers"; 13 | target.appendChild(layerContainer); 14 | 15 | const layers = api.mapLayers(); 16 | for (const layer of layers) { 17 | const node = document.createElement("div"); 18 | node.className = "layer"; 19 | 20 | // create checkbox in node 21 | const checkbox = document.createElement("input"); 22 | checkbox.type = "checkbox"; 23 | if (layer.visible) { 24 | checkbox.checked = true; 25 | } 26 | checkbox.addEventListener("change", () => { 27 | layer.visible = checkbox.checked; 28 | redraw(); 29 | update(); 30 | }); 31 | node.appendChild(checkbox); 32 | 33 | // create name as text node 34 | const textnode = document.createTextNode(layer.name); 35 | node.appendChild(textnode); 36 | 37 | // create opacity slider in node 38 | const slider = document.createElement("input"); 39 | if (!layer.visible) { 40 | slider.style.visibility = "hidden"; 41 | } 42 | slider.type = "range"; 43 | slider.min = "0"; 44 | slider.max = "100"; 45 | slider.value = "" + layer.opacity * 100; 46 | slider.step = "1"; 47 | slider.addEventListener("change", () => { 48 | layer.opacity = parseInt(slider.value) / 100; 49 | redraw(); 50 | }); 51 | 52 | node.appendChild(slider); 53 | layerContainer.appendChild(node); 54 | } 55 | 56 | if (api.mapThemes().length > 0) { 57 | const themeContainer = document.createElement("div"); 58 | themeContainer.className = "themes"; 59 | target.appendChild(themeContainer); 60 | 61 | const select = document.createElement("select"); 62 | select.addEventListener("change", () => { 63 | if (select.value) { 64 | api.setMapTheme(select.value); 65 | redraw(); 66 | update(); 67 | } 68 | }); 69 | themeContainer.appendChild(select); 70 | 71 | const currentTheme = api.getMapTheme(); 72 | 73 | const option = document.createElement("option"); 74 | option.value = ""; 75 | option.text = ""; 76 | if (!currentTheme) { 77 | option.selected = true; 78 | } 79 | select.appendChild(option); 80 | 81 | for (const theme of api.mapThemes()) { 82 | const option = document.createElement("option"); 83 | option.value = theme; 84 | option.text = theme; 85 | if (theme === currentTheme) { 86 | option.selected = true; 87 | } 88 | select.appendChild(option); 89 | } 90 | } 91 | }; 92 | 93 | update(); 94 | 95 | return update; 96 | } 97 | -------------------------------------------------------------------------------- /sites/dev/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /sites/dev/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { resolve } from "path"; 2 | import { defineConfig } from "vite"; 3 | 4 | import QgisRuntimePlugin from "../../build/vite/QgisRuntimePlugin"; 5 | import DirectoryListingPlugin from "../../build/vite/DirectoryListingPlugin"; 6 | import CrossOriginIsolationPlugin, { 7 | CrossOriginIsolationResponseHeaders, 8 | } from "../../build/vite/CrossOriginIsolationPlugin"; 9 | 10 | import { viteStaticCopy } from "vite-plugin-static-copy"; 11 | 12 | import packageJson from "./package.json"; 13 | 14 | export default defineConfig({ 15 | base: "/qgis-js/", 16 | define: { 17 | __QGIS_JS_VERSION: JSON.stringify(packageJson.version), 18 | }, 19 | resolve: { 20 | alias: [ 21 | // don't use the bundlet version of qgis-js and qgis-js-ol to enable HMR 22 | { 23 | find: /^qgis-js$/, 24 | replacement: resolve(__dirname, "../../packages/qgis-js/src/index.ts"), 25 | }, 26 | { 27 | find: /^@qgis-js\/ol$/, 28 | replacement: resolve( 29 | __dirname, 30 | "../../packages/qgis-js-ol/src/index.ts", 31 | ), 32 | }, 33 | { 34 | find: /^@qgis-js\/utils$/, 35 | replacement: resolve( 36 | __dirname, 37 | "../../packages/qgis-js-utils/src/index.ts", 38 | ), 39 | }, 40 | ], 41 | }, 42 | preview: { 43 | headers: { 44 | ...CrossOriginIsolationResponseHeaders, 45 | }, 46 | }, 47 | plugins: [ 48 | QgisRuntimePlugin({ 49 | name: "qgis-js", 50 | outputDir: "build/wasm", 51 | }), 52 | CrossOriginIsolationPlugin(), 53 | DirectoryListingPlugin(["public/projects"]), 54 | viteStaticCopy({ 55 | targets: [ 56 | { 57 | src: "node_modules/coi-serviceworker/coi-serviceworker.min.js", 58 | dest: "", 59 | }, 60 | ], 61 | }), 62 | ], 63 | }); 64 | -------------------------------------------------------------------------------- /sites/performance/.gitignore: -------------------------------------------------------------------------------- 1 | /test-results/ 2 | /playwright-report/ 3 | /blob-report/ 4 | /playwright/.cache/ 5 | /test-results/ 6 | /playwright-report/ 7 | /blob-report/ 8 | /playwright/.cache/ 9 | /test-results/ 10 | /playwright-report/ 11 | /blob-report/ 12 | /playwright/.cache/ 13 | /test-results/ 14 | /playwright-report/ 15 | /blob-report/ 16 | /playwright/.cache/ 17 | public/projects 18 | -------------------------------------------------------------------------------- /sites/performance/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@qgis-js/performance", 3 | "version": "0.0.1", 4 | "private": true, 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite dev", 8 | "build": "vite build", 9 | "preview": "vite preview", 10 | "perf": "playwright test" 11 | }, 12 | "dependencies": { 13 | "qgis-js": "workspace:*", 14 | "@qgis-js/utils": "workspace:*" 15 | }, 16 | "devDependencies": { 17 | "@playwright/test": "^1.51.1", 18 | "@types/node": "^22.13.11", 19 | "typescript": "5.8.2", 20 | "vite": "6.2.2", 21 | "vite-plugin-static-copy": "2.3.0" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /sites/performance/playwright.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig, devices } from "@playwright/test"; 2 | 3 | export default defineConfig({ 4 | testDir: "./tests", 5 | retries: 0, 6 | fullyParallel: false, 7 | workers: 1, 8 | reporter: [["list"], ["json", { outputFile: "test-results.json" }], ["html"]], 9 | use: { 10 | baseURL: "http://127.0.0.1:3000", 11 | 12 | /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ 13 | trace: "on-first-retry", 14 | }, 15 | projects: [ 16 | { 17 | name: "chromium", 18 | use: { ...devices["Desktop Chrome"] }, 19 | }, 20 | 21 | { 22 | name: "firefox", 23 | use: { ...devices["Desktop Firefox"] }, 24 | }, 25 | ], 26 | webServer: { 27 | command: "npm run dev", 28 | url: "http://127.0.0.1:3000", 29 | stdout: "pipe", 30 | stderr: "pipe", 31 | }, 32 | }); 33 | -------------------------------------------------------------------------------- /sites/performance/report.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Performance Report 4 | 19 | 20 | 21 |

Performance Report

22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 |
TaskProjectBaseline
Load project
Load project
Load project
45 |
46 | 47 | 48 | -------------------------------------------------------------------------------- /sites/performance/tests/performance.spec.ts: -------------------------------------------------------------------------------- 1 | import { test, expect } from "@playwright/test"; 2 | 3 | import { join, dirname } from "path"; 4 | import { readdirSync } from "fs"; 5 | import { fileURLToPath } from "url"; 6 | 7 | import { createRequire } from "module"; 8 | const require = createRequire(import.meta.url); 9 | 10 | const __dirname = dirname(fileURLToPath(import.meta.url)); 11 | 12 | test.describe.serial("Performance measurement", () => { 13 | // reading test projects 14 | const projectsDir = join(__dirname, "..", "public", "projects"); 15 | const projectNames = readdirSync(projectsDir); 16 | 17 | // create a test for each project 18 | for (const projectName of projectNames) { 19 | console.log(projectName); 20 | 21 | const json = require(`../public/projects/${projectName}/measure.json`); 22 | console.dir(json); 23 | 24 | test(`Test project "${projectName}"`, async ({ page }) => { 25 | await page.goto("/"); 26 | 27 | await expect(page).toHaveTitle(/^qgis-js-performance$/); 28 | 29 | const btnBoot = page.locator("#boot"); 30 | const btnProject = page.locator("#project"); 31 | const btnFrame = page.locator("#frame"); 32 | const btnStart = page.locator("#start"); 33 | 34 | await test.step("Boot runtime", async () => { 35 | expect(btnBoot).not.toBeNull(); 36 | await btnBoot?.click(); 37 | await expect(btnProject).toBeEnabled(); 38 | }); 39 | 40 | await test.step("Load project", async () => { 41 | expect(btnProject).not.toBeNull(); 42 | 43 | const inpProject = page.locator("#project-input"); 44 | expect(btnProject).not.toBeNull(); 45 | await inpProject.fill(projectName); 46 | 47 | await btnProject?.click(); 48 | 49 | await expect(btnFrame).toBeEnabled({ timeout: 10000 }); 50 | }); 51 | 52 | await test.step("Render first frame", async () => { 53 | expect(btnFrame).not.toBeNull(); 54 | 55 | await btnFrame?.click(); 56 | 57 | await expect(btnStart).toBeEnabled({ timeout: 10000 }); 58 | }); 59 | 60 | await test.step("Run performance measurement", async () => { 61 | expect(btnStart).not.toBeNull(); 62 | 63 | const inpExtent = page.locator("#start-extent-input"); 64 | expect(btnProject).not.toBeNull(); 65 | await inpExtent.fill(JSON.stringify(json.extent, undefined, "")); 66 | 67 | const inpResolution = page.locator("#start-resolution-input"); 68 | expect(inpResolution).not.toBeNull(); 69 | await inpResolution.fill( 70 | JSON.stringify(json.resolution, undefined, ""), 71 | ); 72 | 73 | await btnStart?.click(); 74 | 75 | await page.waitForSelector("#results"); 76 | 77 | // wait until div with id "loader" is gone 78 | await page.waitForSelector("#loading", { state: "detached" }); 79 | }); 80 | 81 | console.log("test done"); 82 | }); 83 | } 84 | }); 85 | -------------------------------------------------------------------------------- /sites/performance/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /sites/performance/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | 3 | import QgisRuntimePlugin from "../../build/vite/QgisRuntimePlugin"; 4 | import DirectoryListingPlugin from "../../build/vite/DirectoryListingPlugin"; 5 | import CrossOriginIsolationPlugin, { 6 | CrossOriginIsolationResponseHeaders, 7 | } from "../../build/vite/CrossOriginIsolationPlugin"; 8 | 9 | import packageJson from "./package.json"; 10 | 11 | export default defineConfig({ 12 | define: { 13 | __QGIS_JS_VERSION: JSON.stringify(packageJson.version), 14 | }, 15 | server: { 16 | port: 3000, 17 | }, 18 | preview: { 19 | headers: { 20 | ...CrossOriginIsolationResponseHeaders, 21 | }, 22 | }, 23 | plugins: [ 24 | QgisRuntimePlugin({ 25 | name: "qgis-js", 26 | outputDir: "build/wasm", 27 | }), 28 | CrossOriginIsolationPlugin(), 29 | DirectoryListingPlugin(["public/projects"]), 30 | ], 31 | }); 32 | -------------------------------------------------------------------------------- /src/api/QgisModel.ts: -------------------------------------------------------------------------------- 1 | import { PointXY, PointXYConstructors } from "../model/PointXY"; 2 | import { Rectangle, RectangleConstructors } from "../model/Rectangle"; 3 | import { MapLayer } from "../model/MapLayer"; 4 | import { QgsMapRendererParallelJob } from "../model/QgsMapRendererParallelJob"; 5 | import { QgsMapRendererJob } from "../model/QgsMapRendererJob"; 6 | import { QgsMapRendererQImageJob } from "../model/QgsMapRendererQImageJob"; 7 | 8 | export type { 9 | QgsMapRendererJob, 10 | QgsMapRendererQImageJob, 11 | QgsMapRendererParallelJob, 12 | PointXY, 13 | Rectangle, 14 | MapLayer, 15 | }; 16 | 17 | /* prettier-ignore */ 18 | 19 | /** 20 | * Geathers all constructors of the QGIS model classes. 21 | */ 22 | export interface QgisModelConstructors 23 | extends 24 | PointXYConstructors, 25 | RectangleConstructors 26 | {} 27 | -------------------------------------------------------------------------------- /src/model/MapLayer.hpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | class MapLayer { 11 | public: 12 | MapLayer(QgsMapLayer *qgsMapLayer) : 13 | qgsMapLayer(qgsMapLayer) 14 | 15 | {} 16 | 17 | std::string name() const { 18 | return this->layer()->name().toStdString(); 19 | } 20 | 21 | void setName(std::string name) { 22 | this->layer()->setName(QString::fromStdString(name)); 23 | } 24 | 25 | bool isVisible() const { 26 | return this->node()->itemVisibilityChecked(); 27 | } 28 | 29 | void setVisible(bool visible) { 30 | this->node()->setItemVisibilityChecked(visible); 31 | } 32 | 33 | double opacity() const { 34 | return this->layer()->opacity(); 35 | } 36 | 37 | void setOpacity(double opacity) { 38 | this->layer()->setOpacity(opacity); 39 | } 40 | 41 | protected: 42 | QgsMapLayer *layer() const { 43 | return qgsMapLayer; 44 | } 45 | 46 | QgsLayerTreeLayer *node() const { 47 | return QgsProject::instance()->layerTreeRoot()->findLayer(this->layer()->id()); 48 | } 49 | 50 | private: 51 | QgsMapLayer *qgsMapLayer; 52 | }; 53 | 54 | EMSCRIPTEN_BINDINGS(MapLayer) { 55 | emscripten::class_("MapLayer") 56 | .property("name", &MapLayer::name, &MapLayer::setName) 57 | .property("visible", &MapLayer::isVisible, &MapLayer::setVisible) 58 | .property("opacity", &MapLayer::opacity, &MapLayer::setOpacity); 59 | } 60 | -------------------------------------------------------------------------------- /src/model/MapLayer.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Represents a map layer. 3 | */ 4 | export interface MapLayer { 5 | name: string; 6 | visible: boolean; 7 | opacity: number; 8 | } 9 | 10 | // Note: Wrapped internal class, no constructors available 11 | -------------------------------------------------------------------------------- /src/model/PointXY.hpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include 5 | 6 | EMSCRIPTEN_BINDINGS(QgsPointXY) { 7 | emscripten::class_("PointXY") 8 | .constructor<>() 9 | .property("x", &QgsPointXY::x, &QgsPointXY::setX) 10 | .property("y", &QgsPointXY::y, &QgsPointXY::setY); 11 | } 12 | -------------------------------------------------------------------------------- /src/model/PointXY.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * A class to represent a 2D point. 3 | * 4 | * {@link https://api.qgis.org/api/classQgsPointXY.html} 5 | */ 6 | export interface PointXY { 7 | x: number; 8 | y: number; 9 | } 10 | 11 | /** 12 | * The {@link PointXY} constructors. 13 | */ 14 | export interface PointXYConstructors { 15 | PointXY: { new (): PointXY }; 16 | } 17 | -------------------------------------------------------------------------------- /src/model/QgsMapRendererJob.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | static void QgsMapRendererJob_finished(QgsMapRendererJob &job, emscripten::val callback) { 8 | QObject::connect(&job, &QgsMapRendererJob::finished, [callback] { callback(); }); 9 | } 10 | 11 | EMSCRIPTEN_BINDINGS(QgsMapRendererJob) { 12 | emscripten::class_("QgsMapRendererJob") 13 | .function("cancel", &QgsMapRendererJob::cancel) 14 | .function("cancelWithoutBlocking", &QgsMapRendererJob::cancelWithoutBlocking) 15 | .function("isActive", &QgsMapRendererJob::isActive) 16 | .function("renderingTime", &QgsMapRendererJob::renderingTime) 17 | // signals 18 | .function("finished", &QgsMapRendererJob_finished); 19 | } 20 | -------------------------------------------------------------------------------- /src/model/QgsMapRendererJob.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Abstract base class for map rendering implementations 3 | * 4 | * {@link https://api.qgis.org/api/classQgsMapRendererJob.html} 5 | */ 6 | export interface QgsMapRendererJob { 7 | /** 8 | * Stop the rendering job - does not return until the job has terminated 9 | */ 10 | cancel(): void; 11 | 12 | /** 13 | * Triggers cancellation of the rendering job without blocking. 14 | */ 15 | cancelWithoutBlocking(): void; 16 | 17 | /** 18 | * Tell whether the rendering job is currently running in background. 19 | * @returns True if the job is active, false otherwise. 20 | */ 21 | isActive(): boolean; 22 | 23 | /** 24 | * Returns the total time it took to finish the job (in milliseconds) 25 | * @returns The rendering time in milliseconds. 26 | */ 27 | renderingTime(): number; 28 | 29 | /** 30 | * Registers a callback function to be called when the map rendering job is finished. 31 | * @param callback The callback function to be called. 32 | */ 33 | finished(callback: () => void): void; 34 | } 35 | -------------------------------------------------------------------------------- /src/model/QgsMapRendererParallelJob.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include "./QgsMapRendererQImageJob.hpp" 8 | 9 | EMSCRIPTEN_BINDINGS(QgsMapRendererParallelJob) { 10 | emscripten::class_>( 11 | "QgsMapRendererParallelJob") 12 | .function("cancel", &QgsMapRendererParallelJob::cancel) 13 | .function("cancelWithoutBlocking", &QgsMapRendererParallelJob::cancelWithoutBlocking) 14 | .function("isActive", &QgsMapRendererParallelJob::isActive) 15 | .function("renderingTime", &QgsMapRendererParallelJob::renderingTime); 16 | } 17 | -------------------------------------------------------------------------------- /src/model/QgsMapRendererParallelJob.ts: -------------------------------------------------------------------------------- 1 | import { QgsMapRendererQImageJob } from "./QgsMapRendererQImageJob"; 2 | 3 | /** 4 | * Job implementation that renders all layers in parallel 5 | * 6 | * {@link https://api.qgis.org/api/classQgsMapRendererParallelJob.html} 7 | */ 8 | export interface QgsMapRendererParallelJob extends QgsMapRendererQImageJob {} 9 | -------------------------------------------------------------------------------- /src/model/QgsMapRendererQImageJob.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include "./QgsMapRendererJob.hpp" 8 | 9 | static emscripten::val QgsMapRendererQImageJob_renderedImage(QgsMapRendererQImageJob &job) { 10 | auto image = std::move(job.renderedImage()).convertToFormat(QImage::Format_RGBA8888); 11 | return emscripten::val(emscripten::typed_memory_view( 12 | image.width() * image.height() * 4, (const unsigned char *)image.constBits())); 13 | } 14 | 15 | EMSCRIPTEN_BINDINGS(QgsMapRendererQImageJob) { 16 | emscripten::class_>( 17 | "QgsMapRendererQImageJob") 18 | .function("renderedImage", &QgsMapRendererQImageJob_renderedImage); 19 | } 20 | -------------------------------------------------------------------------------- /src/model/QgsMapRendererQImageJob.ts: -------------------------------------------------------------------------------- 1 | import { QgsMapRendererJob } from "./QgsMapRendererJob"; 2 | 3 | /** 4 | * Intermediate base class adding functionality that allows client to query the rendered image 5 | * 6 | * {@link https://api.qgis.org/api/classQgsMapRendererQImageJob.html} 7 | */ 8 | export interface QgsMapRendererQImageJob extends QgsMapRendererJob { 9 | /** 10 | * Returns the (preview or final) rendered image as a byte array 11 | * @returns The rendered image as an emscripten typed_memory_view. 12 | */ 13 | renderedImage(): ArrayBufferLike; 14 | } 15 | -------------------------------------------------------------------------------- /src/model/Rectangle.hpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include 5 | 6 | static void QgsRectangle_scale(QgsRectangle &r, double f) { 7 | r.scale(f); 8 | } 9 | 10 | static void QgsRectangle_move(QgsRectangle &r, double dx, double dy) { 11 | r += QgsVector(dx, dy); 12 | } 13 | 14 | EMSCRIPTEN_BINDINGS(QgsRectangle) { 15 | emscripten::class_("Rectangle") 16 | .constructor<>() 17 | .constructor() 18 | .property("xMinimum", &QgsRectangle::xMinimum, &QgsRectangle::setXMinimum) 19 | .property("yMinimum", &QgsRectangle::yMinimum, &QgsRectangle::setYMinimum) 20 | .property("xMaximum", &QgsRectangle::xMaximum, &QgsRectangle::setXMaximum) 21 | .property("yMaximum", &QgsRectangle::yMaximum, &QgsRectangle::setYMaximum) 22 | .function("scale", &QgsRectangle_scale) 23 | .function("move", &QgsRectangle_move) 24 | .function("center", &QgsRectangle::center); 25 | } 26 | -------------------------------------------------------------------------------- /src/model/Rectangle.ts: -------------------------------------------------------------------------------- 1 | import { PointXY } from "./PointXY"; 2 | 3 | /** 4 | * A rectangle specified with double values. 5 | * 6 | * {@link https://api.qgis.org/api/classQgsRectangle.html} 7 | */ 8 | export interface Rectangle { 9 | xMaximum: number; 10 | xMinimum: number; 11 | yMaximum: number; 12 | yMinimum: number; 13 | 14 | scale(factor: number): void; 15 | move(dx: number, dy: number): void; 16 | center(): PointXY; 17 | } 18 | 19 | /** 20 | * The {@link Rectangle} constructors. 21 | */ 22 | export interface RectangleConstructors { 23 | Rectangle: { 24 | new (): Rectangle; 25 | new (xMin: number, yMin: number, xMax: number, yMax: number): Rectangle; 26 | }; 27 | } 28 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2022", 4 | "useDefineForClassFields": true, 5 | "module": "ESNext", 6 | "lib": ["ES2022", "DOM", "DOM.Iterable"], 7 | "skipLibCheck": true, 8 | 9 | /* Bundler mode */ 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "noEmit": true, 15 | 16 | /* Linting */ 17 | "strict": true, 18 | "noUnusedLocals": true, 19 | "noUnusedParameters": true, 20 | "noFallthroughCasesInSwitch": true 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /vcpkg.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "qgis-js", 3 | "version": "0.1.0", 4 | "dependencies": [ 5 | "geos", 6 | { 7 | "name": "sqlite3", 8 | "default-features": false, 9 | "features": ["rtree", "json1", "fts3"] 10 | }, 11 | { 12 | "name": "proj", 13 | "default-features": false, 14 | "features": ["tiff"] 15 | }, 16 | { 17 | "name": "gdal", 18 | "default-features": false, 19 | "features": ["geos", "sqlite3"] 20 | }, 21 | "libspatialindex", 22 | "expat", 23 | { 24 | "name": "libzip", 25 | "default-features": false 26 | }, 27 | "protobuf", 28 | { 29 | "name": "freetype", 30 | "default-features": false, 31 | "features": ["zlib"] 32 | }, 33 | { 34 | "name": "freetype", 35 | "default-features": false, 36 | "host": true 37 | }, 38 | { 39 | "name": "qtbase", 40 | "default-features": false, 41 | "features": [ 42 | "opengl", 43 | "gles3", 44 | "concurrent", 45 | "gui", 46 | "jpeg", 47 | "network", 48 | "widgets", 49 | "sql", 50 | "sql-sqlite", 51 | "testlib" 52 | ] 53 | }, 54 | { 55 | "name": "qtbase", 56 | "host": true, 57 | "default-features": false 58 | }, 59 | { 60 | "name": "qt5compat", 61 | "default-features": false, 62 | "features": ["textcodec"] 63 | }, 64 | { 65 | "name": "qtsvg", 66 | "default-features": false 67 | }, 68 | { 69 | "name": "qca", 70 | "default-features": false 71 | }, 72 | "qtkeychain-qt6", 73 | "qgis-qt6" 74 | ] 75 | } 76 | --------------------------------------------------------------------------------