Skip to content

Commit

Permalink
refactoring of QgsMapToolCapture to integrate shape map tools (#46687)
Browse files Browse the repository at this point in the history
* make QgsMapToolCapture capable of capturing point/line/polygons

This moves part of the code from QgsMapToolDigitizeFeature to QgsMapToolCapture so the tool can actually capture point, line and polygons. It's mainly the 'cadCanvasReleaseEvent` which has been transfered.

* use a current CaptureTechnique in QgsMapToolCapture

QgisApp has been adapted to switch between the different techniques

* add point/line/polygon specific handlers for capture map tool

* convert add part map tool to use QgsMapToolCapture capabilities

* fix use of deprecated methods

* also create a virtual handler for QgsMapToolDigitizeFeature::featureDigitized

* more dox

* use const abstract geom in virtual handlers

* add new class QgsMapToolCaptureLayerGeometry to handle layer specific operation in capture map tool

such as avoiding intersections

* allow to add linear geometries on curved geometry layers

* make actions exclusive

* add settings registry to app

* add a registry for shape map tools

* abstract class for shape map tools

* adapt QgsMapToolCapture to correctly support shape map tools

* clean up of QgisApp

* new class QgsMapToolsDigitizingTechniqueManager to handle actions in app related to capture map tools

* clean up QgisInterface

* sipify

* refactoring of existing shape tools

* refactor add ring to fully support capture map tool

* add missing folder to Doxygen

* fix layout

* fix erasing at iterator pos

* fix unused warning

* fix more dox

* fix cpp check warning

* fix unused warning

* fix annotation map tool does not support shape + set tool name

* correctly handle case when the capture is not done on a vector layer (annotation, mesh, …)

* enable shapes in annotation map tool

* correctly undo and clean

* adapt existing shape tests

the deletion test with circular vertices has been dropped since the capture map tool behaves differently

* fix warning

* refactor fill ring to support shape digitizing

* fix win build

* fix more tests

* avoid detach warnings

* fix app test + clean up

* harmonize new settings with existing ones

* fix categories

* support adding multi lines as a part

* fix adding curve part to multi line

* also handle points

* code a bit clearer

* cast not always valid

* allow adding curved polygon to multipolygon

* add test for QgsGeometry::addPart with curved parts on non-curved geoms (lines and polygons)

* fix with Python < 3.9

* better dox for deprecated interface actions methods

* remove files leftover

* remove leftover circular string curve point tool

* add default Z/M values when calling QgsGeometry::coerceToType

* Apply suggestions from code review

Co-authored-by: Nyall Dawson <nyall.dawson@gmail.com>

* fixes from review

* move layer specific part to specific tool

* fix typo

* fix leak

* fix dox

* fix segmentization

* call map tool implementation of addCurve when adding trace curve to avoid point duplication

* call sub-class implementation

* fix since 3.24 -> 3.26

* fix test

* add test to avoid extra curves when using tracing

* fix headers

Co-authored-by: Nyall Dawson <nyall.dawson@gmail.com>
  • Loading branch information
3nids and nyalldawson authored Feb 22, 2022
2 parents 2d2cd13 + 4185783 commit 36a1019
Show file tree
Hide file tree
Showing 132 changed files with 4,920 additions and 4,011 deletions.
1 change: 1 addition & 0 deletions doc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ if(WITH_APIDOC)
${CMAKE_SOURCE_DIR}/src/gui/layertree
${CMAKE_SOURCE_DIR}/src/gui/layout
${CMAKE_SOURCE_DIR}/src/gui/locator
${CMAKE_SOURCE_DIR}/src/gui/maptools
${CMAKE_SOURCE_DIR}/src/gui/mesh
${CMAKE_SOURCE_DIR}/src/gui/numericformats
${CMAKE_SOURCE_DIR}/src/gui/ogr
Expand Down
2 changes: 2 additions & 0 deletions images/images.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,9 @@
<file>themes/default/mActionDeleteTable.svg</file>
<file>themes/default/mActionDeselectAll.svg</file>
<file>themes/default/mActionDeselectActiveLayer.svg</file>
<file>themes/default/mActionDigitizeShape.svg</file>
<file>themes/default/mActionDigitizeWithCurve.svg</file>
<file>themes/default/mActionDigitizeWithSegment.svg</file>
<file>themes/default/mActionDuplicateLayer.svg</file>
<file>themes/default/mActionDuplicateComposer.svg</file>
<file>themes/default/mActionEditCopy.svg</file>
Expand Down
52 changes: 52 additions & 0 deletions images/themes/default/mActionDigitizeShape.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
67 changes: 67 additions & 0 deletions images/themes/default/mActionDigitizeWithSegment.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions python/gui/auto_additions/qgsmaptoolcapture.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# The following has been generated automatically from src/gui/qgsmaptoolcapture.h
QgsMapToolCapture.CaptureTechnique.baseClass = QgsMapToolCapture
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/maptools/qgsmaptoolcapturelayergeometry.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/




class QgsMapToolCaptureLayerGeometry : QgsMapToolCapture
{
%Docstring(signature="appended")
:py:class:`QgsMapToolCaptureLayerGeometry` is a base class for map tools digitizing layer geometries
This map tool subclass automatically handles intersection avoidance with other layers in the active project whenever a geometry is digitized by the user.

.. versionadded:: 3.26
%End

%TypeHeaderCode
#include "qgsmaptoolcapturelayergeometry.h"
%End
public:
QgsMapToolCaptureLayerGeometry( QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDockWidget, CaptureMode mode );
%Docstring
Constructor
%End

private:
virtual void layerGeometryCaptured( const QgsGeometry &geometry );
%Docstring
Called when the geometry is captured
A more specific handler is also called afterwards (layerPointCaptured, layerLineCaptured or layerPolygonCaptured)
%End
virtual void layerPointCaptured( const QgsPoint &point );
%Docstring
Called when a point is captured
The generic :py:func:`~QgsMapToolCaptureLayerGeometry.geometryCaptured` signal will be emitted immediately before this point-specific signal.
%End
virtual void layerLineCaptured( const QgsCurve *line );
%Docstring
Called when a line is captured
The generic :py:func:`~QgsMapToolCaptureLayerGeometry.geometryCaptured` signal will be emitted immediately before this line-specific signal.
%End
virtual void layerPolygonCaptured( const QgsCurvePolygon *polygon );
%Docstring
Called when a polygon is captured
The generic :py:func:`~QgsMapToolCaptureLayerGeometry.geometryCaptured` signal will be emitted immediately before this polygon-specific signal.
%End
};

/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/maptools/qgsmaptoolcapturelayergeometry.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
96 changes: 80 additions & 16 deletions python/gui/auto_generated/qgisinterface.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -672,69 +672,133 @@ Returns the Hide Deselected Layers action.
virtual QAction *actionCheckQgisVersion() = 0;
virtual QAction *actionAbout() = 0;

virtual QAction *actionCircle2Points() = 0;

virtual QAction *actionCircle2Points() /Deprecated/;
%Docstring
Returns the native add circle from 2 points action. Call :py:func:`~QgisInterface.trigger` on it to set the map tool.

.. deprecated:: QGIS 3.26
shape digitizing is now part of the add feature tool. To enable the shape tool, use :py:func:`QgsMapToolCapture.setCurrentCaptureTechnique()` and then :py:func:`QgsMapToolCapture.setCurrentShapeMapTool()`.
%End
virtual QAction *actionCircle3Points() = 0;

virtual QAction *actionCircle3Points() /Deprecated/;
%Docstring
Returns the native add circle from 3 points action. Call :py:func:`~QgisInterface.trigger` on it to set the map tool.

.. deprecated:: QGIS 3.26
shape digitizing is now part of the add feature tool. To enable the shape tool, use :py:func:`QgsMapToolCapture.setCurrentCaptureTechnique()` and then :py:func:`QgsMapToolCapture.setCurrentShapeMapTool()`.
%End
virtual QAction *actionCircle3Tangents() = 0;

virtual QAction *actionCircle3Tangents() /Deprecated/;
%Docstring
Returns the native add circle from 3 tangents action. Call :py:func:`~QgisInterface.trigger` on it to set the map tool.

.. deprecated:: QGIS 3.26
shape digitizing is now part of the add feature tool. To enable the shape tool, use :py:func:`QgsMapToolCapture.setCurrentCaptureTechnique()` and then :py:func:`QgsMapToolCapture.setCurrentShapeMapTool()`.
%End
virtual QAction *actionCircle2TangentsPoint() = 0;

virtual QAction *actionCircle2TangentsPoint() /Deprecated/;
%Docstring
Returns the native add circle from 2 tangents and a point action. Call :py:func:`~QgisInterface.trigger` on it to set the map tool.

.. deprecated:: QGIS 3.26
shape digitizing is now part of the add feature tool. To enable the shape tool, use :py:func:`QgsMapToolCapture.setCurrentCaptureTechnique()` and then :py:func:`QgsMapToolCapture.setCurrentShapeMapTool()`.
%End
virtual QAction *actionCircleCenterPoint() = 0;

virtual QAction *actionCircleCenterPoint() /Deprecated/;
%Docstring
Returns the native add circle from center action. Call :py:func:`~QgisInterface.trigger` on it to set the map tool.

.. deprecated:: QGIS 3.26
shape digitizing is now part of the add feature tool. To enable the shape tool, use :py:func:`QgsMapToolCapture.setCurrentCaptureTechnique()` and then :py:func:`QgsMapToolCapture.setCurrentShapeMapTool()`.
%End
virtual QAction *actionEllipseCenter2Points() = 0;

virtual QAction *actionEllipseCenter2Points() /Deprecated/;
%Docstring
Returns the native add ellipse from center and 2 points action. Call :py:func:`~QgisInterface.trigger` on it to set the map tool.

.. deprecated:: QGIS 3.26
shape digitizing is now part of the add feature tool. To enable the shape tool, use :py:func:`QgsMapToolCapture.setCurrentCaptureTechnique()` and then :py:func:`QgsMapToolCapture.setCurrentShapeMapTool()`.
%End
virtual QAction *actionEllipseCenterPoint() = 0;

virtual QAction *actionEllipseCenterPoint() /Deprecated/;
%Docstring
Returns the native add ellipse from center and a point action. Call :py:func:`~QgisInterface.trigger` on it to set the map tool.

.. deprecated:: QGIS 3.26
shape digitizing is now part of the add feature tool. To enable the shape tool, use :py:func:`QgsMapToolCapture.setCurrentCaptureTechnique()` and then :py:func:`QgsMapToolCapture.setCurrentShapeMapTool()`.
%End
virtual QAction *actionEllipseExtent() = 0;

virtual QAction *actionEllipseExtent() /Deprecated/;
%Docstring
Returns the native add ellipse from an extent action. Call :py:func:`~QgisInterface.trigger` on it to set the map tool.

.. deprecated:: QGIS 3.26
shape digitizing is now part of the add feature tool. To enable the shape tool, use :py:func:`QgsMapToolCapture.setCurrentCaptureTechnique()` and then :py:func:`QgsMapToolCapture.setCurrentShapeMapTool()`.
%End
virtual QAction *actionEllipseFoci() = 0;

virtual QAction *actionEllipseFoci() /Deprecated/;
%Docstring
Returns the native add ellipse from foci action. Call :py:func:`~QgisInterface.trigger` on it to set the map tool.

.. deprecated:: QGIS 3.26
shape digitizing is now part of the add feature tool. To enable the shape tool, use :py:func:`QgsMapToolCapture.setCurrentCaptureTechnique()` and then :py:func:`QgsMapToolCapture.setCurrentShapeMapTool()`.
%End
virtual QAction *actionRectangleCenterPoint() = 0;

virtual QAction *actionRectangleCenterPoint() /Deprecated/;
%Docstring
Returns the native add rectangle from center and a point action. Call :py:func:`~QgisInterface.trigger` on it to set the map tool.

.. deprecated:: QGIS 3.26
shape digitizing is now part of the add feature tool. To enable the shape tool, use :py:func:`QgsMapToolCapture.setCurrentCaptureTechnique()` and then :py:func:`QgsMapToolCapture.setCurrentShapeMapTool()`.
%End
virtual QAction *actionRectangleExtent() = 0;

virtual QAction *actionRectangleExtent() /Deprecated/;
%Docstring
Returns the native add rectangle from extent action. Call :py:func:`~QgisInterface.trigger` on it to set the map tool.

.. deprecated:: QGIS 3.26
shape digitizing is now part of the add feature tool. To enable the shape tool, use :py:func:`QgsMapToolCapture.setCurrentCaptureTechnique()` and then :py:func:`QgsMapToolCapture.setCurrentShapeMapTool()`.
%End
virtual QAction *actionRectangle3PointsDistance() = 0;

virtual QAction *actionRectangle3PointsDistance() /Deprecated/;
%Docstring
Returns the native add rectangle from 3 points (distance from 2nd and 3rd points) action. Call :py:func:`~QgisInterface.trigger` on it to set the map tool.

.. deprecated:: QGIS 3.26
shape digitizing is now part of the add feature tool. To enable the shape tool, use :py:func:`QgsMapToolCapture.setCurrentCaptureTechnique()` and then :py:func:`QgsMapToolCapture.setCurrentShapeMapTool()`.
%End
virtual QAction *actionRectangle3PointsProjected() = 0;

virtual QAction *actionRectangle3PointsProjected() /Deprecated/;
%Docstring
Returns the native add rectangle from 3 points (distance from projected 3rd point on segment p1 and p2) action. Call :py:func:`~QgisInterface.trigger` on it to set the map tool.

.. deprecated:: QGIS 3.26
shape digitizing is now part of the add feature tool. To enable the shape tool, use :py:func:`QgsMapToolCapture.setCurrentCaptureTechnique()` and then :py:func:`QgsMapToolCapture.setCurrentShapeMapTool()`.
%End
virtual QAction *actionRegularPolygon2Points() = 0;

virtual QAction *actionRegularPolygon2Points() /Deprecated/;
%Docstring
Returns the native add regular polygon from 2 points action. Call :py:func:`~QgisInterface.trigger` on it to set the map tool.

.. deprecated:: QGIS 3.26
shape digitizing is now part of the add feature tool. To enable the shape tool, use :py:func:`QgsMapToolCapture.setCurrentCaptureTechnique()` and then :py:func:`QgsMapToolCapture.setCurrentShapeMapTool()`.
%End
virtual QAction *actionRegularPolygonCenterPoint() = 0;

virtual QAction *actionRegularPolygonCenterPoint() /Deprecated/;
%Docstring
Returns the native add regular polygon from center and a point action. Call :py:func:`~QgisInterface.trigger` on it to set the map tool.

.. deprecated:: QGIS 3.26
shape digitizing is now part of the add feature tool. To enable the shape tool, use :py:func:`QgsMapToolCapture.setCurrentCaptureTechnique()` and then :py:func:`QgsMapToolCapture.setCurrentShapeMapTool()`.
%End
virtual QAction *actionRegularPolygonCenterCorner() = 0;

virtual QAction *actionRegularPolygonCenterCorner() /Deprecated/;
%Docstring
Returns the native add regular polygon from center and a corner action. Call :py:func:`~QgisInterface.trigger` on it to set the map tool.

.. deprecated:: QGIS 3.26
shape digitizing is now part of the add feature tool. To enable the shape tool, use :py:func:`QgsMapToolCapture.setCurrentCaptureTechnique()` and then :py:func:`QgsMapToolCapture.setCurrentShapeMapTool()`.
%End

virtual QgsVectorLayerTools *vectorLayerTools() = 0;
Expand Down
10 changes: 5 additions & 5 deletions python/gui/auto_generated/qgsmaptool.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,11 @@ The default implementation does nothing and returns false.
is present in :py:func:`~QgsMapTool.flags`.

.. versionadded:: 3.18
%End

QgsPointXY toMapCoordinates( QPoint point );
%Docstring
Transforms a ``point`` from screen coordinates to map coordinates.
%End

signals:
Expand Down Expand Up @@ -289,11 +294,6 @@ signal emitted once the map tool is deactivated
QgsMapTool( QgsMapCanvas *canvas /TransferThis/ );
%Docstring
Constructor takes a map canvas as a parameter.
%End

QgsPointXY toMapCoordinates( QPoint point );
%Docstring
Transforms a ``point`` from screen coordinates to map coordinates.
%End

QgsPoint toLayerCoordinates( const QgsMapLayer *layer, const QgsPoint &point ) /PyName=toLayerCoordinatesV2/;
Expand Down
Loading

0 comments on commit 36a1019

Please sign in to comment.