4

Intent is to have two variables (QgsVectorLayer and feature.id() within said layer) as input for the Identify feature map tool in Qgis (2.6). Wondering if a feature can be selected programmatically (via PyQGIS) to be highlighted in mapCanvas()?

I have reached 'writers' block after the following:

    layerID,featureID = [i for i in layerAndFeatureIDs.split("_")] 
    layerRef = ftools_utils.getMapLayerByName(unicode(layerID)) 
    infoTool = QgsMapToolIdentifyFeature(self.iface.mapCanvas(),layerRef) 
    ...? 

Runs without error - but hopeful to find out if calling a specific feature within a designated layer is possible. Either by way of a feature.id(), or even the centroid of said feature as a QgsPoint reference.


This command might be relevant. It activates the tool in question, but is it possible after triggering to subsequently highlight or info-select programmatically?

        self.iface.actionIdentify().trigger()

I wondered if an alternative method would be to source the feature in questions centroid. Yet upon deriving such - and (futily?) implacing that location into a simulated click event on mapCanvas(); no results were had. Although, a print of 'working' did return...

    for feature in layerRef.getFeatures():
        if feature.id() != int(featureID):
           pass
        elif feature.id() == int(featureID):
           x,y = feature.geometry().centroid().asPoint()[0],feature.geometry().centroid().asPoint()[1]
    self.iface.setActiveLayer(layerRef)
    self.iface.actionIdentify().trigger()
    virtualMouseClick = QtGui.QMouseEvent(QtCore.QEvent.MouseButtonPress,QtCore.QPoint(x,y), \
                        QtCore.Qt.LeftButton,QtCore.Qt.LeftButton,QtCore.Qt.NoModifier)
    try:
        self.iface.mapCanvas().mousePressEvent(virtualMouseClick)
        print 'working'
    except:
        print 'not working'

After @sigeal's advice, I have given a go at implementing some things - but run into a bit of a problem. I am supposing that the sub-classed tool needs its x,y coordinates as pixel rather than map coordinate origin. Yet use of QgsMapToPixel returns '-inf' (negative infinity) values.

What might be the syntax error I am committing, and am I off target in actions on @sigeal's advice?

#-------From main class----------------------
    ...
    for feature in layerRef.getFeatures():
        if feature.id() != int(featureID):
            pass
        elif feature.id() == int(featureID):
            point = feature.geometry().centroid().asPoint()
            x,y = point[0],point[1]
            deviceX,deviceY = QgsMapToPixel().transform(float(x),float(y))[0],QgsMapToPixel().transform(float(x),float(y))[1]
            print deviceX,deviceY
    self.iface.setActiveLayer(layerRef)
    self.iface.actionIdentify().trigger()
    try:
        featureIdentifyTool(self.iface,layerRef,deviceX,deviceY)
        print 'working'
    except:
        print 'not working'

    ...

class featureIdentifyTool(QgsMapToolIdentifyFeature):
   geomIdentified = pyqtSignal(object, object)
   def __init__(self, iface, layer, x, y):
       QgsMapToolIdentify.__init__(self, iface.mapCanvas())
       self.canvasReleaseEvent(layer,x,y)
   def canvasReleaseEvent(self,layer,x,y):
       results = self.identify(x, y, self.ActiveLayer, [layer], self.VectorLayer)
       print results
       if len(results) > 0:
          self.geomIdentified.emit(results[0].mLayer, results[0].mFeature)
0

2 Answers 2

2

The custom featureDialog may do what you need. I use it extensively in my plugin Telemetry Layer: http://southweb.co.nz/telemetrylayer. It can be called with a layer and feature or respond to user clicks. There are some quirks with it though.

7
  • Digging into the feature Dialog now to see if I or the plugin is capable, thanks for sharing!
    – Katalpa
    Commented Jan 17, 2015 at 13:24
  • Does your implementation of featureDialog also highlight the particular feature on the canvas; ergo - a visual reference aid?
    – Katalpa
    Commented Jan 17, 2015 at 14:22
  • If a feature is selected QGIS will show a red outline.
    – NZ Farmer
    Commented Jan 18, 2015 at 1:57
  • That is indeed the sought functionality.
    – Katalpa
    Commented Jan 18, 2015 at 12:41
  • Any clue on the appropriate module to reference on GitHub?
    – Katalpa
    Commented Jan 18, 2015 at 12:49
1

Just a hint : you can subclass QgsMapToolIdentifyFeature. This way you can override methods you need to customize :

class YourIdentifyTool(QgsMapToolIdentifyFeature):

    geomIdentified = pyqtSignal(object, object)

    def __init__(self, iface):

        # Parent constructor
        QgsMapToolIdentify.__init__(self, iface.mapCanvas())

    def canvasReleaseEvent(self, mouseEvent):

        results = self.identify(mouseEvent.x(), mouseEvent.y(), self.TopDownStopAtFirst, [self.arretLayer], self.VectorLayer)
        if len(results) > 0:
            self.geomIdentified.emit(results[0].mLayer, results[0].mFeature)

Actually I have only used this technique to define a custom identify tool that is intended to be used interactively. To do that, I connect the toolButton's clicked signal with a method which is run when the tool is activated (selected), and in that method I connect the tool's geomIdentified signal with the method I want to run when a feature is identified.

# toolButton's clicked signal connection
toolButton.clicked.connect(toolButtonSelect)

# Method run when toolButton is activated
def toolButtonSelect(self, checked):

    # If the toolButton is checked
    if checked:
        self.featIdentTool = FeatureIdentifyTool(self.iface)
        self.featIdentTool.geomIdentified.connect(self.toolButtonAction)
        self.iface.mapCanvas().setMapTool(self.featIdentTool)

# Method run when a feature in layer is identified by featIdentTool
def toolButtonAction(self, layer, feature):

    # Do something with identified feature
    if isinstance(layer, QgsVectorLayer) and isinstance(feature, QgsFeature):
        self.featIdentTool.doWhatEver(feature)

Now, I don't know how to trigger the geomdentified signal and send it xy coordinates... May be this link can help you : http://pyqt.sourceforge.net/Docs/PyQt4/new_style_signals_slots.html

1
  • This looks like it might be right on target, however my tool-belt might be lacking proficiency in connecting this clue towards what I have in place. Am I right to assume I need to call this sub-classed tool with the virtual-mouse click? Additionally, the x,y coordinates embedded within the virtual mouseclick sent should probably not be in mapCoordinates(as they are at current), but rather in pixel coordinates? Finally, thanks for responding!
    – Katalpa
    Commented Jan 17, 2015 at 13:22

Your Answer

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

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