Coverage for gws-app/gws/plugin/qgis/__init__.py: 100%
1 statements
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-05 13:35 +0200
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-05 13:35 +0200
1"""QGIS support.
3This plugin uses QGIS projects as data sources for layers, search, models,
4legends and print templates. Projects are stored in files (``.qgs`` or
5zipped ``.qgz``) or in a Postgres table (``qgis_projects``, the QGIS
6"store project in PostgreSQL" format). Projects are parsed by reading the
7project XML directly; no QGIS APIs are used. Rendering, feature info,
8legends and printing are done by sending requests to a QGIS Server instance,
9whose address comes from the ``server.qgis`` application settings.
11Submodules
12----------
14- ``project`` - loading and storing QGIS projects (`project.Object`,
15 `project.Store`), in files or in a Postgres database.
16- ``caps`` - the project XML parser. It produces a `caps.Caps` object with
17 the project metadata, CRS, extents, source layers, print layouts,
18 visibility presets and custom properties, and also parses layer data
19 source strings (``parse_datasource``).
20- ``provider`` - the service provider (`provider.Object`). It loads the
21 project, computes the project bounds, talks to QGIS Server (GetMap,
22 GetFeatureInfo and other requests) and creates the configuration of leaf
23 layers for the ``qgis`` tree layer.
24- ``layer`` - the ``qgis`` layer, a group that shows the project as a tree
25 of layers.
26- ``flatlayer`` - the ``qgisflat`` layer, which renders selected project
27 layers as a single image. By default, it gets a ``qgis`` model and a
28 ``qgis`` finder for its queryable source layers and a ``qgis`` legend,
29 whose options are merged with the provider's ``defaultLegendOptions``.
30- ``grabber`` - the raster grabber for ``qgisflat`` layers and composite
31 ``qgis`` layers; it requests boxes from QGIS Server with GetMap. Boxes are
32 requested in the target CRS, QGIS Server reprojects as needed.
33- ``finder`` - the ``qgis`` finder, which searches project layers by point
34 with GetFeatureInfo.
35- ``model`` - the ``qgis`` model for features found with the finder.
36- ``legend`` - the ``qgis`` legend, rendered with GetLegendGraphic. Rendered
37 images are cached for ``cacheMaxAge``.
38- ``template`` - the ``qgis`` print template, based on a print layout of
39 the project.
40- ``cli`` - the ``gws qgis caps`` and ``gws qgis copy`` commands.
42Design
43------
45Layers, finders, models, legends and templates refer to a project through
46their ``provider`` configuration. A provider created from the same
47configuration is shared between objects. When the provider has
48``withWatch`` enabled, it checks the project periodically and reloads the
49application when the project changes.
51The ``qgis`` layer creates a child layer for each source layer of the
52project, keeping the group structure. By default, a child is a
53``qgisflat`` layer that renders through QGIS Server. With the provider
54options ``directRender`` and ``directSearch``, children based on WMS, WMTS
55or XYZ sources are rendered by WebSuite directly (``wmsflat``, ``wmts`` or
56``tile`` layers), and WMS, WFS and Postgres sources get their own finders
57(and, for Postgres, models) instead of going through QGIS Server. With
58``compositeRender``, the ``qgis`` layer renders all visible ``qgisflat``
59children as one image with one GetMap request. It then creates grabbers like
60an image layer, and the client gets a ``compositeBox`` or ``compositeTile``
61layer whose children are ``compositeLeaf`` layers; the client sends the
62visible children in ``compositeLayerUids``.
64Print templates work as follows. The project is reloaded on each render.
65The map is rendered by WebSuite as a PDF.
66Label and HTML items of the QGIS layout are treated as WebSuite ``html``
67templates, so they can use placeholders such as ``@legend``; if any of them
68changes, a temporary copy of the project with the rendered HTML is created.
69The layout is then printed by QGIS Server with GetPrint, and the QGIS PDF is
70placed over the map PDF, so that grids and other decorations are drawn
71above the map. For this to work, the page and the map item of the layout
72must be transparent, and since the project is copied, it must use absolute
73paths to its assets. Integer map positions and sizes in the layout give the
74best alignment.
76Project and layer extents
77-------------------------
79QGIS does not provide complete project and layer extents with respect to
80symbology. Only data-based extents are known at parse time. Extents are
81computed with the following logic:
83- if a project provides an explicit WMS extent (Project Properties ->
84 QGIS Server -> WMS), this extent is used as the project render extent
85 (``bounds``)
86- otherwise, if ``useCanvasExtent`` is true, the canvas extent is used
87- otherwise, the project render extent is the union of the layers' data
88 extents plus the configured ``extentBuffer``
89- if the render extent is empty, the CRS extent is taken
90- for layers, the data extent is either an explicit extent (Layer
91 Properties -> Metadata -> Extent) or an implicit data extent
92- the layer data extent is used as a "zoom" extent, but when rendering a
93 layer, the project extent is used
95Example::
97 map.layers+ {
98 title "City"
99 type "qgis"
100 provider.path "/data/city.qgs"
101 provider.directSearch [ "wms" "wfs" "postgres" ]
102 }
104 map.layers+ {
105 title "Districts"
106 type "qgisflat"
107 provider.path "/data/city.qgs"
108 sourceLayers.names [ "districts" ]
109 }
111 printers+ {
112 template {
113 type "qgis"
114 provider.path "/data/print.qgs"
115 index 0
116 }
117 }
118"""
120from . import provider, project, caps