Friday, 10 February 2017

pyqgis - Is it possible to change legend symbols in the QGIS print composer legend?


I have some layers with very complex data-defined symbols. If I use a legend in the print composer these symbols are not drawn correctly.



Is there a way to change the legend-symbols with pyqgis, so I can use custom PNG or SVG images instead of the default legend symbol for these layers?


I know how to add a Push Button to the Print composer and how to connect it with a function. I want to add a button to the Legend-Settings to allow me to replace the automatically generated legend icon with a custom image. So what I still need is the information of how I can access the legend-symbols with pyqgis/pyqt, and how to replace them with a QImage on a QLabel or something like that?


Very basic mockup of the button used to change the symbol:


enter image description here


Automatically generated Legend:


enter image description here


Legend with custom legend symbol:


enter image description here


I already found out how to access the items of the legend in the print composer but not yet how to access the symbol itself:


import qgis

from PyQt4.QtCore import *
from PyQt4.QtGui import *

activeComposer = iface.activeComposers()

for item in activeComposer:
if item.composerWindow().windowTitle()=='test':
for i in item.items():
if isinstance(i,QgsComposerLegend):
#print i

#print i.model()
legend = i
for i in xrange(legend.modelV2().rowCount()):
posteleg=legend.modelV2().index(i, 0)
print posteleg.data()

Edit 1:


I have also found out how to Access QIcon-Objects of the legend-tree but cannot swap them yet:


def run(self):


activeComposer = self.iface.activeComposers()
#print(self.resolve('icon.png'))
for item in activeComposer:
if item.composerWindow().windowTitle()=='test':
for i in item.items():
if isinstance(i,QgsComposerLegend):
legend = i

layerIcon = QIcon(os.path.join(os.path.dirname(__file__), "icon.png"))


for i in xrange(legend.modelV2().rowCount()):
posteleg=legend.modelV2().index(i, 0)
posteleg.model().iconGroup().swap(layerIcon)
print posteleg.data()

Here is one real life example where you can see a symbology combined of many symbol layers: enter image description here This will end up in the legend like this: enter image description here


As I need the proper symbol in the legend I would like to make a screenshot of my symbol, crop it and use it as an image in my legend.


I know I could just overlay a seperate image on top of my legend which covers the automatically generated symbol but I would like to have a "cleaner" solution that allows me to replace the symbols in the legend with custom images.


Edit 2:


In the meantime I have found another way to gain access to the legend entries:



from qgis.core import QgsLegendRenderer, QgsComposerLegendStyle

compDict = {}
for comp in iface.activeComposers():
# workaround to get name: read it from window title
compDict[comp.composerWindow().windowTitle()] = comp.composition()
if "mycomposername" in compDict:
itemLlegend = compDict["mycomposername"].getComposerItemById("mylegend_id")
if itemLlegend:
print itemLlegend


tree_layer_layer = itemLlegend.modelV2().rootGroup().children()
for item in tree_layer_layer:
if item.layerName()=="MyLayername":
print "match"
QgsLegendRenderer.setNodeLegendStyle(item, QgsComposerLegendStyle.Group)

This allows me to access the QgsLayerTreeLayer objects and I can switch the legend Style (Group,Subgroup,Hidden). But I still have no idea how to access the legend-symbol. Any ideas?




No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...