QGIS API Documentation 3.99.0-Master (2fe06baccd8)
Loading...
Searching...
No Matches
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
20#include "qgsfillsymbol.h"
21#include "qgsmaplayer.h"
22#include "qgsmarkersymbol.h"
23#include "qgspainting.h"
24#include "qgsproject.h"
25#include "qgsshapegenerator.h"
27#include "qgssymbol.h"
28#include "qgssymbollayerutils.h"
29
30#include <QPainter>
31#include <QPen>
32
33#include "moc_qgsannotation.cpp"
34
36 : QObject( parent )
37 , mMarkerSymbol( new QgsMarkerSymbol() )
38{
39 QVariantMap props;
40 props.insert( QStringLiteral( "color" ), QStringLiteral( "white" ) );
41 props.insert( QStringLiteral( "style" ), QStringLiteral( "solid" ) );
42 props.insert( QStringLiteral( "style_border" ), QStringLiteral( "solid" ) );
43 props.insert( QStringLiteral( "color_border" ), QStringLiteral( "black" ) );
44 props.insert( QStringLiteral( "width_border" ), QStringLiteral( "0.3" ) );
45 props.insert( QStringLiteral( "joinstyle" ), QStringLiteral( "miter" ) );
46 mFillSymbol = QgsFillSymbol::createSimple( props );
47}
48
50
52{
53 if ( mVisible == visible )
54 return;
55
56 mVisible = visible;
57 emit appearanceChanged();
58}
59
61{
62 if ( mHasFixedMapPosition == fixed )
63 return;
64
65 mHasFixedMapPosition = fixed;
66 emit moved();
67}
68
70{
71 mMapPosition = position;
72 emit moved();
73}
74
76{
77 mMapPositionCrs = crs;
78 emit moved();
79}
80
81void QgsAnnotation::setRelativePosition( QPointF position )
82{
83 mRelativePosition = position;
84 emit moved();
85}
86
88{
89 // convert from offset in pixels at 96 dpi to mm
90 setFrameOffsetFromReferencePointMm( offset / 3.7795275 );
91}
92
94{
95 return mOffsetFromReferencePoint / 3.7795275;
96}
97
99{
100 mOffsetFromReferencePoint = offset;
101
102 emit moved();
103 emit appearanceChanged();
104}
105
107{
108 // convert from size in pixels at 96 dpi to mm
109 setFrameSizeMm( size / 3.7795275 );
110}
111
113{
114 return mFrameSize / 3.7795275;
115}
116
118{
119 const QSizeF frameSize = minimumFrameSize().expandedTo( size ); //don't allow frame sizes below minimum
120 mFrameSize = frameSize;
121 emit moved();
122 emit appearanceChanged();
123}
124
126{
127 mContentsMargins = margins;
128 emit appearanceChanged();
129}
130
132{
133 mFillSymbol.reset( symbol );
134 emit appearanceChanged();
135}
136
138{
139 return mFillSymbol.get();
140}
141
143{
144 QPainter *painter = context.painter();
145 if ( !painter || ( context.feedback() && context.feedback()->isCanceled() ) )
146 {
147 return;
148 }
149
150 const QgsScopedQPainterState painterState( context.painter() );
152
153 drawFrame( context );
154 if ( mHasFixedMapPosition )
155 {
156 drawMarkerSymbol( context );
157 }
158 if ( mHasFixedMapPosition )
159 {
160 painter->translate( context.convertToPainterUnits( mOffsetFromReferencePoint.x(), Qgis::RenderUnit::Millimeters ) + context.convertToPainterUnits( mContentsMargins.left(), Qgis::RenderUnit::Millimeters ),
161 context.convertToPainterUnits( mOffsetFromReferencePoint.y(), Qgis::RenderUnit::Millimeters ) + context.convertToPainterUnits( mContentsMargins.top(), Qgis::RenderUnit::Millimeters ) );
162 }
163 else
164 {
165 painter->translate( context.convertToPainterUnits( mContentsMargins.left(), Qgis::RenderUnit::Millimeters ),
166 context.convertToPainterUnits( mContentsMargins.top(), Qgis::RenderUnit::Millimeters ) );
167 }
168 const QSizeF size( context.convertToPainterUnits( mFrameSize.width(), Qgis::RenderUnit::Millimeters ) - context.convertToPainterUnits( mContentsMargins.left() + mContentsMargins.right(), Qgis::RenderUnit::Millimeters ),
169 context.convertToPainterUnits( mFrameSize.height(), Qgis::RenderUnit::Millimeters ) - context.convertToPainterUnits( mContentsMargins.top() + mContentsMargins.bottom(), Qgis::RenderUnit::Millimeters ) );
170
171 // scale back from painter dpi to 96 dpi --
172// double dotsPerMM = context.painter()->device()->logicalDpiX() / ( 25.4 * 3.78 );
173// context.painter()->scale( dotsPerMM, dotsPerMM );
174
175 renderAnnotation( context, size );
176}
177
179{
180 mMarkerSymbol.reset( symbol );
181 emit appearanceChanged();
182}
183
185{
186 mMapLayer = layer;
187 emit mapLayerChanged();
188}
189
191{
192 mFeature = feature;
193}
194
196{
197 // NOTE: if visitEnter returns false it means "don't visit the annotation", not "abort all further visitations"
198 if ( !visitor->visitEnter( QgsStyleEntityVisitorInterface::Node( QgsStyleEntityVisitorInterface::NodeType::Annotation, QStringLiteral( "annotation" ), tr( "Annotation" ) ) ) )
199 return true;
200
201 if ( mMarkerSymbol )
202 {
203 QgsStyleSymbolEntity entity( mMarkerSymbol.get() );
204 if ( !visitor->visit( QgsStyleEntityVisitorInterface::StyleLeaf( &entity, QStringLiteral( "marker" ), QObject::tr( "Marker" ) ) ) )
205 return false;
206 }
207
208 if ( mFillSymbol )
209 {
210 QgsStyleSymbolEntity entity( mFillSymbol.get() );
211 if ( !visitor->visit( QgsStyleEntityVisitorInterface::StyleLeaf( &entity, QStringLiteral( "fill" ), QObject::tr( "Fill" ) ) ) )
212 return false;
213 }
214
215 if ( !visitor->visitExit( QgsStyleEntityVisitorInterface::Node( QgsStyleEntityVisitorInterface::NodeType::Annotation, QStringLiteral( "annotation" ), tr( "Annotation" ) ) ) )
216 return false;
217
218 return true;
219}
220
222{
223 return QSizeF( 0, 0 );
224}
225
226void QgsAnnotation::drawFrame( QgsRenderContext &context ) const
227{
228 if ( !mFillSymbol )
229 return;
230
231 auto scaleSize = [&context]( double size )->double
232 {
234 };
235
236 const QRectF frameRect( mHasFixedMapPosition ? scaleSize( mOffsetFromReferencePoint.x() ) : 0,
237 mHasFixedMapPosition ? scaleSize( mOffsetFromReferencePoint.y() ) : 0,
238 scaleSize( mFrameSize.width() ),
239 scaleSize( mFrameSize.height() ) );
240 const QgsPointXY origin = mHasFixedMapPosition ? QgsPointXY( 0, 0 ) : QgsPointXY( frameRect.center().x(), frameRect.center().y() );
241
242 const QPolygonF poly = QgsShapeGenerator::createBalloon( origin, frameRect, context.convertToPainterUnits( mSegmentPointWidthMm, Qgis::RenderUnit::Millimeters ) );
243
244 mFillSymbol->startRender( context );
245 const QVector<QPolygonF> rings; //empty list
246 mFillSymbol->renderPolygon( poly, &rings, nullptr, context );
247 mFillSymbol->stopRender( context );
248}
249
250void QgsAnnotation::drawMarkerSymbol( QgsRenderContext &context ) const
251{
252 if ( !context.painter() )
253 {
254 return;
255 }
256
257 if ( mMarkerSymbol )
258 {
259 mMarkerSymbol->startRender( context );
260 mMarkerSymbol->renderPoint( QPointF( 0, 0 ), nullptr, context );
261 mMarkerSymbol->stopRender( context );
262 }
263}
264
265void QgsAnnotation::_writeXml( QDomElement &itemElem, QDomDocument &doc, const QgsReadWriteContext &context ) const
266{
267 if ( itemElem.isNull() )
268 {
269 return;
270 }
271 QDomElement annotationElem = doc.createElement( QStringLiteral( "AnnotationItem" ) );
272 annotationElem.setAttribute( QStringLiteral( "mapPositionFixed" ), mHasFixedMapPosition );
273 annotationElem.setAttribute( QStringLiteral( "mapPosX" ), qgsDoubleToString( mMapPosition.x() ) );
274 annotationElem.setAttribute( QStringLiteral( "mapPosY" ), qgsDoubleToString( mMapPosition.y() ) );
275 if ( mMapPositionCrs.isValid() )
276 mMapPositionCrs.writeXml( annotationElem, doc );
277 annotationElem.setAttribute( QStringLiteral( "offsetXMM" ), qgsDoubleToString( mOffsetFromReferencePoint.x() ) );
278 annotationElem.setAttribute( QStringLiteral( "offsetYMM" ), qgsDoubleToString( mOffsetFromReferencePoint.y() ) );
279 annotationElem.setAttribute( QStringLiteral( "frameWidthMM" ), qgsDoubleToString( mFrameSize.width() ) );
280 annotationElem.setAttribute( QStringLiteral( "frameHeightMM" ), qgsDoubleToString( mFrameSize.height() ) );
281 annotationElem.setAttribute( QStringLiteral( "canvasPosX" ), qgsDoubleToString( mRelativePosition.x() ) );
282 annotationElem.setAttribute( QStringLiteral( "canvasPosY" ), qgsDoubleToString( mRelativePosition.y() ) );
283 annotationElem.setAttribute( QStringLiteral( "contentsMargin" ), mContentsMargins.toString() );
284 annotationElem.setAttribute( QStringLiteral( "visible" ), isVisible() );
285 if ( mMapLayer )
286 {
287 annotationElem.setAttribute( QStringLiteral( "mapLayer" ), mMapLayer->id() );
288 }
289 if ( mMarkerSymbol )
290 {
291 const QDomElement symbolElem = QgsSymbolLayerUtils::saveSymbol( QStringLiteral( "marker symbol" ), mMarkerSymbol.get(), doc, context );
292 if ( !symbolElem.isNull() )
293 {
294 annotationElem.appendChild( symbolElem );
295 }
296 }
297 if ( mFillSymbol )
298 {
299 QDomElement fillElem = doc.createElement( QStringLiteral( "fillSymbol" ) );
300 const QDomElement symbolElem = QgsSymbolLayerUtils::saveSymbol( QStringLiteral( "fill symbol" ), mFillSymbol.get(), doc, context );
301 if ( !symbolElem.isNull() )
302 {
303 fillElem.appendChild( symbolElem );
304 annotationElem.appendChild( fillElem );
305 }
306 }
307 itemElem.appendChild( annotationElem );
308}
309
310void QgsAnnotation::_readXml( const QDomElement &annotationElem, const QgsReadWriteContext &context )
311{
312 if ( annotationElem.isNull() )
313 {
314 return;
315 }
316 QPointF pos;
317 pos.setX( annotationElem.attribute( QStringLiteral( "canvasPosX" ), QStringLiteral( "0" ) ).toDouble() );
318 pos.setY( annotationElem.attribute( QStringLiteral( "canvasPosY" ), QStringLiteral( "0" ) ).toDouble() );
319 if ( pos.x() >= 1 || pos.x() < 0 || pos.y() < 0 || pos.y() >= 1 )
320 mRelativePosition = QPointF();
321 else
322 mRelativePosition = pos;
323 QgsPointXY mapPos;
324 mapPos.setX( annotationElem.attribute( QStringLiteral( "mapPosX" ), QStringLiteral( "0" ) ).toDouble() );
325 mapPos.setY( annotationElem.attribute( QStringLiteral( "mapPosY" ), QStringLiteral( "0" ) ).toDouble() );
326 mMapPosition = mapPos;
327
328 if ( !mMapPositionCrs.readXml( annotationElem ) )
329 {
330 mMapPositionCrs = QgsCoordinateReferenceSystem();
331 }
332
333 mContentsMargins = QgsMargins::fromString( annotationElem.attribute( QStringLiteral( "contentsMargin" ) ) );
334 const double dpiScale = 25.4 / QgsPainting::qtDefaultDpiX();
335 if ( annotationElem.hasAttribute( QStringLiteral( "frameWidthMM" ) ) )
336 mFrameSize.setWidth( annotationElem.attribute( QStringLiteral( "frameWidthMM" ), QStringLiteral( "5" ) ).toDouble() );
337 else
338 mFrameSize.setWidth( dpiScale * annotationElem.attribute( QStringLiteral( "frameWidth" ), QStringLiteral( "50" ) ).toDouble() );
339 if ( annotationElem.hasAttribute( QStringLiteral( "frameHeightMM" ) ) )
340 mFrameSize.setHeight( annotationElem.attribute( QStringLiteral( "frameHeightMM" ), QStringLiteral( "3" ) ).toDouble() );
341 else
342 mFrameSize.setHeight( dpiScale * annotationElem.attribute( QStringLiteral( "frameHeight" ), QStringLiteral( "50" ) ).toDouble() );
343
344 if ( annotationElem.hasAttribute( QStringLiteral( "offsetXMM" ) ) )
345 mOffsetFromReferencePoint.setX( annotationElem.attribute( QStringLiteral( "offsetXMM" ), QStringLiteral( "0" ) ).toDouble() );
346 else
347 mOffsetFromReferencePoint.setX( dpiScale * annotationElem.attribute( QStringLiteral( "offsetX" ), QStringLiteral( "0" ) ).toDouble() );
348 if ( annotationElem.hasAttribute( QStringLiteral( "offsetYMM" ) ) )
349 mOffsetFromReferencePoint.setY( annotationElem.attribute( QStringLiteral( "offsetYMM" ), QStringLiteral( "0" ) ).toDouble() );
350 else
351 mOffsetFromReferencePoint.setY( dpiScale * annotationElem.attribute( QStringLiteral( "offsetY" ), QStringLiteral( "0" ) ).toDouble() );
352
353 mHasFixedMapPosition = annotationElem.attribute( QStringLiteral( "mapPositionFixed" ), QStringLiteral( "1" ) ).toInt();
354 mVisible = annotationElem.attribute( QStringLiteral( "visible" ), QStringLiteral( "1" ) ).toInt();
355 if ( annotationElem.hasAttribute( QStringLiteral( "mapLayer" ) ) )
356 {
357 mMapLayer = QgsProject::instance()->mapLayer( annotationElem.attribute( QStringLiteral( "mapLayer" ) ) ); // skip-keyword-check
358 }
359
360 //marker symbol
361 {
362 const QDomElement symbolElem = annotationElem.firstChildElement( QStringLiteral( "symbol" ) );
363 if ( !symbolElem.isNull() )
364 {
365 std::unique_ptr< QgsMarkerSymbol > symbol = QgsSymbolLayerUtils::loadSymbol<QgsMarkerSymbol>( symbolElem, context );
366 if ( symbol )
367 {
368 mMarkerSymbol = std::move( symbol );
369 }
370 }
371 }
372
373 mFillSymbol.reset( nullptr );
374 const QDomElement fillElem = annotationElem.firstChildElement( QStringLiteral( "fillSymbol" ) );
375 if ( !fillElem.isNull() )
376 {
377 const QDomElement symbolElem = fillElem.firstChildElement( QStringLiteral( "symbol" ) );
378 if ( !symbolElem.isNull() )
379 {
380 std::unique_ptr< QgsFillSymbol >symbol = QgsSymbolLayerUtils::loadSymbol<QgsFillSymbol>( symbolElem, context );
381 if ( symbol )
382 {
383 mFillSymbol = std::move( symbol );
384 }
385 }
386 }
387 if ( !mFillSymbol )
388 {
389 QColor frameColor;
390 frameColor.setNamedColor( annotationElem.attribute( QStringLiteral( "frameColor" ), QStringLiteral( "#000000" ) ) );
391 frameColor.setAlpha( annotationElem.attribute( QStringLiteral( "frameColorAlpha" ), QStringLiteral( "255" ) ).toInt() );
392 QColor frameBackgroundColor;
393 frameBackgroundColor.setNamedColor( annotationElem.attribute( QStringLiteral( "frameBackgroundColor" ) ) );
394 frameBackgroundColor.setAlpha( annotationElem.attribute( QStringLiteral( "frameBackgroundColorAlpha" ), QStringLiteral( "255" ) ).toInt() );
395 double frameBorderWidth = annotationElem.attribute( QStringLiteral( "frameBorderWidth" ), QStringLiteral( "0.5" ) ).toDouble();
396 // need to roughly convert border width from pixels to mm - just assume 96 dpi
397 frameBorderWidth = frameBorderWidth * 25.4 / 96.0;
398 QVariantMap props;
399 props.insert( QStringLiteral( "color" ), frameBackgroundColor.name() );
400 props.insert( QStringLiteral( "style" ), QStringLiteral( "solid" ) );
401 props.insert( QStringLiteral( "style_border" ), QStringLiteral( "solid" ) );
402 props.insert( QStringLiteral( "color_border" ), frameColor.name() );
403 props.insert( QStringLiteral( "width_border" ), QString::number( frameBorderWidth ) );
404 props.insert( QStringLiteral( "joinstyle" ), QStringLiteral( "miter" ) );
405 mFillSymbol = QgsFillSymbol::createSimple( props );
406 }
407
408 emit mapLayerChanged();
409}
410
412{
413 target->mVisible = mVisible;
414 target->mHasFixedMapPosition = mHasFixedMapPosition;
415 target->mMapPosition = mMapPosition;
416 target->mMapPositionCrs = mMapPositionCrs;
417 target->mRelativePosition = mRelativePosition;
418 target->mOffsetFromReferencePoint = mOffsetFromReferencePoint;
419 target->mFrameSize = mFrameSize;
420 target->mMarkerSymbol.reset( mMarkerSymbol ? mMarkerSymbol->clone() : nullptr );
421 target->mContentsMargins = mContentsMargins;
422 target->mFillSymbol.reset( mFillSymbol ? mFillSymbol->clone() : nullptr );
423 target->mSegmentPointWidthMm = mSegmentPointWidthMm;
424 target->mMapLayer = mMapLayer;
425 target->mFeature = mFeature;
426}
427
@ Millimeters
Millimeters.
Definition qgis.h:5184
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.
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.
void mapLayerChanged()
Emitted when the map layer associated with the annotation changes.
void setMapLayer(QgsMapLayer *layer)
Sets the map layer associated with the annotation.
Represents a coordinate reference system (CRS).
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:58
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition qgsfeedback.h:53
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
static std::unique_ptr< 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:80
Defines the four margins of a rectangle.
Definition qgsmargins.h:38
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...
A marker symbol type, for rendering Point and MultiPoint geometries.
static int qtDefaultDpiX()
Returns the default Qt horizontal DPI.
Represents a 2D point.
Definition qgspointxy.h:60
void setY(double y)
Sets the y value of the point.
Definition qgspointxy.h:129
void setX(double x)
Sets the x value of the point.
Definition qgspointxy.h:119
static QgsProject * instance()
Returns the QgsProject singleton instance.
Q_INVOKABLE QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
A container for the context for various read/write operations on objects.
Contains information about the context of a rendering operation.
double convertToPainterUnits(double size, Qgis::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
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 ...
QgsFeedback * feedback() const
Returns the feedback object that can be queried regularly during rendering to check if rendering shou...
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.
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:1397
static std::unique_ptr< QgsSymbol > loadSymbol(const QDomElement &element, const QgsReadWriteContext &context)
Attempts to load a symbol from a DOM element.
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition qgis.h:6524
Contains information relating to a node (i.e.
Contains information relating to the style entity currently being visited.