Skip to content
Permalink
Browse files
Add method to apply a annotation item edit operation directly
onto a QgsAnnotationLayer
  • Loading branch information
nyalldawson committed Sep 10, 2021
1 parent 6313432 commit 1fe874315a71a9d503c80723bfc2fbed1898a9b7
@@ -11,6 +11,7 @@




class QgsAnnotationLayer : QgsMapLayer
{
%Docstring(signature="appended")
@@ -116,6 +117,15 @@ rendered using the given render ``context``.

The optional ``feedback`` argument can be used to cancel the search early.

.. versionadded:: 3.22
%End

bool applyEdit( QgsAbstractAnnotationItemEditOperation *operation );
%Docstring
Applies an edit ``operation`` to the layer.

Returns ``True`` if the operation was successfully applied.

.. versionadded:: 3.22
%End

@@ -23,6 +23,7 @@
#include "qgspainting.h"
#include "qgsmaplayerfactory.h"
#include "qgsfeedback.h"
#include "qgsannotationitemeditoperation.h"
#include <QUuid>
#include "RTree.h"

@@ -231,6 +232,30 @@ QStringList QgsAnnotationLayer::itemsInBounds( const QgsRectangle &bounds, QgsRe
return res;
}

bool QgsAnnotationLayer::applyEdit( QgsAbstractAnnotationItemEditOperation *operation )
{
bool res = false;
if ( QgsAnnotationItem *targetItem = item( operation->itemId() ) )
{
// remove item from index if present
auto it = mNonIndexedItems.find( operation->itemId() );
if ( it == mNonIndexedItems.end() )
{
mSpatialIndex->remove( operation->itemId(), targetItem->boundingBox() );
}
res = targetItem->applyEdit( operation );

// and re-add to index if possible
if ( !( targetItem->flags() & Qgis::AnnotationItemFlag::ScaleDependentBoundingBox ) )
mSpatialIndex->insert( operation->itemId(), targetItem->boundingBox() );
}

if ( res )
triggerRepaint();

return res;
}

Qgis::MapLayerProperties QgsAnnotationLayer::properties() const
{
// annotation layers are always editable
@@ -24,6 +24,8 @@


class QgsAnnotationItem;
class QgsAbstractAnnotationItemEditOperation;

///@cond PRIVATE
class QgsAnnotationLayerSpatialIndex;
///@endcond
@@ -146,6 +148,15 @@ class CORE_EXPORT QgsAnnotationLayer : public QgsMapLayer
*/
QStringList itemsInBounds( const QgsRectangle &bounds, QgsRenderContext &context, QgsFeedback *feedback = nullptr ) const;

/**
* Applies an edit \a operation to the layer.
*
* Returns TRUE if the operation was successfully applied.
*
* \since QGIS 3.22
*/
bool applyEdit( QgsAbstractAnnotationItemEditOperation *operation );

Qgis::MapLayerProperties properties() const override;
QgsAnnotationLayer *clone() const override SIP_FACTORY;
QgsMapLayerRenderer *createMapRenderer( QgsRenderContext &rendererContext ) override SIP_FACTORY;
@@ -40,7 +40,11 @@
QgsMarkerSymbol,
QgsMapRendererSequentialJob,
QgsMapRendererParallelJob,
QgsGeometry
QgsGeometry,
QgsAbstractAnnotationItemEditOperation,
QgsAnnotationItemEditOperationMoveNode,
QgsVertexId,
QgsPointXY
)
from qgis.testing import start_app, unittest

@@ -259,6 +263,37 @@ def testProjectMainAnnotationLayer(self):
self.assertIsInstance(p2.mainAnnotationLayer().items()[linestring_item_id], QgsAnnotationLineItem)
self.assertIsInstance(p2.mainAnnotationLayer().items()[marker_item_id], QgsAnnotationMarkerItem)

def test_apply_edit(self):
"""
Test applying edits to a layer
"""
layer = QgsAnnotationLayer('test', QgsAnnotationLayer.LayerOptions(QgsProject.instance().transformContext()))
self.assertTrue(layer.isValid())

polygon_item_id = layer.addItem(QgsAnnotationPolygonItem(
QgsPolygon(QgsLineString([QgsPoint(12, 13), QgsPoint(14, 13), QgsPoint(14, 15), QgsPoint(12, 13)]))))
linestring_item_id = layer.addItem(
QgsAnnotationLineItem(QgsLineString([QgsPoint(11, 13), QgsPoint(12, 13), QgsPoint(12, 15)])))
marker_item_id = layer.addItem(QgsAnnotationMarkerItem(QgsPoint(12, 13)))

rc = QgsRenderContext()
self.assertCountEqual(layer.itemsInBounds(QgsRectangle(1, 1, 20, 20), rc), [polygon_item_id, linestring_item_id, marker_item_id])

# can't apply the abstract operation to a layer
self.assertFalse(layer.applyEdit(QgsAbstractAnnotationItemEditOperation(polygon_item_id)))

# can't apply a move to an item which doesn't exist in the layer
self.assertFalse(layer.applyEdit(QgsAnnotationItemEditOperationMoveNode('xxx', QgsVertexId(0, 0, 2), QgsPointXY(14, 15), QgsPointXY(19, 15))))

# apply move to polygon
self.assertTrue(layer.applyEdit(
QgsAnnotationItemEditOperationMoveNode(polygon_item_id, QgsVertexId(0, 0, 2), QgsPointXY(14, 15),
QgsPointXY(19, 15))))

self.assertEqual(layer.item(polygon_item_id).geometry().asWkt(), 'Polygon ((12 13, 14 13, 19 15, 12 13))')
# ensure that spatial index was updated
self.assertCountEqual(layer.itemsInBounds(QgsRectangle(18, 1, 20, 16), rc), [polygon_item_id])

def testRenderLayer(self):
layer = QgsAnnotationLayer('test', QgsAnnotationLayer.LayerOptions(QgsProject.instance().transformContext()))
layer.setCrs(QgsCoordinateReferenceSystem('EPSG:4326'))

0 comments on commit 1fe8743

Please sign in to comment.