I upgrade a 2.18 plugin to 3.4.

PluginLayer has been refactored and I could not create a custom legend as simple as previous major version of QGIS 2 :

QgsDefaultPluginLayerLegend was removed. Use QgsMapLayer::setLegend() to provide legend nodes for plugin layers. as it's wrote here https://qgis.org/api/api_break.html

Well I followed steps :

  • create my customed pluginlayer
  • add to mapLayer

QgsProject.instance().addMapLayer(layer) legend = layer.makeLegend() layer.setLegend(legend)

here my pluginLayer class :

class PSudLayer(QgsPluginLayer):

def __init__(self,session, type, name):
    QgsPluginLayer.__init__(self, type, name)
    self.layerType = type
    self.conf = None
    self.transparency = 0

def makeLegend(self):
    return PSudLegend(self.session,self.conf['uuid'])

and here may customed legend

class PSudLegend(QgsMapLayerLegend):

def __init__(self, session, uuid):
    self.nodes = []
    url = session.baseUrl+'/geocat/legend/'+uuid
    r = session.get(url)
    self.legends = json.loads(r.readAll().data().decode())
    self.globalcount = 0
    self.countBoucle = 0
    self.countRecursive = 0
    self.icon = QIcon()

def recursiveLoad(self,legends, nodeLayer):
    self.countRecursive +=1
    self.countBoucle = 0
    size = legends['children'].__len__()
    for child in legends['children']:
        if 'children' in child:
            self.recursiveLoad(child, nodeLayer)
            if size > self.nodes.__len__(): # hack car la boucle passe plus d'une fois ....
                image = QPixmap()
                iStr= child["icon"].split(",")[1]
                i64 = base64.b64encode(iStr.encode()) # hack parsing error (multiple de 4)
                self.icon = QIcon(image)
                node = QgsSimpleLegendNode(nodeLayer,child['title'],self.icon)

def createLayerTreeModelLegendNodes(self, nodeLayer):
    if 'children' in self.legends:
        self.recursiveLoad(self.legends, nodeLayer)

    return self.nodes

def removeLegend(self):
    for node in  self.nodes:
        node = None
    self.nodes = None
    self.icon =None
    return True 

All work fine as I remove the layer from the treeLayerPanel. QGIS simply crash.

I tried to remove nodes in my legend with no succes. and call it when removeLayer is called


def removeLayer(self,layerid):

    for layer in self.parent.service_layers:
        if layer.id() == layerid:

I get a typeError when I tried the filtering option of the layerTree. PSudLegend.createLayerTreeModelLegendNodes(), index 0 has type 'QgsSimpleLegendNode' but 'QgsLayerTreeModelLegendNode' is expected Which I don't understand cause QgsLayerTreeModelLegendNode is an abstract class and QgsSimpleLegendNode extended from QgsLayerTreeModelLegendNode.

When I tried to refreshLayerLegend() from the LayerTreeModel and I also get the same TypeError...

very confused.

  • just to figure out : if I don't set the legend to the layer with layer.setLegend(legend) QGIS does not crash when I remove the layer. – Hugo Roussaffa - GeoDatup Aug 7 '19 at 4:03
  • If you delete this line layer.legend.removeLegend() , it also crashes? – Fran Raga Aug 8 '19 at 7:00
  • I had comment ` QgsProject.instance().layerWillBeRemoved.connect(self.PSudData.removeLayer) ` and Qgis still crash – Hugo Roussaffa - GeoDatup Aug 9 '19 at 3:47
  • the crash come up before/during the "layerWillBeRemoved" event of the QgsProject and also on the "willBeDeleted" event of the QgsMapLayer Object – Hugo Roussaffa - GeoDatup Aug 9 '19 at 5:23
  • this also happen when I move by drag and drop a layer in the treeLayer – Hugo Roussaffa - GeoDatup Aug 12 '19 at 4:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.