QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
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"
24#include "qgsshapegenerator.h"
25#include "qgssymbol.h"
26#include "qgsmarkersymbol.h"
27#include "qgsfillsymbol.h"
28
29#include <QPen>
30#include <QPainter>
31
32Q_GUI_EXPORT extern int qt_defaultDpiX();
33
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
50void 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
80void 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
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
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() );
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
225void 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
249void 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
264void 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
309void 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:477
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:1342
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:2466
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.