Coverage for gws-app/gws/plugin/qgis/flatlayer.py: 0%
109 statements
« prev ^ index » next coverage.py v7.11.0, created at 2025-10-16 23:09 +0200
« prev ^ index » next coverage.py v7.11.0, created at 2025-10-16 23:09 +0200
1from typing import Optional
3import gws
4import gws.base.layer
5import gws.config.util
6import gws.lib.crs
7import gws.lib.bounds
8import gws.lib.extent
9import gws.gis.source
10import gws.gis.zoom
11import gws.base.metadata
12import gws.lib.osx
14from . import provider
16gws.ext.new.layer('qgisflat')
19class Config(gws.base.layer.Config):
20 """Flat Qgis layer"""
22 provider: Optional[provider.Config]
23 """Qgis provider."""
24 sourceLayers: Optional[gws.gis.source.LayerFilter]
25 """Source layers to use."""
26 sqlFilters: Optional[dict]
27 """Per-layer sql filters. (added in 8.2)"""
30class Object(gws.base.layer.image.Object):
31 serviceProvider: provider.Object
32 sqlFilters: dict
33 imageLayers: list[gws.SourceLayer]
34 searchLayers: list[gws.SourceLayer]
36 def configure(self):
37 self.sqlFilters = self.cfg('sqlFilters', default={})
38 self.configure_layer()
40 def configure_provider(self):
41 return gws.config.util.configure_service_provider_for(self, provider.Object)
43 def configure_sources(self):
44 if super().configure_sources():
45 return True
46 self.configure_source_layers()
47 self.imageLayers = gws.gis.source.filter_layers(self.sourceLayers, is_image=True)
48 self.searchLayers = gws.gis.source.filter_layers(self.sourceLayers, is_queryable=True)
50 def configure_source_layers(self):
51 return gws.config.util.configure_source_layers_for(
52 self,
53 self.serviceProvider.sourceLayers,
54 is_image=True,
55 is_visible=True,
56 )
58 def configure_models(self):
59 return gws.config.util.configure_models_for(self, with_default=True)
61 def create_model(self, cfg):
62 return self.create_child(
63 gws.ext.object.model,
64 cfg,
65 type='qgis',
66 _defaultProvider=self.serviceProvider,
67 _defaultSourceLayers=self.searchLayers,
68 )
70 def configure_bounds(self):
71 if super().configure_bounds():
72 return True
73 self.bounds = gws.lib.bounds.transform(self.serviceProvider.bounds, self.mapCrs)
74 return True
76 def configure_zoom_bounds(self):
77 if super().configure_zoom_bounds():
78 return True
79 b = gws.gis.source.combined_bounds(self.sourceLayers, self.mapCrs)
80 if b:
81 self.zoomBounds = b
82 return True
84 def configure_resolutions(self):
85 if super().configure_resolutions():
86 return True
87 self.resolutions = gws.gis.zoom.resolutions_from_source_layers(self.sourceLayers, self.cfg('_parentResolutions'))
88 if not self.resolutions:
89 raise gws.Error(f'layer {self.uid!r}: no matching resolutions')
91 def configure_grid(self):
92 if super().configure_grid():
93 return True
94 self.grid = gws.TileGrid(
95 origin=gws.Origin.nw,
96 tileSize=256,
97 bounds=self.bounds,
98 resolutions=self.resolutions,
99 )
100 return True
102 def configure_legend(self):
103 # cannot use super() here, because the config must be extended with defaults
104 if not self.cfg('withLegend'):
105 return True
106 cc = self.cfg('legend')
107 options = gws.u.merge(self.serviceProvider.defaultLegendOptions, cc.options if cc else {})
108 self.legend = self.create_child(
109 gws.ext.object.legend,
110 cc,
111 type='qgis',
112 options=options,
113 _defaultProvider=self.serviceProvider,
114 _defaultSourceLayers=self.imageLayers,
115 )
116 return True
118 def configure_metadata(self):
119 if super().configure_metadata():
120 return True
121 if len(self.sourceLayers) == 1:
122 self.metadata = self.sourceLayers[0].metadata
123 return True
125 def configure_templates(self):
126 return gws.config.util.configure_templates_for(self)
128 def configure_search(self):
129 if super().configure_search():
130 return True
131 if self.searchLayers:
132 self.finders.append(self.create_finder(None))
133 return True
135 def create_finder(self, cfg):
136 return self.create_child(
137 gws.ext.object.finder,
138 cfg,
139 type='qgis',
140 _defaultProvider=self.serviceProvider,
141 _defaultSourceLayers=self.searchLayers,
142 )
144 ##
146 def get_render_params(self, lri: gws.LayerRenderInput, parent_sql_filters: dict=None) -> dict:
147 params = dict(lri.extraParams or {})
149 layers = [sl.name for sl in self.imageLayers]
150 # NB reversed: see the note in plugin/ows_client/wms/provider.py
151 params['LAYERS'] = list(reversed(layers))
153 filters = []
154 sqlf = gws.u.merge({}, self.sqlFilters, parent_sql_filters)
155 for name in layers:
156 flt = sqlf.get(name) or sqlf.get('*')
157 if flt:
158 filters.append(name + ': ' + flt)
159 if filters:
160 params['FILTER'] = ';'.join(filters)
162 return params
164 def render(self, lri):
165 if lri.type != gws.LayerRenderInputType.box:
166 return
168 params = self.get_render_params(lri)
170 def get_box(bounds, width, height):
171 return self.serviceProvider.get_map(self, bounds, width, height, params)
173 content = gws.base.layer.util.generic_render_box(self, lri, get_box)
174 return gws.LayerRenderOutput(content=content)