Skip to content

Commit

Permalink
Add an annotation item edit operation for adding nodes
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Sep 10, 2021
1 parent a7d299d commit 4cb06c0
Show file tree
Hide file tree
Showing 13 changed files with 153 additions and 5 deletions.
3 changes: 2 additions & 1 deletion python/core/auto_additions/qgsannotationitemeditoperation.py
Expand Up @@ -2,6 +2,7 @@
# monkey patching scoped based enum
QgsAbstractAnnotationItemEditOperation.Type.MoveNode.__doc__ = "Move a node"
QgsAbstractAnnotationItemEditOperation.Type.DeleteNode.__doc__ = "Delete a node"
QgsAbstractAnnotationItemEditOperation.Type.AddNode.__doc__ = "Add a node"
QgsAbstractAnnotationItemEditOperation.Type.TranslateItem.__doc__ = "Translate (move) an item"
QgsAbstractAnnotationItemEditOperation.Type.__doc__ = 'Operation type\n\n' + '* ``MoveNode``: ' + QgsAbstractAnnotationItemEditOperation.Type.MoveNode.__doc__ + '\n' + '* ``DeleteNode``: ' + QgsAbstractAnnotationItemEditOperation.Type.DeleteNode.__doc__ + '\n' + '* ``TranslateItem``: ' + QgsAbstractAnnotationItemEditOperation.Type.TranslateItem.__doc__
QgsAbstractAnnotationItemEditOperation.Type.__doc__ = 'Operation type\n\n' + '* ``MoveNode``: ' + QgsAbstractAnnotationItemEditOperation.Type.MoveNode.__doc__ + '\n' + '* ``DeleteNode``: ' + QgsAbstractAnnotationItemEditOperation.Type.DeleteNode.__doc__ + '\n' + '* ``AddNode``: ' + QgsAbstractAnnotationItemEditOperation.Type.AddNode.__doc__ + '\n' + '* ``TranslateItem``: ' + QgsAbstractAnnotationItemEditOperation.Type.TranslateItem.__doc__
# --
Expand Up @@ -26,6 +26,7 @@ Abstract base class for annotation item edit operations
{
MoveNode,
DeleteNode,
AddNode,
TranslateItem,
};

Expand Down Expand Up @@ -129,6 +130,34 @@ Returns the node position before the delete occurred (in layer coordinates).

};

class QgsAnnotationItemEditOperationAddNode : QgsAbstractAnnotationItemEditOperation
{
%Docstring(signature="appended")
Annotation item edit operation consisting of adding a node

.. versionadded:: 3.22
%End

%TypeHeaderCode
#include "qgsannotationitemeditoperation.h"
%End
public:

QgsAnnotationItemEditOperationAddNode( const QString &itemId, const QgsPoint &point );
%Docstring
Constructor for QgsAnnotationItemEditOperationAddNode at the specified ``point``.
%End

virtual Type type() const;


QgsPoint point() const;
%Docstring
Returns the node position (in layer coordinates).
%End

};


class QgsAnnotationItemEditOperationTranslateItem : QgsAbstractAnnotationItemEditOperation
{
Expand Down
17 changes: 17 additions & 0 deletions src/core/annotations/qgsannotationitemeditoperation.cpp
Expand Up @@ -79,3 +79,20 @@ QgsAbstractAnnotationItemEditOperation::Type QgsAnnotationItemEditOperationTrans
{
return Type::TranslateItem;
}


//
// QgsAnnotationItemEditOperationAddNode
//

QgsAnnotationItemEditOperationAddNode::QgsAnnotationItemEditOperationAddNode( const QString &itemId, const QgsPoint &point )
: QgsAbstractAnnotationItemEditOperation( itemId )
, mPoint( point )
{

}

QgsAbstractAnnotationItemEditOperation::Type QgsAnnotationItemEditOperationAddNode::type() const
{
return Type::AddNode;
}
29 changes: 28 additions & 1 deletion src/core/annotations/qgsannotationitemeditoperation.h
Expand Up @@ -40,6 +40,7 @@ class CORE_EXPORT QgsAbstractAnnotationItemEditOperation
{
MoveNode, //!< Move a node
DeleteNode, //!< Delete a node
AddNode, //!< Add a node
TranslateItem, //!< Translate (move) an item
};

Expand Down Expand Up @@ -145,6 +146,33 @@ class CORE_EXPORT QgsAnnotationItemEditOperationDeleteNode : public QgsAbstractA

};

