[QGIS-Developer] Using embedded widgets in the layer tree on a python plugin

Ricardo Filipe Soares Garcia da ricardo.garcia.silva at gmail.com
Sun Sep 16 15:10:01 PDT 2018


Hi all (specially Martin Dobias)

I'm working on a plugin that will use embedded widgets in the layer tree. I
am using the following as reference:

-  Martin's PR that brought this feature into existence (thanks for that
BTW):
https://github.com/qgis/QGIS/pull/3170/files#diff-3b9be845f2ea37602ca451f18acceab4

-  This QGIS dev thread where Martin provides some more detail on how to
refresh the legend:
http://osgeo-org.1560.x6.nabble.com/QgsLayerTreeViewMenuProvider-and-default-values-tt5296424.html#a5296695

-  This stackexchange thread where the transparency slider is discussed:
https://gis.stackexchange.com/questions/232367/showing-transparency-slider-by-default-in-layers-panel-of-qgis

-  The master branch of QGIS' repo

I'm starting out by just showing a simple QLabel in the layer's legend,
just as a proof of concept. I want my plugin to work with OGC services
layers (WMS, WFS, etc), meaning it shall only try to add widgets to layers
that are of these types.

I have roughly the following python code:

```
logger = partial(qgis.utils.QgsMessageLog.logMessage, tag=__name__)

class MyWidgetProvider(
        qgis.gui.QgsLayerTreeEmbeddedWidgetProvider):

    SUPPORTED_DATA_PROVIDERS = [
        "wms",
    ]

    def __init__(self, *args, **kwargs):
        logger("Instantiating provider...")
        super().__init__(*args, **kwargs)
        self.creation_timestamp = int(time.time())

    def id(self):
        logger("id called")
        return "{}_{}".format(self.__class__.__name__,
self.creation_timestamp)

    def name(self):
        logger("name called")
        return "My Widgetss"

    def createWidget(self, map_layer, widget_index):
        logger("createWidget called")
        widget = widgets.QLabel("hi world!")
        widget.setAutoFillBackground(True)
        return widget

    def supportsLayer(self, map_layer):
        logger("supportsLayer called")
        provider = map_layer.dataProvider()
        name = provider.name()
        result = True if name in self.SUPPORTED_DATA_PROVIDERS else False
        logger("supportsLayer: {}".format(result),
level=qgis.core.Qgis.Debug)
        return result
```


This code kind of works, but I'm facing two problems at the moment:

1. The `MyWidgetProvider.supportsLayer()` method is never called. The
logging call does not show up on the console and I also see that my
provider is offered on WMS layers, but also on some local vector layers
(which is not what I intend). grep'ping around the QGIS' source code I
could not find some place where this method would be called and used, so
I'm wondering if this is implemented. I would expect this method to be
called when the layer properties dialog is opened, so that my provider
would get filtered out for layers that were of the wrong type;

2. This code does not update the legend for the layer, UNLESS it is a
vector layer. If I try to add this provider to a WMS layer, the legend is
not updated. If I add it to a shapefile, it works as expected. In order to
get my QLabel to show up on WMS layers, I have to manually run this in the
QGIS python shell:

```
view = iface.layerTreeView()
view.model().refreshLayerLegend(view.currentNode())
```

However, I am not seeing where in my plugin's code can I add this snippet.
I only want the layer tree to be updated AFTER my provider creates the
widget, but this moment seems to be out of my control. Also, I am puzzled
by the fact that vector layers work just fine while my raster (WMS) does
not.


Thanks in advance for your help :)


Best regards

-- 
___________________________ ___ __
Ricardo Garcia Silva
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osgeo.org/pipermail/qgis-developer/attachments/20180916/2ef04f71/attachment.html>


More information about the QGIS-Developer mailing list