[Qgis-developer] QgsMapLayerRegistry questions

Germán Carrillo carrillo.german at gmail.com
Sat Sep 4 13:04:07 EDT 2010


Hi Ricardo,

what if you use the legendInterface class for getting the loaded layers?

Try this (in the Python console):
-------------------------------------------------------
from PyQt4.QtCore import SIGNAL

q = qgis.utils.iface
l = q.legendInterface()
def f( layerId ):
for i in l.layers():
 print i.name(), i.geometryType()

q.connect( QgsMapLayerRegistry.instance(), SIGNAL(
"layerWillBeRemoved(QString)" ), f )
-------------------------------------------------------

I'm not sure it works if the user starts a new project...

Regards,

Germán

On Sat, Sep 4, 2010 at 7:53 AM, Ricardo Filipe Soares Garcia da <
ricardo.garcia.silva at gmail.com> wrote:

> Hi list
>
> I'm trying to toggle my plugin's availability based on the presence or
> absence of loaded vector layers of type 'line'.
> For this purpose I have a _get_loaded_layers() and a
> toggle_availability() methods (code follows in the end of this
> message).
>
> After searching the online API docs, it seems that the
> QgsMapLayerRegistry class is the one that notifies the rest of the
> application about layers being added or removed.
> So I connect my plugin's toggle_availability() method to the
> layerWasAdded() and layerWillBeRemoved() signals of the
> QgsMapLayerRegistry.instance() object.
>
> When the user adds a new layer everything goes fine, my plugin's
> availability is toggled based on the presence of vector lines,
> including the new layer that was added.
> Also, if the user removes just one layer at a time, everything works
> as expected as well.
>
> Unfortunately, when several layers are removed at the same time (for
> example, if the user had an open project and decides to create a new
> one), my plugin is causing Qgis to segfault (very ugly!).
>
> It seems to be connected to what is happening with the
> QgsmapLayerRegistry instance when the layerWillBeRemoved() signal is
> emmited repeatedly. It seems to me that I am crashing Qgis because I
> am trying to call QgsMapLayerRegistry.instance().mapLayers() while the
> layers are being deleted... and that causes the segfault.
> I don't know what happens to the mapLayerRegistry instance, but its
> mapLayers() method seems to be the source of the error.
>
> Reading the pyQgis cookbook, I realized that when layers are removed
> from the mapLayerRegistry they are also deleted from Qgis, which seems
> a bit inconsistent, compared with the loading procedure. What I mean
> is, if layers can be loaded without being automatically added to the
> mapLayerRegistry, maybe they could also be removed from the
> mapLayerRegistry without being deleted from Qgis (Maybe this is the
> reason for having a layerWillBeRemoved() signal instead of a
> layerWasRemoved()?).
>
> Anyway, I don't understand why it works OK if layers are removed one
> at a time and not if they all get removed.
> I've tried to use the QgsMapLayerRegistry.removedAll() signal to catch
> those situations when all layers get removed at once. It does work,
> but the problem is that the QgsMapLayerRegistry.layerWillBeRemoved()
> is still geting called at the same time and will crash Qgis.
>
> So, I'd like to request your help in determining the best way to be
> notified when a layer is removed from the map canvas.
>
> Thanks
>
> #(python code follows)
>
>
> def initGui(self):
>        self.action = QAction(QIcon(":/plugins/ProfileFromLine/icon.png"), \
>            "Profile from line", self.iface.mainWindow())
>        self.toggle_plugin_availability()
>        QObject.connect(self.action, SIGNAL("activated()"), self.run)
>        self.iface.addToolBarIcon(self.action)
>        self.iface.addPluginToMenu("&Profile from line", self.action)
>        QObject.connect(self.layerRegistry,
> SIGNAL("layerWasAdded(QgsMapLayer *)"),
> self.toggle_plugin_availability)
>        QObject.connect(self.layerRegistry,
> SIGNAL("layerWillBeRemoved(QString)"),
> self.toggle_plugin_availability)
>
>
> def _get_loaded_layers(self):
>        availableLayers = {"vectorLine" : [], "raster" : []}
>        loadedLayers = self.layerRegistry.mapLayers()
>        for layer in loadedLayers.itervalues():
>            layerType = layer.type()
>            if layerType == 0: # it's a vector layer
>                if layer.geometryType() == 1: # it's a line
>                    availableLayers["vectorLine"].append(layer)
>            elif layerType == 1: #it's a raster layer
>                availableLayers["raster"].append(layer)
>        return availableLayers
>
> def toggle_plugin_availability(self, arg=None):
>        print("toggle_plugin_availability method called")
>        numLinesLayers = len(self._get_loaded_layers()["vectorLine"])
>        if numLinesLayers == 0:
>            self.action.setEnabled(False)
>        elif numLinesLayers == 1 and type(arg) == QString:
>            layerAboutToGo = self.layerRegistry.mapLayer(arg)
>            if layerAboutToGo.type() == 0:
>                if layerAboutToGo.geometryType() == 1:
>                    self.action.setEnabled(False)
>
>
>
> --
> ___________________________ ___ __
> Ricardo Garcia Silva
> _______________________________________________
> Qgis-developer mailing list
> Qgis-developer at lists.osgeo.org
> http://lists.osgeo.org/mailman/listinfo/qgis-developer
>

-- 
-----------
  |\__
(:>__)(
  |/

Soluciones Geoinformáticas Libres
http://geotux.tuxfamily.org/
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.osgeo.org/pipermail/qgis-developer/attachments/20100904/913176b4/attachment.html


More information about the Qgis-developer mailing list