10

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 written here https://qgis.org/api/api_break.html

I followed steps :

  • create my custom pluginlayer
  • add to mapLayer
QgsProject.instance().addMapLayer(layer)
legend = layer.makeLegend()
layer.setLegend(legend)

Here is my pluginLayer class :

class PSudLayer(QgsPluginLayer):

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

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

and here my custom legend

class PSudLegend(QgsMapLayerLegend):
def __init__(self, session, uuid):
    QgsMapLayerLegend.__init__(self)
    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)
        else:
            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)
                image.loadFromData(QByteArray.fromBase64(base64.b64decode(i64)))
                self.icon = QIcon(image)
                node = QgsSimpleLegendNode(nodeLayer,child['title'],self.icon)
                self.nodes.append(node)

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 works fine as I remove the layer from the treeLayerPanel. QGIS simply crashes.

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

QgsProject.instance().layerWillBeRemoved.connect(self.PSudData.removeLayer)

def removeLayer(self,layerid):
for layer in self.parent.service_layers:
    if layer.id() == layerid:
        layer.legend.removeLegend()
        QgsProject.instance().removeMapLayer(layer)

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 because QgsLayerTreeModelLegendNode is an abstract class and QgsSimpleLegendNode extends from QgsLayerTreeModelLegendNode.

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

Very confused.

Lilium
  • 1,057
  • 1
  • 6
  • 17
Hugo Roussaffa
  • 2,191
  • 15
  • 40
  • 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 Aug 07 '19 at 04:03
  • If you delete this line layer.legend.removeLegend() , it also crashes? – Fran Raga Aug 08 '19 at 07:00
  • I had comment QgsProject.instance().layerWillBeRemoved.connect(self.PSudData.removeLayer) and Qgis still crash – Hugo Roussaffa Aug 09 '19 at 03: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 Aug 09 '19 at 05:23
  • this also happen when I move by drag and drop a layer in the treeLayer – Hugo Roussaffa Aug 12 '19 at 04:53
  • If you debug the code where QGIS dies?, it can help you a little more. You could also prepare an example so that the people can reproduce it better – Fran Raga Aug 20 '19 at 18:04
  • the last place I can stop QGIS befor it died is an Qevent : "ChildRemoved". The crash come up also with any action which need refreshing the legend layer. I could have a python TypeError : PSudLegend.createLayerTreeModelLegendNodes(), index 0 has type 'QgsSimpleLegendNode' but 'QgsLayerTreeModelLegendNode' is expected – Hugo Roussaffa Aug 23 '19 at 05:59
  • You can look at this example in case it can help you https://github.com/BRGM/gml_application_schema_toolbox/blob/474df9894000132c757e1f15a2daabbac902e699/gml_application_schema_toolbox/core/load_gmlas_in_qgis.py#L62 – Fran Raga Aug 23 '19 at 07:58

0 Answers0