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