Skip to content

Commit

Permalink
[feature] Modify annotation tool can now be used to move nodes in
Browse files Browse the repository at this point in the history
an annotation item

Left clicking over a node will start moving it, a second left
click will confirm the move. Right click cancels the move.
  • Loading branch information
nyalldawson committed Sep 10, 2021
1 parent 5ea9c63 commit a85c8cb
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 23 deletions.
128 changes: 107 additions & 21 deletions src/gui/annotations/qgsmaptoolmodifyannotation.cpp
Expand Up @@ -158,18 +158,21 @@ void QgsMapToolModifyAnnotation::cadCanvasMoveEvent( QgsMapMouseEvent *event )


// track hovered node too!... here we want to identify the closest node to the cursor position // track hovered node too!... here we want to identify the closest node to the cursor position
QgsAnnotationItemNode hoveredNode; QgsAnnotationItemNode hoveredNode;
double currentNodeDistance = std::numeric_limits< double >::max(); if ( closestItem->itemId() == mSelectedItemId && closestItem->layerId() == mSelectedItemLayerId )
mHoveredItemNodesSpatialIndex->intersects( searchRect, [&hoveredNode, &currentNodeDistance, &mapPoint, this]( int index )-> bool
{ {
const QgsAnnotationItemNode &thisNode = mHoveredItemNodes.at( index ); double currentNodeDistance = std::numeric_limits< double >::max();
const double nodeDistance = thisNode.point().sqrDist( mapPoint ); mHoveredItemNodesSpatialIndex->intersects( searchRect, [&hoveredNode, &currentNodeDistance, &mapPoint, this]( int index )-> bool
if ( nodeDistance < currentNodeDistance )
{ {
hoveredNode = thisNode; const QgsAnnotationItemNode &thisNode = mHoveredItemNodes.at( index );
currentNodeDistance = nodeDistance; const double nodeDistance = thisNode.point().sqrDist( mapPoint );
} if ( nodeDistance < currentNodeDistance )
return true; {
} ); hoveredNode = thisNode;
currentNodeDistance = nodeDistance;
}
return true;
} );
}


if ( hoveredNode.point().isEmpty() ) if ( hoveredNode.point().isEmpty() )
{ {
Expand Down Expand Up @@ -210,6 +213,28 @@ void QgsMapToolModifyAnnotation::cadCanvasMoveEvent( QgsMapMouseEvent *event )
break; break;
} }


case Action::MoveNode:
{
if ( QgsAnnotationItem *item = annotationItemFromId( mSelectedItemLayerId, mSelectedItemId ) )
{
QgsAnnotationLayer *layer = annotationLayerFromId( mSelectedItemLayerId );
const QgsPointXY endPointLayer = toLayerCoordinates( layer, event->mapPoint() );
QgsAnnotationItemEditOperationMoveNode operation( mSelectedItemId, mTargetNode.id(), mTargetNode.point(), endPointLayer );
std::unique_ptr< QgsAnnotationItemEditOperationTransientResults > operationResults( item->transientEditResults( &operation ) );
if ( operationResults )
{
mTemporaryRubberBand.reset( new QgsRubberBand( mCanvas, operationResults->representativeGeometry().type() ) );
const double scaleFactor = canvas()->fontMetrics().xHeight() * .2;
mTemporaryRubberBand->setWidth( scaleFactor );
mTemporaryRubberBand->setToGeometry( operationResults->representativeGeometry(), layer->crs() );
}
else
{
mTemporaryRubberBand.reset();
}
}
break;
}
} }


} }
Expand All @@ -232,23 +257,50 @@ void QgsMapToolModifyAnnotation::cadCanvasPressEvent( QgsMapMouseEvent *event )
// press is on selected item => move that item // press is on selected item => move that item
if ( QgsAnnotationLayer *layer = annotationLayerFromId( mSelectedItemLayerId ) ) if ( QgsAnnotationLayer *layer = annotationLayerFromId( mSelectedItemLayerId ) )
{ {
mCurrentAction = Action::MoveItem; const QgsPointXY mapPoint = event->mapPoint();
mMoveStartPointCanvasCrs = event->mapPoint(); QgsRectangle searchRect = QgsRectangle( mapPoint.x(), mapPoint.y(), mapPoint.x(), mapPoint.y() );
searchRect.grow( searchRadiusMU( canvas() ) );

QgsAnnotationItemNode hoveredNode;
double currentNodeDistance = std::numeric_limits< double >::max();
mHoveredItemNodesSpatialIndex->intersects( searchRect, [&hoveredNode, &currentNodeDistance, &mapPoint, this]( int index )-> bool
{
const QgsAnnotationItemNode &thisNode = mHoveredItemNodes.at( index );
const double nodeDistance = thisNode.point().sqrDist( mapPoint );
if ( nodeDistance < currentNodeDistance )
{
hoveredNode = thisNode;
currentNodeDistance = nodeDistance;
}
return true;
} );

mMoveStartPointCanvasCrs = mapPoint;
mMoveStartPointLayerCrs = toLayerCoordinates( layer, mMoveStartPointCanvasCrs ); mMoveStartPointLayerCrs = toLayerCoordinates( layer, mMoveStartPointCanvasCrs );
if ( mHoverRubberBand ) if ( mHoverRubberBand )
mHoverRubberBand->hide(); mHoverRubberBand->hide();
if ( mSelectedRubberBand ) if ( mSelectedRubberBand )
mSelectedRubberBand->hide(); mSelectedRubberBand->hide();


QgsAnnotationItem *item = annotationItemFromId( mSelectedItemLayerId, mSelectedItemId ); if ( hoveredNode.point().isEmpty() )
QgsGeometry rubberBandGeom = item->rubberBandGeometry(); {
if ( rubberBandGeom.isNull() ) mCurrentAction = Action::MoveItem;
rubberBandGeom = mSelectedRubberBand->asGeometry();

QgsAnnotationItem *item = annotationItemFromId( mSelectedItemLayerId, mSelectedItemId );
mTemporaryRubberBand.reset( new QgsRubberBand( mCanvas, rubberBandGeom.type() ) ); QgsGeometry rubberBandGeom = item->rubberBandGeometry();
const double scaleFactor = canvas()->fontMetrics().xHeight() * .2; if ( rubberBandGeom.isNull() )
mTemporaryRubberBand->setWidth( scaleFactor ); rubberBandGeom = mSelectedRubberBand->asGeometry();
mTemporaryRubberBand->setToGeometry( rubberBandGeom, layer->crs() );
mTemporaryRubberBand.reset( new QgsRubberBand( mCanvas, rubberBandGeom.type() ) );
const double scaleFactor = canvas()->fontMetrics().xHeight() * .2;
mTemporaryRubberBand->setWidth( scaleFactor );
mTemporaryRubberBand->setToGeometry( rubberBandGeom, layer->crs() );
}
else
{
mCurrentAction = Action::MoveNode;
mTargetNode = hoveredNode;
}
} }
} }
else else
Expand Down Expand Up @@ -305,6 +357,37 @@ void QgsMapToolModifyAnnotation::cadCanvasPressEvent( QgsMapMouseEvent *event )
} }
break; break;
} }

