Hello to all contributors,

I am trying to implement a custom bad layer handler that I would ship with a plugin (for QGIS 3.4 and above).

The plugin creates map layouts and places a default world map layer in them, which we ship with the plugin. However when users shave the project file and share it among each other, many find this layer to be broken. The layer points to a data in the plugin path, which is not the same across machines.

The custom bad layer handler would try to see if this specific layer is broken and fix it for the user, then call the regular bad layer handling "file dialog" to allow them to fix any eventual broken layers that are unrelated to the plugin.

I am creating my bad layer handler by subclassing QgsProjectBadLayerHandler,
thin I pass it to QgsProject by calling its setBadLayerHandler() method.
Since I want to pass it before any layer is actually loaded (so when launching qgis to open a project file, it would work right away) I had to resort to a sort of ugly way of using the QgsProject.layerLoaded signal to make this happen.

This actually works, for the 1st time when I open a project file with bad layers. Then the 2nd time, QGIS always crashes. It seems once I replaced the bad layer handler during project start, QGIS is not able to open a subsequent new project properly.

Here is my example in code:

class MyBadLayerHandler(QgsProjectBadLayerHandler):
""" This is a custom bad layer handler that would work as the default one, except it would automatically fix a specific layer that is broken. """ def __init__(self, path):
        QgsProjectBadLayerHandler.__init__(self)
        self.validLayerPath = path

    def handleBadLayers(self, domNodes):
# Some logic to look for a specific DomNode to fix, oversimplified here: for domin domNodes:
            dataSource =self.dataSource(dom)

            if dataSourceis 'the broken path to the layer I want to fix':
                # set correct data source then force re-read 
self.setDataSource(domNodes, self.validLayerPath)
                QgsProject.instance().readLayer(dom)

# TODO: after this, call the GUI file dialog as in the default bad layer handler, to allow the user to fix # any other broken layers... not sure how to do this class MyPlugin:
    """My plugin""" def __init__(self):
        self.validPath ='valid path to layer' self.badLayerHandler =None def 
hackyAndUglyReplacer(self, i, n):
""" This hacky ugly function is to replace the bad layer handler early on, before any layers would be loaded. it is meant to be connected to the `layerLoaded` signal of `QgsProject` """ # do not run further if there were other layers loaded before (e.g. the signal was emitted before) if i !=0:
            return if not self.badLayerHandler:
            self.badLayerHandler = MyBadLayerHandler(self.validPath)
            QgsProject.instance().setBadLayerHandler(self.badLayerHandler)

    def initGui(self):
        # start-up code here... #connect to signal 
QgsProject.instance().layerLoaded.connect(self.hackyAndUglyReplacer)

    def unload(self):
        try:
            QgsProject.instance().layerLoaded.disconnect()
        except Exception:
            pass


Does anyone know what am I doing wrong here? Have I missed something?
Why does QGIS crash every 2nd time?

I would be happy to pass the bad layer handler a better way than with the current signal above. But the other signals I found are emitted 'too late' already.
Perhaps here I am also doing something wrong?

I tried looking for help but the web barely has any trace of documentation on this.

I also tried to see how this is done in other plugins e.g. the changeDataSource plugin, but the authors  seem to have removed the code when they ported the plugin to QGIS 3.x
(perhaps a bad sign)

In general it seems to me this part was also overhauled in QGIS3 but there aren't many leads to follow on what is the current way of using custom bad layer handlers.

Maybe if we could put the story together on how to do this correctly, I could document it and put it on the web for others to refer to.

Hope you are having / had a great Sunday!

Best regards,
Aron

_______________________________________________
QGIS-Developer mailing list
[email protected]
List info: https://lists.osgeo.org/mailman/listinfo/qgis-developer
Unsubscribe: https://lists.osgeo.org/mailman/listinfo/qgis-developer

Reply via email to