2

I have a layer where each feature represents a route, and I want these routes to be automatically categorized based on their unique IDs. In other words, if I have two routes, I should have two categories, and when I add a third route, it should automatically be assigned its own category.

Furthermore, when a route is deleted, its corresponding category should also be removed. Essentially, the number of categories should always correspond to the number of routes/features in the layer. I have managed to categorize these features manually, but this doesn't update automatically when I add or remove features.

I understand that this might involve some sort of scripting, possibly with PyQGIS. How can I achieve this?

1

1 Answer 1

2

To get results like this:

screencast

Put this code in the macros tab of your project file and replace the layer_name and field_name parameters.

macros tab


from qgis.core import (QgsProject,
                       QgsRandomColorRamp,
                       QgsRendererCategory)
from qgis.utils import iface
from PyQt5.QtCore import QVariant, Qt


def update_layer_categories(layer, field_name):
    renderer = layer.renderer()
    unique_field_values = layer.dataProvider().uniqueValues(layer.fields().indexOf(field_name))

    renderer.deleteAllCategories()

    for value in unique_field_values:
        symbol = renderer.sourceSymbol().clone()
        index = renderer.categoryIndexForValue(value)

        if isinstance(value, QVariant):
            if QVariant.isNull:
                value = None

        # add new categories
        if index == -1:
            category = QgsRendererCategory()
            category.setValue(value)
            category.setLabel(str(value))
            category.setSymbol(symbol)
            renderer.addCategory(category)
            index = renderer.categoryIndexForValue(value)

        renderer.updateCategoryLabel(index, value)

    renderer.updateColorRamp(QgsRandomColorRamp())
    renderer.updateSymbols(symbol)
    renderer.sortByLabel(Qt.DescendingOrder)
    layer.triggerRepaint()
    iface.layerTreeView().refreshLayerSymbology(layer.id())


def openProject():
    layer_name = 'legal'
    layer = QgsProject.instance().mapLayersByName(layer_name)[0]
    layer.afterCommitChanges.connect(lambda field_name='document_name': update_layer_categories(layer, field_name))


def saveProject():
    pass


def closeProject():
    pass


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.