case Action::MoveNode:
{
if ( event->button() == Qt::RightButton )
{
mCurrentAction = Action::NoAction;
mTemporaryRubberBand.reset();
mHoveredItemNodeRubberBands.clear();
mTemporaryRubberBand.reset();
setCursor( Qt::ArrowCursor );
}
else if ( event->button() == Qt::LeftButton )
{
if ( QgsAnnotationLayer *layer = annotationLayerFromId( mSelectedItemLayerId ) )
{
const QgsPointXY endPointLayer = toLayerCoordinates( layer, event->mapPoint() );
QgsAnnotationItemEditOperationMoveNode operation( mSelectedItemId, mTargetNode.id(), mTargetNode.point(), endPointLayer );
if ( layer->applyEdit( &operation ) )
QgsProject::instance()->setDirty( true );
mRefreshSelectedItemAfterRedraw = true;
}

mTemporaryRubberBand.reset();
mHoveredItemNodeRubberBands.clear();
mHoveredItemNodes.clear();
mTemporaryRubberBand.reset();
mCurrentAction = Action::NoAction;
setCursor( Qt::ArrowCursor );
}
break;
}
} }
} }


Expand Down Expand Up @@ -349,6 +432,7 @@ void QgsMapToolModifyAnnotation::keyPressEvent( QKeyEvent *event )
} }


case Action::MoveItem: case Action::MoveItem:
case Action::MoveNode:
{ {
if ( event->key() == Qt::Key_Escape ) if ( event->key() == Qt::Key_Escape )
{ {
Expand Down Expand Up @@ -406,6 +490,8 @@ void QgsMapToolModifyAnnotation::onCanvasRefreshed()
void QgsMapToolModifyAnnotation::setHoveredItem( const QgsRenderedAnnotationItemDetails *item, const QgsRectangle &itemMapBounds ) void QgsMapToolModifyAnnotation::setHoveredItem( const QgsRenderedAnnotationItemDetails *item, const QgsRectangle &itemMapBounds )
{ {
mHoveredItemNodeRubberBands.clear(); mHoveredItemNodeRubberBands.clear();
if ( mHoveredNodeRubberBand )
mHoveredNodeRubberBand->hide();
mHoveredItemId = item->itemId(); mHoveredItemId = item->itemId();
mHoveredItemLayerId = item->layerId(); mHoveredItemLayerId = item->layerId();
if ( !mHoverRubberBand ) if ( !mHoverRubberBand )
Expand Down
7 changes: 5 additions & 2 deletions src/gui/annotations/qgsmaptoolmodifyannotation.h
Expand Up @@ -22,13 +22,13 @@
#include "qgsmaptooladvanceddigitizing.h" #include "qgsmaptooladvanceddigitizing.h"
#include "qobjectuniqueptr.h" #include "qobjectuniqueptr.h"
#include "qgspointxy.h" #include "qgspointxy.h"
#include "qgsannotationitemnode.h"


class QgsRubberBand; class QgsRubberBand;
class QgsRenderedAnnotationItemDetails; class QgsRenderedAnnotationItemDetails;
class QgsAnnotationItem; class QgsAnnotationItem;
class QgsAnnotationLayer; class QgsAnnotationLayer;
class QgsAnnotationItemNodesSpatialIndex; class QgsAnnotationItemNodesSpatialIndex;
class QgsAnnotationItemNode;


/** /**
* \ingroup gui * \ingroup gui
Expand Down Expand Up @@ -72,7 +72,8 @@ class GUI_EXPORT QgsMapToolModifyAnnotation : public QgsMapToolAdvancedDigitizin
enum class Action enum class Action
{ {
NoAction, NoAction,
MoveItem MoveItem,
MoveNode
}; };


void clearHoveredItem(); void clearHoveredItem();
Expand Down Expand Up @@ -118,6 +119,8 @@ class GUI_EXPORT QgsMapToolModifyAnnotation : public QgsMapToolAdvancedDigitizin


bool mRefreshSelectedItemAfterRedraw = false; bool mRefreshSelectedItemAfterRedraw = false;


QgsAnnotationItemNode mTargetNode;

}; };


#endif // QGSMAPTOOLMODIFYANNOTATION_H #endif // QGSMAPTOOLMODIFYANNOTATION_H

0 comments on commit a85c8cb

Please sign in to comment.