/**
* \ingroup core
* \brief Annotation item edit operation consisting of adding a node
* \since QGIS 3.22
*/
class CORE_EXPORT QgsAnnotationItemEditOperationAddNode : public QgsAbstractAnnotationItemEditOperation
{
public:

/**
* Constructor for QgsAnnotationItemEditOperationAddNode at the specified \a point.
*/
QgsAnnotationItemEditOperationAddNode( const QString &itemId, const QgsPoint &point );

Type type() const override;

/**
* Returns the node position (in layer coordinates).
*/
QgsPoint point() const { return mPoint; }

private:

QgsPoint mPoint;

};


/**
* \ingroup core
Expand Down Expand Up @@ -188,7 +216,6 @@ class CORE_EXPORT QgsAnnotationItemEditOperationTranslateItem : public QgsAbstra
double mTranslateX = 0;
double mTranslateY = 0;


};

/**
Expand Down
13 changes: 13 additions & 0 deletions src/core/annotations/qgsannotationlineitem.cpp
Expand Up @@ -112,6 +112,18 @@ Qgis::AnnotationItemEditOperationResult QgsAnnotationLineItem::applyEdit( QgsAbs
break;
}

case QgsAbstractAnnotationItemEditOperation::Type::AddNode:
{
QgsAnnotationItemEditOperationAddNode *addOperation = qgis::down_cast< QgsAnnotationItemEditOperationAddNode * >( operation );

QgsPoint segmentPoint;
QgsVertexId endOfSegmentVertex;
mCurve->closestSegment( addOperation->point(), segmentPoint, endOfSegmentVertex );
if ( mCurve->insertVertex( endOfSegmentVertex, addOperation->point() ) )
return Qgis::AnnotationItemEditOperationResult::Success;
break;
}

case QgsAbstractAnnotationItemEditOperation::Type::TranslateItem:
{
QgsAnnotationItemEditOperationTranslateItem *moveOperation = qgis::down_cast< QgsAnnotationItemEditOperationTranslateItem * >( operation );
Expand Down Expand Up @@ -149,6 +161,7 @@ QgsAnnotationItemEditOperationTransientResults *QgsAnnotationLineItem::transient
}

case QgsAbstractAnnotationItemEditOperation::Type::DeleteNode:
case QgsAbstractAnnotationItemEditOperation::Type::AddNode:
break;
}
return nullptr;
Expand Down
4 changes: 4 additions & 0 deletions src/core/annotations/qgsannotationmarkeritem.cpp
Expand Up @@ -103,6 +103,9 @@ Qgis::AnnotationItemEditOperationResult QgsAnnotationMarkerItem::applyEdit( QgsA
mPoint.setY( mPoint.y() + moveOperation->translationY() );
return Qgis::AnnotationItemEditOperationResult::Success;
}

case QgsAbstractAnnotationItemEditOperation::Type::AddNode:
break;
}

return Qgis::AnnotationItemEditOperationResult::Invalid;
Expand All @@ -125,6 +128,7 @@ QgsAnnotationItemEditOperationTransientResults *QgsAnnotationMarkerItem::transie
}

case QgsAbstractAnnotationItemEditOperation::Type::DeleteNode:
case QgsAbstractAnnotationItemEditOperation::Type::AddNode:
break;
}
return nullptr;
Expand Down
4 changes: 4 additions & 0 deletions src/core/annotations/qgsannotationpointtextitem.cpp
Expand Up @@ -161,6 +161,9 @@ Qgis::AnnotationItemEditOperationResult QgsAnnotationPointTextItem::applyEdit( Q
mPoint.setY( mPoint.y() + moveOperation->translationY() );
return Qgis::AnnotationItemEditOperationResult::Success;
}

case QgsAbstractAnnotationItemEditOperation::Type::AddNode:
break;
}

return Qgis::AnnotationItemEditOperationResult::Invalid;
Expand All @@ -183,6 +186,7 @@ QgsAnnotationItemEditOperationTransientResults *QgsAnnotationPointTextItem::tran
}

case QgsAbstractAnnotationItemEditOperation::Type::DeleteNode:
case QgsAbstractAnnotationItemEditOperation::Type::AddNode:
break;
}
return nullptr;
Expand Down
13 changes: 13 additions & 0 deletions src/core/annotations/qgsannotationpolygonitem.cpp
Expand Up @@ -142,6 +142,18 @@ Qgis::AnnotationItemEditOperationResult QgsAnnotationPolygonItem::applyEdit( Qgs
break;
}

case QgsAbstractAnnotationItemEditOperation::Type::AddNode:
{
QgsAnnotationItemEditOperationAddNode *addOperation = qgis::down_cast< QgsAnnotationItemEditOperationAddNode * >( operation );

QgsPoint segmentPoint;
QgsVertexId endOfSegmentVertex;
mPolygon->closestSegment( addOperation->point(), segmentPoint, endOfSegmentVertex );
if ( mPolygon->insertVertex( endOfSegmentVertex, addOperation->point() ) )
return Qgis::AnnotationItemEditOperationResult::Success;
break;
}

case QgsAbstractAnnotationItemEditOperation::Type::TranslateItem:
{
QgsAnnotationItemEditOperationTranslateItem *moveOperation = qgis::down_cast< QgsAnnotationItemEditOperationTranslateItem * >( operation );
Expand Down Expand Up @@ -179,6 +191,7 @@ QgsAnnotationItemEditOperationTransientResults *QgsAnnotationPolygonItem::transi
}

case QgsAbstractAnnotationItemEditOperation::Type::DeleteNode:
case QgsAbstractAnnotationItemEditOperation::Type::AddNode:
break;
}
return nullptr;
Expand Down
13 changes: 13 additions & 0 deletions tests/src/python/test_qgsannotationitemeditoperation.py
Expand Up @@ -16,6 +16,8 @@
from qgis.core import (
QgsAnnotationItemEditOperationMoveNode,
QgsAnnotationItemEditOperationDeleteNode,
QgsAnnotationItemEditOperationTranslateItem,
QgsAnnotationItemEditOperationAddNode,
QgsVertexId,
QgsPoint,
QgsPointXY
Expand Down Expand Up @@ -43,6 +45,17 @@ def test_delete_node_operation(self):
self.assertEqual(operation.nodeId(), QgsVertexId(1, 2, 3))
self.assertEqual(operation.before(), QgsPoint(6, 7))

def test_add_node_operation(self):
operation = QgsAnnotationItemEditOperationAddNode('item id', QgsPoint(6, 7))
self.assertEqual(operation.itemId(), 'item id')
self.assertEqual(operation.point(), QgsPoint(6, 7))

def test_translate_operation(self):
operation = QgsAnnotationItemEditOperationTranslateItem('item id', 6, 7)
self.assertEqual(operation.itemId(), 'item id')
self.assertEqual(operation.translationX(), 6)
self.assertEqual(operation.translationY(), 7)


if __name__ == '__main__':
unittest.main()
10 changes: 9 additions & 1 deletion tests/src/python/test_qgsannotationlineitem.py
Expand Up @@ -39,7 +39,8 @@
QgsVertexId,
QgsAnnotationItemEditOperationMoveNode,
QgsAnnotationItemEditOperationDeleteNode,
QgsAnnotationItemEditOperationTranslateItem
QgsAnnotationItemEditOperationTranslateItem,
QgsAnnotationItemEditOperationAddNode
)
from qgis.PyQt.QtXml import QDomDocument

Expand Down Expand Up @@ -115,6 +116,13 @@ def test_apply_delete_node_edit(self):
self.assertEqual(item.applyEdit(QgsAnnotationItemEditOperationDeleteNode('', QgsVertexId(0, 0, 1), QgsPoint(16, 17))), Qgis.AnnotationItemEditOperationResult.ItemCleared)
self.assertEqual(item.geometry().asWkt(), 'LineString EMPTY')

def test_apply_add_node_edit(self):
item = QgsAnnotationLineItem(QgsLineString([QgsPoint(12, 13), QgsPoint(14, 13), QgsPoint(14, 15), QgsPoint(16, 17)]))
self.assertEqual(item.geometry().asWkt(), 'LineString (12 13, 14 13, 14 15, 16 17)')

self.assertEqual(item.applyEdit(QgsAnnotationItemEditOperationAddNode('', QgsPoint(15, 16))), Qgis.AnnotationItemEditOperationResult.Success)
self.assertEqual(item.geometry().asWkt(), 'LineString (12 13, 14 13, 14 15, 15 16, 16 17)')

def test_transient_move_operation(self):
item = QgsAnnotationLineItem(QgsLineString([QgsPoint(12, 13), QgsPoint(14, 13), QgsPoint(14, 15)]))
self.assertEqual(item.geometry().asWkt(), 'LineString (12 13, 14 13, 14 15)')
Expand Down
7 changes: 6 additions & 1 deletion tests/src/python/test_qgsannotationmarkeritem.py
Expand Up @@ -37,7 +37,8 @@
QgsVertexId,
QgsAnnotationItemEditOperationMoveNode,
QgsAnnotationItemEditOperationDeleteNode,
QgsAnnotationItemEditOperationTranslateItem
QgsAnnotationItemEditOperationTranslateItem,
QgsAnnotationItemEditOperationAddNode
)
from qgis.PyQt.QtXml import QDomDocument

Expand Down Expand Up @@ -102,6 +103,10 @@ def test_apply_delete_node_edit(self):

self.assertEqual(item.applyEdit(QgsAnnotationItemEditOperationDeleteNode('', QgsVertexId(0, 0, 0), QgsPoint(12, 13))), Qgis.AnnotationItemEditOperationResult.ItemCleared)

def test_apply_add_node_edit(self):
item = QgsAnnotationMarkerItem(QgsPoint(12, 13))
self.assertEqual(item.applyEdit(QgsAnnotationItemEditOperationAddNode('', QgsPoint(13, 14))), Qgis.AnnotationItemEditOperationResult.Invalid)

def test_transient_move_operation(self):
item = QgsAnnotationMarkerItem(QgsPoint(12, 13))
self.assertEqual(item.geometry().asWkt(), 'POINT(12 13)')
Expand Down
5 changes: 5 additions & 0 deletions tests/src/python/test_qgsannotationpointtextitem.py
Expand Up @@ -38,6 +38,7 @@
QgsVertexId,
QgsAnnotationItemEditOperationMoveNode,
QgsAnnotationItemEditOperationDeleteNode,
QgsAnnotationItemEditOperationAddNode,
QgsAnnotationItemEditOperationTranslateItem,
QgsPoint
)
Expand Down Expand Up @@ -128,6 +129,10 @@ def test_apply_delete_node_edit(self):

self.assertEqual(item.applyEdit(QgsAnnotationItemEditOperationDeleteNode('', QgsVertexId(0, 0, 0), QgsPoint(12, 13))), Qgis.AnnotationItemEditOperationResult.ItemCleared)

def test_apply_add_node_edit(self):
item = QgsAnnotationPointTextItem('my text', QgsPointXY(12, 13))
self.assertEqual(item.applyEdit(QgsAnnotationItemEditOperationAddNode('', QgsPoint(13, 14))), Qgis.AnnotationItemEditOperationResult.Invalid)

def testReadWriteXml(self):
doc = QDomDocument("testdoc")
elem = doc.createElement('test')
Expand Down
11 changes: 10 additions & 1 deletion tests/src/python/test_qgsannotationpolygonitem.py
Expand Up @@ -41,7 +41,8 @@
QgsVertexId,
QgsAnnotationItemEditOperationMoveNode,
QgsAnnotationItemEditOperationDeleteNode,
QgsAnnotationItemEditOperationTranslateItem
QgsAnnotationItemEditOperationTranslateItem,
QgsAnnotationItemEditOperationAddNode
)
from qgis.PyQt.QtXml import QDomDocument

Expand Down Expand Up @@ -121,6 +122,14 @@ def test_apply_delete_node_edit(self):
self.assertEqual(item.applyEdit(QgsAnnotationItemEditOperationDeleteNode('', QgsVertexId(0, 0, 0), QgsPoint(12, 13))), Qgis.AnnotationItemEditOperationResult.ItemCleared)
self.assertEqual(item.geometry().asWkt(), 'Polygon EMPTY')

def test_apply_add_node_edit(self):
item = QgsAnnotationPolygonItem(
QgsPolygon(QgsLineString([QgsPoint(12, 13), QgsPoint(14, 13), QgsPoint(14, 15), QgsPoint(14.5, 15.5), QgsPoint(14.5, 16.5), QgsPoint(14.5, 17.5), QgsPoint(12, 13)])))
self.assertEqual(item.geometry().asWkt(), 'Polygon ((12 13, 14 13, 14 15, 14.5 15.5, 14.5 16.5, 14.5 17.5, 12 13))')

self.assertEqual(item.applyEdit(QgsAnnotationItemEditOperationAddNode('', QgsPoint(15, 16))), Qgis.AnnotationItemEditOperationResult.Success)
self.assertEqual(item.geometry().asWkt(), 'Polygon ((12 13, 14 13, 14 15, 14.5 15.5, 15 16, 14.5 16.5, 14.5 17.5, 12 13))')

def test_transient_move_operation(self):
item = QgsAnnotationPolygonItem(
QgsPolygon(QgsLineString([QgsPoint(12, 13), QgsPoint(14, 13), QgsPoint(14, 15), QgsPoint(12, 13)])))
Expand Down

0 comments on commit 4cb06c0

Please sign in to comment.