1

I am attempting to re-join all layers within a group to another layer ("Main.shp") outside of this group. The idea is for users to change values in one of the group's layers. As these layers are initially joined, the have to be re-joined in order to see the updated values in "Main.shp". So the code below basically:

  1. Identifies the "Main.shp" layer
  2. Identifies all layers within a specified group
  3. Defines the field parameters used for the joining process
  4. Removes the joins
  5. Adds the joins back to "Main.shp"
  6. Refreshes "Main.shp"

When the code finishes, there is a progress bar shown in the Status bar but it hangs. If I go see the Join properties of "Main.shp", I noticed that the Memory cache is not enabled for some layers (this changes randomly) whereas intially it was enabled for all layers:

Joins properties

And no layers can be viewed, they just become invisible. I have to restart QGIS again in order to see the updated values in "Main.shp".


After the comment by @Matte, I am now fairly certain that the cause of this issue is due to the caching of layers. If one joined layer is not cached, the "Main.shp" will not load and eventually crashes QGIS. I have edited the code below. Unfortunately when running the function, not all of the layers are immediately cached. I have to run it a few times before it works for all layers.

Is there a way to ensure that all joined layers are cached?

Code:

shp = QgsMapLayerRegistry.instance().mapLayersByName( "Main" )[0]
shpField = 'ID'
root = QgsProject.instance().layerTreeRoot()
subGroup = root.findGroup('Group')
def update():
    for child in subGroup.children():
        if isinstance(child, QgsLayerTreeLayer):
            shp.removeJoin(child.layer().id())
            childField = 'ID'
            joinObject = QgsVectorJoinInfo()
            joinObject.joinLayerId = child.layer().id()
            joinObject.joinFieldName = childField
            joinObject.targetFieldName = shpField               
            shp.addJoin(joinObject)
            shp.createJoinCaches()

update()
shp.triggerRepaint()
  • Well this is rather annoying! I spent last night and this morning trying to find out what's wrong and now all of a sudden it works...the Memory cache is still not enabled for all joined layers but the map refreshes and can see the results of the updated values almost immediately. Going to toy some more with this and see if it hangs again or not. – Joseph Apr 22 '16 at 13:16
  • 1
    My experience with caches is that they are unpredicatble when it is not clear when they do update. The Hashtable Qgis uses to create the index of the joins might just got to large or encountered some error. When you often updating, when testing for example, there might be those problems. But i´m not familiar enough with c++ to really understand what is going on. You might try to set the QgsVectorLayer.createJoinCaches() at the end of your loop. – Matte Apr 22 '16 at 15:02
  • @Matte - Ahh interesting, thank you for that tip! I will look into it =) – Joseph Apr 22 '16 at 15:06
0

Adding joinObject.memoryCache = True before adding the join ensures that all layers are cached (QgsVectorJoinInfo::memoryCache):

shp = QgsMapLayerRegistry.instance().mapLayersByName( "Main" )[0]
shpField = 'ID'
root = QgsProject.instance().layerTreeRoot()
subGroup = root.findGroup('Group')
def update():
    for child in subGroup.children():
        shp.removeJoin(child.layer().id())
        childField = 'ID'
        joinObject = QgsVectorJoinInfo()
        joinObject.joinLayerId = child.layer().id()
        joinObject.joinFieldName = childField
        joinObject.targetFieldName = shpField               
        joinObject.memoryCache = True
        shp.addJoin(joinObject)

update()
shp.triggerRepaint()

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.