QGIS API Documentation 3.41.0-Master (181b2f43d8e)
Loading...
Searching...
No Matches
qgsdiagramrenderer.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsdiagramrenderer.cpp
3 ---------------------
4 begin : March 2011
5 copyright : (C) 2011 by Marco Hugentobler
6 email : marco dot hugentobler at sourcepole dot ch
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15#include "qgsdiagramrenderer.h"
16
17#include "qgscolorutils.h"
24#include "qgsrendercontext.h"
26#include "qgsfontutils.h"
27#include "qgssymbollayerutils.h"
29#include "qgspainteffect.h"
30#include "qgsapplication.h"
31#include "qgslinesymbol.h"
32#include "qgsmarkersymbol.h"
33#include "qgsunittypes.h"
34#include "qgsscaleutils.h"
35
36#include <QDomElement>
37#include <QPainter>
38
39QgsPropertiesDefinition QgsDiagramLayerSettings::sPropertyDefinitions;
40
41void QgsDiagramLayerSettings::initPropertyDefinitions()
42{
43 if ( !sPropertyDefinitions.isEmpty() )
44 return;
45
46 const QString origin = QStringLiteral( "diagram" );
47
48 sPropertyDefinitions = QgsPropertiesDefinition
49 {
50 { static_cast< int >( QgsDiagramLayerSettings::Property::BackgroundColor ), QgsPropertyDefinition( "backgroundColor", QObject::tr( "Background color" ), QgsPropertyDefinition::ColorWithAlpha, origin ) },
51 { static_cast< int >( QgsDiagramLayerSettings::Property::StrokeColor ), QgsPropertyDefinition( "strokeColor", QObject::tr( "Stroke color" ), QgsPropertyDefinition::ColorWithAlpha, origin ) },
52 { static_cast< int >( QgsDiagramLayerSettings::Property::StrokeWidth ), QgsPropertyDefinition( "strokeWidth", QObject::tr( "Stroke width" ), QgsPropertyDefinition::StrokeWidth, origin ) },
53 { static_cast< int >( QgsDiagramLayerSettings::Property::PositionX ), QgsPropertyDefinition( "positionX", QObject::tr( "Position (X)" ), QgsPropertyDefinition::Double, origin ) },
54 { static_cast< int >( QgsDiagramLayerSettings::Property::PositionY ), QgsPropertyDefinition( "positionY", QObject::tr( "Position (Y)" ), QgsPropertyDefinition::Double, origin ) },
55 { static_cast< int >( QgsDiagramLayerSettings::Property::Distance ), QgsPropertyDefinition( "distance", QObject::tr( "Placement distance" ), QgsPropertyDefinition::DoublePositive, origin ) },
56 { static_cast< int >( QgsDiagramLayerSettings::Property::Priority ), QgsPropertyDefinition( "priority", QObject::tr( "Placement priority" ), QgsPropertyDefinition::DoublePositive, origin ) },
57 { static_cast< int >( QgsDiagramLayerSettings::Property::ZIndex ), QgsPropertyDefinition( "zIndex", QObject::tr( "Placement z-index" ), QgsPropertyDefinition::Double, origin ) },
58 { static_cast< int >( QgsDiagramLayerSettings::Property::IsObstacle ), QgsPropertyDefinition( "isObstacle", QObject::tr( "Diagram is an obstacle" ), QgsPropertyDefinition::Boolean, origin ) },
59 { static_cast< int >( QgsDiagramLayerSettings::Property::Show ), QgsPropertyDefinition( "show", QObject::tr( "Show diagram" ), QgsPropertyDefinition::Boolean, origin ) },
60 { static_cast< int >( QgsDiagramLayerSettings::Property::AlwaysShow ), QgsPropertyDefinition( "alwaysShow", QObject::tr( "Always show diagram" ), QgsPropertyDefinition::Boolean, origin ) },
61 { static_cast< int >( QgsDiagramLayerSettings::Property::StartAngle ), QgsPropertyDefinition( "startAngle", QObject::tr( "Pie chart start angle" ), QgsPropertyDefinition::Rotation, origin ) },
62 };
63}
64
66{
67 initPropertyDefinitions();
68 return sPropertyDefinitions;
69}
70
72{
73 initPropertyDefinitions();
74}
75
77 : mCt( rh.mCt )
78 , mPlacement( rh.mPlacement )
79 , mPlacementFlags( rh.mPlacementFlags )
80 , mPriority( rh.mPriority )
81 , mZIndex( rh.mZIndex )
82 , mObstacle( rh.mObstacle )
83 , mDistance( rh.mDistance )
84 , mRenderer( rh.mRenderer ? rh.mRenderer->clone() : nullptr )
85 , mShowAll( rh.mShowAll )
86 , mDataDefinedProperties( rh.mDataDefinedProperties )
87{
88 initPropertyDefinitions();
89}
90
92{
93 mPlacement = rh.mPlacement;
94 mPlacementFlags = rh.mPlacementFlags;
95 mPriority = rh.mPriority;
96 mZIndex = rh.mZIndex;
97 mObstacle = rh.mObstacle;
98 mDistance = rh.mDistance;
99 mRenderer = rh.mRenderer ? rh.mRenderer->clone() : nullptr;
100 mCt = rh.mCt;
101 mShowAll = rh.mShowAll;
102 mDataDefinedProperties = rh.mDataDefinedProperties;
103 return *this;
104}
105
110
112{
113 if ( diagramRenderer == mRenderer )
114 return;
115
116 delete mRenderer;
117 mRenderer = diagramRenderer;
118}
119
121{
122 mCt = transform;
123}
124
125void QgsDiagramLayerSettings::readXml( const QDomElement &elem )
126{
127 const QDomNodeList propertyElems = elem.elementsByTagName( QStringLiteral( "properties" ) );
128 if ( !propertyElems.isEmpty() )
129 {
130 ( void )mDataDefinedProperties.readXml( propertyElems.at( 0 ).toElement(), sPropertyDefinitions );
131 }
132 else
133 {
134 mDataDefinedProperties.clear();
135 }
136
137 mPlacement = static_cast< Placement >( elem.attribute( QStringLiteral( "placement" ) ).toInt() );
138 mPlacementFlags = static_cast< LinePlacementFlag >( elem.attribute( QStringLiteral( "linePlacementFlags" ) ).toInt() );
139 mPriority = elem.attribute( QStringLiteral( "priority" ) ).toInt();
140 mZIndex = elem.attribute( QStringLiteral( "zIndex" ) ).toDouble();
141 mObstacle = elem.attribute( QStringLiteral( "obstacle" ) ).toInt();
142 mDistance = elem.attribute( QStringLiteral( "dist" ) ).toDouble();
143 mShowAll = ( elem.attribute( QStringLiteral( "showAll" ), QStringLiteral( "0" ) ) != QLatin1String( "0" ) );
144}
145
146void QgsDiagramLayerSettings::writeXml( QDomElement &layerElem, QDomDocument &doc ) const
147{
148 QDomElement diagramLayerElem = doc.createElement( QStringLiteral( "DiagramLayerSettings" ) );
149 QDomElement propertiesElem = doc.createElement( QStringLiteral( "properties" ) );
150 ( void )mDataDefinedProperties.writeXml( propertiesElem, sPropertyDefinitions );
151 diagramLayerElem.appendChild( propertiesElem );
152 diagramLayerElem.setAttribute( QStringLiteral( "placement" ), mPlacement );
153 diagramLayerElem.setAttribute( QStringLiteral( "linePlacementFlags" ), mPlacementFlags );
154 diagramLayerElem.setAttribute( QStringLiteral( "priority" ), mPriority );
155 diagramLayerElem.setAttribute( QStringLiteral( "zIndex" ), mZIndex );
156 diagramLayerElem.setAttribute( QStringLiteral( "obstacle" ), mObstacle );
157 diagramLayerElem.setAttribute( QStringLiteral( "dist" ), QString::number( mDistance ) );
158 diagramLayerElem.setAttribute( QStringLiteral( "showAll" ), mShowAll );
159 layerElem.appendChild( diagramLayerElem );
160}
161
163{
164 return mDataDefinedProperties.prepare( context );
165}
166
168{
169 QSet< QString > referenced;
170 if ( mRenderer )
171 referenced = mRenderer->referencedFields( context );
172
173 //add the ones needed for data defined settings
174 referenced.unite( mDataDefinedProperties.referencedFields( context ) );
175
176 return referenced;
177}
178
179void QgsDiagramSettings::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
180{
181 enabled = ( elem.attribute( QStringLiteral( "enabled" ), QStringLiteral( "1" ) ) != QLatin1String( "0" ) );
182 if ( !QgsFontUtils::setFromXmlChildNode( font, elem, QStringLiteral( "fontProperties" ) ) )
183 {
184 font.fromString( elem.attribute( QStringLiteral( "font" ) ) );
185 }
186 backgroundColor.setNamedColor( elem.attribute( QStringLiteral( "backgroundColor" ) ) );
187 backgroundColor.setAlpha( elem.attribute( QStringLiteral( "backgroundAlpha" ) ).toInt() );
188 size.setWidth( elem.attribute( QStringLiteral( "width" ) ).toDouble() );
189 size.setHeight( elem.attribute( QStringLiteral( "height" ) ).toDouble() );
190 if ( elem.hasAttribute( QStringLiteral( "transparency" ) ) )
191 {
192 opacity = 1 - elem.attribute( QStringLiteral( "transparency" ), QStringLiteral( "0" ) ).toInt() / 255.0;
193 }
194 else
195 {
196 opacity = elem.attribute( QStringLiteral( "opacity" ), QStringLiteral( "1.00" ) ).toDouble();
197 }
198
199 penColor.setNamedColor( elem.attribute( QStringLiteral( "penColor" ) ) );
200 const int penAlpha = elem.attribute( QStringLiteral( "penAlpha" ), QStringLiteral( "255" ) ).toInt();
201 penColor.setAlpha( penAlpha );
202 penWidth = elem.attribute( QStringLiteral( "penWidth" ) ).toDouble();
203
204 mDirection = static_cast< Direction >( elem.attribute( QStringLiteral( "direction" ), QStringLiteral( "1" ) ).toInt() );
205
206 maximumScale = elem.attribute( QStringLiteral( "minScaleDenominator" ), QStringLiteral( "-1" ) ).toDouble();
207 minimumScale = elem.attribute( QStringLiteral( "maxScaleDenominator" ), QStringLiteral( "-1" ) ).toDouble();
208 if ( elem.hasAttribute( QStringLiteral( "scaleBasedVisibility" ) ) )
209 {
210 scaleBasedVisibility = ( elem.attribute( QStringLiteral( "scaleBasedVisibility" ), QStringLiteral( "1" ) ) != QLatin1String( "0" ) );
211 }
212 else
213 {
215 }
216
217 //diagram size unit type and scale
218 if ( elem.attribute( QStringLiteral( "sizeType" ) ) == QLatin1String( "MapUnits" ) )
219 {
220 //compatibility with pre-2.16 project files
222 }
223 else
224 {
225 sizeType = QgsUnitTypes::decodeRenderUnit( elem.attribute( QStringLiteral( "sizeType" ) ) );
226 }
227 sizeScale = QgsSymbolLayerUtils::decodeMapUnitScale( elem.attribute( QStringLiteral( "sizeScale" ) ) );
228
229 //line width unit type and scale
230 lineSizeUnit = QgsUnitTypes::decodeRenderUnit( elem.attribute( QStringLiteral( "lineSizeType" ) ) );
231 lineSizeScale = QgsSymbolLayerUtils::decodeMapUnitScale( elem.attribute( QStringLiteral( "lineSizeScale" ) ) );
232
233 mSpacing = elem.attribute( QStringLiteral( "spacing" ) ).toDouble();
234 mSpacingUnit = QgsUnitTypes::decodeRenderUnit( elem.attribute( QStringLiteral( "spacingUnit" ) ) );
235 mSpacingMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( elem.attribute( QStringLiteral( "spacingUnitScale" ) ) );
236
237 mStackedDiagramSpacing = elem.attribute( QStringLiteral( "stackedDiagramSpacing" ) ).toDouble();
238 mStackedDiagramSpacingUnit = QgsUnitTypes::decodeRenderUnit( elem.attribute( QStringLiteral( "stackedDiagramSpacingUnit" ) ) );
239 mStackedDiagramSpacingMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( elem.attribute( QStringLiteral( "stackedDiagramSpacingUnitScale" ) ) );
240
241 //label placement method
242 if ( elem.attribute( QStringLiteral( "labelPlacementMethod" ) ) == QLatin1String( "Height" ) )
243 {
245 }
246 else
247 {
249 }
250
251 // orientation
252 if ( elem.attribute( QStringLiteral( "diagramOrientation" ) ) == QLatin1String( "Left" ) )
253 {
255 }
256 else if ( elem.attribute( QStringLiteral( "diagramOrientation" ) ) == QLatin1String( "Right" ) )
257 {
259 }
260 else if ( elem.attribute( QStringLiteral( "diagramOrientation" ) ) == QLatin1String( "Down" ) )
261 {
263 }
264 else
265 {
267 }
268
269 // stacked mode
270 if ( elem.attribute( QStringLiteral( "stackedDiagramMode" ) ) == QLatin1String( "Horizontal" ) )
271 {
273 }
274 else if ( elem.attribute( QStringLiteral( "stackedDiagramMode" ) ) == QLatin1String( "Vertical" ) )
275 {
277 }
278
279 // scale dependency
280 if ( elem.attribute( QStringLiteral( "scaleDependency" ) ) == QLatin1String( "Diameter" ) )
281 {
282 scaleByArea = false;
283 }
284 else
285 {
286 scaleByArea = true;
287 }
288
289 barWidth = elem.attribute( QStringLiteral( "barWidth" ) ).toDouble();
290
291 if ( elem.hasAttribute( QStringLiteral( "angleOffset" ) ) )
292 rotationOffset = std::fmod( 360.0 - elem.attribute( QStringLiteral( "angleOffset" ) ).toInt() / 16.0, 360.0 );
293 else
294 rotationOffset = elem.attribute( QStringLiteral( "rotationOffset" ) ).toDouble();
295
296 minimumSize = elem.attribute( QStringLiteral( "minimumSize" ) ).toDouble();
297
298 const QDomNodeList axisSymbolNodes = elem.elementsByTagName( QStringLiteral( "axisSymbol" ) );
299 if ( axisSymbolNodes.count() > 0 )
300 {
301 const QDomElement axisSymbolElem = axisSymbolNodes.at( 0 ).toElement().firstChildElement();
302 mAxisLineSymbol.reset( QgsSymbolLayerUtils::loadSymbol<QgsLineSymbol>( axisSymbolElem, context ) );
303 }
304 else
305 {
306 mAxisLineSymbol = std::make_unique< QgsLineSymbol >();
307 }
308
309 mShowAxis = elem.attribute( QStringLiteral( "showAxis" ), QStringLiteral( "0" ) ).toInt();
310
311 //colors
312 categoryColors.clear();
313 const QDomNodeList attributes = elem.elementsByTagName( QStringLiteral( "attribute" ) );
314
315
316 if ( attributes.length() > 0 )
317 {
318 for ( int i = 0; i < attributes.size(); i++ )
319 {
320 const QDomElement attrElem = attributes.at( i ).toElement();
321 QColor newColor( attrElem.attribute( QStringLiteral( "color" ) ) );
322 newColor.setAlphaF( attrElem.attribute( QStringLiteral( "colorOpacity" ), QStringLiteral( "1.0" ) ).toDouble() );
323 categoryColors.append( newColor );
324 categoryAttributes.append( attrElem.attribute( QStringLiteral( "field" ) ) );
325 categoryLabels.append( attrElem.attribute( QStringLiteral( "label" ) ) );
326 if ( categoryLabels.constLast().isEmpty() )
327 {
328 categoryLabels.back() = categoryAttributes.back();
329 }
330 }
331 }
332 else
333 {
334 // Restore old format attributes and colors
335
336 const QStringList colorList = elem.attribute( QStringLiteral( "colors" ) ).split( '/' );
337 QStringList::const_iterator colorIt = colorList.constBegin();
338 for ( ; colorIt != colorList.constEnd(); ++colorIt )
339 {
340 QColor newColor( *colorIt );
341 categoryColors.append( QColor( newColor ) );
342 }
343
344 //attribute indices
345 categoryAttributes.clear();
346 const QStringList catList = elem.attribute( QStringLiteral( "categories" ) ).split( '/' );
347 QStringList::const_iterator catIt = catList.constBegin();
348 for ( ; catIt != catList.constEnd(); ++catIt )
349 {
350 categoryAttributes.append( *catIt );
351 categoryLabels.append( *catIt );
352 }
353 }
354
355 const QDomElement effectElem = elem.firstChildElement( QStringLiteral( "effect" ) );
356 if ( !effectElem.isNull() )
357 setPaintEffect( QgsApplication::paintEffectRegistry()->createEffect( effectElem ) );
358 else
360}
361
362void QgsDiagramSettings::writeXml( QDomElement &rendererElem, QDomDocument &doc, const QgsReadWriteContext &context ) const
363{
364 QDomElement categoryElem = doc.createElement( QStringLiteral( "DiagramCategory" ) );
365 categoryElem.setAttribute( QStringLiteral( "enabled" ), enabled );
366 categoryElem.appendChild( QgsFontUtils::toXmlElement( font, doc, QStringLiteral( "fontProperties" ) ) );
367 categoryElem.setAttribute( QStringLiteral( "backgroundColor" ), backgroundColor.name() );
368 categoryElem.setAttribute( QStringLiteral( "backgroundAlpha" ), backgroundColor.alpha() );
369 categoryElem.setAttribute( QStringLiteral( "width" ), QString::number( size.width() ) );
370 categoryElem.setAttribute( QStringLiteral( "height" ), QString::number( size.height() ) );
371 categoryElem.setAttribute( QStringLiteral( "penColor" ), penColor.name() );
372 categoryElem.setAttribute( QStringLiteral( "penAlpha" ), penColor.alpha() );
373 categoryElem.setAttribute( QStringLiteral( "penWidth" ), QString::number( penWidth ) );
374 categoryElem.setAttribute( QStringLiteral( "scaleBasedVisibility" ), scaleBasedVisibility );
375 categoryElem.setAttribute( QStringLiteral( "minScaleDenominator" ), QString::number( maximumScale ) );
376 categoryElem.setAttribute( QStringLiteral( "maxScaleDenominator" ), QString::number( minimumScale ) );
377 categoryElem.setAttribute( QStringLiteral( "opacity" ), QString::number( opacity ) );
378 categoryElem.setAttribute( QStringLiteral( "spacing" ), QString::number( mSpacing ) );
379 categoryElem.setAttribute( QStringLiteral( "spacingUnit" ), QgsUnitTypes::encodeUnit( mSpacingUnit ) );
380 categoryElem.setAttribute( QStringLiteral( "spacingUnitScale" ), QgsSymbolLayerUtils::encodeMapUnitScale( mSpacingMapUnitScale ) );
381 categoryElem.setAttribute( QStringLiteral( "stackedDiagramSpacing" ), QString::number( mStackedDiagramSpacing ) );
382 categoryElem.setAttribute( QStringLiteral( "stackedDiagramSpacingUnit" ), QgsUnitTypes::encodeUnit( mStackedDiagramSpacingUnit ) );
383 categoryElem.setAttribute( QStringLiteral( "stackedDiagramSpacingUnitScale" ), QgsSymbolLayerUtils::encodeMapUnitScale( mStackedDiagramSpacingMapUnitScale ) );
384 categoryElem.setAttribute( QStringLiteral( "direction" ), QString::number( mDirection ) );
385
386 //diagram size unit type and scale
387 categoryElem.setAttribute( QStringLiteral( "sizeType" ), QgsUnitTypes::encodeUnit( sizeType ) );
388 categoryElem.setAttribute( QStringLiteral( "sizeScale" ), QgsSymbolLayerUtils::encodeMapUnitScale( sizeScale ) );
389
390 //line width unit type and scale
391 categoryElem.setAttribute( QStringLiteral( "lineSizeType" ), QgsUnitTypes::encodeUnit( lineSizeUnit ) );
392 categoryElem.setAttribute( QStringLiteral( "lineSizeScale" ), QgsSymbolLayerUtils::encodeMapUnitScale( lineSizeScale ) );
393
394 // label placement method (text diagram)
396 {
397 categoryElem.setAttribute( QStringLiteral( "labelPlacementMethod" ), QStringLiteral( "Height" ) );
398 }
399 else
400 {
401 categoryElem.setAttribute( QStringLiteral( "labelPlacementMethod" ), QStringLiteral( "XHeight" ) );
402 }
403
404 if ( scaleByArea )
405 {
406 categoryElem.setAttribute( QStringLiteral( "scaleDependency" ), QStringLiteral( "Area" ) );
407 }
408 else
409 {
410 categoryElem.setAttribute( QStringLiteral( "scaleDependency" ), QStringLiteral( "Diameter" ) );
411 }
412
413 // orientation (histogram)
414 switch ( diagramOrientation )
415 {
416 case Left:
417 categoryElem.setAttribute( QStringLiteral( "diagramOrientation" ), QStringLiteral( "Left" ) );
418 break;
419
420 case Right:
421 categoryElem.setAttribute( QStringLiteral( "diagramOrientation" ), QStringLiteral( "Right" ) );
422 break;
423
424 case Down:
425 categoryElem.setAttribute( QStringLiteral( "diagramOrientation" ), QStringLiteral( "Down" ) );
426 break;
427
428 case Up:
429 categoryElem.setAttribute( QStringLiteral( "diagramOrientation" ), QStringLiteral( "Up" ) );
430 break;
431 }
432
433 // stacked mode
434 switch ( stackedDiagramMode )
435 {
436 case Horizontal:
437 categoryElem.setAttribute( QStringLiteral( "stackedDiagramMode" ), QStringLiteral( "Horizontal" ) );
438 break;
439
440 case Vertical:
441 categoryElem.setAttribute( QStringLiteral( "stackedDiagramMode" ), QStringLiteral( "Vertical" ) );
442 break;
443 }
444
445 categoryElem.setAttribute( QStringLiteral( "barWidth" ), QString::number( barWidth ) );
446 categoryElem.setAttribute( QStringLiteral( "minimumSize" ), QString::number( minimumSize ) );
447 categoryElem.setAttribute( QStringLiteral( "rotationOffset" ), QString::number( rotationOffset ) );
448
449 const int nCats = std::min( categoryColors.size(), categoryAttributes.size() );
450 for ( int i = 0; i < nCats; ++i )
451 {
452 QDomElement attributeElem = doc.createElement( QStringLiteral( "attribute" ) );
453
454 attributeElem.setAttribute( QStringLiteral( "field" ), categoryAttributes.at( i ) );
455 attributeElem.setAttribute( QStringLiteral( "color" ), categoryColors.at( i ).name() );
456 attributeElem.setAttribute( QStringLiteral( "colorOpacity" ), QString::number( categoryColors.at( i ).alphaF() ) );
457 attributeElem.setAttribute( QStringLiteral( "label" ), categoryLabels.at( i ) );
458 categoryElem.appendChild( attributeElem );
459 }
460
461 categoryElem.setAttribute( QStringLiteral( "showAxis" ), mShowAxis ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
462 QDomElement axisSymbolElem = doc.createElement( QStringLiteral( "axisSymbol" ) );
463 const QDomElement symbolElem = QgsSymbolLayerUtils::saveSymbol( QString(), mAxisLineSymbol.get(), doc, context );
464 axisSymbolElem.appendChild( symbolElem );
465 categoryElem.appendChild( axisSymbolElem );
466
467 if ( mPaintEffect && !QgsPaintEffectRegistry::isDefaultStack( mPaintEffect.get() ) )
468 mPaintEffect->saveProperties( doc, categoryElem );
469
470 rendererElem.appendChild( categoryElem );
471}
472
474{
475 if ( mDiagram.get() == d )
476 return;
477
478 mDiagram.reset( d );
479}
480
482 : mDiagram( other.mDiagram ? other.mDiagram->clone() : nullptr )
483 , mShowAttributeLegend( other.mShowAttributeLegend )
484{
485}
486
488{
489 mDiagram.reset( other.mDiagram ? other.mDiagram->clone() : nullptr );
491 return *this;
492}
493
494void QgsDiagramRenderer::renderDiagram( const QgsFeature &feature, QgsRenderContext &c, QPointF pos, const QgsPropertyCollection &properties ) const
495{
496 if ( !mDiagram )
497 {
498 return;
499 }
500
502 if ( !diagramSettings( feature, c, s ) )
503 {
504 return;
505 }
506
507 if ( properties.hasActiveProperties() )
508 {
509 c.expressionContext().setOriginalValueVariable( QgsColorUtils::colorToString( s.backgroundColor ) );
511 c.expressionContext().setOriginalValueVariable( QgsColorUtils::colorToString( s.penColor ) );
512 s.penColor = properties.valueAsColor( QgsDiagramLayerSettings::Property::StrokeColor, c.expressionContext(), s.penColor );
513 c.expressionContext().setOriginalValueVariable( s.penWidth );
514 s.penWidth = properties.valueAsDouble( QgsDiagramLayerSettings::Property::StrokeWidth, c.expressionContext(), s.penWidth );
515 c.expressionContext().setOriginalValueVariable( s.rotationOffset );
517 }
518
519 QgsPaintEffect *effect = s.paintEffect();
520 std::unique_ptr< QgsEffectPainter > effectPainter;
521 if ( effect && effect->enabled() )
522 {
523 effectPainter = std::make_unique< QgsEffectPainter >( c, effect );
524 }
525
526 mDiagram->renderDiagram( feature, c, s, pos );
527}
528
529QSizeF QgsDiagramRenderer::sizeMapUnits( const QgsFeature &feature, const QgsRenderContext &c ) const
530{
532 if ( !diagramSettings( feature, c, s ) || !s.enabled )
533 {
534 return QSizeF();
535 }
536
537 if ( s.scaleBasedVisibility )
538 {
539 // Note: scale might be a non-round number, so compare with qgsDoubleNear
540 const double rendererScale = c.rendererScale();
541
542 // maxScale is inclusive ( < --> no size )
543 double maxScale = s.maximumScale;
544 if ( maxScale > 0 && QgsScaleUtils::lessThanMaximumScale( rendererScale, maxScale ) )
545 {
546 return QSizeF();
547 }
548
549 // minScale is exclusive ( >= --> no size)
550 double minScale = s.minimumScale;
551 if ( minScale > 0 && QgsScaleUtils::equalToOrGreaterThanMinimumScale( rendererScale, minScale ) )
552 {
553 return QSizeF();
554 }
555 }
556
557 QSizeF size = diagramSize( feature, c );
558 if ( size.isValid() )
559 {
560 const double width = c.convertToMapUnits( size.width(), s.sizeType, s.sizeScale );
561 size.rheight() *= width / size.width();
562 size.setWidth( width );
563 }
564 return size;
565}
566
568{
569 QSet< QString > referenced;
570
571 if ( !mDiagram )
572 return referenced;
573
574 const auto constDiagramAttributes = diagramAttributes();
575 for ( const QString &att : constDiagramAttributes )
576 {
577 QgsExpression *expression = mDiagram->getExpression( att, context );
578 const auto constReferencedColumns = expression->referencedColumns();
579 for ( const QString &field : constReferencedColumns )
580 {
581 referenced << field;
582 }
583 }
584 return referenced;
585}
586
587void QgsDiagramRenderer::convertSizeToMapUnits( QSizeF &size, const QgsRenderContext &context ) const
588{
589 if ( !size.isValid() )
590 {
591 return;
592 }
593
594 const double pixelToMap = context.scaleFactor() * context.mapToPixel().mapUnitsPerPixel();
595 size.rwidth() *= pixelToMap;
596 size.rheight() *= pixelToMap;
597}
598
599int QgsDiagramRenderer::dpiPaintDevice( const QPainter *painter )
600{
601 if ( painter )
602 {
603 QPaintDevice *device = painter->device();
604 if ( device )
605 {
606 return device->logicalDpiX();
607 }
608 }
609 return -1;
610}
611
612void QgsDiagramRenderer::_readXml( const QDomElement &elem, const QgsReadWriteContext &context )
613{
614 Q_UNUSED( context )
615 mDiagram.reset();
616 const QString diagramType = elem.attribute( QStringLiteral( "diagramType" ) );
617 if ( diagramType == QgsPieDiagram::DIAGRAM_NAME_PIE )
618 {
619 mDiagram.reset( new QgsPieDiagram() );
620 }
621 else if ( diagramType == QgsTextDiagram::DIAGRAM_NAME_TEXT )
622 {
623 mDiagram.reset( new QgsTextDiagram() );
624 }
625 else if ( diagramType == QgsHistogramDiagram::DIAGRAM_NAME_HISTOGRAM )
626 {
627 mDiagram.reset( new QgsHistogramDiagram() );
628 }
629 else if ( diagramType == QgsStackedBarDiagram::DIAGRAM_NAME_STACKED_BAR )
630 {
631 mDiagram.reset( new QgsStackedBarDiagram() );
632 }
633 else if ( diagramType == QgsStackedDiagram::DIAGRAM_NAME_STACKED )
634 {
635 mDiagram.reset( new QgsStackedDiagram() );
636 }
637 else
638 {
639 // unknown diagram type -- default to histograms
640 mDiagram.reset( new QgsHistogramDiagram() );
641 }
642 mShowAttributeLegend = ( elem.attribute( QStringLiteral( "attributeLegend" ), QStringLiteral( "1" ) ) != QLatin1String( "0" ) );
643}
644
645void QgsDiagramRenderer::_writeXml( QDomElement &rendererElem, QDomDocument &doc, const QgsReadWriteContext &context ) const
646{
647 Q_UNUSED( doc )
648 Q_UNUSED( context )
649
650 if ( mDiagram )
651 {
652 rendererElem.setAttribute( QStringLiteral( "diagramType" ), mDiagram->diagramName() );
653 }
654 rendererElem.setAttribute( QStringLiteral( "attributeLegend" ), mShowAttributeLegend );
655}
656
657const QString QgsSingleCategoryDiagramRenderer::DIAGRAM_RENDERER_NAME_SINGLE_CATEGORY = QStringLiteral( "SingleCategory" );
658
663
665{
666 Q_UNUSED( c )
667 s = mSettings;
668 return true;
669}
670
672{
673 return mDiagram->diagramSize( feature.attributes(), c, mSettings );
674}
675
677{
678 QList<QgsDiagramSettings> settingsList;
679 settingsList.push_back( mSettings );
680 return settingsList;
681}
682
683void QgsSingleCategoryDiagramRenderer::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
684{
685 const QDomElement categoryElem = elem.firstChildElement( QStringLiteral( "DiagramCategory" ) );
686 if ( categoryElem.isNull() )
687 {
688 return;
689 }
690
691 mSettings.readXml( categoryElem, context );
692 _readXml( elem, context );
693}
694
695void QgsSingleCategoryDiagramRenderer::writeXml( QDomElement &layerElem, QDomDocument &doc, const QgsReadWriteContext &context ) const
696{
697 QDomElement rendererElem = doc.createElement( QStringLiteral( "SingleCategoryDiagramRenderer" ) );
698 mSettings.writeXml( rendererElem, doc, context );
699 _writeXml( rendererElem, doc, context );
700 layerElem.appendChild( rendererElem );
701}
702
703const QString QgsLinearlyInterpolatedDiagramRenderer::DIAGRAM_RENDERER_NAME_LINEARLY_INTERPOLATED = QLatin1String( "LinearlyInterpolated" );
704
709
711 : QgsDiagramRenderer( other )
712 , mSettings( other.mSettings )
713 , mInterpolationSettings( other.mInterpolationSettings )
714 , mDataDefinedSizeLegend( other.mDataDefinedSizeLegend ? new QgsDataDefinedSizeLegend( *other.mDataDefinedSizeLegend ) : nullptr )
715{
716}
717
722
724{
725 if ( &other == this )
726 {
727 return *this;
728 }
729 mSettings = other.mSettings;
730 mInterpolationSettings = other.mInterpolationSettings;
731 delete mDataDefinedSizeLegend;
732 mDataDefinedSizeLegend = new QgsDataDefinedSizeLegend( *other.mDataDefinedSizeLegend );
733 return *this;
734}
735
740
742{
743 QList<QgsDiagramSettings> settingsList;
744 settingsList.push_back( mSettings );
745 return settingsList;
746}
747
749{
750 s = mSettings;
751 s.size = diagramSize( feature, c );
752 return true;
753}
754
756{
757 return mSettings.categoryAttributes;
758}
759
761{
762 QSet< QString > referenced = QgsDiagramRenderer::referencedFields( context );
763 if ( mInterpolationSettings.classificationAttributeIsExpression )
764 {
765 QgsExpression *expression = mDiagram->getExpression( mInterpolationSettings.classificationAttributeExpression, context );
766 const auto constReferencedColumns = expression->referencedColumns();
767 for ( const QString &field : constReferencedColumns )
768 {
769 referenced << field;
770 }
771 }
772 else
773 {
774 referenced << mInterpolationSettings.classificationField;
775 }
776 return referenced;
777}
778
780{
781 return mDiagram->diagramSize( feature, c, mSettings, mInterpolationSettings );
782}
783
784void QgsLinearlyInterpolatedDiagramRenderer::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
785{
786 mInterpolationSettings.lowerValue = elem.attribute( QStringLiteral( "lowerValue" ) ).toDouble();
787 mInterpolationSettings.upperValue = elem.attribute( QStringLiteral( "upperValue" ) ).toDouble();
788 mInterpolationSettings.lowerSize.setWidth( elem.attribute( QStringLiteral( "lowerWidth" ) ).toDouble() );
789 mInterpolationSettings.lowerSize.setHeight( elem.attribute( QStringLiteral( "lowerHeight" ) ).toDouble() );
790 mInterpolationSettings.upperSize.setWidth( elem.attribute( QStringLiteral( "upperWidth" ) ).toDouble() );
791 mInterpolationSettings.upperSize.setHeight( elem.attribute( QStringLiteral( "upperHeight" ) ).toDouble() );
792 mInterpolationSettings.classificationAttributeIsExpression = elem.hasAttribute( QStringLiteral( "classificationAttributeExpression" ) );
793 if ( mInterpolationSettings.classificationAttributeIsExpression )
794 {
795 mInterpolationSettings.classificationAttributeExpression = elem.attribute( QStringLiteral( "classificationAttributeExpression" ) );
796 }
797 else
798 {
799 mInterpolationSettings.classificationField = elem.attribute( QStringLiteral( "classificationField" ) );
800 }
801 const QDomElement settingsElem = elem.firstChildElement( QStringLiteral( "DiagramCategory" ) );
802 if ( !settingsElem.isNull() )
803 {
804 mSettings.readXml( settingsElem );
805 }
806
807 delete mDataDefinedSizeLegend;
808
809 const QDomElement ddsLegendSizeElem = elem.firstChildElement( QStringLiteral( "data-defined-size-legend" ) );
810 if ( !ddsLegendSizeElem.isNull() )
811 {
812 mDataDefinedSizeLegend = QgsDataDefinedSizeLegend::readXml( ddsLegendSizeElem, context );
813 }
814 else
815 {
816 // pre-3.0 projects
817 if ( elem.attribute( QStringLiteral( "sizeLegend" ), QStringLiteral( "0" ) ) != QLatin1String( "0" ) )
818 {
819 mDataDefinedSizeLegend = new QgsDataDefinedSizeLegend();
820 const QDomElement sizeLegendSymbolElem = elem.firstChildElement( QStringLiteral( "symbol" ) );
821 if ( !sizeLegendSymbolElem.isNull() && sizeLegendSymbolElem.attribute( QStringLiteral( "name" ) ) == QLatin1String( "sizeSymbol" ) )
822 {
823 mDataDefinedSizeLegend->setSymbol( QgsSymbolLayerUtils::loadSymbol<QgsMarkerSymbol>( sizeLegendSymbolElem, context ) );
824 }
825 }
826 else
827 {
828 mDataDefinedSizeLegend = nullptr;
829 }
830 }
831
832 _readXml( elem, context );
833}
834
835void QgsLinearlyInterpolatedDiagramRenderer::writeXml( QDomElement &layerElem, QDomDocument &doc, const QgsReadWriteContext &context ) const
836{
837 QDomElement rendererElem = doc.createElement( QStringLiteral( "LinearlyInterpolatedDiagramRenderer" ) );
838 rendererElem.setAttribute( QStringLiteral( "lowerValue" ), QString::number( mInterpolationSettings.lowerValue ) );
839 rendererElem.setAttribute( QStringLiteral( "upperValue" ), QString::number( mInterpolationSettings.upperValue ) );
840 rendererElem.setAttribute( QStringLiteral( "lowerWidth" ), QString::number( mInterpolationSettings.lowerSize.width() ) );
841 rendererElem.setAttribute( QStringLiteral( "lowerHeight" ), QString::number( mInterpolationSettings.lowerSize.height() ) );
842 rendererElem.setAttribute( QStringLiteral( "upperWidth" ), QString::number( mInterpolationSettings.upperSize.width() ) );
843 rendererElem.setAttribute( QStringLiteral( "upperHeight" ), QString::number( mInterpolationSettings.upperSize.height() ) );
844 if ( mInterpolationSettings.classificationAttributeIsExpression )
845 {
846 rendererElem.setAttribute( QStringLiteral( "classificationAttributeExpression" ), mInterpolationSettings.classificationAttributeExpression );
847 }
848 else
849 {
850 rendererElem.setAttribute( QStringLiteral( "classificationField" ), mInterpolationSettings.classificationField );
851 }
852 mSettings.writeXml( rendererElem, doc );
853
854 if ( mDataDefinedSizeLegend )
855 {
856 QDomElement ddsLegendElem = doc.createElement( QStringLiteral( "data-defined-size-legend" ) );
857 mDataDefinedSizeLegend->writeXml( ddsLegendElem, context );
858 rendererElem.appendChild( ddsLegendElem );
859 }
860
861 _writeXml( rendererElem, doc, context );
862 layerElem.appendChild( rendererElem );
863}
864
865const QString QgsStackedDiagramRenderer::DIAGRAM_RENDERER_NAME_STACKED = QStringLiteral( "Stacked" );
866
868 : QgsDiagramRenderer( other )
869 , mSettings( other.mSettings )
870 , mDiagramRenderers()
871{
872 for ( QgsDiagramRenderer *renderer : std::as_const( other.mDiagramRenderers ) )
873 {
874 if ( renderer )
875 mDiagramRenderers << renderer->clone();
876 }
877}
878
880{
881 mSettings = other.mSettings;
882 qDeleteAll( mDiagramRenderers );
883 mDiagramRenderers.clear();
884 for ( QgsDiagramRenderer *renderer : std::as_const( other.mDiagramRenderers ) )
885 {
886 if ( renderer )
887 mDiagramRenderers << renderer->clone();
888 }
889
890 return *this;
891}
892
894{
895 qDeleteAll( mDiagramRenderers );
896}
897
902
904{
905 QSizeF stackedSize( 0, 0 );
906 int enabledDiagramCount = 0; // We'll add spacing only for enabled subDiagrams
907
908 // Iterate renderers. For each renderer, get the diagram
909 // size for the feature and add it to the total size
910 // accounting for stacked diagram defined spacing
911 for ( const QgsDiagramRenderer *subRenderer : std::as_const( mDiagramRenderers ) )
912 {
913 QSizeF size = subRenderer->sizeMapUnits( feature, c );
914
915 if ( size.isValid() )
916 {
917 enabledDiagramCount++;
918 switch ( mSettings.stackedDiagramMode )
919 {
921 stackedSize.setWidth( stackedSize.width() + size.width() );
922 stackedSize.setHeight( std::max( stackedSize.height(), size.height() ) );
923 break;
924
926 stackedSize.setWidth( std::max( stackedSize.width(), size.width() ) );
927 stackedSize.setHeight( stackedSize.height() + size.height() );
928 break;
929 }
930 }
931 }
932
933 if ( stackedSize.isValid() )
934 {
935 const double spacing = c.convertToMapUnits( mSettings.stackedDiagramSpacing(), mSettings.stackedDiagramSpacingUnit(), mSettings.stackedDiagramSpacingMapUnitScale() );
936
937 switch ( mSettings.stackedDiagramMode )
938 {
940 stackedSize.scale( stackedSize.width() + spacing * ( enabledDiagramCount - 1 ), stackedSize.height(), Qt::IgnoreAspectRatio );
941 break;
942
944 stackedSize.scale( stackedSize.width(), stackedSize.height() + spacing * ( enabledDiagramCount - 1 ), Qt::IgnoreAspectRatio );
945 break;
946 }
947 }
948 return stackedSize;
949}
950
951void QgsStackedDiagramRenderer::renderDiagram( const QgsFeature &feature, QgsRenderContext &c, QPointF pos, const QgsPropertyCollection &properties ) const
952{
953 if ( !mDiagram )
954 {
955 return;
956 }
957
958 QPointF newPos = pos; // Each subdiagram will have its own newPos
959
960 // Get subrenderers sorted by mode (vertical diagrams are returned backwards)
961 const QList< QgsDiagramRenderer * > stackedRenderers = renderers( true );
962
963 for ( const QgsDiagramRenderer *stackedRenderer : stackedRenderers )
964 {
965 if ( stackedRenderer->rendererName() == QgsStackedDiagramRenderer::DIAGRAM_RENDERER_NAME_STACKED )
966 {
967 // Nested stacked diagrams will use this recursion
968 stackedRenderer->renderDiagram( feature, c, newPos, properties );
969 continue;
970 }
971
973 if ( !stackedRenderer->diagramSettings( feature, c, s ) )
974 {
975 continue;
976 }
977
978 if ( !s.enabled )
979 {
980 continue;
981 }
982
983 if ( s.scaleBasedVisibility )
984 {
985 // Note: scale might be a non-round number, so compare with qgsDoubleNear
986 const double rendererScale = c.rendererScale();
987
988 // maxScale is inclusive ( < --> no diagram )
989 double maxScale = s.maximumScale;
990 if ( maxScale > 0 && QgsScaleUtils::lessThanMaximumScale( rendererScale, maxScale ) )
991 {
992 continue;
993 }
994
995 // minScale is exclusive ( >= --> no diagram)
996 double minScale = s.minimumScale;
997 if ( minScale > 0 && QgsScaleUtils::equalToOrGreaterThanMinimumScale( rendererScale, minScale ) )
998 {
999 continue;
1000 }
1001 }
1002
1003 if ( properties.hasActiveProperties() )
1004 {
1005 c.expressionContext().setOriginalValueVariable( QgsColorUtils::colorToString( s.backgroundColor ) );
1007 c.expressionContext().setOriginalValueVariable( QgsColorUtils::colorToString( s.penColor ) );
1008 s.penColor = properties.valueAsColor( QgsDiagramLayerSettings::Property::StrokeColor, c.expressionContext(), s.penColor );
1009 c.expressionContext().setOriginalValueVariable( s.penWidth );
1010 s.penWidth = properties.valueAsDouble( QgsDiagramLayerSettings::Property::StrokeWidth, c.expressionContext(), s.penWidth );
1011 c.expressionContext().setOriginalValueVariable( s.rotationOffset );
1013 }
1014
1015 QgsPaintEffect *effect = s.paintEffect();
1016 std::unique_ptr< QgsEffectPainter > effectPainter;
1017 if ( effect && effect->enabled() )
1018 {
1019 effectPainter = std::make_unique< QgsEffectPainter >( c, effect );
1020 }
1021
1022 stackedRenderer->diagram()->renderDiagram( feature, c, s, newPos );
1023 QgsStackedDiagram *stackedDiagram = dynamic_cast< QgsStackedDiagram *>( mDiagram.get() );
1024 stackedDiagram->subDiagramPosition( newPos, c, mSettings, s );
1025 }
1026}
1027
1029{
1030 Q_UNUSED( feature )
1031 Q_UNUSED( c )
1032 Q_UNUSED( s )
1033 return false;
1034}
1035
1037{
1038 Q_UNUSED( feature )
1039 Q_UNUSED( c )
1040 return QSizeF( 0, 0 );
1041}
1042
1043QList<QgsDiagramSettings> QgsStackedDiagramRenderer::diagramSettings() const
1044{
1045 QList<QgsDiagramSettings> settingsList;
1046 settingsList.push_back( mSettings );
1047 return settingsList;
1048}
1049
1051{
1052 return mSettings.categoryAttributes;
1053}
1054
1055QList< QgsLayerTreeModelLegendNode * > QgsStackedDiagramRenderer::legendItems( QgsLayerTreeLayer *nodeLayer ) const
1056{
1057 QList< QgsLayerTreeModelLegendNode * > nodes;
1058 for ( const QgsDiagramRenderer *renderer : std::as_const( mDiagramRenderers ) )
1059 {
1060 nodes << renderer->legendItems( nodeLayer );
1061 }
1062
1063 return nodes;
1064}
1065
1066QList< QgsDiagramRenderer * > QgsStackedDiagramRenderer::renderers( bool sortByDiagramMode ) const
1067{
1068 QList< QgsDiagramRenderer * > renderers = mDiagramRenderers;
1069
1070 if ( sortByDiagramMode && mSettings.stackedDiagramMode == QgsDiagramSettings::Vertical )
1071 {
1072 // We draw vertical diagrams backwards, so
1073 // we return the subrenderers in reverse order
1074 std::reverse( renderers.begin(), renderers.end() );
1075 }
1076 return renderers;
1077}
1078
1080{
1081 if ( renderer )
1082 {
1083 mDiagramRenderers.append( renderer );
1084 }
1085}
1086
1088{
1089 return mDiagramRenderers.value( index );
1090}
1091
1093{
1094 return mDiagramRenderers.size();
1095}
1096
1097void QgsStackedDiagramRenderer::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
1098{
1099 const QDomElement categoryElem = elem.firstChildElement( QStringLiteral( "DiagramCategory" ) );
1100 if ( categoryElem.isNull() )
1101 {
1102 return;
1103 }
1104
1105 mSettings.readXml( categoryElem, context );
1106 _readXml( elem, context );
1107 _readXmlSubRenderers( elem, context );
1108}
1109
1110void QgsStackedDiagramRenderer::_readXmlSubRenderers( const QDomElement &elem, const QgsReadWriteContext &context )
1111{
1112 qDeleteAll( mDiagramRenderers );
1113 mDiagramRenderers.clear();
1114
1115 const QDomElement subRenderersElem = elem.firstChildElement( QStringLiteral( "DiagramRenderers" ) );
1116
1117 if ( !subRenderersElem.isNull() )
1118 {
1119 const QDomNodeList childRendererList = subRenderersElem.childNodes();
1120
1121 for ( int i = 0; i < childRendererList.size(); i++ )
1122 {
1123 const QDomElement subRendererElem = childRendererList.at( i ).toElement();
1124
1125 if ( subRendererElem.nodeName() == QLatin1String( "SingleCategoryDiagramRenderer" ) )
1126 {
1127 std::unique_ptr< QgsSingleCategoryDiagramRenderer > singleCatDiagramRenderer = std::make_unique< QgsSingleCategoryDiagramRenderer >();
1128 singleCatDiagramRenderer->readXml( subRendererElem, context );
1129 addRenderer( singleCatDiagramRenderer.release() );
1130 }
1131 else if ( subRendererElem.nodeName() == QLatin1String( "LinearlyInterpolatedDiagramRenderer" ) )
1132 {
1133 std::unique_ptr< QgsLinearlyInterpolatedDiagramRenderer > linearDiagramRenderer = std::make_unique< QgsLinearlyInterpolatedDiagramRenderer >();
1134 linearDiagramRenderer->readXml( subRendererElem, context );
1135 addRenderer( linearDiagramRenderer.release() );
1136 }
1137 else if ( subRendererElem.nodeName() == QLatin1String( "StackedDiagramRenderer" ) )
1138 {
1139 std::unique_ptr< QgsStackedDiagramRenderer > stackedDiagramRenderer = std::make_unique< QgsStackedDiagramRenderer >();
1140 stackedDiagramRenderer->readXml( subRendererElem, context );
1141 addRenderer( stackedDiagramRenderer.release() );
1142 }
1143 }
1144 }
1145}
1146
1147void QgsStackedDiagramRenderer::writeXml( QDomElement &layerElem, QDomDocument &doc, const QgsReadWriteContext &context ) const
1148{
1149 QDomElement rendererElem = doc.createElement( QStringLiteral( "StackedDiagramRenderer" ) );
1150 mSettings.writeXml( rendererElem, doc, context );
1151 _writeXml( rendererElem, doc, context );
1152 _writeXmlSubRenderers( rendererElem, doc, context );
1153 layerElem.appendChild( rendererElem );
1154}
1155
1156void QgsStackedDiagramRenderer::_writeXmlSubRenderers( QDomElement &rendererElem, QDomDocument &doc, const QgsReadWriteContext &context ) const
1157{
1158 QDomElement renderersElem = doc.createElement( QStringLiteral( "DiagramRenderers" ) );
1159
1160 // Iterate sub renderers and write their settings to a DOM object
1161 for ( int i = 0; i < mDiagramRenderers.count(); i++ )
1162 {
1163 mDiagramRenderers.at( i )->writeXml( renderersElem, doc, context );
1164 }
1165 rendererElem.appendChild( renderersElem );
1166}
1167
1168QList< QgsLayerTreeModelLegendNode * > QgsDiagramSettings::legendItems( QgsLayerTreeLayer *nodeLayer ) const
1169{
1170 QList< QgsLayerTreeModelLegendNode * > list;
1171 list.reserve( categoryLabels.size() );
1172 for ( int i = 0; i < categoryLabels.size(); ++i )
1173 {
1174 QPixmap pix( 16, 16 );
1175 pix.fill( categoryColors[i] );
1176 list << new QgsSimpleLegendNode( nodeLayer, categoryLabels[i], QIcon( pix ), nullptr, QStringLiteral( "diagram_%1" ).arg( QString::number( i ) ) );
1177 }
1178 return list;
1179}
1180
1182{
1183 return mAxisLineSymbol.get();
1184}
1185
1187{
1188 if ( axisLineSymbol != mAxisLineSymbol.get() )
1189 mAxisLineSymbol.reset( axisLineSymbol );
1190}
1191
1193{
1194 return mShowAxis;
1195}
1196
1198{
1199 mShowAxis = showAxis;
1200}
1201
1203{
1204 return mPaintEffect.get();
1205}
1206
1208{
1209 if ( effect != mPaintEffect.get() )
1210 mPaintEffect.reset( effect );
1211}
1212
1214 : mAxisLineSymbol( std::make_unique< QgsLineSymbol >() )
1215{
1216}
1217
1219
1221 : enabled( other.enabled )
1222 , font( other.font )
1223 , categoryColors( other.categoryColors )
1224 , categoryAttributes( other.categoryAttributes )
1225 , categoryLabels( other.categoryLabels )
1226 , size( other.size )
1227 , sizeType( other.sizeType )
1228 , sizeScale( other.sizeScale )
1229 , lineSizeUnit( other.lineSizeUnit )
1230 , lineSizeScale( other.lineSizeScale )
1231 , backgroundColor( other.backgroundColor )
1232 , penColor( other.penColor )
1233 , penWidth( other.penWidth )
1234 , labelPlacementMethod( other.labelPlacementMethod )
1235 , diagramOrientation( other.diagramOrientation )
1236 , stackedDiagramMode( other.stackedDiagramMode )
1237 , barWidth( other.barWidth )
1238 , opacity( other.opacity )
1239 , scaleByArea( other.scaleByArea )
1240 , rotationOffset( other.rotationOffset )
1241 , scaleBasedVisibility( other.scaleBasedVisibility )
1242 , maximumScale( other.maximumScale )
1243 , minimumScale( other.minimumScale )
1244 , minimumSize( other.minimumSize )
1245 , mSpacing( other.mSpacing )
1246 , mSpacingUnit( other.mSpacingUnit )
1247 , mSpacingMapUnitScale( other.mSpacingMapUnitScale )
1248 , mStackedDiagramSpacing( other.mStackedDiagramSpacing )
1249 , mStackedDiagramSpacingUnit( other.mStackedDiagramSpacingUnit )
1250 , mStackedDiagramSpacingMapUnitScale( other.mStackedDiagramSpacingMapUnitScale )
1251 , mDirection( other.mDirection )
1252 , mShowAxis( other.mShowAxis )
1253 , mAxisLineSymbol( other.mAxisLineSymbol ? other.mAxisLineSymbol->clone() : nullptr )
1254 , mPaintEffect( other.mPaintEffect ? other.mPaintEffect->clone() : nullptr )
1255{
1256
1257}
1258
1260{
1261 enabled = other.enabled;
1262 font = other.font;
1266 size = other.size;
1267 sizeType = other.sizeType;
1268 sizeScale = other.sizeScale;
1269 lineSizeUnit = other.lineSizeUnit;
1272 penColor = other.penColor;
1273 penWidth = other.penWidth;
1277 barWidth = other.barWidth;
1278 opacity = other.opacity;
1279 scaleByArea = other.scaleByArea;
1282 maximumScale = other.maximumScale;
1283 minimumScale = other.minimumScale;
1284 minimumSize = other.minimumSize;
1285 mSpacing = other.mSpacing;
1286 mSpacingUnit = other.mSpacingUnit;
1287 mSpacingMapUnitScale = other.mSpacingMapUnitScale;
1288 mStackedDiagramSpacing = other.mStackedDiagramSpacing;
1289 mStackedDiagramSpacingUnit = other.mStackedDiagramSpacingUnit;
1290 mStackedDiagramSpacingMapUnitScale = other.mStackedDiagramSpacingMapUnitScale;
1291 mDirection = other.mDirection;
1292 mAxisLineSymbol.reset( other.mAxisLineSymbol ? other.mAxisLineSymbol->clone() : nullptr );
1293 mShowAxis = other.mShowAxis;
1294 mPaintEffect.reset( other.mPaintEffect ? other.mPaintEffect->clone() : nullptr );
1295 return *this;
1296}
1297
1299{
1300 return mDirection;
1301}
1302
1304{
1305 mDirection = direction;
1306}
1307
1308QList< QgsLayerTreeModelLegendNode * > QgsDiagramRenderer::legendItems( QgsLayerTreeLayer * ) const
1309{
1310 return QList< QgsLayerTreeModelLegendNode * >();
1311}
1312
1313QList< QgsLayerTreeModelLegendNode * > QgsSingleCategoryDiagramRenderer::legendItems( QgsLayerTreeLayer *nodeLayer ) const
1314{
1315 QList< QgsLayerTreeModelLegendNode * > nodes;
1316 if ( mShowAttributeLegend && mSettings.enabled )
1317 nodes = mSettings.legendItems( nodeLayer );
1318
1319 return nodes;
1320}
1321
1322QList< QgsLayerTreeModelLegendNode * > QgsLinearlyInterpolatedDiagramRenderer::legendItems( QgsLayerTreeLayer *nodeLayer ) const
1323{
1324 QList< QgsLayerTreeModelLegendNode * > nodes;
1325 if ( !mSettings.enabled )
1326 {
1327 return nodes;
1328 }
1329
1331 nodes = mSettings.legendItems( nodeLayer );
1332
1333 if ( mDataDefinedSizeLegend && mDiagram )
1334 {
1335 // add size legend
1336 QgsMarkerSymbol *legendSymbol = mDataDefinedSizeLegend->symbol() ? mDataDefinedSizeLegend->symbol()->clone() : QgsMarkerSymbol::createSimple( QVariantMap() );
1337 legendSymbol->setSizeUnit( mSettings.sizeType );
1338 legendSymbol->setSizeMapUnitScale( mSettings.sizeScale );
1339
1340 QgsDataDefinedSizeLegend ddSizeLegend( *mDataDefinedSizeLegend );
1341 ddSizeLegend.setSymbol( legendSymbol ); // transfers ownership
1342
1343 QList<QgsDataDefinedSizeLegend::SizeClass> sizeClasses;
1344 if ( ddSizeLegend.classes().isEmpty() )
1345 {
1346 // automatic class creation if the classes are not defined manually
1347 const auto prettyBreaks { QgsSymbolLayerUtils::prettyBreaks( mInterpolationSettings.lowerValue, mInterpolationSettings.upperValue, 4 ) };
1348 for ( const double v : prettyBreaks )
1349 {
1350 const double size = mDiagram->legendSize( v, mSettings, mInterpolationSettings );
1351 sizeClasses << QgsDataDefinedSizeLegend::SizeClass( size, QString::number( v ) );
1352 }
1353 }
1354 else
1355 {
1356 // manual classes need to get size scaled because the QgsSizeScaleTransformer is not used in diagrams :-(
1357 const auto constClasses = ddSizeLegend.classes();
1358 for ( const QgsDataDefinedSizeLegend::SizeClass &sc : constClasses )
1359 {
1360 const double size = mDiagram->legendSize( sc.size, mSettings, mInterpolationSettings );
1361 sizeClasses << QgsDataDefinedSizeLegend::SizeClass( size, sc.label );
1362 }
1363 }
1364 ddSizeLegend.setClasses( sizeClasses );
1365
1366 const auto constLegendSymbolList = ddSizeLegend.legendSymbolList();
1367 for ( const QgsLegendSymbolItem &si : constLegendSymbolList )
1368 {
1369 if ( auto *lDataDefinedSizeLegendSettings = si.dataDefinedSizeLegendSettings() )
1370 nodes << new QgsDataDefinedSizeLegendNode( nodeLayer, *lDataDefinedSizeLegendSettings );
1371 else
1372 nodes << new QgsSymbolLegendNode( nodeLayer, si );
1373 }
1374 }
1375
1376 return nodes;
1377}
1378
1380{
1381 delete mDataDefinedSizeLegend;
1382 mDataDefinedSizeLegend = settings;
1383}
1384
@ MapUnits
Map units.
QColor valueAsColor(int key, const QgsExpressionContext &context, const QColor &defaultColor=QColor(), bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a color.
double valueAsDouble(int key, const QgsExpressionContext &context, double defaultValue=0.0, bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a double.
virtual bool readXml(const QDomElement &collectionElem, const QgsPropertiesDefinition &definitions)
Reads property collection state from an XML element.
virtual bool writeXml(QDomElement &collectionElem, const QgsPropertiesDefinition &definitions) const
Writes the current state of the property collection into an XML element.
static QgsPaintEffectRegistry * paintEffectRegistry()
Returns the application's paint effect registry, used for managing paint effects.
static QString colorToString(const QColor &color)
Encodes a color into a string value.
Class for doing transforms between two map coordinate systems.
Produces legend node with a marker symbol.
Object that keeps configuration of appearance of marker symbol's data-defined size in legend.
QList< QgsDataDefinedSizeLegend::SizeClass > classes() const
Returns list of classes: each class is a pair of symbol size (in units used by the symbol) and label.
void setSymbol(QgsMarkerSymbol *symbol SIP_TRANSFER)
Sets marker symbol that will be used to draw markers in legend.
QgsMarkerSymbol * symbol() const
Returns marker symbol that will be used to draw markers in legend.
void setClasses(const QList< QgsDataDefinedSizeLegend::SizeClass > &classes)
Sets list of classes: each class is a pair of symbol size (in units used by the symbol) and label.
static QgsDataDefinedSizeLegend * readXml(const QDomElement &elem, const QgsReadWriteContext &context) SIP_FACTORY
Creates instance from given element and returns it (caller takes ownership). Returns nullptr on error...
void writeXml(QDomElement &elem, const QgsReadWriteContext &context) const
Writes configuration to the given XML element.
QgsLegendSymbolList legendSymbolList() const
Generates legend symbol items according to the configuration.
QString classificationField
Name of the field for classification.
Stores the settings for rendering of all diagrams for a layer.
LinePlacementFlag
Line placement flags for controlling line based placements.
QgsDiagramLayerSettings & operator=(const QgsDiagramLayerSettings &rh)
void setRenderer(QgsDiagramRenderer *diagramRenderer)
Sets the diagram renderer associated with the layer.
@ PositionX
X-coordinate data defined diagram position.
@ Distance
Distance to diagram from feature.
@ PositionY
Y-coordinate data defined diagram position.
@ Show
Whether to show the diagram.
@ Priority
Diagram priority (between 0 and 10)
@ ZIndex
Z-index for diagram ordering.
@ BackgroundColor
Diagram background color.
@ StartAngle
Angle offset for pie diagram.
@ IsObstacle
Whether diagram features act as obstacles for other diagrams/labels.
@ AlwaysShow
Whether the diagram should always be shown, even if it overlaps other diagrams/labels.
void readXml(const QDomElement &elem)
Reads the diagram settings from a DOM element.
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the diagram property definitions.
QSet< QString > referencedFields(const QgsExpressionContext &context=QgsExpressionContext()) const
Returns the set of any fields referenced by the layer's diagrams.
void writeXml(QDomElement &layerElem, QDomDocument &doc) const
Writes the diagram settings to a DOM element.
bool prepare(const QgsExpressionContext &context=QgsExpressionContext()) const
Prepares the diagrams for a specified expression context.
void setCoordinateTransform(const QgsCoordinateTransform &transform)
Sets the coordinate transform associated with the layer.
Evaluates and returns the diagram settings relating to a diagram for a specific feature.
virtual QList< QgsLayerTreeModelLegendNode * > legendItems(QgsLayerTreeLayer *nodeLayer) const
Returns list of legend nodes for the diagram.
virtual QSizeF diagramSize(const QgsFeature &feature, const QgsRenderContext &c) const =0
Returns size of the diagram (in painter units) or an invalid size in case of error.
void _writeXml(QDomElement &rendererElem, QDomDocument &doc, const QgsReadWriteContext &context) const
Writes internal QgsDiagramRenderer diagram state to a DOM element.
virtual QSet< QString > referencedFields(const QgsExpressionContext &context=QgsExpressionContext()) const
Returns the set of any fields required for diagram rendering.
virtual void renderDiagram(const QgsFeature &feature, QgsRenderContext &c, QPointF pos, const QgsPropertyCollection &properties=QgsPropertyCollection()) const
Renders the diagram for a specified feature at a specific position in the passed render context.
void _readXml(const QDomElement &elem, const QgsReadWriteContext &context)
Reads internal QgsDiagramRenderer state from a DOM element.
QgsDiagramRenderer & operator=(const QgsDiagramRenderer &other)
virtual QSizeF sizeMapUnits(const QgsFeature &feature, const QgsRenderContext &c) const
Returns size of the diagram for a feature in map units. Returns an invalid QSizeF in case of error.
virtual QList< QString > diagramAttributes() const =0
Returns attribute indices needed for diagram rendering.
std::unique_ptr< QgsDiagram > mDiagram
Reference to the object that does the real diagram rendering.
void convertSizeToMapUnits(QSizeF &size, const QgsRenderContext &context) const
Converts size from mm to map units.
virtual QList< QgsDiagramSettings > diagramSettings() const =0
Returns list with all diagram settings in the renderer.
bool mShowAttributeLegend
Whether to show an attribute legend for the diagrams.
QgsDiagramRenderer()=default
void setDiagram(QgsDiagram *d)
virtual QgsDiagramRenderer * clone() const =0
Returns new instance that is equivalent to this one.
static int dpiPaintDevice(const QPainter *)
Returns the paint device dpi (or -1 in case of error.
Stores the settings for rendering a single diagram.
Direction direction() const
Returns the chart's angular direction.
StackedDiagramMode stackedDiagramMode
void setDirection(Direction direction)
Sets the chart's angular direction.
bool showAxis() const
Returns true if the diagram axis should be shown.
LabelPlacementMethod labelPlacementMethod
void readXml(const QDomElement &elem, const QgsReadWriteContext &context=QgsReadWriteContext())
Reads diagram settings from XML.
double opacity
Opacity, from 0 (transparent) to 1.0 (opaque)
QgsDiagramSettings & operator=(const QgsDiagramSettings &other)
QgsLineSymbol * axisLineSymbol() const
Returns the line symbol to use for rendering axis in diagrams.
Qgis::RenderUnit sizeType
Diagram size unit.
QList< QString > categoryAttributes
QList< QString > categoryLabels
Qgis::RenderUnit stackedDiagramSpacingUnit() const
Returns the units for the spacing between subdiagrams in a stacked diagram.
DiagramOrientation diagramOrientation
QList< QgsLayerTreeModelLegendNode * > legendItems(QgsLayerTreeLayer *nodeLayer) const
Returns list of legend nodes for the diagram.
QgsMapUnitScale lineSizeScale
Line unit scale.
void writeXml(QDomElement &rendererElem, QDomDocument &doc, const QgsReadWriteContext &context=QgsReadWriteContext()) const
Writes diagram settings to XML.
QList< QColor > categoryColors
double rotationOffset
Rotation offset, in degrees clockwise from horizontal.
QgsMapUnitScale sizeScale
Diagram size unit scale.
double minimumScale
The minimum map scale (i.e.
const QgsMapUnitScale & stackedDiagramSpacingMapUnitScale() const
Returns the map unit scale for the spacing between subdiagrams in a stacked diagram.
double maximumScale
The maximum map scale (i.e.
void setAxisLineSymbol(QgsLineSymbol *symbol)
Sets the line symbol to use for rendering axis in diagrams.
Qgis::RenderUnit lineSizeUnit
Line unit index.
double minimumSize
Scale diagrams smaller than mMinimumSize to mMinimumSize.
Direction
Angular directions.
void setShowAxis(bool showAxis)
Sets whether the diagram axis should be shown.
double stackedDiagramSpacing() const
Returns the spacing between subdiagrams in a stacked diagram.
void setPaintEffect(QgsPaintEffect *effect)
Sets the paint effect to use while rendering diagrams.
QgsPaintEffect * paintEffect() const
Returns the paint effect to use while rendering diagrams.
Base class for all diagram types.
Definition qgsdiagram.h:40
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Class for parsing and evaluation of expressions (formerly called "search strings").
QSet< QString > referencedColumns() const
Gets list of columns referenced by the expression.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:58
QgsAttributes attributes
Definition qgsfeature.h:67
static bool setFromXmlChildNode(QFont &font, const QDomElement &element, const QString &childNode)
Sets the properties of a font to match the properties stored in an XML child node.
static QDomElement toXmlElement(const QFont &font, QDomDocument &document, const QString &elementName)
Returns a DOM element containing the properties of the font.
A histogram style diagram.
static const QString DIAGRAM_NAME_HISTOGRAM
Layer tree node points to a map layer.
The class stores information about one class/rule of a vector layer renderer in a unified way that ca...
A line symbol type, for rendering LineString and MultiLineString geometries.
Alters the size of rendered diagrams using a linear scaling.
void setDataDefinedSizeLegend(QgsDataDefinedSizeLegend *settings)
Configures appearance of legend.
QSizeF diagramSize(const QgsFeature &, const QgsRenderContext &c) const override
Returns size of the diagram (in painter units) or an invalid size in case of error.
QList< QString > diagramAttributes() const override
Returns attribute indices needed for diagram rendering.
QSet< QString > referencedFields(const QgsExpressionContext &context=QgsExpressionContext()) const override
Returns the set of any fields required for diagram rendering.
QList< QgsDiagramSettings > diagramSettings() const override
Returns list with all diagram settings in the renderer.
void writeXml(QDomElement &layerElem, QDomDocument &doc, const QgsReadWriteContext &context) const override
Writes diagram state to a DOM element.
QgsLinearlyInterpolatedDiagramRenderer * clone() const override
Returns new instance that is equivalent to this one.
QList< QgsLayerTreeModelLegendNode * > legendItems(QgsLayerTreeLayer *nodeLayer) const override
Returns list of legend nodes for the diagram.
void readXml(const QDomElement &elem, const QgsReadWriteContext &context) override
Reads diagram state from a DOM element.
QgsDataDefinedSizeLegend * dataDefinedSizeLegend() const
Returns configuration of appearance of legend.
QgsLinearlyInterpolatedDiagramRenderer & operator=(const QgsLinearlyInterpolatedDiagramRenderer &other)
static const QString DIAGRAM_RENDERER_NAME_LINEARLY_INTERPOLATED
double mapUnitsPerPixel() const
Returns the current map units per pixel.
A marker symbol type, for rendering Point and MultiPoint geometries.
static QgsMarkerSymbol * createSimple(const QVariantMap &properties)
Create a marker symbol with one symbol layer: SimpleMarker with specified properties.
QgsMarkerSymbol * clone() const override
Returns a deep copy of this symbol.
void setSizeMapUnitScale(const QgsMapUnitScale &scale) const
Sets the size map unit scale for the whole symbol (including all symbol layers).
void setSizeUnit(Qgis::RenderUnit unit) const
Sets the size units for the whole symbol (including all symbol layers).
static QgsPaintEffect * defaultStack()
Returns a new effect stack consisting of a sensible selection of default effects.
static bool isDefaultStack(QgsPaintEffect *effect)
Tests whether a paint effect matches the default effects stack.
Base class for visual effects which can be applied to QPicture drawings.
bool enabled() const
Returns whether the effect is enabled.
A pie chart diagram.
static const QString DIAGRAM_NAME_PIE
A grouped map of multiple QgsProperty objects, each referenced by a integer key value.
void clear() final
Removes all properties from the collection.
bool prepare(const QgsExpressionContext &context=QgsExpressionContext()) const final
Prepares the collection against a specified expression context.
bool hasActiveProperties() const final
Returns true if the collection has any active properties, or false if all properties within the colle...
QSet< QString > referencedFields(const QgsExpressionContext &context=QgsExpressionContext(), bool ignoreContext=false) const final
Returns the set of any fields referenced by the active properties from the collection.
Definition for a property.
Definition qgsproperty.h:45
@ Double
Double value (including negative values)
Definition qgsproperty.h:55
@ StrokeWidth
Line stroke width.
Definition qgsproperty.h:70
@ Boolean
Boolean value.
Definition qgsproperty.h:51
@ Rotation
Rotation (value between 0-360 degrees)
Definition qgsproperty.h:58
@ ColorWithAlpha
Color with alpha channel.
Definition qgsproperty.h:62
@ DoublePositive
Positive double value (including 0)
Definition qgsproperty.h:56
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.
double scaleFactor() const
Returns the scaling factor for the render to convert painter units to physical sizes.
const QgsMapToPixel & mapToPixel() const
Returns the context's map to pixel transform, which transforms between map coordinates and device coo...
static bool equalToOrGreaterThanMinimumScale(const double scale, const double minScale)
Returns whether the scale is equal to or greater than the minScale, taking non-round numbers into acc...
static bool lessThanMaximumScale(const double scale, const double maxScale)
Returns whether the scale is less than the maxScale, taking non-round numbers into account.
Implementation of legend node interface for displaying arbitrary label with icon.
Renders the diagrams for all features with the same settings.
QSizeF diagramSize(const QgsFeature &, const QgsRenderContext &c) const override
Returns size of the diagram (in painter units) or an invalid size in case of error.
void writeXml(QDomElement &layerElem, QDomDocument &doc, const QgsReadWriteContext &context) const override
Writes diagram state to a DOM element.
QgsSingleCategoryDiagramRenderer * clone() const override
Returns new instance that is equivalent to this one.
QList< QgsLayerTreeModelLegendNode * > legendItems(QgsLayerTreeLayer *nodeLayer) const override
Returns list of legend nodes for the diagram.
void readXml(const QDomElement &elem, const QgsReadWriteContext &context) override
Reads diagram state from a DOM element.
QList< QgsDiagramSettings > diagramSettings() const override
Returns list with all diagram settings in the renderer.
static const QString DIAGRAM_RENDERER_NAME_SINGLE_CATEGORY
A stacked bar chart diagram.
static const QString DIAGRAM_NAME_STACKED_BAR
Renders diagrams using mixed diagram render types.
QgsStackedDiagramRenderer * clone() const override
Returns new instance that is equivalent to this one.
QList< QgsDiagramSettings > diagramSettings() const override
Returns list with all diagram settings in the renderer.
QSizeF diagramSize(const QgsFeature &, const QgsRenderContext &c) const override
Returns size of the diagram (in painter units) or an invalid size in case of error.
virtual void renderDiagram(const QgsFeature &feature, QgsRenderContext &c, QPointF pos, const QgsPropertyCollection &properties=QgsPropertyCollection()) const override
Renders the diagram for a specified feature at a specific position in the passed render context,...
QList< QString > diagramAttributes() const override
Returns attribute indices needed for diagram rendering.
void writeXml(QDomElement &layerElem, QDomDocument &doc, const QgsReadWriteContext &context) const override
Writes diagram state to a DOM element.
static const QString DIAGRAM_RENDERER_NAME_STACKED
QgsStackedDiagramRenderer & operator=(const QgsStackedDiagramRenderer &other)
void readXml(const QDomElement &elem, const QgsReadWriteContext &context) override
Reads diagram state from a DOM element.
void addRenderer(QgsDiagramRenderer *renderer)
Adds a renderer to the stacked renderer object.
void _writeXmlSubRenderers(QDomElement &rendererElem, QDomDocument &doc, const QgsReadWriteContext &context) const
Writes stacked renderers state to a DOM element.
QList< QgsDiagramRenderer * > renderers(bool sortByDiagramMode=false) const
Returns an ordered list with the renderers of the stacked renderer object.
const QgsDiagramRenderer * renderer(const int index) const
Returns the renderer at the given index.
void _readXmlSubRenderers(const QDomElement &elem, const QgsReadWriteContext &context)
Reads stacked renderers state from a DOM element.
int rendererCount() const
Returns the number of sub renderers in the stacked diagram renderer.
QList< QgsLayerTreeModelLegendNode * > legendItems(QgsLayerTreeLayer *nodeLayer) const override
Returns list of legend nodes for the diagram.
QgsStackedDiagramRenderer()=default
virtual QSizeF sizeMapUnits(const QgsFeature &feature, const QgsRenderContext &c) const override
Returns size of the diagram for a feature in map units. Returns an invalid QSizeF in case of error.
A diagram composed of several subdiagrams, located side by side.
static const QString DIAGRAM_NAME_STACKED
void subDiagramPosition(QPointF &newPos, const QgsRenderContext &c, const QgsDiagramSettings &s, const QgsDiagramSettings &subSettings)
Calculates the position for the next subdiagram, updating the newPos object.
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
static QList< double > prettyBreaks(double minimum, double maximum, int classes)
Computes a sequence of about 'classes' equally spaced round values which cover the range of values fr...
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
Implementation of legend node interface for displaying preview of vector symbols and their labels and...
A text based diagram.
static const QString DIAGRAM_NAME_TEXT
static Q_INVOKABLE Qgis::RenderUnit decodeRenderUnit(const QString &string, bool *ok=nullptr)
Decodes a render unit from a string.
static Q_INVOKABLE QString encodeUnit(Qgis::DistanceUnit unit)
Encodes a distance unit to a string.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
QMap< int, QgsPropertyDefinition > QgsPropertiesDefinition
Definition of available properties.
Definition of one class for the legend.