QGIS API Documentation 3.99.0-Master (1d785854362)
Loading...
Searching...
No Matches
qgsmaptoolselectannotation.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsmaptoolselectannotation.cpp
3 ----------------
4 copyright : (C) 2025 by Mathieu Pellerin
5 email : mathieu at opengis dot ch
6 ***************************************************************************/
7
8/***************************************************************************
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 ***************************************************************************/
16
18
19#include "qgsannotationitem.h"
22#include "qgsannotationlayer.h"
23#include "qgsapplication.h"
24#include "qgsmapcanvas.h"
26#include "qgsproject.h"
30#include "qgsrubberband.h"
31#include "qgssnapindicator.h"
32
33#include <QGraphicsSceneHoverEvent>
34#include <QKeySequence>
35#include <QScreen>
36#include <QTransform>
37#include <QWindow>
38
39#include "moc_qgsmaptoolselectannotation.cpp"
40
42 : QgsRubberBand( canvas, Qgis::GeometryType::Line )
43 , mLayerId( layerId )
44 , mItemId( itemId )
45{
46 setFlags( flags() | QGraphicsItem::ItemIsSelectable );
47
48 setWidth( canvas->fontMetrics().xHeight() * .2 );
49 setSecondaryStrokeColor( QColor( 255, 255, 255, 100 ) );
50 setColor( QColor( 50, 50, 50, 200 ) );
51 setZValue( 10 );
52 setSelected( false );
53}
54
56{
57 QgsAnnotationLayer *lyr = qobject_cast<QgsAnnotationLayer *>( QgsProject::instance()->mapLayer( mLayerId ) );
58 if ( !lyr && mLayerId == QgsProject::instance()->mainAnnotationLayer()->id() )
59 {
61 }
62 return lyr;
63}
64
66{
68 return lyr ? lyr->item( mItemId ) : nullptr;
69}
70
72{
73 mBoundingBox = boundingBox;
74 QgsAnnotationItem *annotationItem = item();
75 mNeedsUpdatedBoundingBox = annotationItem && ( annotationItem->flags() & Qgis::AnnotationItemFlag::ScaleDependentBoundingBox );
76
78 addPoint( QgsPointXY( boundingBox.xMinimum(), boundingBox.yMinimum() ) );
79 addPoint( QgsPointXY( boundingBox.xMaximum(), boundingBox.yMinimum() ) );
80 addPoint( QgsPointXY( boundingBox.xMaximum(), boundingBox.yMaximum() ) );
81 addPoint( QgsPointXY( boundingBox.xMinimum(), boundingBox.yMaximum() ) );
82 addPoint( QgsPointXY( boundingBox.xMinimum(), boundingBox.yMinimum() ) );
83
84 show();
85 setSelected( true );
86}
87
92
93
101
103{
104 mSelectionRubberBand.reset();
105 mMouseHandles.reset();
106}
107
109{
110 mMouseHandles.reset( new QgsMapToolSelectAnnotationMouseHandles( this, mCanvas ) );
111
113}
114
116{
117 mSelectionRubberBand.reset();
118 mMouseHandles.reset();
119
120 mSelectedItems.clear();
121
122 mCopiedItems.clear();
123 mCopiedItemsTopLeft = QPointF();
124
126}
127
129{
130 const QPointF scenePos = mCanvas->mapToScene( event->pos() );
131
132 if ( event->buttons() == Qt::NoButton )
133 {
134 if ( mMouseHandles->isDragging() )
135 {
136 QGraphicsSceneMouseEvent forwardedEvent( QEvent::GraphicsSceneMouseMove );
137 forwardedEvent.setPos( mMouseHandles->mapFromScene( scenePos ) );
138 forwardedEvent.setScenePos( scenePos );
139 forwardedEvent.setLastScenePos( mLastScenePos );
140 forwardedEvent.setButton( Qt::LeftButton );
141 mMouseHandles->mouseMoveEvent( &forwardedEvent );
142 }
143 else
144 {
145 if ( mMouseHandles->sceneBoundingRect().contains( scenePos ) )
146 {
147 QGraphicsSceneHoverEvent forwardedEvent( QEvent::GraphicsSceneHoverMove );
148 forwardedEvent.setPos( mMouseHandles->mapFromScene( scenePos ) );
149 forwardedEvent.setScenePos( scenePos );
150 mMouseHandles->hoverMoveEvent( &forwardedEvent );
151 mHoveringMouseHandles = true;
152 }
153 else if ( mHoveringMouseHandles )
154 {
155 QGraphicsSceneHoverEvent forwardedEvent( QEvent::GraphicsSceneHoverLeave );
156 forwardedEvent.setPos( mMouseHandles->mapFromScene( scenePos ) );
157 forwardedEvent.setScenePos( scenePos );
158 mMouseHandles->hoverMoveEvent( &forwardedEvent );
159 mHoveringMouseHandles = false;
160 }
161 }
162 }
163 else if ( event->buttons() == Qt::LeftButton )
164 {
165 if ( mMouseHandles->shouldBlockEvent( event ) )
166 {
167 QGraphicsSceneMouseEvent forwardedEvent( QEvent::GraphicsSceneMouseMove );
168 forwardedEvent.setPos( mMouseHandles->mapFromScene( scenePos ) );
169 forwardedEvent.setScenePos( scenePos );
170 forwardedEvent.setLastScenePos( mLastScenePos );
171 forwardedEvent.setButton( Qt::LeftButton );
172 mMouseHandles->mouseMoveEvent( &forwardedEvent );
173 }
174 else
175 {
176 if ( !mDragging )
177 {
178 mDragging = true;
179 mSelectionRubberBand.reset( new QgsRubberBand( mCanvas, Qgis::GeometryType::Polygon ) );
180 QColor color( Qt::blue );
181 color.setAlpha( 63 );
182 mSelectionRubberBand->setColor( color );
183 mSelectionRect.setTopLeft( event->pos() );
184 }
185
186 mSelectionRect.setBottomRight( event->pos() );
187 if ( mSelectionRubberBand )
188 {
189 mSelectionRubberBand->setToCanvasRectangle( mSelectionRect );
190 mSelectionRubberBand->show();
191 }
192 }
193 }
194
195 mLastScenePos = scenePos;
196}
197
199{
200 if ( event->button() != Qt::LeftButton )
201 {
202 return;
203 }
204
205 QPointF scenePos = mCanvas->mapToScene( event->pos() );
206 const bool toggleSelection = event->modifiers() & Qt::ShiftModifier;
207
208 if ( !toggleSelection && !mSelectedItems.empty() && mMouseHandles->sceneBoundingRect().contains( scenePos ) )
209 {
210 QGraphicsSceneMouseEvent forwardedEvent( QEvent::GraphicsSceneMousePress );
211 forwardedEvent.setPos( mMouseHandles->mapFromScene( scenePos ) );
212 forwardedEvent.setScenePos( scenePos );
213 forwardedEvent.setLastScenePos( mLastScenePos );
214 forwardedEvent.setButton( Qt::LeftButton );
215 mMouseHandles->mousePressEvent( &forwardedEvent );
216 }
217 else
218 {
219 mSelectionRect.setTopLeft( event->pos() );
220 mSelectionRect.setBottomRight( event->pos() );
221 }
222
223 mLastScenePos = scenePos;
224}
225
227{
228 if ( event->button() != Qt::LeftButton )
229 {
230 return;
231 }
232
233 QPointF scenePos = mCanvas->mapToScene( event->pos() );
234
235 if ( mMouseHandles->shouldBlockEvent( event ) )
236 {
237 QGraphicsSceneMouseEvent forwardedEvent( QEvent::GraphicsSceneMouseRelease );
238 forwardedEvent.setPos( mMouseHandles->mapFromScene( scenePos ) );
239 forwardedEvent.setScenePos( scenePos );
240 forwardedEvent.setLastScenePos( mLastScenePos );
241 forwardedEvent.setButton( Qt::LeftButton );
242 mMouseHandles->mouseReleaseEvent( &forwardedEvent );
243 }
244 else
245 {
246 if ( mCanceled )
247 {
248 mCanceled = false;
249 mDragging = false;
250 return;
251 }
252
253 if ( mDragging )
254 {
255 mDragging = false;
256 mSelectionRubberBand.reset();
257
258 const QgsPointXY topLeft = toMapCoordinates( mSelectionRect.topLeft() );
259 const QgsPointXY bottomRight = toMapCoordinates( mSelectionRect.bottomRight() );
260 const QgsRectangle searchRect( topLeft, bottomRight );
261
262 setSelectedItemsFromRect( searchRect, ( event->modifiers() & Qt::ShiftModifier ) );
263 }
264 else
265 {
266 setSelectedItemFromPoint( event->mapPoint(), ( event->modifiers() & Qt::ShiftModifier ) );
267 }
268
269 mMouseHandles->setSelected( !mSelectedItems.empty() );
270 }
271}
272
274{
275 if ( mMouseHandles->isDragging() || mMouseHandles->isResizing() || mMouseHandles->isRotating() )
276 {
277 return;
278 }
279
280 if ( mSelectedItems.empty() )
281 {
282 return;
283 }
284
285 if ( event->key() == Qt::Key_Backspace || event->key() == Qt::Key_Delete )
286 {
287 while ( !mSelectedItems.empty() )
288 {
289 if ( QgsAnnotationLayer *annotationLayer = mSelectedItems.back()->layer() )
290 {
291 annotationLayer->removeItem( mSelectedItems.back()->itemId() );
292 }
293 mSelectedItems.pop_back();
294 }
296 updateSelectedItem();
297 event->ignore();
298 }
299 else if ( event->key() == Qt::Key_Left
300 || event->key() == Qt::Key_Right
301 || event->key() == Qt::Key_Up
302 || event->key() == Qt::Key_Down )
303 {
304 const int pixels = ( event->modifiers() & Qt::ShiftModifier ) ? 1 : 50;
305 int deltaX = 0;
306 int deltaY = 0;
307 if ( event->key() == Qt::Key_Up )
308 {
309 deltaY = -pixels;
310 }
311 else if ( event->key() == Qt::Key_Down )
312 {
313 deltaY = pixels;
314 }
315 else if ( event->key() == Qt::Key_Left )
316 {
317 deltaX = -pixels;
318 }
319 else if ( event->key() == Qt::Key_Right )
320 {
321 deltaX = pixels;
322 }
323
324 for ( std::unique_ptr<QgsAnnotationItemRubberBand> &selectedItem : mSelectedItems )
325 {
326 attemptMoveBy( selectedItem.get(), deltaX, deltaY );
327 }
328 event->ignore();
329 }
330}
331
333{
334 if ( mMouseHandles->isDragging() || mMouseHandles->isResizing() || mMouseHandles->isRotating() )
335 {
336 return true;
337 }
338 // NOLINTBEGIN(bugprone-narrowing-conversions)
339 QKeySequence keySequence( event->key() | event->modifiers() );
340 // NOLINTEND(bugprone-narrowing-conversions)
341 if ( keySequence == QKeySequence::Copy || keySequence == QKeySequence::Cut )
342 {
343 mCopiedItems.clear();
344 mCopiedItemsTopLeft = toMapCoordinates( QPoint( mMouseHandles->sceneBoundingRect().topLeft().x(), mMouseHandles->sceneBoundingRect().topLeft().y() ) );
345 for ( std::unique_ptr<QgsAnnotationItemRubberBand> &selectedItem : mSelectedItems )
346 {
347 if ( QgsAnnotationItem *annotationItem = selectedItem->item() )
348 {
349 std::unique_ptr<QgsAnnotationItem> copiedItem;
350 copiedItem.reset( annotationItem->clone() );
351 mCopiedItems.push_back( std::move( copiedItem ) );
352 }
353 }
354
355 if ( keySequence == QKeySequence::Cut )
356 {
357 while ( !mSelectedItems.empty() )
358 {
359 if ( QgsAnnotationLayer *annotationLayer = mSelectedItems.back()->layer() )
360 {
361 annotationLayer->removeItem( mSelectedItems.back()->itemId() );
362 }
363 mSelectedItems.pop_back();
364 }
366 }
367
368 return true;
369 }
370 else if ( keySequence == QKeySequence::Paste )
371 {
372 const QgsPointXY copiedItemsSceneTopLeft = mCanvas->mapSettings().mapToPixel().transform( mCopiedItemsTopLeft );
373 const double deltaX = mLastScenePos.x() - copiedItemsSceneTopLeft.x();
374 const double deltaY = mLastScenePos.y() - copiedItemsSceneTopLeft.y();
375 if ( !mSelectedItems.empty() )
376 {
377 mSelectedItems.clear();
378 }
379
380 for ( std::unique_ptr<QgsAnnotationItem> &copiedItem : mCopiedItems )
381 {
382 QgsAnnotationLayer *annotationLayer = dynamic_cast<QgsAnnotationLayer *>( layer() );
383 if ( !annotationLayer )
384 {
385 annotationLayer = QgsProject::instance()->mainAnnotationLayer();
386 }
387 QString pastedItemId = annotationLayer->addItem( copiedItem->clone() );
388 mSelectedItems.push_back( std::make_unique<QgsAnnotationItemRubberBand>( annotationLayer->id(), pastedItemId, mCanvas ) );
389 attemptMoveBy( mSelectedItems.back().get(), deltaX, deltaY );
390 mSelectedItems.back().get()->setNeedsUpdatedBoundingBox( true );
391 }
393
394 return true;
395 }
396
397 return false;
398}
399
400QList<QgsAnnotationItemRubberBand *> QgsMapToolSelectAnnotation::selectedItems() const
401{
402 QList<QgsAnnotationItemRubberBand *> items;
403 for ( const std::unique_ptr<QgsAnnotationItemRubberBand> &selectedItem : mSelectedItems )
404 {
405 if ( !selectedItem.get()->boundingBox().isEmpty() )
406 {
407 items << selectedItem.get();
408 }
409 }
410 return items;
411}
412
413void QgsMapToolSelectAnnotation::onCanvasRefreshed()
414{
415 const QgsRenderedItemResults *renderedItemResults = canvas()->renderedItemResults( false );
416 if ( !renderedItemResults )
417 {
418 return;
419 }
420
421 const QList<QgsRenderedItemDetails *> items = renderedItemResults->renderedItems();
422 bool needsSelectedItemsUpdate = false;
423 for ( std::unique_ptr<QgsAnnotationItemRubberBand> &selectedItem : mSelectedItems )
424 {
425 if ( selectedItem->needsUpdatedBoundingBox() )
426 {
427 needsSelectedItemsUpdate = true;
428
429 auto it = std::find_if( items.begin(), items.end(), [&selectedItem]( const QgsRenderedItemDetails *item ) {
430 if ( const QgsRenderedAnnotationItemDetails *annotationItem = dynamic_cast<const QgsRenderedAnnotationItemDetails *>( item ) )
431 {
432 if ( annotationItem->itemId() == selectedItem->itemId() && annotationItem->layerId() == selectedItem->layerId() )
433 {
434 return true;
435 }
436 }
437 return false;
438 } );
439
440 if ( it != items.end() )
441 {
442 selectedItem->updateBoundingBox( ( *it )->boundingBox() );
443 }
444 }
445 }
446
447 if ( needsSelectedItemsUpdate )
448 {
449 emit selectedItemsChanged();
450 }
451}
452
453long long QgsMapToolSelectAnnotation::annotationItemRubberBandIndexFromId( const QString &layerId, const QString &itemId )
454{
455 if ( mSelectedItems.empty() )
456 {
457 return -1;
458 }
459
460 auto it = std::find_if( mSelectedItems.begin(), mSelectedItems.end(), [&layerId, &itemId]( auto &item ) { return item->layerId() == layerId && item->itemId() == itemId; } );
461 return it != mSelectedItems.end() ? std::distance( mSelectedItems.begin(), it ) : -1;
462}
463
464void QgsMapToolSelectAnnotation::setSelectedItemsFromRect( const QgsRectangle &mapRect, bool toggleSelection )
465{
466 const QgsRenderedItemResults *renderedItemResults = canvas()->renderedItemResults( false );
467 if ( !renderedItemResults )
468 {
469 if ( !toggleSelection )
470 {
471 clearSelectedItems();
472 }
473 return;
474 }
475
476 const QList<const QgsRenderedAnnotationItemDetails *> items = renderedItemResults->renderedAnnotationItemsInBounds( mapRect );
477 if ( items.empty() )
478 {
479 if ( !toggleSelection )
480 {
481 clearSelectedItems();
482 }
483 return;
484 }
485
486 if ( !toggleSelection )
487 {
488 mSelectedItems.clear();
489 }
490 for ( const QgsRenderedAnnotationItemDetails *item : items )
491 {
492 QgsAnnotationItem *annotationItem = annotationItemFromId( item->layerId(), item->itemId() );
493 if ( annotationItem )
494 {
495 if ( toggleSelection )
496 {
497 long long index = annotationItemRubberBandIndexFromId( item->layerId(), item->itemId() );
498 if ( index >= 0 )
499 {
500 mSelectedItems.erase( mSelectedItems.begin() + index );
501 continue;
502 }
503 }
504 mSelectedItems.push_back( std::make_unique<QgsAnnotationItemRubberBand>( item->layerId(), item->itemId(), mCanvas ) );
505 mSelectedItems.back()->updateBoundingBox( item->boundingBox() );
506 }
507 }
509 updateSelectedItem();
510}
511
512void QgsMapToolSelectAnnotation::setSelectedItemFromPoint( const QgsPointXY &mapPoint, bool toggleSelection )
513{
514 QgsRectangle searchRect = QgsRectangle( mapPoint.x(), mapPoint.y(), mapPoint.x(), mapPoint.y() );
515 searchRect.grow( searchRadiusMU( canvas() ) );
516
517 const QgsRenderedItemResults *renderedItemResults = canvas()->renderedItemResults( false );
518 if ( !renderedItemResults )
519 {
520 clearSelectedItems();
521 return;
522 }
523
524 const QList<const QgsRenderedAnnotationItemDetails *> items = renderedItemResults->renderedAnnotationItemsInBounds( searchRect );
525 if ( items.empty() )
526 {
527 if ( !toggleSelection )
528 {
529 clearSelectedItems();
530 }
531 return;
532 }
533
534 QgsRectangle itemBounds;
535 const QgsRenderedAnnotationItemDetails *closestItem = findClosestItemToPoint( mapPoint, items, itemBounds );
536 if ( !closestItem )
537 {
538 if ( !toggleSelection )
539 {
540 clearSelectedItems();
541 }
542 return;
543 }
544
545 long long index = annotationItemRubberBandIndexFromId( closestItem->layerId(), closestItem->itemId() );
546 if ( index >= 0 )
547 {
548 if ( toggleSelection )
549 {
550 mSelectedItems.erase( mSelectedItems.begin() + index );
551 }
552 }
553 else
554 {
555 if ( !toggleSelection )
556 {
557 mSelectedItems.clear();
558 }
559
560 mSelectedItems.push_back( std::make_unique<QgsAnnotationItemRubberBand>( closestItem->layerId(), closestItem->itemId(), mCanvas ) );
561 mSelectedItems.back()->updateBoundingBox( closestItem->boundingBox() );
562 }
564 updateSelectedItem();
565}
566
567void QgsMapToolSelectAnnotation::updateSelectedItem()
568{
569 if ( mSelectedItems.size() > 1 )
570 {
572 }
573 else if ( mSelectedItems.size() == 1 )
574 {
575 emit singleItemSelected( mSelectedItems[0]->layer(), mSelectedItems[0]->itemId() );
576 }
577 else
578 {
579 emit selectionCleared();
580 }
581}
582
583void QgsMapToolSelectAnnotation::clearSelectedItems()
584{
585 const bool hadSelection = !mSelectedItems.empty();
586 mSelectedItems.clear();
587
588 if ( hadSelection )
589 {
591 updateSelectedItem();
592 }
593}
594
595void QgsMapToolSelectAnnotation::attemptMoveBy( QgsAnnotationItemRubberBand *annotationItemRubberBand, double deltaX, double deltaY )
596{
597 if ( QgsAnnotationItem *annotationItem = annotationItemRubberBand->item() )
598 {
599 QgsRectangle boundingBox = annotationItemRubberBand->boundingBox();
600 const double mupp = mCanvas->mapSettings().mapUnitsPerPixel();
601 QgsVector translation( deltaX * mupp, -deltaY * mupp );
602 QgsAnnotationLayer *annotationLayer = annotationItemRubberBand->layer();
603
605 context.setCurrentItemBounds( boundingBox );
607
608 const QList<QgsAnnotationItemNode> itemNodes = annotationItem->nodesV2( context );
609 for ( const QgsAnnotationItemNode &node : itemNodes )
610 {
611 QgsPointXY mapPoint = mCanvas->mapSettings().layerToMapCoordinates( annotationLayer, node.point() );
612 mapPoint += translation;
613 QgsPointXY modifiedPoint = mCanvas->mapSettings().mapToLayerCoordinates( annotationLayer, mapPoint );
614
615 QgsAnnotationItemEditOperationMoveNode operation( annotationItemRubberBand->itemId(), node.id(), QgsPoint( node.point() ), QgsPoint( modifiedPoint ) );
616 switch ( annotationLayer->applyEditV2( &operation, context ) )
617 {
620 annotationItemRubberBand->setNeedsUpdatedBoundingBox( true );
621 break;
622
625 break;
626 }
627 }
628 boundingBox += translation;
629 annotationItemRubberBand->updateBoundingBox( boundingBox );
630 }
631}
632
633void QgsMapToolSelectAnnotation::attemptRotateBy( QgsAnnotationItemRubberBand *annotationItemRubberBand, double deltaDegree )
634{
635 if ( QgsAnnotationLayer *annotationLayer = annotationItemRubberBand->layer() )
636 {
637 const QgsRectangle boundingBox = mCanvas->mapSettings().mapToLayerCoordinates( annotationLayer, annotationItemRubberBand->boundingBox() );
639 context.setCurrentItemBounds( boundingBox );
641
642 QgsAnnotationItemEditOperationRotateItem operation( annotationItemRubberBand->itemId(), deltaDegree );
643 switch ( annotationLayer->applyEditV2( &operation, context ) )
644 {
647 annotationItemRubberBand->setNeedsUpdatedBoundingBox( true );
648 break;
649
652 break;
653 }
654 }
655}
656
657void QgsMapToolSelectAnnotation::attemptSetSceneRect( QgsAnnotationItemRubberBand *annotationItemRubberBand, const QRectF &rect )
658{
659 if ( QgsAnnotationItem *annotationItem = annotationItemRubberBand->item() )
660 {
661 const double widthRatio = rect.width() / annotationItemRubberBand->boundingRect().width();
662 const double heightRatio = rect.height() / annotationItemRubberBand->boundingRect().height();
663 const double deltaX = rect.x() - annotationItemRubberBand->x() + 1;
664 const double deltaY = rect.y() - annotationItemRubberBand->y() + 1;
665 attemptMoveBy( annotationItemRubberBand, deltaX, deltaY );
666
667 QgsAnnotationLayer *annotationLayer = annotationItemRubberBand->layer();
668 const QgsRectangle boundingBox = mCanvas->mapSettings().mapToLayerCoordinates( annotationLayer, annotationItemRubberBand->boundingBox() );
669 const QgsRectangle modifiedBoundingBox( boundingBox.xMinimum(), boundingBox.yMaximum() - boundingBox.height() * heightRatio, boundingBox.xMinimum() + boundingBox.width() * widthRatio, boundingBox.yMaximum() );
670
672 context.setCurrentItemBounds( boundingBox );
674
675 const QList<QgsAnnotationItemNode> itemNodes = annotationItem->nodesV2( context );
676 for ( const QgsAnnotationItemNode &node : itemNodes )
677 {
678 const double modifiedX = modifiedBoundingBox.xMinimum() + modifiedBoundingBox.width() * ( ( node.point().x() - boundingBox.xMinimum() ) / boundingBox.width() );
679 const double modifiedY = modifiedBoundingBox.yMaximum() - modifiedBoundingBox.height() * ( ( boundingBox.yMaximum() - node.point().y() ) / boundingBox.height() );
680 QgsPointXY modifiedPoint( modifiedX, modifiedY );
681 QgsAnnotationItemEditOperationMoveNode operation( annotationItemRubberBand->itemId(), node.id(), QgsPoint( node.point() ), QgsPoint( modifiedPoint ) );
682 switch ( annotationLayer->applyEditV2( &operation, context ) )
683 {
686 annotationItemRubberBand->setNeedsUpdatedBoundingBox( true );
687 break;
688
691 break;
692 }
693 }
694 }
695}
Provides global constants and enumerations for use throughout the application.
Definition qgis.h:59
@ ScaleDependentBoundingBox
Item's bounding box will vary depending on map scale.
Definition qgis.h:2523
@ Invalid
Operation has invalid parameters for the item, no change occurred.
Definition qgis.h:2579
@ Success
Item was modified successfully.
Definition qgis.h:2578
@ ItemCleared
The operation results in the item being cleared, and the item should be removed from the layer as a r...
Definition qgis.h:2580
@ Line
Lines.
Definition qgis.h:367
@ Polygon
Polygons.
Definition qgis.h:368
A dockable widget used to handle the CAD tools on top of a selection of map tools.
Encapsulates the context for an annotation item edit operation.
void setCurrentItemBounds(const QgsRectangle &bounds)
Sets the current rendered bounds of the item, in the annotation layer's CRS.
void setRenderContext(const QgsRenderContext &context)
Sets the render context associated with the edit operation.
Annotation item edit operation consisting of moving a node.
Annotation item edit operation consisting of rotating an item.
Contains information about a node used for editing an annotation item.
An annotation item rubberband used by QgsMapToolSelectAnnotation to represent selected items.
bool needsUpdatedBoundingBox() const
Returns true if the bounding box requires updating on fresh annotation item rendering.
QgsRectangle boundingBox() const
Returns the item bounding box.
QString itemId() const
Returns the annotation item ID.
QgsAnnotationItemRubberBand(const QString &layerId, const QString &itemId, QgsMapCanvas *canvas)
Constructor for QgsAnnotationItemRubberBand.
QgsAnnotationItem * item() const
Returns a pointer to the annotation item.
QgsAnnotationLayer * layer() const
Returns a pointer to the annotation layer.
void updateBoundingBox(const QgsRectangle &boundingBox)
Update the rubberband using the provided annotation item bounding box.
QString layerId() const
Returns the annotation layer ID.
void setNeedsUpdatedBoundingBox(bool needsUpdatedBoundingBox)
Sets whether the bounding box requires updating on fresh annotation item rendering.
Abstract base class for annotation items which are drawn with QgsAnnotationLayers.
virtual QList< QgsAnnotationItemNode > nodesV2(const QgsAnnotationItemEditContext &context) const
Returns the nodes for the item, used for editing the item.
virtual Qgis::AnnotationItemFlags flags() const
Returns item flags.
Represents a map layer containing a set of georeferenced annotations, e.g.
Qgis::AnnotationItemEditOperationResult applyEditV2(QgsAbstractAnnotationItemEditOperation *operation, const QgsAnnotationItemEditContext &context)
Applies an edit operation to the layer.
QString addItem(QgsAnnotationItem *item)
Adds an item to the layer.
QgsAnnotationItem * item(const QString &id) const
Returns the item with the specified id, or nullptr if no matching item was found.
QgsAnnotationMapTool(QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDockWidget)
Constructor for QgsAnnotationMapTool.
const QgsRenderedAnnotationItemDetails * findClosestItemToPoint(const QgsPointXY &mapPoint, const QList< const QgsRenderedAnnotationItemDetails * > &items, QgsRectangle &bounds)
Returns the closest item from a list of annotation items to a given map point.
QgsAnnotationItem * annotationItemFromId(const QString &layerId, const QString &itemId)
Returns the annotation item matching a given pair of layer and item IDs.
QRectF boundingRect() const override
Map canvas is a class for displaying all GIS data types on a canvas.
const QgsRenderedItemResults * renderedItemResults(bool allowOutdatedResults=true) const
Gets access to the rendered item results (may be nullptr), which includes the results of rendering an...
void mapCanvasRefreshed()
Emitted when canvas finished a refresh request.
QString id
Definition qgsmaplayer.h:86
A mouse event which is the result of a user interaction with a QgsMapCanvas.
QgsPointXY mapPoint() const
mapPoint returns the point in coordinates
void deactivate() override
Unregisters this maptool from the cad dock widget.
virtual QgsMapLayer * layer() const
Returns the layer associated with the map tool.
QgsAdvancedDigitizingDockWidget * cadDockWidget() const
void setAdvancedDigitizingAllowed(bool allowed)
Sets whether functionality of advanced digitizing dock widget is currently allowed.
void activate() override
Registers this maptool with the cad dock widget.
QList< QgsAnnotationItemRubberBand * > selectedItems() const
Returns the current list of selected annotation item rubberband items.
void cadCanvasReleaseEvent(QgsMapMouseEvent *event) override
Override this method when subclassing this class.
void singleItemSelected(QgsAnnotationLayer *layer, const QString &itemId)
Emitted when the selected items list has changed and a single item is selected.
void attemptRotateBy(QgsAnnotationItemRubberBand *annotationItemRubberBand, double deltaDegree)
Attempts to rotate am annotation item.
void keyPressEvent(QKeyEvent *event) override
Key event for overriding. Default implementation does nothing.
void activate() override
Registers this maptool with the cad dock widget.
void attemptSetSceneRect(QgsAnnotationItemRubberBand *annotationItemRubberBand, const QRectF &rect)
Attempts to move and resize an annotation item.
QgsMapToolSelectAnnotation(QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDockWidget)
Constructor for QgsMapToolSelectAnnotation.
void multipleItemsSelected()
Emitted when the selected items list has changed and multiple items are selected.
void cadCanvasMoveEvent(QgsMapMouseEvent *event) override
Override this method when subclassing this class.
void attemptMoveBy(QgsAnnotationItemRubberBand *annotationItemRubberBand, double deltaX, double deltaY)
Attempts to move an annotation item.
void cadCanvasPressEvent(QgsMapMouseEvent *event) override
Override this method when subclassing this class.
void selectedItemsChanged()
Emitted when the selected items list has changed.
void selectionCleared()
Emitted when the selected items list is cleared.
void deactivate() override
Unregisters this maptool from the cad dock widget.
bool shortcutEvent(QKeyEvent *event) override
Shortcut events coming from the application for overriding.
QgsMapCanvas * canvas() const
returns pointer to the tool's map canvas
QgsPointXY toMapCoordinates(QPoint point)
Transforms a point from screen coordinates to map coordinates.
QPointer< QgsMapCanvas > mCanvas
The pointer to the map canvas.
Definition qgsmaptool.h:369
static double searchRadiusMU(const QgsRenderContext &context)
Gets search radius in map units for given context.
Represents a 2D point.
Definition qgspointxy.h:62
double y
Definition qgspointxy.h:66
double x
Definition qgspointxy.h:65
Point geometry type, with support for z-dimension and m-values.
Definition qgspoint.h:53
static QgsProject * instance()
Returns the QgsProject singleton instance.
QgsAnnotationLayer * mainAnnotationLayer()
Returns the main annotation layer associated with the project.
void setDirty(bool b=true)
Flag the project as dirty (modified).
A rectangle specified with double values.
double xMinimum
void grow(double delta)
Grows the rectangle in place by the specified amount.
double yMaximum
static QgsRenderContext fromMapSettings(const QgsMapSettings &mapSettings)
create initialized QgsRenderContext instance from given QgsMapSettings
QString itemId() const
Returns the item ID of the associated annotation item.
QString layerId() const
Returns the layer ID of the associated map layer.
QgsRectangle boundingBox() const
Returns the bounding box of the item (in map units).
Stores collated details of rendered items during a map rendering operation.
QList< const QgsRenderedAnnotationItemDetails * > renderedAnnotationItemsInBounds(const QgsRectangle &bounds) const
Returns a list with details of the rendered annotation items within the specified bounds.
QList< QgsRenderedItemDetails * > renderedItems() const
Returns a list of all rendered items.
Responsible for drawing transient features (e.g.
QgsRubberBand(QgsMapCanvas *mapCanvas, Qgis::GeometryType geometryType=Qgis::GeometryType::Line)
Creates a new RubberBand.
void setWidth(double width)
Sets the width of the line.
void reset(Qgis::GeometryType geometryType=Qgis::GeometryType::Line)
Clears all the geometries in this rubberband.
void setSecondaryStrokeColor(const QColor &color)
Sets a secondary stroke color for the rubberband which will be drawn under the main stroke color.
void setColor(const QColor &color)
Sets the color for the rubberband.
void addPoint(const QgsPointXY &p, bool doUpdate=true, int geometryIndex=0, int ringIndex=0)
Adds a vertex to the rubberband and update canvas.
Represent a 2-dimensional vector.
Definition qgsvector.h:34