Skip to content

Instantly share code, notes, and snippets.

@jdlom
Created February 10, 2021 15:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jdlom/5b9709a70503e359d9143ff03adf14c7 to your computer and use it in GitHub Desktop.
Save jdlom/5b9709a70503e359d9143ff03adf14c7 to your computer and use it in GitHub Desktop.
Gist created by PyQGIS Console
"""
POC from https://gis.stackexchange.com/questions/385525/qgis-how-to-invert-the-values-in-a-layout-legend/386746?noredirect=1#comment633627_386746
Based on Ben W answer
Does not work for every legend
"""
class InvertStyleConfigWidget(QgsMapLayerConfigWidget):
"""
Emulates the QGS Layer Property Dialogs "Information" page
"""
def __init__(self, layer: QgsMapLayer, canvas: QgsMapCanvas, parent=None):
super().__init__(layer, canvas, parent=parent)
self.setLayout(QVBoxLayout())
self.invertButton : QPushButton = QPushButton('Invert legend')
self.layer = layer
self.layout().addWidget(self.invertButton)
self.layout().setAlignment(Qt.AlignTop)
self.invertButton.clicked.connect(self.invert_legend)
def invert_legend(self):
root = QgsProject.instance().layerTreeRoot()
model = QgsLegendModel(root)
layer_node=root.findLayer( self.layer.id())
view_model = iface.layerTreeView().layerTreeModel()
order_property = layer_node.customProperty('legend/node-order')
if order_property:
current_order = [ int(i) for i in order_property.split(',')]
else:
current_order = [ int(i) for i in range(model.legendRootRowCount(layer_node))]
QgsMapLayerLegendUtils.setLegendNodeOrder(layer_node, current_order[::-1])
view_model.refreshLayerLegend(layer_node)
def shouldTriggerLayerRepaint(self):
return False
def apply(self):
pass
class InvertStyleConfigWidgetFactory(QgsMapLayerConfigWidgetFactory):
def __init__(self, title='Invert Legend', icon=QIcon(':images/themes/default/mActionSharingImport.svg')):
super(InvertStyleConfigWidgetFactory, self).__init__(title, icon)
self.setSupportLayerPropertiesDialog(True)
self.setSupportsStyleDock(True)
def createWidget(self, layer, canvas, dockWidget=False, parent=None):
return InvertStyleConfigWidget(layer, canvas, parent=parent)
def supportLayerPropertiesDialog(self):
"""For some reasons it does not work with raster layer"""
return True
def supportsStyleDock(self):
return True
def supportsLayer(self, layer):
return True
#iface.unregisterMapLayerConfigWidgetFactory(factory)
factory = InvertStyleConfigWidgetFactory()
iface.registerMapLayerConfigWidgetFactory(factory)
@benwirf
Copy link

benwirf commented Feb 26, 2021

Hi @jdlom,
Just letting you know that I have discovered an annoying issue which is apparently caused by setting a legend node order on a QgsLayerTreeLayer in the main layer tree view. After setting a new node order on a layer with e.g. 5 nodes, if you then go back into the symbology dialog and increase the number of classes and apply the new render settings, only 5 nodes are shown in the legend! One must either manually run: QgsMapLayerLegendUtils.setLegendNodeOrder(layer_node, ...) and pass an order list which contains the new number of nodes or remove and reload the layer. I have searched but not yet found a simple solution. It seems that in the source code, this method is only used on layout legends. For the time being, I have removed the part in my stack exchange answer about updating the TOC.
Regards

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment