2

I'm writing a photo grouping plugin. My current problem can be broken up into "end goal" and "baby steps", because I think that's what I want. But if there's a way to get to the end by a different means, that's what I really need.

End goal: given 2 different QGIS layers, 'nodes' and 'sections', and given a bunch of groups of photos, mouse over a 'node' > click to assign photos to node. mouse over a 'section' > click to assign. Repeat indefinitely, not necessarily in order. Without toggling active layer back and forth and making selection(s) first.

Baby Step #1: find out what feature(s) on which vector layer(s) is under the mouse position.

I found the "Value Tool" plugin last night, read through the code, and it reports values from multiple raster layers based on the mouse position. I was super excited! Unfortunately, it seems that QgsVectorDataProvider doesn't have anything analogous to the QgsRasterDataProvider's identify(position) method, which is how that plugin works.

So I've been playing around with QgsVectorDataProvider.select(), but can't get it working. Probably doing something stupid. This post: https://gis.stackexchange.com/a/22919/6690 makes it sound like it's possible.

Can anyone tell me what I'm doing wrong?

Steps (in Python console for now):

  1. load vector layer in QGIS
  2. iface = qgis.utils.iface; canvas = iface.mapCanvas(); layer = canvas.layer(0)
  3. layer.dataProvider().attributeIndexes() >> [0,1,2,3,4,5]
  4. A = layer.dataProvider.select((0,1,2,3,4,5),canvas.extent())
  5. checks: A >> nothing; type(A) >> 'type 'NoneType''

Once I can get a selection by position, I think I can get the list of layers I want to check, iterate through them with position, check & flag on overlaps, and we're off...

2
  • passing layer.dataProvider().extent() to select has the same result (not that I expect the rectangles to be the same, but both should contain some selection set)
    – B Freed
    Mar 28, 2013 at 15:21
  • Update: still not sure why the dataProvider version isn't working, but QgsVectorLayer has a select() method as well, that takes either an ID or a QgsRectangle. So if my step 4 is layer.select(canvas.extent(),0), it works (the 0/1, listed as "lock" in the documentation controls whether the selection emits a signal or not, which controls screen refresh). Next step I guess is to pass a buffered mouse location instead of canvas extents and see if select/deselect is quick enough to call on mouse moves. Really wish there was a lightweight 'is the cursor intersecting something' method.
    – B Freed
    Mar 28, 2013 at 19:21

1 Answer 1

2

If you look at the API documentation for QgsVectorDataProvider you'll see that the select method returns void (see http://qgis.org/api/1.8/classQgsVectorDataProvider.html). This is why A is of NoneType in Python.

To access the features you need to iterate over the selection set after your select statement. Here is an example using a shapefile of cities, zoomed to a small area:

iface = qgis.utils.iface
canvas = iface.mapCanvas()
layer = canvas.layer(0)
provider = layer.dataProvider()
provider.select(provider.attributeIndexes(), canvas.extent())
feature = QgsFeature()
while provider.nextFeature(feature):
    attributes = feature.attributeMap()
    print attributes[0].toString()

This results in:

... 
Seward
Anchorage
>>> 

See Iterating over Vector Layer in the PyQGIS Cookbook: http://www.qgis.org/pyqgis-cookbook/vector.html

1
  • doh! Thanks, that's exactly the sort of thing I was afraid I was missing. Read the cookbook a while back - looks like it's time for a refresher.
    – B Freed
    Apr 1, 2013 at 10:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.