QGIS API Documentation 3.99.0-Master (d270888f95f)
Loading...
Searching...
No Matches
qgsannotationrectitem.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsannotationrectitem.cpp
3 ----------------
4 begin : July 2024
5 copyright : (C) 2024 by Nyall Dawson
6 email : nyall dot dawson at gmail dot com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
19
22#include "qgsapplication.h"
23#include "qgscalloutsregistry.h"
24#include "qgsfillsymbol.h"
25#include "qgsfillsymbollayer.h"
26#include "qgsgeometry.h"
27#include "qgslinestring.h"
28#include "qgslinesymbollayer.h"
29#include "qgspainting.h"
30#include "qgspolygon.h"
31#include "qgsrendercontext.h"
32#include "qgssymbollayerutils.h"
33#include "qgsunittypes.h"
34
35#include <QString>
36
37using namespace Qt::StringLiterals;
38
41 , mBounds( bounds )
42{
43 mBackgroundSymbol = std::make_unique< QgsFillSymbol >( QgsSymbolLayerList
44 {
45 new QgsSimpleFillSymbolLayer( QColor( 255, 255, 255 ), Qt::BrushStyle::SolidPattern, QColor( 0, 0, 0 ), Qt::PenStyle::NoPen )
46 } );
47 QgsSimpleLineSymbolLayer *borderSymbol = new QgsSimpleLineSymbolLayer( QColor( 0, 0, 0 ) );
48 borderSymbol->setPenJoinStyle( Qt::MiterJoin );
49 mFrameSymbol = std::make_unique< QgsFillSymbol >( QgsSymbolLayerList{ borderSymbol } );
50}
51
53
68
70{
71 QgsRectangle bounds = mBounds;
73 {
74 try
75 {
76 bounds = context.coordinateTransform().transformBoundingBox( mBounds );
77 }
78 catch ( QgsCsException & )
79 {
80 return;
81 }
82 }
83
84 QRectF painterBounds;
85
86 switch ( mPlacementMode )
87 {
89 painterBounds = context.mapToPixel().transformBounds( bounds.toRectF() );
90 break;
91
93 {
94 const double widthPixels = context.convertToPainterUnits( mFixedSize.width(), mFixedSizeUnit );
95 const double heightPixels = context.convertToPainterUnits( mFixedSize.height(), mFixedSizeUnit );
96
97 if ( callout() && !calloutAnchor().isEmpty() )
98 {
99 QgsGeometry anchor = calloutAnchor();
100
101 const double calloutOffsetWidthPixels = context.convertToPainterUnits( offsetFromCallout().width(), offsetFromCalloutUnit() );
102 const double calloutOffsetHeightPixels = context.convertToPainterUnits( offsetFromCallout().height(), offsetFromCalloutUnit() );
103
104 QPointF anchorPoint = anchor.asQPointF();
105 if ( context.coordinateTransform().isValid() )
106 {
107 double x = anchorPoint.x();
108 double y = anchorPoint.y();
109 double z = 0.0;
110 context.coordinateTransform().transformInPlace( x, y, z );
111 anchorPoint = QPointF( x, y );
112 }
113
114 context.mapToPixel().transformInPlace( anchorPoint.rx(), anchorPoint.ry() );
115
116 painterBounds = QRectF( anchorPoint.x() + calloutOffsetWidthPixels,
117 anchorPoint.y() + calloutOffsetHeightPixels, widthPixels, heightPixels );
118 }
119 else
120 {
121 QPointF center = bounds.center().toQPointF();
122
123 context.mapToPixel().transformInPlace( center.rx(), center.ry() );
124 painterBounds = QRectF( center.x() - widthPixels * 0.5,
125 center.y() - heightPixels * 0.5,
126 widthPixels, heightPixels );
127 }
128 break;
129 }
130
132 {
133 const double widthPixels = context.convertToPainterUnits( mFixedSize.width(), mFixedSizeUnit );
134 const double heightPixels = context.convertToPainterUnits( mFixedSize.height(), mFixedSizeUnit );
135
136 QPointF center = bounds.center().toQPointF();
137 center.rx() *= context.outputSize().width();
138 center.ry() *= context.outputSize().height();
139
140 painterBounds = QRectF( center.x() - widthPixels * 0.5,
141 center.y() - heightPixels * 0.5,
142 widthPixels, heightPixels );
143 break;
144 }
145 }
146
147 if ( painterBounds.width() < 1 || painterBounds.height() < 1 )
148 return;
149
150 if ( mDrawBackground && mBackgroundSymbol )
151 {
152 mBackgroundSymbol->startRender( context );
153 mBackgroundSymbol->renderPolygon( painterBounds, nullptr, nullptr, context );
154 mBackgroundSymbol->stopRender( context );
155 }
156
158 {
159 QgsCallout::QgsCalloutContext calloutContext;
160 renderCallout( context, painterBounds, 0, calloutContext, feedback );
161 }
162
163 renderInBounds( context, painterBounds, feedback );
164
165 if ( mDrawFrame && mFrameSymbol )
166 {
167 mFrameSymbol->startRender( context );
168 mFrameSymbol->renderPolygon( painterBounds, nullptr, nullptr, context );
169 mFrameSymbol->stopRender( context );
170 }
171}
172
173QList<QgsAnnotationItemNode> QgsAnnotationRectItem::nodesV2( const QgsAnnotationItemEditContext &context ) const
174{
175 QList<QgsAnnotationItemNode> res;
176 switch ( mPlacementMode )
177 {
179 {
180 res =
181 {
182 QgsAnnotationItemNode( QgsVertexId( 0, 0, 0 ), QgsPointXY( mBounds.xMinimum(), mBounds.yMinimum() ), Qgis::AnnotationItemNodeType::VertexHandle, Qt::CursorShape::SizeBDiagCursor ),
183 QgsAnnotationItemNode( QgsVertexId( 0, 0, 1 ), QgsPointXY( mBounds.xMaximum(), mBounds.yMinimum() ), Qgis::AnnotationItemNodeType::VertexHandle, Qt::CursorShape::SizeFDiagCursor ),
184 QgsAnnotationItemNode( QgsVertexId( 0, 0, 2 ), QgsPointXY( mBounds.xMaximum(), mBounds.yMaximum() ), Qgis::AnnotationItemNodeType::VertexHandle, Qt::CursorShape::SizeBDiagCursor ),
185 QgsAnnotationItemNode( QgsVertexId( 0, 0, 3 ), QgsPointXY( mBounds.xMinimum(), mBounds.yMaximum() ), Qgis::AnnotationItemNodeType::VertexHandle, Qt::CursorShape::SizeFDiagCursor ),
186 };
187
188 QgsPointXY calloutNodePoint;
189 if ( !calloutAnchor().isEmpty() )
190 {
191 calloutNodePoint = calloutAnchor().asPoint();
192 }
193 else
194 {
195 calloutNodePoint = mBounds.center();
196 }
197 res.append( QgsAnnotationItemNode( QgsVertexId( 1, 0, 0 ), calloutNodePoint, Qgis::AnnotationItemNodeType::CalloutHandle ) );
198
199 return res;
200 }
201
203 {
204 res =
205 {
207 };
208
209 QgsPointXY calloutNodePoint;
210 if ( !calloutAnchor().isEmpty() )
211 {
212 calloutNodePoint = calloutAnchor().asPoint();
213 }
214 else
215 {
216 calloutNodePoint = QgsPointXY( context.currentItemBounds().xMinimum(), context.currentItemBounds().yMinimum() );
217 }
218 res.append( QgsAnnotationItemNode( QgsVertexId( 1, 0, 0 ), calloutNodePoint, Qgis::AnnotationItemNodeType::CalloutHandle ) );
219
220 return res;
221 }
222
224 {
225 return
226 {
229 };
230 }
231 }
233}
234
236{
237 switch ( operation->type() )
238 {
240 {
241 QgsAnnotationItemEditOperationMoveNode *moveOperation = qgis::down_cast< QgsAnnotationItemEditOperationMoveNode * >( operation );
242 if ( moveOperation->nodeId().part == 0 )
243 {
244 switch ( mPlacementMode )
245 {
247 {
248 switch ( moveOperation->nodeId().vertex )
249 {
250 case 0:
251 mBounds = QgsRectangle( moveOperation->after().x(),
252 moveOperation->after().y(),
253 mBounds.xMaximum(),
254 mBounds.yMaximum() );
255 break;
256 case 1:
257 mBounds = QgsRectangle( mBounds.xMinimum(),
258 moveOperation->after().y(),
259 moveOperation->after().x(),
260 mBounds.yMaximum() );
261 break;
262 case 2:
263 mBounds = QgsRectangle( mBounds.xMinimum(),
264 mBounds.yMinimum(),
265 moveOperation->after().x(),
266 moveOperation->after().y() );
267 break;
268 case 3:
269 mBounds = QgsRectangle( moveOperation->after().x(),
270 mBounds.yMinimum(),
271 mBounds.xMaximum(),
272 moveOperation->after().y() );
273 break;
274 default:
275 break;
276 }
278 }
279
281 {
282 mBounds = QgsRectangle::fromCenterAndSize( moveOperation->after(),
283 mBounds.width(),
284 mBounds.height() );
286 }
287
289 {
290 const double deltaX = moveOperation->translationXPixels() / context.renderContext().outputSize().width();
291 const double deltaY = moveOperation->translationYPixels() / context.renderContext().outputSize().height();
292 mBounds = QgsRectangle::fromCenterAndSize( QgsPointXY( mBounds.center().x() + deltaX, mBounds.center().y() + deltaY ),
293 mBounds.width(), mBounds.height() );
295 }
296 }
297 }
298 else if ( moveOperation->nodeId().part == 1 )
299 {
300 setCalloutAnchor( QgsGeometry::fromPoint( moveOperation->after() ) );
301 if ( !callout() )
302 {
303 setCallout( QgsApplication::calloutRegistry()->defaultCallout() );
304 }
306 }
307 break;
308 }
309
311 {
312 QgsAnnotationItemEditOperationTranslateItem *moveOperation = qgis::down_cast< QgsAnnotationItemEditOperationTranslateItem * >( operation );
313 switch ( mPlacementMode )
314 {
315
317 mBounds = QgsRectangle( mBounds.xMinimum() + moveOperation->translationX(),
318 mBounds.yMinimum() + moveOperation->translationY(),
319 mBounds.xMaximum() + moveOperation->translationX(),
320 mBounds.yMaximum() + moveOperation->translationY() );
321 break;
322
324 {
325 if ( callout() && !calloutAnchor().isEmpty() )
326 {
327 const double xOffset = context.renderContext().convertFromPainterUnits( moveOperation->translationXPixels(), offsetFromCalloutUnit() );
328 const double yOffset = context.renderContext().convertFromPainterUnits( moveOperation->translationYPixels(), offsetFromCalloutUnit() );
329 setOffsetFromCallout( QSizeF( offsetFromCallout().width() + xOffset, offsetFromCallout().height() + yOffset ) );
330 }
331 else
332 {
333 mBounds = QgsRectangle( mBounds.xMinimum() + moveOperation->translationX(),
334 mBounds.yMinimum() + moveOperation->translationY(),
335 mBounds.xMaximum() + moveOperation->translationX(),
336 mBounds.yMaximum() + moveOperation->translationY() );
337 }
338 break;
339 }
340
342 {
343 const double deltaX = moveOperation->translationXPixels() / context.renderContext().outputSize().width();
344 const double deltaY = moveOperation->translationYPixels() / context.renderContext().outputSize().height();
345 mBounds = QgsRectangle::fromCenterAndSize( QgsPointXY( mBounds.center().x() + deltaX, mBounds.center().y() + deltaY ),
346 mBounds.width(), mBounds.height() );
347 break;
348 }
349 }
351 }
352
356 break;
357 }
359}
360
362{
363 switch ( operation->type() )
364 {
366 {
367 QgsAnnotationItemEditOperationMoveNode *moveOperation = qgis::down_cast< QgsAnnotationItemEditOperationMoveNode * >( operation );
368 if ( moveOperation->nodeId().part == 0 )
369 {
370 switch ( mPlacementMode )
371 {
373 {
374 QgsRectangle modifiedBounds = mBounds;
375 switch ( moveOperation->nodeId().vertex )
376 {
377 case 0:
378 modifiedBounds.setXMinimum( moveOperation->after().x() );
379 modifiedBounds.setYMinimum( moveOperation->after().y() );
380 break;
381 case 1:
382 modifiedBounds.setXMaximum( moveOperation->after().x() );
383 modifiedBounds.setYMinimum( moveOperation->after().y() );
384 break;
385 case 2:
386 modifiedBounds.setXMaximum( moveOperation->after().x() );
387 modifiedBounds.setYMaximum( moveOperation->after().y() );
388 break;
389 case 3:
390 modifiedBounds.setXMinimum( moveOperation->after().x() );
391 modifiedBounds.setYMaximum( moveOperation->after().y() );
392 break;
393 default:
394 break;
395 }
397 }
399 {
400 const QgsRectangle currentBounds = context.currentItemBounds();
401 const QgsRectangle newBounds = QgsRectangle::fromCenterAndSize( moveOperation->after(), currentBounds.width(), currentBounds.height() );
403 }
405 {
406 const QgsRectangle currentBounds = context.currentItemBounds();
407 const QgsRectangle newBounds = QgsRectangle::fromCenterAndSize( currentBounds.center() + ( moveOperation->after() - moveOperation->before() ),
408 currentBounds.width(), currentBounds.height() );
410 }
411 }
412 }
413 else
414 {
415 QgsAnnotationItemEditOperationMoveNode *moveOperation = qgis::down_cast< QgsAnnotationItemEditOperationMoveNode * >( operation );
416 return new QgsAnnotationItemEditOperationTransientResults( QgsGeometry( moveOperation->after().clone() ) );
417 }
418 break;
419 }
420
422 {
423 QgsAnnotationItemEditOperationTranslateItem *moveOperation = qgis::down_cast< QgsAnnotationItemEditOperationTranslateItem * >( operation );
424 switch ( mPlacementMode )
425 {
427 {
428 const QgsRectangle modifiedBounds( mBounds.xMinimum() + moveOperation->translationX(),
429 mBounds.yMinimum() + moveOperation->translationY(),
430 mBounds.xMaximum() + moveOperation->translationX(),
431 mBounds.yMaximum() + moveOperation->translationY() );
433 }
434
436 {
437 if ( callout() && !calloutAnchor().isEmpty() )
438 {
439 QgsGeometry anchor = calloutAnchor();
440
441 const double calloutOffsetWidthPixels = context.renderContext().convertToPainterUnits( offsetFromCallout().width(), offsetFromCalloutUnit() )
442 + moveOperation->translationXPixels();
443 const double calloutOffsetHeightPixels = context.renderContext().convertToPainterUnits( offsetFromCallout().height(), offsetFromCalloutUnit() )
444 + moveOperation->translationYPixels();
445
446 QPointF anchorPoint = anchor.asQPointF();
447 if ( context.renderContext().coordinateTransform().isValid() )
448 {
449 double x = anchorPoint.x();
450 double y = anchorPoint.y();
451 double z = 0.0;
453 anchorPoint = QPointF( x, y );
454 }
455
456 context.renderContext().mapToPixel().transformInPlace( anchorPoint.rx(), anchorPoint.ry() );
457
458 const double textOriginXPixels = anchorPoint.x() + calloutOffsetWidthPixels;
459 const double textOriginYPixels = anchorPoint.y() + calloutOffsetHeightPixels;
460
461 const double widthPixels = context.renderContext().convertToPainterUnits( mFixedSize.width(), mFixedSizeUnit );
462 const double heightPixels = context.renderContext().convertToPainterUnits( mFixedSize.height(), mFixedSizeUnit );
463
464 QgsLineString ls( QVector<QgsPointXY> { QgsPointXY( textOriginXPixels, textOriginYPixels ),
465 QgsPointXY( textOriginXPixels + widthPixels, textOriginYPixels ),
466 QgsPointXY( textOriginXPixels + widthPixels, textOriginYPixels + heightPixels ),
467 QgsPointXY( textOriginXPixels, textOriginYPixels + heightPixels ),
468 QgsPointXY( textOriginXPixels, textOriginYPixels )
469 } );
470
471 QgsGeometry g( new QgsPolygon( ls.clone() ) );
472 g.transform( context.renderContext().mapToPixel().transform().inverted() );
475 }
476 else
477 {
478 const QgsRectangle currentBounds = context.currentItemBounds();
479 const QgsRectangle newBounds = QgsRectangle::fromCenterAndSize( mBounds.center() + QgsVector( moveOperation->translationX(), moveOperation->translationY() ),
480 currentBounds.width(), currentBounds.height() );
482 }
483 }
484
486 {
487 const QgsRectangle currentBounds = context.currentItemBounds();
488 const QgsRectangle newBounds = QgsRectangle::fromCenterAndSize( currentBounds.center() + QgsVector( moveOperation->translationX(), moveOperation->translationY() ),
489 currentBounds.width(), currentBounds.height() );
491 }
492 }
493 break;
494 }
495
499 break;
500 }
501 return nullptr;
502}
503
505{
507 switch ( mPlacementMode )
508 {
510 {
511 bounds = mBounds;
512 if ( callout() && !calloutAnchor().isEmpty() )
513 {
514 QgsGeometry anchor = calloutAnchor();
515 bounds.combineExtentWith( anchor.boundingBox() );
516 }
517 break;
518 }
519
521 if ( callout() && !calloutAnchor().isEmpty() )
522 {
524 }
525 else
526 {
527 bounds = QgsRectangle( mBounds.center(), mBounds.center() );
528 }
529 break;
530
532 bounds = mBounds;
533 break;
534 }
535
536 return bounds;
537}
538
540{
541 switch ( mPlacementMode )
542 {
545
547 {
548 const double widthPixels = context.convertToPainterUnits( mFixedSize.width(), mFixedSizeUnit );
549 const double heightPixels = context.convertToPainterUnits( mFixedSize.height(), mFixedSizeUnit );
550
551 QRectF boundsInPixels;
552 if ( callout() && !calloutAnchor().isEmpty() )
553 {
554 QgsGeometry anchor = calloutAnchor();
555
556 const double calloutOffsetWidthPixels = context.convertToPainterUnits( offsetFromCallout().width(), offsetFromCalloutUnit() );
557 const double calloutOffsetHeightPixels = context.convertToPainterUnits( offsetFromCallout().height(), offsetFromCalloutUnit() );
558
559 QPointF anchorPoint = anchor.asQPointF();
560 if ( context.coordinateTransform().isValid() )
561 {
562 double x = anchorPoint.x();
563 double y = anchorPoint.y();
564 double z = 0.0;
565 context.coordinateTransform().transformInPlace( x, y, z );
566 anchorPoint = QPointF( x, y );
567 }
568
569 context.mapToPixel().transformInPlace( anchorPoint.rx(), anchorPoint.ry() );
570
571 QgsRectangle textRect( anchorPoint.x() + calloutOffsetWidthPixels,
572 anchorPoint.y() + calloutOffsetHeightPixels,
573 anchorPoint.x() + calloutOffsetWidthPixels + widthPixels,
574 anchorPoint.y() + calloutOffsetHeightPixels + heightPixels );
575 QgsRectangle anchorRect( anchorPoint.x(), anchorPoint.y(), anchorPoint.x(), anchorPoint.y() );
576 anchorRect.combineExtentWith( textRect );
577
578 boundsInPixels = anchorRect.toRectF();
579 }
580 else
581 {
582 QPointF center = mBounds.center().toQPointF();
583 if ( context.coordinateTransform().isValid() )
584 {
585 double x = center.x();
586 double y = center.y();
587 double z = 0.0;
588 context.coordinateTransform().transformInPlace( x, y, z );
589 center = QPointF( x, y );
590 }
591
592 context.mapToPixel().transformInPlace( center.rx(), center.ry() );
593 boundsInPixels = QRectF( center.x() - widthPixels * 0.5,
594 center.y() - heightPixels * 0.5,
595 widthPixels, heightPixels );
596 }
597 const QgsPointXY topLeft = context.mapToPixel().toMapCoordinates( boundsInPixels.left(), boundsInPixels.top() );
598 const QgsPointXY topRight = context.mapToPixel().toMapCoordinates( boundsInPixels.right(), boundsInPixels.top() );
599 const QgsPointXY bottomLeft = context.mapToPixel().toMapCoordinates( boundsInPixels.left(), boundsInPixels.bottom() );
600 const QgsPointXY bottomRight = context.mapToPixel().toMapCoordinates( boundsInPixels.right(), boundsInPixels.bottom() );
601
602 const QgsRectangle boundsMapUnits = QgsRectangle( topLeft.x(), bottomLeft.y(), bottomRight.x(), topRight.y() );
604 return textRect;
605 }
606
608 {
609 const double widthPixels = context.convertToPainterUnits( mFixedSize.width(), mFixedSizeUnit );
610 const double heightPixels = context.convertToPainterUnits( mFixedSize.height(), mFixedSizeUnit );
611
612 QRectF boundsInPixels;
613
614 const double centerMapX = context.mapExtent().xMinimum() + mBounds.center().x() * context.mapExtent().width();
615 const double centerMapY = context.mapExtent().yMaximum() - mBounds.center().y() * context.mapExtent().height();
616 QPointF center( centerMapX, centerMapY );
617 if ( context.coordinateTransform().isValid() )
618 {
619 double x = centerMapX;
620 double y = centerMapY;
621 double z = 0.0;
622 context.coordinateTransform().transformInPlace( x, y, z );
623 center = QPointF( x, y );
624 }
625
626 context.mapToPixel().transformInPlace( center.rx(), center.ry() );
627 boundsInPixels = QRectF( center.x() - widthPixels * 0.5,
628 center.y() - heightPixels * 0.5,
629 widthPixels, heightPixels );
630
631 const QgsPointXY topLeft = context.mapToPixel().toMapCoordinates( boundsInPixels.left(), boundsInPixels.top() );
632 const QgsPointXY topRight = context.mapToPixel().toMapCoordinates( boundsInPixels.right(), boundsInPixels.top() );
633 const QgsPointXY bottomLeft = context.mapToPixel().toMapCoordinates( boundsInPixels.left(), boundsInPixels.bottom() );
634 const QgsPointXY bottomRight = context.mapToPixel().toMapCoordinates( boundsInPixels.right(), boundsInPixels.bottom() );
635
636 const QgsRectangle boundsMapUnits = QgsRectangle( topLeft.x(), bottomLeft.y(), bottomRight.x(), topRight.y() );
638 return textRect;
639 }
640 }
642}
643
645{
646 mBounds = bounds;
647}
648
650{
651 return mBackgroundSymbol.get();
652}
653
655{
656 mBackgroundSymbol.reset( symbol );
657}
658
660{
661 return mFrameSymbol.get();
662}
663
665{
666 mFrameSymbol.reset( symbol );
667}
668
670{
671 if ( const QgsAnnotationRectItem *otherRect = dynamic_cast< const QgsAnnotationRectItem * >( other ) )
672 {
673 setPlacementMode( otherRect->mPlacementMode );
674 setFixedSize( otherRect->mFixedSize );
675 setFixedSizeUnit( otherRect->mFixedSizeUnit );
676
677 setBackgroundEnabled( otherRect->mDrawBackground );
678 if ( otherRect->mBackgroundSymbol )
679 setBackgroundSymbol( otherRect->mBackgroundSymbol->clone() );
680
681 setFrameEnabled( otherRect->mDrawFrame );
682 if ( otherRect->mFrameSymbol )
683 setFrameSymbol( otherRect->mFrameSymbol->clone() );
684 }
685
687}
688
689bool QgsAnnotationRectItem::writeCommonProperties( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const
690{
691 element.setAttribute( u"xMin"_s, qgsDoubleToString( mBounds.xMinimum() ) );
692 element.setAttribute( u"xMax"_s, qgsDoubleToString( mBounds.xMaximum() ) );
693 element.setAttribute( u"yMin"_s, qgsDoubleToString( mBounds.yMinimum() ) );
694 element.setAttribute( u"yMax"_s, qgsDoubleToString( mBounds.yMaximum() ) );
695 element.setAttribute( u"sizeMode"_s, qgsEnumValueToKey( mPlacementMode ) );
696 element.setAttribute( u"fixedWidth"_s, qgsDoubleToString( mFixedSize.width() ) );
697 element.setAttribute( u"fixedHeight"_s, qgsDoubleToString( mFixedSize.height() ) );
698 element.setAttribute( u"fixedSizeUnit"_s, QgsUnitTypes::encodeUnit( mFixedSizeUnit ) );
699
700 element.setAttribute( u"backgroundEnabled"_s, mDrawBackground ? u"1"_s : u"0"_s );
701 if ( mBackgroundSymbol )
702 {
703 QDomElement backgroundElement = document.createElement( u"backgroundSymbol"_s );
704 backgroundElement.appendChild( QgsSymbolLayerUtils::saveSymbol( u"backgroundSymbol"_s, mBackgroundSymbol.get(), document, context ) );
705 element.appendChild( backgroundElement );
706 }
707
708 element.setAttribute( u"frameEnabled"_s, mDrawFrame ? u"1"_s : u"0"_s );
709 if ( mFrameSymbol )
710 {
711 QDomElement frameElement = document.createElement( u"frameSymbol"_s );
712 frameElement.appendChild( QgsSymbolLayerUtils::saveSymbol( u"frameSymbol"_s, mFrameSymbol.get(), document, context ) );
713 element.appendChild( frameElement );
714 }
715
716 return QgsAnnotationItem::writeCommonProperties( element, document, context );
717}
718
719bool QgsAnnotationRectItem::readCommonProperties( const QDomElement &element, const QgsReadWriteContext &context )
720{
721 mBounds.setXMinimum( element.attribute( u"xMin"_s ).toDouble() );
722 mBounds.setXMaximum( element.attribute( u"xMax"_s ).toDouble() );
723 mBounds.setYMinimum( element.attribute( u"yMin"_s ).toDouble() );
724 mBounds.setYMaximum( element.attribute( u"yMax"_s ).toDouble() );
725
726 mPlacementMode = qgsEnumKeyToValue( element.attribute( u"sizeMode"_s ), Qgis::AnnotationPlacementMode::SpatialBounds );
727
728 mFixedSize = QSizeF(
729 element.attribute( u"fixedWidth"_s ).toDouble(),
730 element.attribute( u"fixedHeight"_s ).toDouble()
731 );
732 mFixedSizeUnit = QgsUnitTypes::decodeRenderUnit( element.attribute( u"fixedSizeUnit"_s ) );
733
734 mDrawBackground = element.attribute( u"backgroundEnabled"_s, u"0"_s ).toInt();
735 const QDomElement backgroundSymbolElem = element.firstChildElement( u"backgroundSymbol"_s ).firstChildElement();
736 if ( !backgroundSymbolElem.isNull() )
737 {
738 setBackgroundSymbol( QgsSymbolLayerUtils::loadSymbol< QgsFillSymbol >( backgroundSymbolElem, context ).release() );
739 }
740
741 mDrawFrame = element.attribute( u"frameEnabled"_s, u"0"_s ).toInt();
742 const QDomElement frameSymbolElem = element.firstChildElement( u"frameSymbol"_s ).firstChildElement();
743 if ( !frameSymbolElem.isNull() )
744 {
745 setFrameSymbol( QgsSymbolLayerUtils::loadSymbol< QgsFillSymbol >( frameSymbolElem, context ).release() );
746 }
747
748 return QgsAnnotationItem::readCommonProperties( element, context );
749}
750
752{
753 return mFixedSize;
754}
755
756void QgsAnnotationRectItem::setFixedSize( const QSizeF &size )
757{
758 mFixedSize = size;
759}
760
762{
763 return mFixedSizeUnit;
764}
765
767{
768 mFixedSizeUnit = unit;
769}
770
772{
773 return mPlacementMode;
774}
775
777{
778 mPlacementMode = mode;
779}
@ VertexHandle
Node is a handle for manipulating vertices.
Definition qgis.h:2566
@ CalloutHandle
Node is a handle for manipulating callouts.
Definition qgis.h:2567
@ ScaleDependentBoundingBox
Item's bounding box will vary depending on map scale.
Definition qgis.h:2523
@ SupportsCallouts
Item supports callouts.
Definition qgis.h:2525
AnnotationItemEditOperationResult
Results from an edit operation on an annotation item.
Definition qgis.h:2577
@ Invalid
Operation has invalid parameters for the item, no change occurred.
Definition qgis.h:2579
@ Success
Item was modified successfully.
Definition qgis.h:2578
QFlags< AnnotationItemFlag > AnnotationItemFlags
Annotation item flags.
Definition qgis.h:2528
RenderUnit
Rendering size units.
Definition qgis.h:5255
AnnotationPlacementMode
Annotation item placement modes.
Definition qgis.h:2538
@ SpatialBounds
Item is rendered inside fixed spatial bounds, and size will depend on map scale.
Definition qgis.h:2539
@ FixedSize
Item is rendered at a fixed size, regardless of map scale. Item's location is georeferenced to a spat...
Definition qgis.h:2540
@ RelativeToMapFrame
Items size and placement is relative to the map's frame, and the item will always be rendered in the ...
Definition qgis.h:2541
@ Reverse
Reverse/inverse transform (from destination to source).
Definition qgis.h:2731
Abstract base class for annotation item edit operations.
virtual Type type() const =0
Returns the operation type.
Encapsulates the context for an annotation item edit operation.
QgsRectangle currentItemBounds() const
Returns the current rendered bounds of the item, in the annotation layer's CRS.
QgsRenderContext renderContext() const
Returns the render context associated with the edit operation.
Annotation item edit operation consisting of moving a node.
double translationYPixels() const
Returns the y-axis translation, in pixels.
QgsPoint before() const
Returns the node position before the move occurred (in layer coordinates).
QgsPoint after() const
Returns the node position after the move occurred (in layer coordinates).
double translationXPixels() const
Returns the x-axis translation, in pixels.
QgsVertexId nodeId() const
Returns the associated node ID.
Encapsulates the transient results of an in-progress annotation edit operation.
Annotation item edit operation consisting of translating (moving) an item.
double translationY() const
Returns the y-axis translation, in layer units.
double translationX() const
Returns the x-axis translation, in layer units.
double translationYPixels() const
Returns the y-axis translation, in pixels.
double translationXPixels() const
Returns the x-axis translation, in pixels.
Contains information about a node used for editing an annotation item.
virtual bool writeCommonProperties(QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context) const
Writes common properties from the base class into an XML element.
void setCallout(QgsCallout *callout)
Sets the item's callout renderer, responsible for drawing item callouts.
void setOffsetFromCallout(const QSizeF &offset)
Sets the offset of the annotation item from the calloutAnchor().
QgsGeometry calloutAnchor() const
Returns the callout's anchor geometry.
Qgis::RenderUnit offsetFromCalloutUnit() const
Returns the units for the offsetFromCallout().
virtual void copyCommonProperties(const QgsAnnotationItem *other)
Copies common properties from the base class from an other item.
void setCalloutAnchor(const QgsGeometry &anchor)
Sets the callout's anchor geometry.
QSizeF offsetFromCallout() const
Returns the (optional) offset of the annotation item from the calloutAnchor().
QgsCallout * callout() const
Returns the item's callout renderer, responsible for drawing item callouts.
virtual bool readCommonProperties(const QDomElement &element, const QgsReadWriteContext &context)
Reads common properties from the base class from the given DOM element.
void renderCallout(QgsRenderContext &context, const QRectF &rect, double angle, QgsCallout::QgsCalloutContext &calloutContext, QgsFeedback *feedback)
Renders the item's callout.
virtual void renderInBounds(QgsRenderContext &context, const QRectF &painterRect, QgsFeedback *feedback)=0
Renders the item to the specified render context.
Qgis::AnnotationItemFlags flags() const override
Returns item flags.
void copyCommonProperties(const QgsAnnotationItem *other) override
Copies common properties from the base class from an other item.
QgsRectangle bounds() const
Returns the bounds of the item.
void render(QgsRenderContext &context, QgsFeedback *feedback) override
Renders the item to the specified render context.
QgsAnnotationItemEditOperationTransientResults * transientEditResultsV2(QgsAbstractAnnotationItemEditOperation *operation, const QgsAnnotationItemEditContext &context) override
Retrieves the results of a transient (in progress) edit operation on the item.
Qgis::AnnotationItemEditOperationResult applyEditV2(QgsAbstractAnnotationItemEditOperation *operation, const QgsAnnotationItemEditContext &context) override
Applies an edit operation to the item.
~QgsAnnotationRectItem() override
bool readCommonProperties(const QDomElement &element, const QgsReadWriteContext &context) override
Reads common properties from the base class from the given DOM element.
Qgis::RenderUnit fixedSizeUnit() const
Returns the units to use for fixed item sizes, when the placementMode() is Qgis::AnnotationPlacementM...
QSizeF fixedSize() const
Returns the fixed size to use for the item, when the placementMode() is Qgis::AnnotationPlacementMode...
void setFixedSizeUnit(Qgis::RenderUnit unit)
Sets the unit to use for fixed item sizes, when the placementMode() is Qgis::AnnotationPlacementMode:...
QgsAnnotationRectItem(const QgsRectangle &bounds)
Constructor for QgsAnnotationRectItem, rendering the annotation within the specified bounds geometry.
void setBackgroundSymbol(QgsFillSymbol *symbol)
Sets the symbol used to render the item's background.
void setFrameSymbol(QgsFillSymbol *symbol)
Sets the symbol used to render the item's frame.
void setBounds(const QgsRectangle &bounds)
Sets the bounds of the item.
void setPlacementMode(Qgis::AnnotationPlacementMode mode)
Sets the placement mode for the item.
bool writeCommonProperties(QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context) const override
Writes common properties from the base class into an XML element.
const QgsFillSymbol * frameSymbol() const
Returns the symbol used to render the item's frame.
void setBackgroundEnabled(bool enabled)
Sets whether the item's background should be rendered.
QList< QgsAnnotationItemNode > nodesV2(const QgsAnnotationItemEditContext &context) const override
Returns the nodes for the item, used for editing the item.
void setFrameEnabled(bool enabled)
Sets whether the item's frame should be rendered.
QgsRectangle boundingBox() const override
Returns the bounding box of the item's geographic location, in the parent layer's coordinate referenc...
void setFixedSize(const QSizeF &size)
Sets the fixed size to use for the item, when the placementMode() is Qgis::AnnotationPlacementMode::F...
Qgis::AnnotationPlacementMode placementMode() const
Returns the placement mode for the item.
const QgsFillSymbol * backgroundSymbol() const
Returns the symbol used to render the item's background.
static QgsCalloutRegistry * calloutRegistry()
Returns the application's callout registry, used for managing callout types.
Contains additional contextual information about the context in which a callout is being rendered.
Definition qgscallout.h:250
void transformInPlace(double &x, double &y, double &z, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward) const
Transforms an array of x, y and z double coordinates in place, from the source CRS to the destination...
QgsRectangle transformBoundingBox(const QgsRectangle &rectangle, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool handle180Crossover=false) const
Transforms a rectangle from the source CRS to the destination CRS.
bool isValid() const
Returns true if the coordinate transform is valid, ie both the source and destination CRS have been s...
Custom exception class for Coordinate Reference System related exceptions.
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Definition qgsfeedback.h:44
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
A geometry is the spatial representation of a feature.
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
QgsPointXY asPoint() const
Returns the contents of the geometry as a 2-dimensional point.
QPointF asQPointF() const
Returns contents of the geometry as a QPointF if wkbType is WKBPoint, otherwise returns a null QPoint...
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
static QgsGeometry fromPoint(const QgsPoint &point)
Creates a new geometry from a QgsPoint object.
Line string geometry type, with support for z-dimension and m-values.
QRectF transformBounds(const QRectF &bounds) const
Transforms a bounding box from map coordinates to device coordinates.
QgsPointXY toMapCoordinates(int x, int y) const
Transforms device coordinates to map (world) coordinates.
QgsPointXY transform(const QgsPointXY &p) const
Transforms a point p from map (world) coordinates to device coordinates.
void transformInPlace(double &x, double &y) const
Transforms map coordinates to device coordinates.
Represents a 2D point.
Definition qgspointxy.h:62
double y
Definition qgspointxy.h:66
double x
Definition qgspointxy.h:65
QgsPoint * clone() const override
Clones the geometry by performing a deep copy.
Definition qgspoint.cpp:111
double x
Definition qgspoint.h:56
double y
Definition qgspoint.h:57
Polygon geometry type.
Definition qgspolygon.h:37
A container for the context for various read/write operations on objects.
A rectangle specified with double values.
double xMinimum
double yMinimum
void setYMinimum(double y)
Set the minimum y value.
void setXMinimum(double x)
Set the minimum x value.
QRectF toRectF() const
Returns a QRectF with same coordinates as the rectangle.
void setYMaximum(double y)
Set the maximum y value.
void setXMaximum(double x)
Set the maximum x value.
double yMaximum
void combineExtentWith(const QgsRectangle &rect)
Expands the rectangle so that it covers both the original rectangle and the given rectangle.
static QgsRectangle fromCenterAndSize(const QgsPointXY &center, double width, double height)
Creates a new rectangle, given the specified center point and width and height.
QgsPointXY center
Contains information about the context of a rendering operation.
double convertFromPainterUnits(double size, Qgis::RenderUnit unit) const
Converts a size from painter units (pixels) to the specified render unit.
double convertToPainterUnits(double size, Qgis::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
QSize outputSize() const
Returns the size of the resulting rendered image, in pixels.
QgsRectangle mapExtent() const
Returns the original extent of the map being rendered.
const QgsMapToPixel & mapToPixel() const
Returns the context's map to pixel transform, which transforms between map coordinates and device coo...
QgsCoordinateTransform coordinateTransform() const
Returns the current coordinate transform for the context.
Renders polygons using a single fill and stroke color.
A simple line symbol layer, which renders lines using a line in a variety of styles (e....
static std::unique_ptr< QgsSymbol > loadSymbol(const QDomElement &element, const QgsReadWriteContext &context)
Attempts to load a symbol from a DOM element.
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
static Q_INVOKABLE Qgis::RenderUnit decodeRenderUnit(const QString &string, bool *ok=nullptr)
Decodes a render unit from a string.
static Q_INVOKABLE QString encodeUnit(Qgis::DistanceUnit unit)
Encodes a distance unit to a string.
Represent a 2-dimensional vector.
Definition qgsvector.h:34
T qgsEnumKeyToValue(const QString &key, const T &defaultValue, bool tryValueAsKey=true, bool *returnOk=nullptr)
Returns the value corresponding to the given key of an enum.
Definition qgis.h:7110
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition qgis.h:6817
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
Definition qgis.h:7091
#define BUILTIN_UNREACHABLE
Definition qgis.h:7489
QList< QgsSymbolLayer * > QgsSymbolLayerList
Definition qgssymbol.h:30
Utility class for identifying a unique vertex within a geometry.
Definition qgsvertexid.h:34
int vertex
Vertex number.
Definition qgsvertexid.h:98
int part
Part number.
Definition qgsvertexid.h:92