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.
layer.setLegend(legend)QGIS does not crash when I remove the layer. – Hugo Roussaffa Aug 07 '19 at 04:03layer.legend.removeLegend(), it also crashes? – Fran Raga Aug 08 '19 at 07:00QgsProject.instance().layerWillBeRemoved.connect(self.PSudData.removeLayer)and Qgis still crash – Hugo Roussaffa Aug 09 '19 at 03:47PSudLegend.createLayerTreeModelLegendNodes(), index 0 has type 'QgsSimpleLegendNode' but 'QgsLayerTreeModelLegendNode' is expected– Hugo Roussaffa Aug 23 '19 at 05:59