-
-
Notifications
You must be signed in to change notification settings - Fork 153
Fix #5934: Display legend for external WMS layers #6114
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
External WMS layers were showing empty legend icons because QGIS Server returns empty icon fields in JSON GetLegendGraphic responses. - Added getLegendGraphicPNG() method to WMS class - Modified updateLayerTreeLayersSymbology() to detect external WMS layers - External WMS layers now fetch PNG legend and convert to base64 - Normal layers continue using JSON format (no breaking changes)
|
Thanks @meyerlor Can you provide a printscreen with your fix ? I'm not sure that the GetLegendGraphic will be well displayed as an icon. |
|
I'm away from a computer the next three weeks, will get back at it as soon I'm back! |
ac3f5a4 to
1e8f8ba
Compare
Fixed the external WMS layer detection to use the correct property path and handle both boolean and string values from the backend. Changes: - Updated path from itemState.externalWmsToggle to itemState.layerConfig.externalWmsToggle - Added support for string value 'True' in addition to boolean true - Cleaned up unnecessary comments for better code clarity This ensures external WMS layers are properly detected and their legends are fetched in PNG format instead of JSON.
Previously, externalWmsToggle was only set for layers with EPSG:3857. This change enables it for ALL external WMS layers regardless of CRS. Changes: - Set externalWmsToggle = 'True' for all external WMS layers - Keep EPSG:3857 specific handling for future use - Allows legend display for external WMS in any projection This works together with the JavaScript improvements to properly display legends for all external WMS layers.
Updated the property path to access externalWmsToggle correctly through the internal object structure. Changes: - Access via _mapItemState._layerItemState._layerTreeItemCfg._layerCfg - Check _externalWmsToggle (private property with underscore) - Maintains support for both boolean true and string 'True' This ensures external WMS layers are properly detected and their legends are displayed correctly.
Added LAYERTITLE: 'FALSE' parameter for external WMS layers to suppress the layer title in the legend graphic response. Changes: - Moved wmsParams definition into separate if/else blocks - External WMS: wmsParams includes LAYERTITLE: 'FALSE' - Normal layers: wmsParams without LAYERTITLE (unchanged behavior) This improves the legend display by removing unnecessary titles from external WMS layer legends.
Restored all original comments that were removed in previous commits: - Added back comment about empty tree layers check - Restored comment about fetching PNG and converting to base64 - Restored inline comment about removing data:image/png;base64 prefix - Restored comment about fallback to default icon - Restored comments about symbology type property checks - Restored detailed error handling comments for POST method timeout Also removed German comment and replaced with original structure: - Removed: 'POST method code bleibt unverändert...' This improves code readability and maintains original documentation.
rldhont
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @meyerlor,
First of all, thanks for your pull request. I suggest some improvements.
The main for me is to do not load the legend image and simulate a symbology but to enhance the Treeview component to display the legend as image when it is needed.
You will have to enhance the this._layerTemplate in assets/src/components/Treeview.js
| const layerCfg = treeLayer._mapItemState?._layerItemState?._layerTreeItemCfg?._layerCfg; | ||
| const isExternalWMS = layerCfg?._externalWmsToggle === true | ||
| || layerCfg?._externalWmsToggle === 'True'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| const layerCfg = treeLayer._mapItemState?._layerItemState?._layerTreeItemCfg?._layerCfg; | |
| const isExternalWMS = layerCfg?._externalWmsToggle === true | |
| || layerCfg?._externalWmsToggle === 'True'; | |
| const isExternalWMS = treeLayer.layerConfig.externalWmsToggle; |
| }).catch((error) => { | ||
| console.error(error); | ||
| }); | ||
| } else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| } else { | |
| if (!isExternalWMS) { |
Request JSON only for non external WMS
| if (isExternalWMS) { | ||
| // For external WMS layers, get PNG legend directly | ||
| const wmsParams = { | ||
| LAYER: treeLayer.wmsName, | ||
| STYLES: treeLayer.wmsSelectedStyleName, | ||
| LAYERTITLE: 'FALSE', | ||
| }; | ||
| try { | ||
| const pngUrl = wms.getLegendGraphicPNG(wmsParams); | ||
| // Fetch the PNG and convert to base64 | ||
| const response = await fetch(pngUrl); | ||
| const blob = await response.blob(); | ||
| const reader = new FileReader(); | ||
|
|
||
| await new Promise((resolve, reject) => { | ||
| reader.onloadend = () => { | ||
| const base64data = reader.result.split(',')[1]; // Remove data:image/png;base64, prefix | ||
| treeLayer.symbology = { | ||
| type: 'layer', | ||
| name: treeLayer.wmsName, | ||
| title: treeLayer.name, | ||
| icon: base64data | ||
| }; | ||
| resolve(); | ||
| }; | ||
| reader.onerror = reject; | ||
| reader.readAsDataURL(blob); | ||
| }); | ||
| } catch (error) { | ||
| console.error('Error loading external WMS legend:', error); | ||
| // Fallback to default icon will be handled by symbology state |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| if (isExternalWMS) { | |
| // For external WMS layers, get PNG legend directly | |
| const wmsParams = { | |
| LAYER: treeLayer.wmsName, | |
| STYLES: treeLayer.wmsSelectedStyleName, | |
| LAYERTITLE: 'FALSE', | |
| }; | |
| try { | |
| const pngUrl = wms.getLegendGraphicPNG(wmsParams); | |
| // Fetch the PNG and convert to base64 | |
| const response = await fetch(pngUrl); | |
| const blob = await response.blob(); | |
| const reader = new FileReader(); | |
| await new Promise((resolve, reject) => { | |
| reader.onloadend = () => { | |
| const base64data = reader.result.split(',')[1]; // Remove data:image/png;base64, prefix | |
| treeLayer.symbology = { | |
| type: 'layer', | |
| name: treeLayer.wmsName, | |
| title: treeLayer.name, | |
| icon: base64data | |
| }; | |
| resolve(); | |
| }; | |
| reader.onerror = reject; | |
| reader.readAsDataURL(blob); | |
| }); | |
| } catch (error) { | |
| console.error('Error loading external WMS legend:', error); | |
| // Fallback to default icon will be handled by symbology state |
Do not request the image and simulate a child icon. I prefer to enhance the treeview component to display the legend image has a child.
| // Set externalWmsToggle for ALL external WMS layers (not just EPSG:3857) | ||
| $obj->externalWmsToggle = 'True'; | ||
| $obj->externalAccess = $layerDatasource; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| // Set externalWmsToggle for ALL external WMS layers (not just EPSG:3857) | |
| $obj->externalWmsToggle = 'True'; | |
| $obj->externalAccess = $layerDatasource; | |
| if (array_key_exists('type', $layerDatasource) | |
| && $layerDatasource['type'] == 'wms') { | |
| // Set externalWmsToggle for ALL external WMS layers (not just EPSG:3857) | |
| $obj->externalWmsToggle = 'True'; | |
| $obj->externalAccess = $layerDatasource; | |
| } |
Activate external only for WMS layers.
We should verify that the project's projection is recognized by the source service or that the OpenLayers layer created reuses the CRS of the source layer.
| && $layerDatasource['crs'] == 'EPSG:3857') { | ||
| $obj->externalWmsToggle = 'True'; | ||
| $obj->externalAccess = $layerDatasource; | ||
| // Additional external access for EPSG:3857 layers |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
keeps it for other $layerDatasource by using an else if or an || in the previous if

I hope to help and fix the missing legends for external WMS services:
#5934
External WMS layers were showing empty legend icons because QGIS Server
returns empty icon fields in JSON GetLegendGraphic responses.
I'm not sure if that is enough to get a proper legend from the WMS, i was not able to run proper tests, i just wanted to lay the groundwork to get WMS legends working (i hope it does not interfere with the recent changes which sped up the loading time so much! 😃 )