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.si...@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@lists.osgeo.org > http://lists.osgeo.org/mailman/listinfo/qgis-developer > -- ----------- |\__ (:>__)( |/ Soluciones Geoinformáticas Libres http://geotux.tuxfamily.org/
_______________________________________________ Qgis-developer mailing list Qgis-developer@lists.osgeo.org http://lists.osgeo.org/mailman/listinfo/qgis-developer