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

1from typing import Optional 

2 

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 

13 

14from . import provider 

15 

16gws.ext.new.layer('qgisflat') 

17 

18 

19class Config(gws.base.layer.Config): 

20 """Flat Qgis layer""" 

21 

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)""" 

28 

29 

30class Object(gws.base.layer.image.Object): 

31 serviceProvider: provider.Object 

32 sqlFilters: dict 

33 imageLayers: list[gws.SourceLayer] 

34 searchLayers: list[gws.SourceLayer] 

35 

36 def configure(self): 

37 self.sqlFilters = self.cfg('sqlFilters', default={}) 

38 self.configure_layer() 

39 

40 def configure_provider(self): 

41 return gws.config.util.configure_service_provider_for(self, provider.Object) 

42 

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) 

49 

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 ) 

57 

58 def configure_models(self): 

59 return gws.config.util.configure_models_for(self, with_default=True) 

60 

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 ) 

69 

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 

75 

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 

83 

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') 

90 

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 

101 

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 

117 

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 

124 

125 def configure_templates(self): 

126 return gws.config.util.configure_templates_for(self) 

127 

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 

134 

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 ) 

143 

144 ## 

145 

146 def get_render_params(self, lri: gws.LayerRenderInput, parent_sql_filters: dict=None) -> dict: 

147 params = dict(lri.extraParams or {}) 

148 

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)) 

152 

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) 

161 

162 return params 

163 

164 def render(self, lri): 

165 if lri.type != gws.LayerRenderInputType.box: 

166 return 

167 

168 params = self.get_render_params(lri) 

169 

170 def get_box(bounds, width, height): 

171 return self.serviceProvider.get_map(self, bounds, width, height, params) 

172 

173 content = gws.base.layer.util.generic_render_box(self, lri, get_box) 

174 return gws.LayerRenderOutput(content=content)