Re: [Qgis-developer] QgsMapLayerRegistry questions

2010-09-05 Thread Ricardo Filipe Soares Garcia da
Thanks Germán, your suggestion works great.
Now I have the code up and running again!

Cheers

2010/9/4 Germán Carrillo :
> 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
>  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

Re: [Qgis-developer] QgsMapLayerRegistry questions

2010-09-04 Thread Germán Carrillo
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(Fals

[Qgis-developer] QgsMapLayerRegistry questions

2010-09-04 Thread Ricardo Filipe Soares Garcia da
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