Coverage for gws-app/gws/plugin/qgis/layer.py: 0%

84 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2025-10-16 23:09 +0200

1"""qgis layer. 

2 

3"qgis" layers display QGIS layers as WebSuite layers, keeping the tree structure. 

4""" 

5 

6from typing import Optional, cast 

7 

8import gws 

9import gws.base.layer 

10import gws.config.util 

11 

12from . import provider, flatlayer 

13 

14gws.ext.new.layer('qgis') 

15 

16 

17class Config(gws.base.layer.Config, gws.base.layer.tree.Config): 

18 """QGIS Tree layer configuration.""" 

19 

20 provider: Optional[provider.Config] 

21 """Qgis provider.""" 

22 compositeRender: bool = False 

23 """If true, the layer will be rendered as a single image. (added in 8.2)""" 

24 sqlFilters: Optional[dict] 

25 """Per-layer sql filters. (added in 8.2)""" 

26 

27 

28class Object(gws.base.layer.group.Object): 

29 serviceProvider: provider.Object 

30 compositeRender: bool = False 

31 sqlFilters: dict 

32 

33 def configure(self): 

34 self.compositeRender = self.cfg('compositeRender', default=False) 

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

36 

37 def configure_group(self): 

38 gws.config.util.configure_service_provider_for(self, provider.Object) 

39 

40 configs = gws.base.layer.tree.layer_configs_from_layer( 

41 self, 

42 self.serviceProvider.sourceLayers, 

43 self.serviceProvider.leaf_config, 

44 ) 

45 

46 self.configure_group_layers(configs) 

47 

48 def configure_metadata(self): 

49 if super().configure_metadata(): 

50 return True 

51 self.metadata = self.serviceProvider.metadata 

52 return True 

53 

54 def post_configure(self): 

55 if self.compositeRender: 

56 self.canRenderBox = True 

57 

58 def props(self, user): 

59 p = super().props(user) 

60 if not self.compositeRender: 

61 return p 

62 

63 def _to_leaf(la): 

64 pla = la.props(user) 

65 if not pla: 

66 return pla 

67 if pla.get('type') == 'group': 

68 pla['layers'] = [_to_leaf(la) for la in pla['layers']] 

69 elif pla.get('type') == 'box': 

70 pla['type'] = 'compositeLeaf' 

71 return pla 

72 

73 return gws.u.merge( 

74 p, 

75 type='compositeTree', 

76 layers=[_to_leaf(la) for la in p['layers']], 

77 ) 

78 

79 def render(self, lri): 

80 if not self.compositeRender: 

81 return super().render(lri) 

82 

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

84 return 

85 

86 params = self.get_render_params(lri) 

87 if not params: 

88 return 

89 

90 def get_box(bounds, width, height): 

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

92 

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

94 return gws.LayerRenderOutput(content=content) 

95 

96 def get_render_params(self, lri: gws.LayerRenderInput) -> Optional[dict]: 

97 leaves = dict(lri.extraParams or {}).get('compositeLayerUids', []) 

98 if not leaves: 

99 return 

100 

101 layers = [] 

102 filters = [] 

103 

104 for la in self.descendants(): 

105 if la.uid not in leaves: 

106 continue 

107 if la.extType != 'qgisflat': 

108 gws.log.debug(f'skipping {la.uid=} {la.extType=}') 

109 continue 

110 p = cast(flatlayer.Object, la).get_render_params(lri, self.sqlFilters) 

111 if not p: 

112 gws.log.debug(f'skipping {la.uid=} no params') 

113 layers.extend(reversed(p.get('LAYERS', []))) 

114 f = p.get('FILTER') 

115 if f: 

116 filters.append(f) 

117 

118 if not layers: 

119 gws.log.debug(f'no layers') 

120 

121 params = {} 

122 params['LAYERS'] = list(reversed(layers)) 

123 if filters: 

124 params['FILTER'] = ';'.join(filters) 

125 

126 return params