2

I have a group of layers and in my plugin, I would only like one layer from a specific group to be checked at any time. The plugin contains a toggle button which connects each layer to a function. The function finds the checked layer and adds it to a list, it then finds all other layers and I tried to set their node state to Unchecked but clearly I'm missing something.

Here is the code:

root = QgsProject.instance().layerTreeRoot()
group = root.findGroup('Main group')

def check():
    if self.plugin_button.isChecked():
        # Create empty list to contain checked layer
        layer_list = []
        for child in group.children():
            node = root.findLayer(child.layer().id()) 
            if node.isVisible():
                # Add checked layer into list
                layer_list.append(node.name())
            # For layers not in list
            if child.name() not in layer_list:
                ###### Not sure what to do here ######
                node = root.findLayer(child.layer().id()) 
                node.setVisible(Qt.Unchecked)
                iface.legendInterface().setLayerVisible(child.layer(), False)
    else:
        for layers in group.children():
            # Disconnect layers in group from function
            layers.visibilityChanged.disconnect(check)

# Connect layers in group to function
for layers in group.children():
    layers.visibilityChanged.connect(check)

Update:

Made some progress, the following code now only allows one layer to be active at any time. Only issue is when a layer is checked, clicking on any layer unchecks all layers. Still looking to see how to keep one layer checked at all times. Also if a layer is checked, I don't want it unchecked (i.e. I want it 'locked'). The only way to uncheck it is to select another layer.

root = QgsProject.instance().layerTreeRoot()
group = root.findGroup('Main group')

def check(layer):
    if self.plugin_button.isChecked():                
        layer_list = []
        layer_list.append(layer.name())
        for child in group.children():
            if child.name() not in layer_list:
                iface.legendInterface().setLayerVisible(child.layer(), False) 
    else:
        for layers in group.children():
            layers.visibilityChanged.disconnect(check)

# Connect layers in group to function
for layers in group.children():
    layers.visibilityChanged.connect(check)
1

You need to disconnect the function from each layer before using setLayerVisible. Then perform the logic of only activating one layer at a time and then reconnect the function. The clicked layer will always be active (i.e. there will always be one layer active in the group at all times):

root = QgsProject.instance().layerTreeRoot()
group = root.findGroup('Main group')

def check(layer):
    # Store clicked layer's name in list
    layer_list = []
    layer_list.append(layer.name())     
    # Clicked layer will always be visible
    iface.legendInterface().setLayerVisible(layer, True) 
    for layers in group.children():
        # Disconnect slot from signal
        layers.visibilityChanged.disconnect(check)
        if layers.name() not in layer_list:
            # If layers not in list (i.e. not selected), set visible to False
            iface.legendInterface().setLayerVisible(layers.layer(), False) 
        # Reconnect slot to signal
        layers.visibilityChanged.connect(check)

# Connect layers in group to function
for layers in group.children():
    layers.visibilityChanged.connect(check) 

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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