QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
qgsannotation.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsannotation.cpp
3  -----------------
4  begin : January 2017
5  copyright : (C) 2017 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 
18 #include "qgsannotation.h"
19 #include "qgssymbollayerutils.h"
20 #include "qgsmaplayer.h"
21 #include "qgsproject.h"
22 #include "qgsgeometryutils.h"
23 #include "qgsstyleentityvisitor.h"
24 
25 #include <QPen>
26 #include <QPainter>
27 
28 Q_GUI_EXPORT extern int qt_defaultDpiX();
29 
30 QgsAnnotation::QgsAnnotation( QObject *parent )
31  : QObject( parent )
32  , mMarkerSymbol( new QgsMarkerSymbol() )
33 {
34  QgsStringMap props;
35  props.insert( QStringLiteral( "color" ), QStringLiteral( "white" ) );
36  props.insert( QStringLiteral( "style" ), QStringLiteral( "solid" ) );
37  props.insert( QStringLiteral( "style_border" ), QStringLiteral( "solid" ) );
38  props.insert( QStringLiteral( "color_border" ), QStringLiteral( "black" ) );
39  props.insert( QStringLiteral( "width_border" ), QStringLiteral( "0.3" ) );
40  props.insert( QStringLiteral( "joinstyle" ), QStringLiteral( "miter" ) );
41  mFillSymbol.reset( QgsFillSymbol::createSimple( props ) );
42 }
43 
44 void QgsAnnotation::setVisible( bool visible )
45 {
46  if ( mVisible == visible )
47  return;
48 
49  mVisible = visible;
50  emit appearanceChanged();
51 }
52 
54 {
55  if ( mHasFixedMapPosition == fixed )
56  return;
57 
58  mHasFixedMapPosition = fixed;
59  updateBalloon();
60  emit moved();
61 }
62 
64 {
65  mMapPosition = position;
66  emit moved();
67 }
68 
70 {
71  mMapPositionCrs = crs;
72  emit moved();
73 }
74 
75 void QgsAnnotation::setRelativePosition( QPointF position )
76 {
77  mRelativePosition = position;
78  emit moved();
79 }
80 
82 {
83  // convert from offset in pixels at 96 dpi to mm
84  setFrameOffsetFromReferencePointMm( offset / 3.7795275 );
85 }
86 
88 {
89  return mOffsetFromReferencePoint / 3.7795275;
90 }
91 
93 {
94  mOffsetFromReferencePoint = offset;
95 
96  updateBalloon();
97  emit moved();
98  emit appearanceChanged();
99 }
100 
101 void QgsAnnotation::setFrameSize( QSizeF size )
102 {
103  // convert from size in pixels at 96 dpi to mm
104  setFrameSizeMm( size / 3.7795275 );
105 }
106 
108 {
109  return mFrameSize / 3.7795275;
110 }
111 
112 void QgsAnnotation::setFrameSizeMm( QSizeF size )
113 {
114  QSizeF frameSize = minimumFrameSize().expandedTo( size ); //don't allow frame sizes below minimum
115  mFrameSize = frameSize;
116  updateBalloon();
117  emit moved();
118  emit appearanceChanged();
119 }
120 
122 {
123  mContentsMargins = margins;
124  emit appearanceChanged();
125 }
126 
128 {
129  mFillSymbol.reset( symbol );
130  emit appearanceChanged();
131 }
132 
134 {
135  QPainter *painter = context.painter();
136  if ( !painter )
137  {
138  return;
139  }
140 
141  QgsScopedQPainterState painterState( context.painter() );
142  context.setPainterFlagsUsingContext();
143 
144  drawFrame( context );
145  if ( mHasFixedMapPosition )
146  {
147  drawMarkerSymbol( context );
148  }
149  if ( mHasFixedMapPosition )
150  {
151  painter->translate( context.convertToPainterUnits( mOffsetFromReferencePoint.x(), QgsUnitTypes::RenderMillimeters ) + context.convertToPainterUnits( mContentsMargins.left(), QgsUnitTypes::RenderMillimeters ),
152  context.convertToPainterUnits( mOffsetFromReferencePoint.y(), QgsUnitTypes::RenderMillimeters ) + context.convertToPainterUnits( mContentsMargins.top(), QgsUnitTypes::RenderMillimeters ) );
153  }
154  else
155  {
156  painter->translate( context.convertToPainterUnits( mContentsMargins.left(), QgsUnitTypes::RenderMillimeters ),
157  context.convertToPainterUnits( mContentsMargins.top(), QgsUnitTypes::RenderMillimeters ) );
158  }
159  QSizeF size( context.convertToPainterUnits( mFrameSize.width(), QgsUnitTypes::RenderMillimeters ) - context.convertToPainterUnits( mContentsMargins.left() + mContentsMargins.right(), QgsUnitTypes::RenderMillimeters ),
160  context.convertToPainterUnits( mFrameSize.height(), QgsUnitTypes::RenderMillimeters ) - context.convertToPainterUnits( mContentsMargins.top() + mContentsMargins.bottom(), QgsUnitTypes::RenderMillimeters ) );
161 
162  // scale back from painter dpi to 96 dpi --
163 // double dotsPerMM = context.painter()->device()->logicalDpiX() / ( 25.4 * 3.78 );
164 // context.painter()->scale( dotsPerMM, dotsPerMM );
165 
166  renderAnnotation( context, size );
167 }
168 
170 {
171  mMarkerSymbol.reset( symbol );
172  emit appearanceChanged();
173 }
174 
176 {
177  mMapLayer = layer;
178  emit mapLayerChanged();
179 }
180 
182 {
183  mFeature = feature;
184 }
185 
187 {
188  // NOTE: if visitEnter returns false it means "don't visit the annotation", not "abort all further visitations"
189  if ( !visitor->visitEnter( QgsStyleEntityVisitorInterface::Node( QgsStyleEntityVisitorInterface::NodeType::Annotation, QStringLiteral( "annotation" ), tr( "Annotation" ) ) ) )
190  return true;
191 
192  if ( mMarkerSymbol )
193  {
194  QgsStyleSymbolEntity entity( mMarkerSymbol.get() );
195  if ( !visitor->visit( QgsStyleEntityVisitorInterface::StyleLeaf( &entity, QStringLiteral( "marker" ), QObject::tr( "Marker" ) ) ) )
196  return false;
197  }
198 
199  if ( mFillSymbol )
200  {
201  QgsStyleSymbolEntity entity( mFillSymbol.get() );
202  if ( !visitor->visit( QgsStyleEntityVisitorInterface::StyleLeaf( &entity, QStringLiteral( "fill" ), QObject::tr( "Fill" ) ) ) )
203  return false;
204  }
205 
206  if ( !visitor->visitExit( QgsStyleEntityVisitorInterface::Node( QgsStyleEntityVisitorInterface::NodeType::Annotation, QStringLiteral( "annotation" ), tr( "Annotation" ) ) ) )
207  return false;
208 
209  return true;
210 }
211 
213 {
214  return QSizeF( 0, 0 );
215 }
216 
217 void QgsAnnotation::updateBalloon()
218 {
219  //first test if the point is in the frame. In that case we don't need a balloon.
220  if ( !mHasFixedMapPosition ||
221  ( mOffsetFromReferencePoint.x() < 0 && ( mOffsetFromReferencePoint.x() + mFrameSize.width() ) > 0
222  && mOffsetFromReferencePoint.y() < 0 && ( mOffsetFromReferencePoint.y() + mFrameSize.height() ) > 0 ) )
223  {
224  mBalloonSegment = -1;
225  return;
226  }
227 
228  //edge list
229  QList<QLineF> segmentList;
230  segmentList << segment( 0, nullptr );
231  segmentList << segment( 1, nullptr );
232  segmentList << segment( 2, nullptr );
233  segmentList << segment( 3, nullptr );
234 
235  //find closest edge / closest edge point
236  double minEdgeDist = std::numeric_limits<double>::max();
237  int minEdgeIndex = -1;
238  QLineF minEdge;
239  QgsPointXY minEdgePoint;
240  QgsPointXY origin( 0, 0 );
241 
242  for ( int i = 0; i < 4; ++i )
243  {
244  QLineF currentSegment = segmentList.at( i );
245  QgsPointXY currentMinDistPoint;
246  double currentMinDist = origin.sqrDistToSegment( currentSegment.x1(), currentSegment.y1(), currentSegment.x2(), currentSegment.y2(), currentMinDistPoint );
247  bool isPreferredSegment = false;
248  if ( qgsDoubleNear( currentMinDist, minEdgeDist ) )
249  {
250  // two segments are close - work out which looks nicer
251  const double angle = fmod( origin.azimuth( currentMinDistPoint ) + 360.0, 360.0 );
252  if ( angle < 45 || angle > 315 )
253  isPreferredSegment = i == 0;
254  else if ( angle < 135 )
255  isPreferredSegment = i == 3;
256  else if ( angle < 225 )
257  isPreferredSegment = i == 2;
258  else
259  isPreferredSegment = i == 1;
260  }
261  else if ( currentMinDist < minEdgeDist )
262  isPreferredSegment = true;
263 
264  if ( isPreferredSegment )
265  {
266  minEdgeIndex = i;
267  minEdgePoint = currentMinDistPoint;
268  minEdgeDist = currentMinDist;
269  minEdge = currentSegment;
270  }
271  }
272 
273  if ( minEdgeIndex < 0 )
274  {
275  return;
276  }
277 
278  mBalloonSegment = minEdgeIndex;
279  QPointF minEdgeEnd = minEdge.p2();
280  mBalloonSegmentPoint1 = QPointF( minEdgePoint.x(), minEdgePoint.y() );
281  if ( std::sqrt( minEdgePoint.sqrDist( minEdgeEnd.x(), minEdgeEnd.y() ) ) < mSegmentPointWidthMm )
282  {
283  double x = 0;
284  double y = 0;
285  QgsGeometryUtils::pointOnLineWithDistance( minEdge.p2().x(), minEdge.p2().y(), minEdge.p1().x(), minEdge.p1().y(), mSegmentPointWidthMm, x, y );
286  mBalloonSegmentPoint1 = QPointF( x, y );
287  }
288 
289  {
290  double x = 0;
291  double y = 0;
292  QgsGeometryUtils::pointOnLineWithDistance( mBalloonSegmentPoint1.x(), mBalloonSegmentPoint1.y(), minEdge.p2().x(), minEdge.p2().y(), mSegmentPointWidthMm, x, y );
293  mBalloonSegmentPoint2 = QPointF( x, y );
294  }
295 
296 }
297 
298 QLineF QgsAnnotation::segment( int index, QgsRenderContext *context ) const
299 {
300  auto scaleSize = [context]( double size )->double
301  {
302  return context ? context->convertToPainterUnits( size, QgsUnitTypes::RenderMillimeters ) : size;
303  };
304  if ( mHasFixedMapPosition )
305  {
306  switch ( index )
307  {
308  case 0:
309  return QLineF( scaleSize( mOffsetFromReferencePoint.x() ),
310  scaleSize( mOffsetFromReferencePoint.y() ),
311  scaleSize( mOffsetFromReferencePoint.x() ) + scaleSize( mFrameSize.width() ),
312  scaleSize( mOffsetFromReferencePoint.y() ) );
313  case 1:
314  return QLineF( scaleSize( mOffsetFromReferencePoint.x() ) + scaleSize( mFrameSize.width() ),
315  scaleSize( mOffsetFromReferencePoint.y() ),
316  scaleSize( mOffsetFromReferencePoint.x() ) + scaleSize( mFrameSize.width() ),
317  scaleSize( mOffsetFromReferencePoint.y() ) + scaleSize( mFrameSize.height() ) );
318  case 2:
319  return QLineF( scaleSize( mOffsetFromReferencePoint.x() ) + scaleSize( mFrameSize.width() ),
320  scaleSize( mOffsetFromReferencePoint.y() ) + scaleSize( mFrameSize.height() ),
321  scaleSize( mOffsetFromReferencePoint.x() ),
322  scaleSize( mOffsetFromReferencePoint.y() ) + scaleSize( mFrameSize.height() ) );
323  case 3:
324  return QLineF( scaleSize( mOffsetFromReferencePoint.x() ),
325  scaleSize( mOffsetFromReferencePoint.y() ) + scaleSize( mFrameSize.height() ),
326  scaleSize( mOffsetFromReferencePoint.x() ),
327  scaleSize( mOffsetFromReferencePoint.y() ) );
328  default:
329  return QLineF();
330  }
331  }
332  else
333  {
334  switch ( index )
335  {
336  case 0:
337  return QLineF( 0, 0, scaleSize( mFrameSize.width() ), 0 );
338  case 1:
339  return QLineF( scaleSize( mFrameSize.width() ), 0,
340  scaleSize( mFrameSize.width() ), scaleSize( mFrameSize.height() ) );
341  case 2:
342  return QLineF( scaleSize( mFrameSize.width() ), scaleSize( mFrameSize.height() ),
343  0, scaleSize( mFrameSize.height() ) );
344  case 3:
345  return QLineF( 0, scaleSize( mFrameSize.height() ),
346  0, 0 );
347  default:
348  return QLineF();
349  }
350  }
351 }
352 
353 void QgsAnnotation::drawFrame( QgsRenderContext &context ) const
354 {
355  if ( !mFillSymbol )
356  return;
357 
358  QPolygonF poly;
359  poly.reserve( 9 + ( mHasFixedMapPosition ? 3 : 0 ) );
360  QVector<QPolygonF> rings; //empty list
361  for ( int i = 0; i < 4; ++i )
362  {
363  QLineF currentSegment = segment( i, &context );
364  poly << QPointF( currentSegment.p1().x(),
365  currentSegment.p1().y() );
366  if ( i == mBalloonSegment && mHasFixedMapPosition )
367  {
368  poly << QPointF( context.convertToPainterUnits( mBalloonSegmentPoint1.x(), QgsUnitTypes::RenderMillimeters ),
369  context.convertToPainterUnits( mBalloonSegmentPoint1.y(), QgsUnitTypes::RenderMillimeters ) );
370  poly << QPointF( 0, 0 );
371  poly << QPointF( context.convertToPainterUnits( mBalloonSegmentPoint2.x(), QgsUnitTypes::RenderMillimeters ),
372  context.convertToPainterUnits( mBalloonSegmentPoint2.y(), QgsUnitTypes::RenderMillimeters ) );
373  }
374  poly << QPointF( currentSegment.p2().x(), currentSegment.p2().y() );
375  }
376  if ( poly.at( 0 ) != poly.at( poly.count() - 1 ) )
377  poly << poly.at( 0 );
378 
379  mFillSymbol->startRender( context );
380  mFillSymbol->renderPolygon( poly, &rings, nullptr, context );
381  mFillSymbol->stopRender( context );
382 }
383 
384 void QgsAnnotation::drawMarkerSymbol( QgsRenderContext &context ) const
385 {
386  if ( !context.painter() )
387  {
388  return;
389  }
390 
391  if ( mMarkerSymbol )
392  {
393  mMarkerSymbol->startRender( context );
394  mMarkerSymbol->renderPoint( QPointF( 0, 0 ), nullptr, context );
395  mMarkerSymbol->stopRender( context );
396  }
397 }
398 
399 void QgsAnnotation::_writeXml( QDomElement &itemElem, QDomDocument &doc, const QgsReadWriteContext &context ) const
400 {
401  if ( itemElem.isNull() )
402  {
403  return;
404  }
405  QDomElement annotationElem = doc.createElement( QStringLiteral( "AnnotationItem" ) );
406  annotationElem.setAttribute( QStringLiteral( "mapPositionFixed" ), mHasFixedMapPosition );
407  annotationElem.setAttribute( QStringLiteral( "mapPosX" ), qgsDoubleToString( mMapPosition.x() ) );
408  annotationElem.setAttribute( QStringLiteral( "mapPosY" ), qgsDoubleToString( mMapPosition.y() ) );
409  if ( mMapPositionCrs.isValid() )
410  mMapPositionCrs.writeXml( annotationElem, doc );
411  annotationElem.setAttribute( QStringLiteral( "offsetXMM" ), qgsDoubleToString( mOffsetFromReferencePoint.x() ) );
412  annotationElem.setAttribute( QStringLiteral( "offsetYMM" ), qgsDoubleToString( mOffsetFromReferencePoint.y() ) );
413  annotationElem.setAttribute( QStringLiteral( "frameWidthMM" ), qgsDoubleToString( mFrameSize.width() ) );
414  annotationElem.setAttribute( QStringLiteral( "frameHeightMM" ), qgsDoubleToString( mFrameSize.height() ) );
415  annotationElem.setAttribute( QStringLiteral( "canvasPosX" ), qgsDoubleToString( mRelativePosition.x() ) );
416  annotationElem.setAttribute( QStringLiteral( "canvasPosY" ), qgsDoubleToString( mRelativePosition.y() ) );
417  annotationElem.setAttribute( QStringLiteral( "contentsMargin" ), mContentsMargins.toString() );
418  annotationElem.setAttribute( QStringLiteral( "visible" ), isVisible() );
419  if ( mMapLayer )
420  {
421  annotationElem.setAttribute( QStringLiteral( "mapLayer" ), mMapLayer->id() );
422  }
423  if ( mMarkerSymbol )
424  {
425  QDomElement symbolElem = QgsSymbolLayerUtils::saveSymbol( QStringLiteral( "marker symbol" ), mMarkerSymbol.get(), doc, context );
426  if ( !symbolElem.isNull() )
427  {
428  annotationElem.appendChild( symbolElem );
429  }
430  }
431  if ( mFillSymbol )
432  {
433  QDomElement fillElem = doc.createElement( QStringLiteral( "fillSymbol" ) );
434  QDomElement symbolElem = QgsSymbolLayerUtils::saveSymbol( QStringLiteral( "fill symbol" ), mFillSymbol.get(), doc, context );
435  if ( !symbolElem.isNull() )
436  {
437  fillElem.appendChild( symbolElem );
438  annotationElem.appendChild( fillElem );
439  }
440  }
441  itemElem.appendChild( annotationElem );
442 }
443 
444 void QgsAnnotation::_readXml( const QDomElement &annotationElem, const QgsReadWriteContext &context )
445 {
446  if ( annotationElem.isNull() )
447  {
448  return;
449  }
450  QPointF pos;
451  pos.setX( annotationElem.attribute( QStringLiteral( "canvasPosX" ), QStringLiteral( "0" ) ).toDouble() );
452  pos.setY( annotationElem.attribute( QStringLiteral( "canvasPosY" ), QStringLiteral( "0" ) ).toDouble() );
453  if ( pos.x() >= 1 || pos.x() < 0 || pos.y() < 0 || pos.y() >= 1 )
454  mRelativePosition = QPointF();
455  else
456  mRelativePosition = pos;
457  QgsPointXY mapPos;
458  mapPos.setX( annotationElem.attribute( QStringLiteral( "mapPosX" ), QStringLiteral( "0" ) ).toDouble() );
459  mapPos.setY( annotationElem.attribute( QStringLiteral( "mapPosY" ), QStringLiteral( "0" ) ).toDouble() );
460  mMapPosition = mapPos;
461 
462  if ( !mMapPositionCrs.readXml( annotationElem ) )
463  {
464  mMapPositionCrs = QgsCoordinateReferenceSystem();
465  }
466 
467  mContentsMargins = QgsMargins::fromString( annotationElem.attribute( QStringLiteral( "contentsMargin" ) ) );
468  const double dpiScale = 25.4 / qt_defaultDpiX();
469  if ( annotationElem.hasAttribute( QStringLiteral( "frameWidthMM" ) ) )
470  mFrameSize.setWidth( annotationElem.attribute( QStringLiteral( "frameWidthMM" ), QStringLiteral( "5" ) ).toDouble() );
471  else
472  mFrameSize.setWidth( dpiScale * annotationElem.attribute( QStringLiteral( "frameWidth" ), QStringLiteral( "50" ) ).toDouble() );
473  if ( annotationElem.hasAttribute( QStringLiteral( "frameHeightMM" ) ) )
474  mFrameSize.setHeight( annotationElem.attribute( QStringLiteral( "frameHeightMM" ), QStringLiteral( "3" ) ).toDouble() );
475  else
476  mFrameSize.setHeight( dpiScale * annotationElem.attribute( QStringLiteral( "frameHeight" ), QStringLiteral( "50" ) ).toDouble() );
477 
478  if ( annotationElem.hasAttribute( QStringLiteral( "offsetXMM" ) ) )
479  mOffsetFromReferencePoint.setX( annotationElem.attribute( QStringLiteral( "offsetXMM" ), QStringLiteral( "0" ) ).toDouble() );
480  else
481  mOffsetFromReferencePoint.setX( dpiScale * annotationElem.attribute( QStringLiteral( "offsetX" ), QStringLiteral( "0" ) ).toDouble() );
482  if ( annotationElem.hasAttribute( QStringLiteral( "offsetYMM" ) ) )
483  mOffsetFromReferencePoint.setY( annotationElem.attribute( QStringLiteral( "offsetYMM" ), QStringLiteral( "0" ) ).toDouble() );
484  else
485  mOffsetFromReferencePoint.setY( dpiScale * annotationElem.attribute( QStringLiteral( "offsetY" ), QStringLiteral( "0" ) ).toDouble() );
486 
487  mHasFixedMapPosition = annotationElem.attribute( QStringLiteral( "mapPositionFixed" ), QStringLiteral( "1" ) ).toInt();
488  mVisible = annotationElem.attribute( QStringLiteral( "visible" ), QStringLiteral( "1" ) ).toInt();
489  if ( annotationElem.hasAttribute( QStringLiteral( "mapLayer" ) ) )
490  {
491  mMapLayer = QgsProject::instance()->mapLayer( annotationElem.attribute( QStringLiteral( "mapLayer" ) ) );
492  }
493 
494  //marker symbol
495  {
496  QDomElement symbolElem = annotationElem.firstChildElement( QStringLiteral( "symbol" ) );
497  if ( !symbolElem.isNull() )
498  {
499  QgsMarkerSymbol *symbol = QgsSymbolLayerUtils::loadSymbol<QgsMarkerSymbol>( symbolElem, context );
500  if ( symbol )
501  {
502  mMarkerSymbol.reset( symbol );
503  }
504  }
505  }
506 
507  mFillSymbol.reset( nullptr );
508  QDomElement fillElem = annotationElem.firstChildElement( QStringLiteral( "fillSymbol" ) );
509  if ( !fillElem.isNull() )
510  {
511  QDomElement symbolElem = fillElem.firstChildElement( QStringLiteral( "symbol" ) );
512  if ( !symbolElem.isNull() )
513  {
514  QgsFillSymbol *symbol = QgsSymbolLayerUtils::loadSymbol<QgsFillSymbol>( symbolElem, context );
515  if ( symbol )
516  {
517  mFillSymbol.reset( symbol );
518  }
519  }
520  }
521  if ( !mFillSymbol )
522  {
523  QColor frameColor;
524  frameColor.setNamedColor( annotationElem.attribute( QStringLiteral( "frameColor" ), QStringLiteral( "#000000" ) ) );
525  frameColor.setAlpha( annotationElem.attribute( QStringLiteral( "frameColorAlpha" ), QStringLiteral( "255" ) ).toInt() );
526  QColor frameBackgroundColor;
527  frameBackgroundColor.setNamedColor( annotationElem.attribute( QStringLiteral( "frameBackgroundColor" ) ) );
528  frameBackgroundColor.setAlpha( annotationElem.attribute( QStringLiteral( "frameBackgroundColorAlpha" ), QStringLiteral( "255" ) ).toInt() );
529  double frameBorderWidth = annotationElem.attribute( QStringLiteral( "frameBorderWidth" ), QStringLiteral( "0.5" ) ).toDouble();
530  // need to roughly convert border width from pixels to mm - just assume 96 dpi
531  frameBorderWidth = frameBorderWidth * 25.4 / 96.0;
532  QgsStringMap props;
533  props.insert( QStringLiteral( "color" ), frameBackgroundColor.name() );
534  props.insert( QStringLiteral( "style" ), QStringLiteral( "solid" ) );
535  props.insert( QStringLiteral( "style_border" ), QStringLiteral( "solid" ) );
536  props.insert( QStringLiteral( "color_border" ), frameColor.name() );
537  props.insert( QStringLiteral( "width_border" ), QString::number( frameBorderWidth ) );
538  props.insert( QStringLiteral( "joinstyle" ), QStringLiteral( "miter" ) );
539  mFillSymbol.reset( QgsFillSymbol::createSimple( props ) );
540  }
541 
542  updateBalloon();
543  emit mapLayerChanged();
544 }
545 
547 {
548  target->mVisible = mVisible;
549  target->mHasFixedMapPosition = mHasFixedMapPosition;
550  target->mMapPosition = mMapPosition;
551  target->mMapPositionCrs = mMapPositionCrs;
552  target->mRelativePosition = mRelativePosition;
553  target->mOffsetFromReferencePoint = mOffsetFromReferencePoint;
554  target->mFrameSize = mFrameSize;
555  target->mMarkerSymbol.reset( mMarkerSymbol ? mMarkerSymbol->clone() : nullptr );
556  target->mContentsMargins = mContentsMargins;
557  target->mFillSymbol.reset( mFillSymbol ? mFillSymbol->clone() : nullptr );
558  target->mBalloonSegment = mBalloonSegment;
559  target->mBalloonSegmentPoint1 = mBalloonSegmentPoint1;
560  target->mBalloonSegmentPoint2 = mBalloonSegmentPoint2;
561  target->mSegmentPointWidthMm = mSegmentPointWidthMm;
562  target->mMapLayer = mMapLayer;
563  target->mFeature = mFeature;
564 }
565 
QgsMargins::bottom
double bottom() const
Returns the bottom margin.
Definition: qgsmargins.h:90
QgsAnnotation::mapLayerChanged
void mapLayerChanged()
Emitted when the map layer associated with the annotation changes.
QgsAnnotation::setMapPositionCrs
void setMapPositionCrs(const QgsCoordinateReferenceSystem &crs)
Sets the CRS of the map position.
Definition: qgsannotation.cpp:69
QgsPointXY::y
double y
Definition: qgspointxy.h:48
QgsRenderContext::convertToPainterUnits
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale()) const
Converts a size from the specified units to painter units (pixels).
Definition: qgsrendercontext.cpp:318
QgsRenderContext::setPainterFlagsUsingContext
void setPainterFlagsUsingContext(QPainter *painter=nullptr) const
Sets relevant flags on a destination painter, using the flags and settings currently defined for the ...
Definition: qgsrendercontext.cpp:143
QgsMargins::top
double top() const
Returns the top margin.
Definition: qgsmargins.h:78
QgsAnnotation::_readXml
void _readXml(const QDomElement &annotationElem, const QgsReadWriteContext &context)
Reads common annotation properties from a DOM element.
Definition: qgsannotation.cpp:444
QgsReadWriteContext
The class is used as a container of context for various read/write operations on other objects.
Definition: qgsreadwritecontext.h:35
qgsannotation.h
QgsStyleSymbolEntity
A symbol entity for QgsStyle databases.
Definition: qgsstyle.h:1201
QgsAnnotation::setContentsMargin
void setContentsMargin(const QgsMargins &margins)
Sets the margins (in millimeters) between the outside of the frame and the annotation content.
Definition: qgsannotation.cpp:121
QgsPointXY::x
Q_GADGET double x
Definition: qgspointxy.h:47
crs
const QgsCoordinateReferenceSystem & crs
Definition: qgswfsgetfeature.cpp:51
QgsAnnotation::render
void render(QgsRenderContext &context) const
Renders the annotation to a target render context.
Definition: qgsannotation.cpp:133
qgssymbollayerutils.h
QgsPointXY::setY
void setY(double y) SIP_HOLDGIL
Sets the y value of the point.
Definition: qgspointxy.h:117
QgsRenderContext
Contains information about the context of a rendering operation.
Definition: qgsrendercontext.h:58
QgsProject::instance
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:468
QgsStyleEntityVisitorInterface::NodeType::Annotation
@ Annotation
An individual annotation.
QgsStyleEntityVisitorInterface
An interface for classes which can visit style entity (e.g.
Definition: qgsstyleentityvisitor.h:34
QgsUnitTypes::RenderMillimeters
@ RenderMillimeters
Millimeters.
Definition: qgsunittypes.h:168
QgsStyleEntityVisitorInterface::visitExit
virtual bool visitExit(const QgsStyleEntityVisitorInterface::Node &node)
Called when the visitor stops visiting a node.
Definition: qgsstyleentityvisitor.h:183
QgsProject::mapLayer
Q_INVOKABLE QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
Definition: qgsproject.cpp:3208
QgsCoordinateReferenceSystem::readXml
bool readXml(const QDomNode &node)
Restores state from the given DOM node.
Definition: qgscoordinatereferencesystem.cpp:2018
QgsAnnotation::setFrameSize
Q_DECL_DEPRECATED void setFrameSize(QSizeF size)
Sets the size (in pixels) of the annotation's frame (the main area in which the annotation's content ...
Definition: qgsannotation.cpp:101
QgsPointXY::setX
void setX(double x) SIP_HOLDGIL
Sets the x value of the point.
Definition: qgspointxy.h:107
QgsAnnotation::renderAnnotation
virtual void renderAnnotation(QgsRenderContext &context, QSizeF size) const =0
Renders the annotation's contents to a target /a context at the specified /a size.
QgsAnnotation::setFrameOffsetFromReferencePointMm
void setFrameOffsetFromReferencePointMm(QPointF offset)
Sets the annotation's frame's offset (in millimeters) from the mapPosition() reference point.
Definition: qgsannotation.cpp:92
QgsStyleEntityVisitorInterface::StyleLeaf
Contains information relating to the style entity currently being visited.
Definition: qgsstyleentityvisitor.h:61
qgsDoubleToString
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition: qgis.h:275
QgsAnnotation::setMapPosition
void setMapPosition(const QgsPointXY &position)
Sets the map position of the annotation, if it is attached to a fixed map position.
Definition: qgsannotation.cpp:63
QgsAnnotation::setRelativePosition
void setRelativePosition(QPointF position)
Sets the relative position of the annotation, if it is not attached to a fixed map position.
Definition: qgsannotation.cpp:75
QgsPointXY::sqrDist
double sqrDist(double x, double y) const SIP_HOLDGIL
Returns the squared distance between this point a specified x, y coordinate.
Definition: qgspointxy.h:175
QgsMargins::fromString
static QgsMargins fromString(const QString &string)
Returns a QgsMargins object decoded from a string, or a null QgsMargins if the string could not be in...
Definition: qgsmargins.cpp:27
QgsAnnotation::setMarkerSymbol
void setMarkerSymbol(QgsMarkerSymbol *symbol)
Sets the symbol that is drawn at the annotation's map position.
Definition: qgsannotation.cpp:169
QgsMargins::left
double left() const
Returns the left margin.
Definition: qgsmargins.h:72
QgsAnnotation
Abstract base class for annotation items which are drawn over a map.
Definition: qgsannotation.h:50
QgsMargins::toString
QString toString() const
Returns the margins encoded to a string.
Definition: qgsmargins.cpp:18
QgsCoordinateReferenceSystem::writeXml
bool writeXml(QDomNode &node, QDomDocument &doc) const
Stores state to the given Dom node in the given document.
Definition: qgscoordinatereferencesystem.cpp:2123
QgsMarkerSymbol
A marker symbol type, for rendering Point and MultiPoint geometries.
Definition: qgssymbol.h:931
qgsDoubleNear
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:315
qgsmaplayer.h
qt_defaultDpiX
Q_GUI_EXPORT int qt_defaultDpiX()
QgsGeometryUtils::pointOnLineWithDistance
static QgsPoint pointOnLineWithDistance(const QgsPoint &startPoint, const QgsPoint &directionPoint, double distance) SIP_HOLDGIL
Returns a point a specified distance toward a second point.
Definition: qgsgeometryutils.cpp:600
QgsMargins
The QgsMargins class defines the four margins of a rectangle.
Definition: qgsmargins.h:38
QgsCoordinateReferenceSystem::isValid
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
Definition: qgscoordinatereferencesystem.cpp:924
QgsAnnotation::setVisible
void setVisible(bool visible)
Sets whether the annotation is visible and should be rendered.
Definition: qgsannotation.cpp:44
QgsAnnotation::isVisible
bool isVisible() const
Returns true if the annotation is visible and should be rendered.
Definition: qgsannotation.h:89
QgsMargins::right
double right() const
Returns the right margin.
Definition: qgsmargins.h:84
QgsAnnotation::_writeXml
void _writeXml(QDomElement &itemElem, QDomDocument &doc, const QgsReadWriteContext &context) const
Writes common annotation properties to a DOM element.
Definition: qgsannotation.cpp:399
QgsStyleEntityVisitorInterface::Node
Contains information relating to a node (i.e.
Definition: qgsstyleentityvisitor.h:111
QgsScopedQPainterState
Scoped object for saving and restoring a QPainter object's state.
Definition: qgsrendercontext.h:1120
QgsAnnotation::setAssociatedFeature
virtual void setAssociatedFeature(const QgsFeature &feature)
Sets the feature associated with the annotation.
Definition: qgsannotation.cpp:181
QgsCoordinateReferenceSystem
This class represents a coordinate reference system (CRS).
Definition: qgscoordinatereferencesystem.h:206
qgsgeometryutils.h
QgsAnnotation::setFrameSizeMm
void setFrameSizeMm(QSizeF size)
Sets the size (in millimeters) of the annotation's frame (the main area in which the annotation's con...
Definition: qgsannotation.cpp:112
QgsPointXY
A class to represent a 2D point.
Definition: qgspointxy.h:44
QgsStyleEntityVisitorInterface::visitEnter
virtual bool visitEnter(const QgsStyleEntityVisitorInterface::Node &node)
Called when the visitor starts visiting a node.
Definition: qgsstyleentityvisitor.h:169
QgsAnnotation::accept
virtual bool accept(QgsStyleEntityVisitorInterface *visitor) const
Accepts the specified style entity visitor, causing it to visit all style entities associated within ...
Definition: qgsannotation.cpp:186
QgsAnnotation::minimumFrameSize
virtual QSizeF minimumFrameSize() const
Returns the minimum frame size for the annotation.
Definition: qgsannotation.cpp:212
QgsAnnotation::frameSize
QSizeF frameSize
Definition: qgsannotation.h:70
QgsStringMap
QMap< QString, QString > QgsStringMap
Definition: qgis.h:758
QgsAnnotation::setHasFixedMapPosition
void setHasFixedMapPosition(bool fixed)
Sets whether the annotation is attached to a fixed map position, or uses a position relative to the c...
Definition: qgsannotation.cpp:53
QgsAnnotation::QgsAnnotation
QgsAnnotation(QObject *parent=nullptr)
Constructor for QgsAnnotation.
Definition: qgsannotation.cpp:30
QgsMapLayer
Base class for all map layer types.
Definition: qgsmaplayer.h:83
QgsFillSymbol
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
Definition: qgssymbol.h:1234
QgsAnnotation::appearanceChanged
void appearanceChanged()
Emitted whenever the annotation's appearance changes.
QgsStyleEntityVisitorInterface::visit
virtual bool visit(const QgsStyleEntityVisitorInterface::StyleLeaf &entity)
Called when the visitor will visit a style entity.
Definition: qgsstyleentityvisitor.h:153
QgsAnnotation::setFillSymbol
void setFillSymbol(QgsFillSymbol *symbol)
Sets the fill symbol used for rendering the annotation frame.
Definition: qgsannotation.cpp:127
QgsAnnotation::frameOffsetFromReferencePoint
Q_DECL_DEPRECATED QPointF frameOffsetFromReferencePoint() const
Returns the annotation's frame's offset (in pixels) from the mapPosition() reference point.
Definition: qgsannotation.cpp:87
QgsFeature
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:56
QgsFillSymbol::createSimple
static QgsFillSymbol * createSimple(const QgsStringMap &properties)
Create a fill symbol with one symbol layer: SimpleFill with specified properties.
Definition: qgssymbol.cpp:1481
QgsAnnotation::visible
bool visible
Definition: qgsannotation.h:67
QgsRenderContext::painter
QPainter * painter()
Returns the destination QPainter for the render operation.
Definition: qgsrendercontext.h:179
QgsPointXY::sqrDistToSegment
double sqrDistToSegment(double x1, double y1, double x2, double y2, QgsPointXY &minDistPoint, double epsilon=DEFAULT_SEGMENT_EPSILON) const SIP_HOLDGIL
Returns the minimum distance between this point and a segment.
Definition: qgspointxy.cpp:95
QgsAnnotation::setFrameOffsetFromReferencePoint
Q_DECL_DEPRECATED void setFrameOffsetFromReferencePoint(QPointF offset)
Sets the annotation's frame's offset (in pixels) from the mapPosition() reference point.
Definition: qgsannotation.cpp:81
MathUtils::angle
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
Definition: MathUtils.cpp:786
QgsSymbolLayerUtils::saveSymbol
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
Definition: qgssymbollayerutils.cpp:1182
QgsAnnotation::moved
void moved()
Emitted when the annotation's position has changed and items need to be moved to reflect this.
qgsproject.h
qgsstyleentityvisitor.h
QgsAnnotation::copyCommonProperties
void copyCommonProperties(QgsAnnotation *target) const
Copies common annotation properties to the targe annotation.
Definition: qgsannotation.cpp:546
QgsAnnotation::setMapLayer
void setMapLayer(QgsMapLayer *layer)
Sets the map layer associated with the annotation.
Definition: qgsannotation.cpp:175