3

I'm working in a project in which, for some reasons, the beast approach to handle a certain amount of point/vector/raster layers is to load them all into memory, and keep them in the QGIS legend. For sorting and user sanity purposes, I wanted to keep them neatly ordered in groups in the QGIS legend interface.

Unfortunately, a problem has shown up in this (somewhat simple) piece of code:

    for layer in layerList:
        print("Adding layer: "+layer.name()+" which isValid: "+str(layer.isValid()))
        with self.groupAssignmentLock:
            group.addLayer(layer)
        iface.legendInterface().setLayerVisible(layer, False)

I added that lock to guarantee only one thread would try to make any operation in a group at the same time, to no avail.

I have registered listeners to the signals QGIS emits when a layer will be added and has been added to the QgsLayerTreeNode object (signals willAddChildren and addedChildren respectively) and the result is this:

>>> Node will be added with : 114 from 114 to 114
Currently grouped layers: 475 out of 484
Number of elements in this node: 115
Adding layer: 2016-02-17T14:00:00Z_temperature which isValid: True
 >>> Node will be added with : 115 from 115 to 115
Currently grouped layers: 476 out of 484
Number of elements in this node: 116
Adding layer: 2016-02-19T10:00:00Z_temperature which isValid: True
 >>> Node will be added with : 116 from 116 to 116
Currently grouped layers: 477 out of 484
Number of elements in this node: 117
Adding layer: 2016-02-19T17:00:00Z_temperature which isValid: True
 >>> Node will be added with : 117 from 117 to 117
Currently grouped layers: 478 out of 484
Number of elements in this node: 118
Adding layer: 2016-02-18T13:00:00Z_temperature which isValid: True
 >>> Node will be added with : 118 from 118 to 118
Currently grouped layers: 479 out of 484
Number of elements in this node: 119
Adding layer: 2016-02-15T05:00:00Z_temperature which isValid: True
 >>> Node will be added with : 119 from 119 to 119
Currently grouped layers: 480 out of 484
Number of elements in this node: 120

This is the end block of the log file output. For some reason or another, 4 layers in this example were not added to groups (which is a problem, as I use these signals as a way of finding out whenever QGIS has finished preparing everything for the plug-in or not).

An example of what happens when a layer fails to be added is this:

Adding layer: 2016-02-15T16:00:00Z_temperature which isValid: True
 >>> Node will be added with : 48 from 48 to 48
Currently grouped layers: 409 out of 484
Number of elements in this node: 49
Adding layer: 2016-02-14T23:00:00Z_temperature which isValid: True
Adding layer: 2016-02-15T23:00:00Z_temperature which isValid: True
 >>> Node will be added with : 49 from 49 to 49
Currently grouped layers: 410 out of 484
Number of elements in this node: 50

As you can see, two messages of "Adding layer:.." are consecutive, showing how neither willAddChildren nor addedChildren are being called.

I'm not sure it's a problem of my own, thus I decided to ask you if this problem has been experienced before. Otherwise, I'm going to assume it is a QGIS bug.

As a note, I'll append the code of the listeners:

def onChildrenAddedToNodeGroup(self, node, indexFrom, indexTo):
    """
    Will be called every time QGIS loads a new layer into a 
    layer group in the legend interface.
    """
    self.groupedQgisLayers = self.groupedQgisLayers + 1
    print("Currently grouped layers: "+str(self.groupedQgisLayers)+" out of "+str(self.layersToBeGrouped))
    print("Number of elements in this node: "+str(len(node.children())))
    if self.groupedQgisLayers == self.layersToBeGrouped:
        iface.mapCanvas().refresh()
        self.animatorReady.emit(self.animatedLayerCount)


def onChildrenWillBeAddedToGroup(self, node, indexFrom, indexTo):
    print(" >>> Node will be added with : "+str(len(node.children()))
          + " from "+str(indexFrom) + " to "+str(indexTo))
    pass
0

The problem was not in the logic to add the layers to the groups themselves through class QgsLayerTreeGroup as I suspected.

After further inspection, the issue happens because of QgsMapLayer. As can be seen in http://qgis.org/api/qgsmaplayer_8cpp_source.html#l00076, layer ID's are generated by a very simple method, which is appending the current date to their layer name and replacing characters which may cause issues in the XML representation of the layer.

My layers are downloaded and generated asynchronously and as they are organized in groups (which have the layer origin as name) there was no point in naming them with any other thing than their date and layer type (temperature, pressure...). This caused collissions between the generated ID's, which in turn caused the QgsMapLayerRegistry to constantly overwrite certain layers.

When a Layer was appended to a group, the QgsMapLayer with that ID in the QgsMapLayerRegistry is checked for equality against the layer which you are trying to append to it. This check failed because the stored layer with that ID in the registry was different to the one I was trying to add to that group in all but one instances (the last one generated).

The solution (until QGIS solves this issue, I'll post a report) is to append an UUID to the name of any layers which may be generated asynchronously.

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.