QGIS API Documentation  3.21.0-Master (5b68dc587e)
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 #include "qgsshapegenerator.h"
25 #include "qgssymbol.h"
26 #include "qgsmarkersymbol.h"
27 #include "qgsfillsymbol.h"
28 
29 #include <QPen>
30 #include <QPainter>
31 
32 Q_GUI_EXPORT extern int qt_defaultDpiX();
33 
34 QgsAnnotation::QgsAnnotation( QObject *parent )
35  : QObject( parent )
36  , mMarkerSymbol( new QgsMarkerSymbol() )
37 {
38  QVariantMap props;
39  props.insert( QStringLiteral( "color" ), QStringLiteral( "white" ) );
40  props.insert( QStringLiteral( "style" ), QStringLiteral( "solid" ) );
41  props.insert( QStringLiteral( "style_border" ), QStringLiteral( "solid" ) );
42  props.insert( QStringLiteral( "color_border" ), QStringLiteral( "black" ) );
43  props.insert( QStringLiteral( "width_border" ), QStringLiteral( "0.3" ) );
44  props.insert( QStringLiteral( "joinstyle" ), QStringLiteral( "miter" ) );
45  mFillSymbol.reset( QgsFillSymbol::createSimple( props ) );
46 }
47 
49 
50 void QgsAnnotation::setVisible( bool visible )
51 {
52  if ( mVisible == visible )
53  return;
54 
55  mVisible = visible;
56  emit appearanceChanged();
57 }
58 
60 {
61  if ( mHasFixedMapPosition == fixed )
62  return;
63 
64  mHasFixedMapPosition = fixed;
65  emit moved();
66 }
67 
69 {
70  mMapPosition = position;
71  emit moved();
72 }
73 
75 {
76  mMapPositionCrs = crs;
77  emit moved();
78 }
79 
80 void QgsAnnotation::setRelativePosition( QPointF position )
81 {
82  mRelativePosition = position;
83  emit moved();
84 }
85 
87 {
88  // convert from offset in pixels at 96 dpi to mm
89  setFrameOffsetFromReferencePointMm( offset / 3.7795275 );
90 }
91 
93 {
94  return mOffsetFromReferencePoint / 3.7795275;
95 }
96 
98 {
99  mOffsetFromReferencePoint = offset;
100 
101  emit moved();
102  emit appearanceChanged();
103 }
104 
105 void QgsAnnotation::setFrameSize( QSizeF size )
106 {
107  // convert from size in pixels at 96 dpi to mm
108  setFrameSizeMm( size / 3.7795275 );
109 }
110 
112 {
113  return mFrameSize / 3.7795275;
114 }
115 
116 void QgsAnnotation::setFrameSizeMm( QSizeF size )
117 {
118  const QSizeF frameSize = minimumFrameSize().expandedTo( size ); //don't allow frame sizes below minimum
119  mFrameSize = frameSize;
120  emit moved();
121  emit appearanceChanged();
122 }
123 
125 {
126  mContentsMargins = margins;
127  emit appearanceChanged();
128 }
129 
131 {
132  mFillSymbol.reset( symbol );
133  emit appearanceChanged();
134 }
135 
137 {
138  return mFillSymbol.get();
139 }
140 
142 {
143  QPainter *painter = context.painter();
144  if ( !painter )
145  {
146  return;
147  }
148 
149  const QgsScopedQPainterState painterState( context.painter() );
150  context.setPainterFlagsUsingContext();
151 
152  drawFrame( context );
153  if ( mHasFixedMapPosition )
154  {
155  drawMarkerSymbol( context );
156  }
157  if ( mHasFixedMapPosition )
158  {
159  painter->translate( context.convertToPainterUnits( mOffsetFromReferencePoint.x(), QgsUnitTypes::RenderMillimeters ) + context.convertToPainterUnits( mContentsMargins.left(), QgsUnitTypes::RenderMillimeters ),
160  context.convertToPainterUnits( mOffsetFromReferencePoint.y(), QgsUnitTypes::RenderMillimeters ) + context.convertToPainterUnits( mContentsMargins.top(), QgsUnitTypes::RenderMillimeters ) );
161  }
162  else
163  {
164  painter->translate( context.convertToPainterUnits( mContentsMargins.left(), QgsUnitTypes::RenderMillimeters ),
165  context.convertToPainterUnits( mContentsMargins.top(), QgsUnitTypes::RenderMillimeters ) );
166  }
167  const QSizeF size( context.convertToPainterUnits( mFrameSize.width(), QgsUnitTypes::RenderMillimeters ) - context.convertToPainterUnits( mContentsMargins.left() + mContentsMargins.right(), QgsUnitTypes::RenderMillimeters ),
168  context.convertToPainterUnits( mFrameSize.height(), QgsUnitTypes::RenderMillimeters ) - context.convertToPainterUnits( mContentsMargins.top() + mContentsMargins.bottom(), QgsUnitTypes::RenderMillimeters ) );
169 
170  // scale back from painter dpi to 96 dpi --
171 // double dotsPerMM = context.painter()->device()->logicalDpiX() / ( 25.4 * 3.78 );
172 // context.painter()->scale( dotsPerMM, dotsPerMM );
173 
174  renderAnnotation( context, size );
175 }
176 
178 {
179  mMarkerSymbol.reset( symbol );
180  emit appearanceChanged();
181 }
182 
184 {
185  mMapLayer = layer;
186  emit mapLayerChanged();
187 }
188 
190 {
191  mFeature = feature;
192 }
193 
195 {
196  // NOTE: if visitEnter returns false it means "don't visit the annotation", not "abort all further visitations"
197  if ( !visitor->visitEnter( QgsStyleEntityVisitorInterface::Node( QgsStyleEntityVisitorInterface::NodeType::Annotation, QStringLiteral( "annotation" ), tr( "Annotation" ) ) ) )
198  return true;
199 
200  if ( mMarkerSymbol )
201  {
202  QgsStyleSymbolEntity entity( mMarkerSymbol.get() );
203  if ( !visitor->visit( QgsStyleEntityVisitorInterface::StyleLeaf( &entity, QStringLiteral( "marker" ), QObject::tr( "Marker" ) ) ) )
204  return false;
205  }
206 
207  if ( mFillSymbol )
208  {
209  QgsStyleSymbolEntity entity( mFillSymbol.get() );
210  if ( !visitor->visit( QgsStyleEntityVisitorInterface::StyleLeaf( &entity, QStringLiteral( "fill" ), QObject::tr( "Fill" ) ) ) )
211  return false;
212  }
213 
214  if ( !visitor->visitExit( QgsStyleEntityVisitorInterface::Node( QgsStyleEntityVisitorInterface::NodeType::Annotation, QStringLiteral( "annotation" ), tr( "Annotation" ) ) ) )
215  return false;
216 
217  return true;
218 }
219 
221 {
222  return QSizeF( 0, 0 );
223 }
224 
225 void QgsAnnotation::drawFrame( QgsRenderContext &context ) const
226 {
227  if ( !mFillSymbol )
228  return;
229 
230  auto scaleSize = [&context]( double size )->double
231  {
233  };
234 
235  const QRectF frameRect( mHasFixedMapPosition ? scaleSize( mOffsetFromReferencePoint.x() ) : 0,
236  mHasFixedMapPosition ? scaleSize( mOffsetFromReferencePoint.y() ) : 0,
237  scaleSize( mFrameSize.width() ),
238  scaleSize( mFrameSize.height() ) );
239  const QgsPointXY origin = mHasFixedMapPosition ? QgsPointXY( 0, 0 ) : QgsPointXY( frameRect.center().x(), frameRect.center().y() );
240 
241  const QPolygonF poly = QgsShapeGenerator::createBalloon( origin, frameRect, context.convertToPainterUnits( mSegmentPointWidthMm, QgsUnitTypes::RenderMillimeters ) );
242 
243  mFillSymbol->startRender( context );
244  const QVector<QPolygonF> rings; //empty list
245  mFillSymbol->renderPolygon( poly, &rings, nullptr, context );
246  mFillSymbol->stopRender( context );
247 }
248 
249 void QgsAnnotation::drawMarkerSymbol( QgsRenderContext &context ) const
250 {
251  if ( !context.painter() )
252  {
253  return;
254  }
255 
256  if ( mMarkerSymbol )
257  {
258  mMarkerSymbol->startRender( context );
259  mMarkerSymbol->renderPoint( QPointF( 0, 0 ), nullptr, context );
260  mMarkerSymbol->stopRender( context );
261  }
262 }
263 
264 void QgsAnnotation::_writeXml( QDomElement &itemElem, QDomDocument &doc, const QgsReadWriteContext &context ) const
265 {
266  if ( itemElem.isNull() )
267  {
268  return;
269  }
270  QDomElement annotationElem = doc.createElement( QStringLiteral( "AnnotationItem" ) );
271  annotationElem.setAttribute( QStringLiteral( "mapPositionFixed" ), mHasFixedMapPosition );
272  annotationElem.setAttribute( QStringLiteral( "mapPosX" ), qgsDoubleToString( mMapPosition.x() ) );
273  annotationElem.setAttribute( QStringLiteral( "mapPosY" ), qgsDoubleToString( mMapPosition.y() ) );
274  if ( mMapPositionCrs.isValid() )
275  mMapPositionCrs.writeXml( annotationElem, doc );
276  annotationElem.setAttribute( QStringLiteral( "offsetXMM" ), qgsDoubleToString( mOffsetFromReferencePoint.x() ) );
277  annotationElem.setAttribute( QStringLiteral( "offsetYMM" ), qgsDoubleToString( mOffsetFromReferencePoint.y() ) );
278  annotationElem.setAttribute( QStringLiteral( "frameWidthMM" ), qgsDoubleToString( mFrameSize.width() ) );
279  annotationElem.setAttribute( QStringLiteral( "frameHeightMM" ), qgsDoubleToString( mFrameSize.height() ) );
280  annotationElem.setAttribute( QStringLiteral( "canvasPosX" ), qgsDoubleToString( mRelativePosition.x() ) );
281  annotationElem.setAttribute( QStringLiteral( "canvasPosY" ), qgsDoubleToString( mRelativePosition.y() ) );
282  annotationElem.setAttribute( QStringLiteral( "contentsMargin" ), mContentsMargins.toString() );
283  annotationElem.setAttribute( QStringLiteral( "visible" ), isVisible() );
284  if ( mMapLayer )
285  {
286  annotationElem.setAttribute( QStringLiteral( "mapLayer" ), mMapLayer->id() );
287  }
288  if ( mMarkerSymbol )
289  {
290  const QDomElement symbolElem = QgsSymbolLayerUtils::saveSymbol( QStringLiteral( "marker symbol" ), mMarkerSymbol.get(), doc, context );
291  if ( !symbolElem.isNull() )
292  {
293  annotationElem.appendChild( symbolElem );
294  }
295  }
296  if ( mFillSymbol )
297  {
298  QDomElement fillElem = doc.createElement( QStringLiteral( "fillSymbol" ) );
299  const QDomElement symbolElem = QgsSymbolLayerUtils::saveSymbol( QStringLiteral( "fill symbol" ), mFillSymbol.get(), doc, context );
300  if ( !symbolElem.isNull() )
301  {
302  fillElem.appendChild( symbolElem );
303  annotationElem.appendChild( fillElem );
304  }
305  }
306  itemElem.appendChild( annotationElem );
307 }
308 
309 void QgsAnnotation::_readXml( const QDomElement &annotationElem, const QgsReadWriteContext &context )
310 {
311  if ( annotationElem.isNull() )
312  {
313  return;
314  }
315  QPointF pos;
316  pos.setX( annotationElem.attribute( QStringLiteral( "canvasPosX" ), QStringLiteral( "0" ) ).toDouble() );
317  pos.setY( annotationElem.attribute( QStringLiteral( "canvasPosY" ), QStringLiteral( "0" ) ).toDouble() );
318  if ( pos.x() >= 1 || pos.x() < 0 || pos.y() < 0 || pos.y() >= 1 )
319  mRelativePosition = QPointF();
320  else
321  mRelativePosition = pos;
322  QgsPointXY mapPos;
323  mapPos.setX( annotationElem.attribute( QStringLiteral( "mapPosX" ), QStringLiteral( "0" ) ).toDouble() );
324  mapPos.setY( annotationElem.attribute( QStringLiteral( "mapPosY" ), QStringLiteral( "0" ) ).toDouble() );
325  mMapPosition = mapPos;
326 
327  if ( !mMapPositionCrs.readXml( annotationElem ) )
328  {
329  mMapPositionCrs = QgsCoordinateReferenceSystem();
330  }
331 
332  mContentsMargins = QgsMargins::fromString( annotationElem.attribute( QStringLiteral( "contentsMargin" ) ) );
333  const double dpiScale = 25.4 / qt_defaultDpiX();
334  if ( annotationElem.hasAttribute( QStringLiteral( "frameWidthMM" ) ) )
335  mFrameSize.setWidth( annotationElem.attribute( QStringLiteral( "frameWidthMM" ), QStringLiteral( "5" ) ).toDouble() );
336  else
337  mFrameSize.setWidth( dpiScale * annotationElem.attribute( QStringLiteral( "frameWidth" ), QStringLiteral( "50" ) ).toDouble() );
338  if ( annotationElem.hasAttribute( QStringLiteral( "frameHeightMM" ) ) )
339  mFrameSize.setHeight( annotationElem.attribute( QStringLiteral( "frameHeightMM" ), QStringLiteral( "3" ) ).toDouble() );
340  else
341  mFrameSize.setHeight( dpiScale * annotationElem.attribute( QStringLiteral( "frameHeight" ), QStringLiteral( "50" ) ).toDouble() );
342 
343  if ( annotationElem.hasAttribute( QStringLiteral( "offsetXMM" ) ) )
344  mOffsetFromReferencePoint.setX( annotationElem.attribute( QStringLiteral( "offsetXMM" ), QStringLiteral( "0" ) ).toDouble() );
345  else
346  mOffsetFromReferencePoint.setX( dpiScale * annotationElem.attribute( QStringLiteral( "offsetX" ), QStringLiteral( "0" ) ).toDouble() );
347  if ( annotationElem.hasAttribute( QStringLiteral( "offsetYMM" ) ) )
348  mOffsetFromReferencePoint.setY( annotationElem.attribute( QStringLiteral( "offsetYMM" ), QStringLiteral( "0" ) ).toDouble() );
349  else
350  mOffsetFromReferencePoint.setY( dpiScale * annotationElem.attribute( QStringLiteral( "offsetY" ), QStringLiteral( "0" ) ).toDouble() );
351 
352  mHasFixedMapPosition = annotationElem.attribute( QStringLiteral( "mapPositionFixed" ), QStringLiteral( "1" ) ).toInt();
353  mVisible = annotationElem.attribute( QStringLiteral( "visible" ), QStringLiteral( "1" ) ).toInt();
354  if ( annotationElem.hasAttribute( QStringLiteral( "mapLayer" ) ) )
355  {
356  mMapLayer = QgsProject::instance()->mapLayer( annotationElem.attribute( QStringLiteral( "mapLayer" ) ) );
357  }
358 
359  //marker symbol
360  {
361  const QDomElement symbolElem = annotationElem.firstChildElement( QStringLiteral( "symbol" ) );
362  if ( !symbolElem.isNull() )
363  {
364  QgsMarkerSymbol *symbol = QgsSymbolLayerUtils::loadSymbol<QgsMarkerSymbol>( symbolElem, context );
365  if ( symbol )
366  {
367  mMarkerSymbol.reset( symbol );
368  }
369  }
370  }
371 
372  mFillSymbol.reset( nullptr );
373  const QDomElement fillElem = annotationElem.firstChildElement( QStringLiteral( "fillSymbol" ) );
374  if ( !fillElem.isNull() )
375  {
376  const QDomElement symbolElem = fillElem.firstChildElement( QStringLiteral( "symbol" ) );
377  if ( !symbolElem.isNull() )
378  {
379  QgsFillSymbol *symbol = QgsSymbolLayerUtils::loadSymbol<QgsFillSymbol>( symbolElem, context );
380  if ( symbol )
381  {
382  mFillSymbol.reset( symbol );
383  }
384  }
385  }
386  if ( !mFillSymbol )
387  {
388  QColor frameColor;
389  frameColor.setNamedColor( annotationElem.attribute( QStringLiteral( "frameColor" ), QStringLiteral( "#000000" ) ) );
390  frameColor.setAlpha( annotationElem.attribute( QStringLiteral( "frameColorAlpha" ), QStringLiteral( "255" ) ).toInt() );
391  QColor frameBackgroundColor;
392  frameBackgroundColor.setNamedColor( annotationElem.attribute( QStringLiteral( "frameBackgroundColor" ) ) );
393  frameBackgroundColor.setAlpha( annotationElem.attribute( QStringLiteral( "frameBackgroundColorAlpha" ), QStringLiteral( "255" ) ).toInt() );
394  double frameBorderWidth = annotationElem.attribute( QStringLiteral( "frameBorderWidth" ), QStringLiteral( "0.5" ) ).toDouble();
395  // need to roughly convert border width from pixels to mm - just assume 96 dpi
396  frameBorderWidth = frameBorderWidth * 25.4 / 96.0;
397  QVariantMap props;
398  props.insert( QStringLiteral( "color" ), frameBackgroundColor.name() );
399  props.insert( QStringLiteral( "style" ), QStringLiteral( "solid" ) );
400  props.insert( QStringLiteral( "style_border" ), QStringLiteral( "solid" ) );
401  props.insert( QStringLiteral( "color_border" ), frameColor.name() );
402  props.insert( QStringLiteral( "width_border" ), QString::number( frameBorderWidth ) );
403  props.insert( QStringLiteral( "joinstyle" ), QStringLiteral( "miter" ) );
404  mFillSymbol.reset( QgsFillSymbol::createSimple( props ) );
405  }
406 
407  emit mapLayerChanged();
408 }
409 
411 {
412  target->mVisible = mVisible;
413  target->mHasFixedMapPosition = mHasFixedMapPosition;
414  target->mMapPosition = mMapPosition;
415  target->mMapPositionCrs = mMapPositionCrs;
416  target->mRelativePosition = mRelativePosition;
417  target->mOffsetFromReferencePoint = mOffsetFromReferencePoint;
418  target->mFrameSize = mFrameSize;
419  target->mMarkerSymbol.reset( mMarkerSymbol ? mMarkerSymbol->clone() : nullptr );
420  target->mContentsMargins = mContentsMargins;
421  target->mFillSymbol.reset( mFillSymbol ? mFillSymbol->clone() : nullptr );
422  target->mSegmentPointWidthMm = mSegmentPointWidthMm;
423  target->mMapLayer = mMapLayer;
424  target->mFeature = mFeature;
425 }
426 
Abstract base class for annotation items which are drawn over a map.
Definition: qgsannotation.h:54
void appearanceChanged()
Emitted whenever the annotation's appearance changes.
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 ...
void setFillSymbol(QgsFillSymbol *symbol)
Sets the fill symbol used for rendering the annotation frame.
Q_DECL_DEPRECATED void setFrameOffsetFromReferencePoint(QPointF offset)
Sets the annotation's frame's offset (in pixels) from the mapPosition() reference point.
void setRelativePosition(QPointF position)
Sets the relative position of the annotation, if it is not attached to a fixed map position.
virtual void renderAnnotation(QgsRenderContext &context, QSizeF size) const =0
Renders the annotation's contents to a target /a context at the specified /a size.
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's position has changed and items need to be moved to reflect this.
Q_DECL_DEPRECATED QPointF frameOffsetFromReferencePoint() const
Returns the annotation's frame's offset (in pixels) from the mapPosition() reference point.
void _writeXml(QDomElement &itemElem, QDomDocument &doc, const QgsReadWriteContext &context) const
Writes common annotation properties to a DOM element.
virtual bool accept(QgsStyleEntityVisitorInterface *visitor) const
Accepts the specified style entity visitor, causing it to visit all style entities associated within ...
void setContentsMargin(const QgsMargins &margins)
Sets the margins (in millimeters) between the outside of the frame and the annotation content.
void setFrameSizeMm(QSizeF size)
Sets the size (in millimeters) of the annotation's frame (the main area in which the annotation's con...
virtual void setAssociatedFeature(const QgsFeature &feature)
Sets the feature associated with the annotation.
void setFrameOffsetFromReferencePointMm(QPointF offset)
Sets the annotation's frame's offset (in millimeters) from the mapPosition() reference point.
void setMapPositionCrs(const QgsCoordinateReferenceSystem &crs)
Sets the CRS of the map position.
~QgsAnnotation() override
void _readXml(const QDomElement &annotationElem, const QgsReadWriteContext &context)
Reads common annotation properties from a DOM element.
void copyCommonProperties(QgsAnnotation *target) const
Copies common annotation properties to the targe annotation.
void render(QgsRenderContext &context) const
Renders the annotation to a target render context.
virtual QSizeF minimumFrameSize() const
Returns the minimum frame size for the annotation.
bool isVisible() const
Returns true if the annotation is visible and should be rendered.
Definition: qgsannotation.h:95
void setHasFixedMapPosition(bool fixed)
Sets whether the annotation is attached to a fixed map position, or uses a position relative to the c...
QgsAnnotation(QObject *parent=nullptr)
Constructor for QgsAnnotation.
void setMarkerSymbol(QgsMarkerSymbol *symbol)
Sets the symbol that is drawn at the annotation's map position.
QgsFillSymbol * fillSymbol() const
Returns the symbol that is used for rendering the annotation frame.
void setVisible(bool visible)
Sets whether the annotation is visible and should be rendered.
QSizeF frameSize
Definition: qgsannotation.h:74
void mapLayerChanged()
Emitted when the map layer associated with the annotation changes.
void setMapLayer(QgsMapLayer *layer)
Sets the map layer associated with the annotation.
This class represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
bool readXml(const QDomNode &node)
Restores state from the given DOM node.
bool writeXml(QDomNode &node, QDomDocument &doc) const
Stores state to the given Dom node in the given document.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:56
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
Definition: qgsfillsymbol.h:30
static QgsFillSymbol * createSimple(const QVariantMap &properties)
Create a fill symbol with one symbol layer: SimpleFill with specified properties.
Base class for all map layer types.
Definition: qgsmaplayer.h:73
The QgsMargins class defines the four margins of a rectangle.
Definition: qgsmargins.h:38
double top() const
Returns the top margin.
Definition: qgsmargins.h:78
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
double right() const
Returns the right margin.
Definition: qgsmargins.h:84
double bottom() const
Returns the bottom margin.
Definition: qgsmargins.h:90
QString toString() const
Returns the margins encoded to a string.
Definition: qgsmargins.cpp:18
double left() const
Returns the left margin.
Definition: qgsmargins.h:72
A marker symbol type, for rendering Point and MultiPoint geometries.
A class to represent a 2D point.
Definition: qgspointxy.h:59
void setX(double x) SIP_HOLDGIL
Sets the x value of the point.
Definition: qgspointxy.h:122
double y
Definition: qgspointxy.h:63
Q_GADGET double x
Definition: qgspointxy.h:62
void setY(double y) SIP_HOLDGIL
Sets the y value of the point.
Definition: qgspointxy.h:132
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:467
Q_INVOKABLE QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
The class is used as a container of context for various read/write operations on other objects.
Contains information about the context of a rendering operation.
QPainter * painter()
Returns the destination QPainter for the render operation.
void setPainterFlagsUsingContext(QPainter *painter=nullptr) const
Sets relevant flags on a destination painter, using the flags and settings currently defined for the ...
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
Scoped object for saving and restoring a QPainter object's state.
static QPolygonF createBalloon(const QgsPointXY &origin, const QRectF &rect, double wedgeWidth)
Generates a "balloon"/"talking bubble" style shape (as a QPolygonF).
An interface for classes which can visit style entity (e.g.
@ Annotation
An individual annotation.
virtual bool visitExit(const QgsStyleEntityVisitorInterface::Node &node)
Called when the visitor stops visiting a node.
virtual bool visitEnter(const QgsStyleEntityVisitorInterface::Node &node)
Called when the visitor starts visiting a node.
virtual bool visit(const QgsStyleEntityVisitorInterface::StyleLeaf &entity)
Called when the visitor will visit a style entity.
A symbol entity for QgsStyle databases.
Definition: qgsstyle.h:1219
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
@ RenderMillimeters
Millimeters.
Definition: qgsunittypes.h:169
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition: qgis.h:1186
Q_GUI_EXPORT int qt_defaultDpiX()
const QgsCoordinateReferenceSystem & crs
Contains information relating to a node (i.e.
Contains information relating to the style entity currently being visited.