Wednesday 22 July 2015

python - QGIS 2.4: plugin changes map tool canvas click behavior from 2.0


I had created a plugin for QGIS 2.0 to add new features more easily. It involves changing extents and updating snapping options along with triggering the default actionAddFeature(). However, I've decided to update to QGIS 2.4 and now notice that it has changed in behavior, but I cannot figure out why.


I'd created a mapTool to emit a point:


def __init__(self, iface):

...
self.canvas = self.iface.mapCanvas()
self.clickTool = QgsMapToolEmitPoint(self.canvas)
...

I connected the map tool to a function:


def initGui(self):
self.clickTool.canvasClicked.connect(self.zoomTo)

The zoomTo tool zooms into a certain defined rectangle extent and triggers other functions depending on if statements



def zoomTo(self):
...
box = pntBuff.boundingBox()
self.canvas.setExtent(box)
self.canvas.refresh()
if self.iface.activeLayer() == layer1:
self.addElement1()
if self.iface.activeLayer() == layer2:
self.addElement2()


My problem lies here: Using my plugin with QGIS 2.0, the first canvas click zoomed to my desired extent (done by zoomTo()) and required a second canvas click to actually add the feature (triggered by addElement1()). Using the plugin in QGIS 2.4, the first canvas click zooms AND adds the feature at the same time without requiring a second mouse click (this means I can't easily control where exactly I'm placing my elements).


addElement1() and addElement2() both start editing, set active layers, and trigger actionAddFeature for respective layers.


def addElement1(self):
if not layer1.isEditable():
self.layer1.startEditing()
self.iface.setActiveLayer(self.layer1)
self.iface.actionAddFeature().trigger()

My run method zooms out to my layer's extent and sets my map tool:


def run(self):

#zoomOut() defined to set to layer's extent--different from zoomTo
self.zoomOut()
self.canvas.setMapTool(self.clickTool)

UPDATE: I'm still trying to target this issue and have created a second map tool to trigger the add feature action (on top of the original click tool). The first click zooms to the area and the second click should simply trigger the feature add action tool (requiring a third click to actually add the feature and open feature form). However, the second click triggers the action AND adds the feature right away (with only one click). While the difficulties of not being zoomed in previously stated is no longer an issue, it is still problematic as 1) the cursor does not change to "add feature" target symbol and 2) the snapping option cross does not show up.


When testing qgis.utils.iface.addFeatureAction().trigger() in the python console, the add feature button is simply toggled. It must be some combination of my emit point map tool with the add feature action. I wonder how I can access the add feature tool in a more detailed way, keeping it from firing in this unexpected way.


def __init__(self, iface):
...
self.canvas = self.iface.mapCanvas()
self.clickTool = QgsMapToolEmitPoint(self.canvas)

self.addFeatureTool = QgsMapToolEmitPoint(self.canvas)
...

def initGui(self):
self.clickTool.canvasClicked.connect(self.zoomTo)
self.addFeatureTool.canvasClicked.connect(self.addMyFeature)

def zoomTo(self):
...
box = pntBuff.boundingBox()

self.canvas.setExtent(box)
self.canvas.refresh()
if self.iface.activeLayer() == layer1:
self.setMyMapTool()
...

def setMyMapTool(self):
self.canvas.setMapTool(self.addVanneTool)

def addMyFeature(self):

self.iface.actionAddFeature().trigger()

At this point, I feel like i've tried so many things without success. Just wondering if anyone can tell whether this is some sort of bug, or an error on my part.



Answer



QgsMapToolEmitPoint implements the method canvasPressEvent while QgsMapToolAddFeature implements the method canvasReleaseEvent to trigger its actions.


CanvasPressEvent is called before canvasReleaseEvent so if you replace the maptool in the first method, the second one will be called on the new map tool.


I would recommend to create a new map tool that does the same as QgsMapToolEmitPoint but in canvasReleaseEvent


class MyMapToolEmitPoint( QgsMapTool ):
canvasClicked = pyqtSignal( ['QgsPoint', 'Qt::MouseButton'] )
def canvasReleaseEvent( self, mouseEvent ):

pnt = self.toMapCoordinates( mouseEvent.pos() )
self.canvasClicked.emit( pnt, mouseEvent.button() )

No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...