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

39 statements  

« prev     ^ index     » next       coverage.py v7.16.2, created at 2026-10-05 13:35 +0200

1"""QGIS legend.""" 

2 

3from typing import Optional 

4 

5import gws 

6import gws.base.legend 

7import gws.config.util 

8import gws.lib.mime 

9import gws.gis.source 

10import gws.lib.image 

11 

12 

13from . import provider 

14 

15 

16# see https://docs.qgis.org/3.22/de/docs/server_manual/services/wms.html#getlegendgraphics 

17 

18_DEFAULT_LEGEND_PARAMS = { 

19 'BOXSPACE': 2, 

20 'ICONLABELSPACE': 2, 

21 'ITEMFONTBOLD': False, 

22 'ITEMFONTCOLOR': '#000000', 

23 'ITEMFONTFAMILY': 'DejaVuSans', 

24 'ITEMFONTITALIC': False, 

25 'ITEMFONTSIZE': 9, 

26 'LAYERFONTBOLD': True, 

27 'LAYERFONTCOLOR': '#000000', 

28 'LAYERFONTFAMILY': 'DejaVuSans', 

29 'LAYERFONTITALIC': False, 

30 'LAYERFONTSIZE': 9, 

31 'LAYERSPACE': 4, 

32 'LAYERTITLE': True, 

33 'LAYERTITLESPACE': 4, 

34 'RULELABEL': True, 

35 'SYMBOLHEIGHT': 8, 

36 'SYMBOLSPACE': 2, 

37 'SYMBOLWIDTH': 8, 

38} 

39 

40 

41@gws.ext.config.legend('qgis') 

42class Config(gws.base.legend.Config): 

43 """Legend for QGIS project layers, rendered by QGIS Server.""" 

44 

45 provider: Optional[provider.Config] 

46 """QGIS project the legend is rendered from.""" 

47 sourceLayers: Optional[gws.gis.source.LayerFilter] 

48 """Source layers to include in the legend.""" 

49 

50 

51@gws.ext.object.legend('qgis') 

52class Object(gws.base.legend.Object): 

53 """Legend rendered by QGIS Server with GetLegendGraphic.""" 

54 

55 provider: provider.Object 

56 """QGIS provider.""" 

57 sourceLayers: list[gws.SourceLayer] 

58 """Source layers in the legend.""" 

59 params: dict 

60 """GetLegendGraphic request parameters.""" 

61 

62 def configure(self): 

63 self.configure_provider() 

64 self.configure_sources() 

65 self.configure_params() 

66 

67 def configure_provider(self): 

68 """Set the QGIS provider. 

69 

70 Returns: 

71 ``True`` if a provider was set. 

72 

73 Raises: 

74 ``gws.Error``: If no provider is found. 

75 """ 

76 return gws.config.util.configure_provider_for(self, provider.Object) 

77 

78 def configure_sources(self): 

79 """Select the source layers of the legend. 

80 

81 Raises: 

82 ``gws.Error``: If the provider is not set. 

83 """ 

84 gws.u.require(self.provider, 'failed to configure service provider') 

85 self.configure_source_layers() 

86 

87 def configure_source_layers(self): 

88 """Select the source layers from the provider layers. 

89 

90 Returns: 

91 Always ``True``. 

92 """ 

93 return gws.config.util.configure_source_layers_for(self, self.provider.sourceLayers) 

94 

95 def configure_params(self): 

96 """Build the GetLegendGraphic parameters. 

97 

98 Configured ``options`` override the default legend parameters. 

99 """ 

100 defaults = dict( 

101 DPI=96, 

102 FORMAT=gws.lib.mime.PNG, 

103 # qgis legends are rendered bottom-up (rightmost first) 

104 # we need the straight order (leftmost first), like in the config 

105 LAYER=','.join(sl.name for sl in reversed(self.sourceLayers)), 

106 REQUEST=gws.OwsVerb.GetLegendGraphic, 

107 STYLE='', 

108 TRANSPARENT=True, 

109 ) 

110 opts = gws.u.to_upper_dict(self.cfg('options', default={})) 

111 self.params = self.provider.server_params(gws.u.merge(_DEFAULT_LEGEND_PARAMS, defaults, opts)) 

112 

113 ## 

114 

115 def render(self, args=None): 

116 def _get(): 

117 return self.provider.call_server(self.params).content 

118 

119 content = gws.u.get_cached_object( 

120 f'legend_{gws.u.sha256([self.provider.url, self.params])}', 

121 self.cacheMaxAge, 

122 _get, 

123 ) 

124 img = gws.lib.image.from_bytes(content) 

125 return gws.LegendRenderOutput(image=img, size=img.size())