[QGIS-Developer] Difficulties with custom bad layer handler in plugin code
Áron Gergely
aron.gergely at rasterra.nl
Sun Jul 21 04:16:29 PDT 2019
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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osgeo.org/pipermail/qgis-developer/attachments/20190721/2e034831/attachment.html>
More information about the QGIS-Developer
mailing list