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

1"""QGIS support. 

2 

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. 

10 

11Submodules 

12---------- 

13 

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. 

41 

42Design 

43------ 

44 

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. 

50 

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``. 

63 

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. 

75 

76Project and layer extents 

77------------------------- 

78 

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: 

82 

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 

94 

95Example:: 

96 

97 map.layers+ { 

98 title "City" 

99 type "qgis" 

100 provider.path "/data/city.qgs" 

101 provider.directSearch [ "wms" "wfs" "postgres" ] 

102 } 

103 

104 map.layers+ { 

105 title "Districts" 

106 type "qgisflat" 

107 provider.path "/data/city.qgs" 

108 sourceLayers.names [ "districts" ] 

109 } 

110 

111 printers+ { 

112 template { 

113 type "qgis" 

114 provider.path "/data/print.qgs" 

115 index 0 

116 } 

117 } 

118""" 

119 

120from . import provider, project, caps