QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
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
18#include "qgsvectorlayer.h"
23#include "qgsrendercontext.h"
25#include "qgsfontutils.h"
26#include "qgssymbollayerutils.h"
28#include "qgspainteffect.h"
29#include "qgsapplication.h"
30#include "qgslinesymbol.h"
31#include "qgsmarkersymbol.h"
32
33#include <QDomElement>
34#include <QPainter>
35
36QgsPropertiesDefinition QgsDiagramLayerSettings::sPropertyDefinitions;
37
38void QgsDiagramLayerSettings::initPropertyDefinitions()
39{
40 if ( !sPropertyDefinitions.isEmpty() )
41 return;
42
43 const QString origin = QStringLiteral( "diagram" );
44
45 sPropertyDefinitions = QgsPropertiesDefinition
46 {
47 { QgsDiagramLayerSettings::BackgroundColor, QgsPropertyDefinition( "backgroundColor", QObject::tr( "Background color" ), QgsPropertyDefinition::ColorWithAlpha, origin ) },
48 { QgsDiagramLayerSettings::StrokeColor, QgsPropertyDefinition( "strokeColor", QObject::tr( "Stroke color" ), QgsPropertyDefinition::ColorWithAlpha, origin ) },
49 { QgsDiagramLayerSettings::StrokeWidth, QgsPropertyDefinition( "strokeWidth", QObject::tr( "Stroke width" ), QgsPropertyDefinition::StrokeWidth, origin ) },
50 { QgsDiagramLayerSettings::PositionX, QgsPropertyDefinition( "positionX", QObject::tr( "Position (X)" ), QgsPropertyDefinition::Double, origin ) },
51 { QgsDiagramLayerSettings::PositionY, QgsPropertyDefinition( "positionY", QObject::tr( "Position (Y)" ), QgsPropertyDefinition::Double, origin ) },
52 { QgsDiagramLayerSettings::Distance, QgsPropertyDefinition( "distance", QObject::tr( "Placement distance" ), QgsPropertyDefinition::DoublePositive, origin ) },
53 { QgsDiagramLayerSettings::Priority, QgsPropertyDefinition( "priority", QObject::tr( "Placement priority" ), QgsPropertyDefinition::DoublePositive, origin ) },
54 { QgsDiagramLayerSettings::ZIndex, QgsPropertyDefinition( "zIndex", QObject::tr( "Placement z-index" ), QgsPropertyDefinition::Double, origin ) },
55 { QgsDiagramLayerSettings::IsObstacle, QgsPropertyDefinition( "isObstacle", QObject::tr( "Diagram is an obstacle" ), QgsPropertyDefinition::Boolean, origin ) },
56 { QgsDiagramLayerSettings::Show, QgsPropertyDefinition( "show", QObject::tr( "Show diagram" ), QgsPropertyDefinition::Boolean, origin ) },
57 { QgsDiagramLayerSettings::AlwaysShow, QgsPropertyDefinition( "alwaysShow", QObject::tr( "Always show diagram" ), QgsPropertyDefinition::Boolean, origin ) },
58 { QgsDiagramLayerSettings::StartAngle, QgsPropertyDefinition( "startAngle", QObject::tr( "Pie chart start angle" ), QgsPropertyDefinition::Rotation, origin ) },
59 };
60}
61
63{
64 initPropertyDefinitions();
65 return sPropertyDefinitions;
66}
67
69{
70 initPropertyDefinitions();
71}
72
74 : mCt( rh.mCt )
75 , mPlacement( rh.mPlacement )
76 , mPlacementFlags( rh.mPlacementFlags )
77 , mPriority( rh.mPriority )
78 , mZIndex( rh.mZIndex )
79 , mObstacle( rh.mObstacle )
80 , mDistance( rh.mDistance )
81 , mRenderer( rh.mRenderer ? rh.mRenderer->clone() : nullptr )
82 , mShowAll( rh.mShowAll )
83 , mDataDefinedProperties( rh.mDataDefinedProperties )
84{
85 initPropertyDefinitions();
86}
87
89{
90 mPlacement = rh.mPlacement;
91 mPlacementFlags = rh.mPlacementFlags;
92 mPriority = rh.mPriority;
93 mZIndex = rh.mZIndex;
94 mObstacle = rh.mObstacle;
95 mDistance = rh.mDistance;
96 mRenderer = rh.mRenderer ? rh.mRenderer->clone() : nullptr;
97 mCt = rh.mCt;
98 mShowAll = rh.mShowAll;
99 mDataDefinedProperties = rh.mDataDefinedProperties;
100 return *this;
101}
102
104{
105 delete mRenderer;
106}
107
109{
110 if ( diagramRenderer == mRenderer )
111 return;
112
113 delete mRenderer;
114 mRenderer = diagramRenderer;
115}
116
118{
119 mCt = transform;
120}
121
122void QgsDiagramLayerSettings::readXml( const QDomElement &elem )
123{
124 const QDomNodeList propertyElems = elem.elementsByTagName( QStringLiteral( "properties" ) );
125 if ( !propertyElems.isEmpty() )
126 {
127 ( void )mDataDefinedProperties.readXml( propertyElems.at( 0 ).toElement(), sPropertyDefinitions );
128 }
129 else
130 {
131 mDataDefinedProperties.clear();
132 }
133
134 mPlacement = static_cast< Placement >( elem.attribute( QStringLiteral( "placement" ) ).toInt() );
135 mPlacementFlags = static_cast< LinePlacementFlag >( elem.attribute( QStringLiteral( "linePlacementFlags" ) ).toInt() );
136 mPriority = elem.attribute( QStringLiteral( "priority" ) ).toInt();
137 mZIndex = elem.attribute( QStringLiteral( "zIndex" ) ).toDouble();
138 mObstacle = elem.attribute( QStringLiteral( "obstacle" ) ).toInt();
139 mDistance = elem.attribute( QStringLiteral( "dist" ) ).toDouble();
140 mShowAll = ( elem.attribute( QStringLiteral( "showAll" ), QStringLiteral( "0" ) ) != QLatin1String( "0" ) );
141}
142
143void QgsDiagramLayerSettings::writeXml( QDomElement &layerElem, QDomDocument &doc ) const
144{
145 QDomElement diagramLayerElem = doc.createElement( QStringLiteral( "DiagramLayerSettings" ) );
146 QDomElement propertiesElem = doc.createElement( QStringLiteral( "properties" ) );
147 ( void )mDataDefinedProperties.writeXml( propertiesElem, sPropertyDefinitions );
148 diagramLayerElem.appendChild( propertiesElem );
149 diagramLayerElem.setAttribute( QStringLiteral( "placement" ), mPlacement );
150 diagramLayerElem.setAttribute( QStringLiteral( "linePlacementFlags" ), mPlacementFlags );
151 diagramLayerElem.setAttribute( QStringLiteral( "priority" ), mPriority );
152 diagramLayerElem.setAttribute( QStringLiteral( "zIndex" ), mZIndex );
153 diagramLayerElem.setAttribute( QStringLiteral( "obstacle" ), mObstacle );
154 diagramLayerElem.setAttribute( QStringLiteral( "dist" ), QString::number( mDistance ) );
155 diagramLayerElem.setAttribute( QStringLiteral( "showAll" ), mShowAll );
156 layerElem.appendChild( diagramLayerElem );
157}
158
160{
161 return mDataDefinedProperties.prepare( context );
162}
163
165{
166 QSet< QString > referenced;
167 if ( mRenderer )
168 referenced = mRenderer->referencedFields( context );
169
170 //add the ones needed for data defined settings
171 referenced.unite( mDataDefinedProperties.referencedFields( context ) );
172
173 return referenced;
174}
175
176void QgsDiagramSettings::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
177{
178 enabled = ( elem.attribute( QStringLiteral( "enabled" ), QStringLiteral( "1" ) ) != QLatin1String( "0" ) );
179 if ( !QgsFontUtils::setFromXmlChildNode( font, elem, QStringLiteral( "fontProperties" ) ) )
180 {
181 font.fromString( elem.attribute( QStringLiteral( "font" ) ) );
182 }
183 backgroundColor.setNamedColor( elem.attribute( QStringLiteral( "backgroundColor" ) ) );
184 backgroundColor.setAlpha( elem.attribute( QStringLiteral( "backgroundAlpha" ) ).toInt() );
185 size.setWidth( elem.attribute( QStringLiteral( "width" ) ).toDouble() );
186 size.setHeight( elem.attribute( QStringLiteral( "height" ) ).toDouble() );
187 if ( elem.hasAttribute( QStringLiteral( "transparency" ) ) )
188 {
189 opacity = 1 - elem.attribute( QStringLiteral( "transparency" ), QStringLiteral( "0" ) ).toInt() / 255.0;
190 }
191 else
192 {
193 opacity = elem.attribute( QStringLiteral( "opacity" ), QStringLiteral( "1.00" ) ).toDouble();
194 }
195
196 penColor.setNamedColor( elem.attribute( QStringLiteral( "penColor" ) ) );
197 const int penAlpha = elem.attribute( QStringLiteral( "penAlpha" ), QStringLiteral( "255" ) ).toInt();
198 penColor.setAlpha( penAlpha );
199 penWidth = elem.attribute( QStringLiteral( "penWidth" ) ).toDouble();
200
201 mDirection = static_cast< Direction >( elem.attribute( QStringLiteral( "direction" ), QStringLiteral( "1" ) ).toInt() );
202
203 maximumScale = elem.attribute( QStringLiteral( "minScaleDenominator" ), QStringLiteral( "-1" ) ).toDouble();
204 minimumScale = elem.attribute( QStringLiteral( "maxScaleDenominator" ), QStringLiteral( "-1" ) ).toDouble();
205 if ( elem.hasAttribute( QStringLiteral( "scaleBasedVisibility" ) ) )
206 {
207 scaleBasedVisibility = ( elem.attribute( QStringLiteral( "scaleBasedVisibility" ), QStringLiteral( "1" ) ) != QLatin1String( "0" ) );
208 }
209 else
210 {
212 }
213
214 //diagram size unit type and scale
215 if ( elem.attribute( QStringLiteral( "sizeType" ) ) == QLatin1String( "MapUnits" ) )
216 {
217 //compatibility with pre-2.16 project files
219 }
220 else
221 {
222 sizeType = QgsUnitTypes::decodeRenderUnit( elem.attribute( QStringLiteral( "sizeType" ) ) );
223 }
224 sizeScale = QgsSymbolLayerUtils::decodeMapUnitScale( elem.attribute( QStringLiteral( "sizeScale" ) ) );
225
226 //line width unit type and scale
227 lineSizeUnit = QgsUnitTypes::decodeRenderUnit( elem.attribute( QStringLiteral( "lineSizeType" ) ) );
228 lineSizeScale = QgsSymbolLayerUtils::decodeMapUnitScale( elem.attribute( QStringLiteral( "lineSizeScale" ) ) );
229
230 mSpacing = elem.attribute( QStringLiteral( "spacing" ) ).toDouble();
231 mSpacingUnit = QgsUnitTypes::decodeRenderUnit( elem.attribute( QStringLiteral( "spacingUnit" ) ) );
232 mSpacingMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( elem.attribute( QStringLiteral( "spacingUnitScale" ) ) );
233
234 //label placement method
235 if ( elem.attribute( QStringLiteral( "labelPlacementMethod" ) ) == QLatin1String( "Height" ) )
236 {
238 }
239 else
240 {
242 }
243
244 // orientation
245 if ( elem.attribute( QStringLiteral( "diagramOrientation" ) ) == QLatin1String( "Left" ) )
246 {
248 }
249 else if ( elem.attribute( QStringLiteral( "diagramOrientation" ) ) == QLatin1String( "Right" ) )
250 {
252 }
253 else if ( elem.attribute( QStringLiteral( "diagramOrientation" ) ) == QLatin1String( "Down" ) )
254 {
256 }
257 else
258 {
260 }
261
262 // scale dependency
263 if ( elem.attribute( QStringLiteral( "scaleDependency" ) ) == QLatin1String( "Diameter" ) )
264 {
265 scaleByArea = false;
266 }
267 else
268 {
269 scaleByArea = true;
270 }
271
272 barWidth = elem.attribute( QStringLiteral( "barWidth" ) ).toDouble();
273
274 if ( elem.hasAttribute( QStringLiteral( "angleOffset" ) ) )
275 rotationOffset = std::fmod( 360.0 - elem.attribute( QStringLiteral( "angleOffset" ) ).toInt() / 16.0, 360.0 );
276 else
277 rotationOffset = elem.attribute( QStringLiteral( "rotationOffset" ) ).toDouble();
278
279 minimumSize = elem.attribute( QStringLiteral( "minimumSize" ) ).toDouble();
280
281 const QDomNodeList axisSymbolNodes = elem.elementsByTagName( QStringLiteral( "axisSymbol" ) );
282 if ( axisSymbolNodes.count() > 0 )
283 {
284 const QDomElement axisSymbolElem = axisSymbolNodes.at( 0 ).toElement().firstChildElement();
285 mAxisLineSymbol.reset( QgsSymbolLayerUtils::loadSymbol<QgsLineSymbol>( axisSymbolElem, context ) );
286 }
287 else
288 {
289 mAxisLineSymbol = std::make_unique< QgsLineSymbol >();
290 }
291
292 mShowAxis = elem.attribute( QStringLiteral( "showAxis" ), QStringLiteral( "0" ) ).toInt();
293
294 //colors
295 categoryColors.clear();
296 const QDomNodeList attributes = elem.elementsByTagName( QStringLiteral( "attribute" ) );
297
298
299 if ( attributes.length() > 0 )
300 {
301 for ( int i = 0; i < attributes.size(); i++ )
302 {
303 const QDomElement attrElem = attributes.at( i ).toElement();
304 QColor newColor( attrElem.attribute( QStringLiteral( "color" ) ) );
305 newColor.setAlphaF( attrElem.attribute( QStringLiteral( "colorOpacity" ), QStringLiteral( "1.0" ) ).toDouble() );
306 categoryColors.append( newColor );
307 categoryAttributes.append( attrElem.attribute( QStringLiteral( "field" ) ) );
308 categoryLabels.append( attrElem.attribute( QStringLiteral( "label" ) ) );
309 if ( categoryLabels.constLast().isEmpty() )
310 {
311 categoryLabels.back() = categoryAttributes.back();
312 }
313 }
314 }
315 else
316 {
317 // Restore old format attributes and colors
318
319 const QStringList colorList = elem.attribute( QStringLiteral( "colors" ) ).split( '/' );
320 QStringList::const_iterator colorIt = colorList.constBegin();
321 for ( ; colorIt != colorList.constEnd(); ++colorIt )
322 {
323 QColor newColor( *colorIt );
324 categoryColors.append( QColor( newColor ) );
325 }
326
327 //attribute indices
328 categoryAttributes.clear();
329 const QStringList catList = elem.attribute( QStringLiteral( "categories" ) ).split( '/' );
330 QStringList::const_iterator catIt = catList.constBegin();
331 for ( ; catIt != catList.constEnd(); ++catIt )
332 {
333 categoryAttributes.append( *catIt );
334 categoryLabels.append( *catIt );
335 }
336 }
337
338 const QDomElement effectElem = elem.firstChildElement( QStringLiteral( "effect" ) );
339 if ( !effectElem.isNull() )
340 setPaintEffect( QgsApplication::paintEffectRegistry()->createEffect( effectElem ) );
341 else
343}
344
345void QgsDiagramSettings::writeXml( QDomElement &rendererElem, QDomDocument &doc, const QgsReadWriteContext &context ) const
346{
347 QDomElement categoryElem = doc.createElement( QStringLiteral( "DiagramCategory" ) );
348 categoryElem.setAttribute( QStringLiteral( "enabled" ), enabled );
349 categoryElem.appendChild( QgsFontUtils::toXmlElement( font, doc, QStringLiteral( "fontProperties" ) ) );
350 categoryElem.setAttribute( QStringLiteral( "backgroundColor" ), backgroundColor.name() );
351 categoryElem.setAttribute( QStringLiteral( "backgroundAlpha" ), backgroundColor.alpha() );
352 categoryElem.setAttribute( QStringLiteral( "width" ), QString::number( size.width() ) );
353 categoryElem.setAttribute( QStringLiteral( "height" ), QString::number( size.height() ) );
354 categoryElem.setAttribute( QStringLiteral( "penColor" ), penColor.name() );
355 categoryElem.setAttribute( QStringLiteral( "penAlpha" ), penColor.alpha() );
356 categoryElem.setAttribute( QStringLiteral( "penWidth" ), QString::number( penWidth ) );
357 categoryElem.setAttribute( QStringLiteral( "scaleBasedVisibility" ), scaleBasedVisibility );
358 categoryElem.setAttribute( QStringLiteral( "minScaleDenominator" ), QString::number( maximumScale ) );
359 categoryElem.setAttribute( QStringLiteral( "maxScaleDenominator" ), QString::number( minimumScale ) );
360 categoryElem.setAttribute( QStringLiteral( "opacity" ), QString::number( opacity ) );
361 categoryElem.setAttribute( QStringLiteral( "spacing" ), QString::number( mSpacing ) );
362 categoryElem.setAttribute( QStringLiteral( "spacingUnit" ), QgsUnitTypes::encodeUnit( mSpacingUnit ) );
363 categoryElem.setAttribute( QStringLiteral( "spacingUnitScale" ), QgsSymbolLayerUtils::encodeMapUnitScale( mSpacingMapUnitScale ) );
364 categoryElem.setAttribute( QStringLiteral( "direction" ), QString::number( mDirection ) );
365
366 //diagram size unit type and scale
367 categoryElem.setAttribute( QStringLiteral( "sizeType" ), QgsUnitTypes::encodeUnit( sizeType ) );
368 categoryElem.setAttribute( QStringLiteral( "sizeScale" ), QgsSymbolLayerUtils::encodeMapUnitScale( sizeScale ) );
369
370 //line width unit type and scale
371 categoryElem.setAttribute( QStringLiteral( "lineSizeType" ), QgsUnitTypes::encodeUnit( lineSizeUnit ) );
372 categoryElem.setAttribute( QStringLiteral( "lineSizeScale" ), QgsSymbolLayerUtils::encodeMapUnitScale( lineSizeScale ) );
373
374 // label placement method (text diagram)
376 {
377 categoryElem.setAttribute( QStringLiteral( "labelPlacementMethod" ), QStringLiteral( "Height" ) );
378 }
379 else
380 {
381 categoryElem.setAttribute( QStringLiteral( "labelPlacementMethod" ), QStringLiteral( "XHeight" ) );
382 }
383
384 if ( scaleByArea )
385 {
386 categoryElem.setAttribute( QStringLiteral( "scaleDependency" ), QStringLiteral( "Area" ) );
387 }
388 else
389 {
390 categoryElem.setAttribute( QStringLiteral( "scaleDependency" ), QStringLiteral( "Diameter" ) );
391 }
392
393 // orientation (histogram)
394 switch ( diagramOrientation )
395 {
396 case Left:
397 categoryElem.setAttribute( QStringLiteral( "diagramOrientation" ), QStringLiteral( "Left" ) );
398 break;
399
400 case Right:
401 categoryElem.setAttribute( QStringLiteral( "diagramOrientation" ), QStringLiteral( "Right" ) );
402 break;
403
404 case Down:
405 categoryElem.setAttribute( QStringLiteral( "diagramOrientation" ), QStringLiteral( "Down" ) );
406 break;
407
408 case Up:
409 categoryElem.setAttribute( QStringLiteral( "diagramOrientation" ), QStringLiteral( "Up" ) );
410 break;
411 }
412
413 categoryElem.setAttribute( QStringLiteral( "barWidth" ), QString::number( barWidth ) );
414 categoryElem.setAttribute( QStringLiteral( "minimumSize" ), QString::number( minimumSize ) );
415 categoryElem.setAttribute( QStringLiteral( "rotationOffset" ), QString::number( rotationOffset ) );
416
417 const int nCats = std::min( categoryColors.size(), categoryAttributes.size() );
418 for ( int i = 0; i < nCats; ++i )
419 {
420 QDomElement attributeElem = doc.createElement( QStringLiteral( "attribute" ) );
421
422 attributeElem.setAttribute( QStringLiteral( "field" ), categoryAttributes.at( i ) );
423 attributeElem.setAttribute( QStringLiteral( "color" ), categoryColors.at( i ).name() );
424 attributeElem.setAttribute( QStringLiteral( "colorOpacity" ), QString::number( categoryColors.at( i ).alphaF() ) );
425 attributeElem.setAttribute( QStringLiteral( "label" ), categoryLabels.at( i ) );
426 categoryElem.appendChild( attributeElem );
427 }
428
429 categoryElem.setAttribute( QStringLiteral( "showAxis" ), mShowAxis ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
430 QDomElement axisSymbolElem = doc.createElement( QStringLiteral( "axisSymbol" ) );
431 const QDomElement symbolElem = QgsSymbolLayerUtils::saveSymbol( QString(), mAxisLineSymbol.get(), doc, context );
432 axisSymbolElem.appendChild( symbolElem );
433 categoryElem.appendChild( axisSymbolElem );
434
435 if ( mPaintEffect && !QgsPaintEffectRegistry::isDefaultStack( mPaintEffect.get() ) )
436 mPaintEffect->saveProperties( doc, categoryElem );
437
438 rendererElem.appendChild( categoryElem );
439}
440
442{
443 if ( mDiagram.get() == d )
444 return;
445
446 mDiagram.reset( d );
447}
448
450 : mDiagram( other.mDiagram ? other.mDiagram->clone() : nullptr )
451 , mShowAttributeLegend( other.mShowAttributeLegend )
452{
453}
454
456{
457 mDiagram.reset( other.mDiagram ? other.mDiagram->clone() : nullptr );
459 return *this;
460}
461
462void QgsDiagramRenderer::renderDiagram( const QgsFeature &feature, QgsRenderContext &c, QPointF pos, const QgsPropertyCollection &properties ) const
463{
464 if ( !mDiagram )
465 {
466 return;
467 }
468
470 if ( !diagramSettings( feature, c, s ) )
471 {
472 return;
473 }
474
475 if ( properties.hasActiveProperties() )
476 {
477 c.expressionContext().setOriginalValueVariable( QgsSymbolLayerUtils::encodeColor( s.backgroundColor ) );
479 c.expressionContext().setOriginalValueVariable( QgsSymbolLayerUtils::encodeColor( s.penColor ) );
480 s.penColor = properties.valueAsColor( QgsDiagramLayerSettings::StrokeColor, c.expressionContext(), s.penColor );
481 c.expressionContext().setOriginalValueVariable( s.penWidth );
482 s.penWidth = properties.valueAsDouble( QgsDiagramLayerSettings::StrokeWidth, c.expressionContext(), s.penWidth );
483 c.expressionContext().setOriginalValueVariable( s.rotationOffset );
484 s.rotationOffset = properties.valueAsDouble( QgsDiagramLayerSettings::StartAngle, c.expressionContext(), s.rotationOffset );
485 }
486
487 QgsPaintEffect *effect = s.paintEffect();
488 std::unique_ptr< QgsEffectPainter > effectPainter;
489 if ( effect && effect->enabled() )
490 {
491 effectPainter = std::make_unique< QgsEffectPainter >( c, effect );
492 }
493
494 mDiagram->renderDiagram( feature, c, s, pos );
495}
496
497QSizeF QgsDiagramRenderer::sizeMapUnits( const QgsFeature &feature, const QgsRenderContext &c ) const
498{
500 if ( !diagramSettings( feature, c, s ) )
501 {
502 return QSizeF();
503 }
504
505 QSizeF size = diagramSize( feature, c );
506 if ( size.isValid() )
507 {
508 const double width = c.convertToMapUnits( size.width(), s.sizeType, s.sizeScale );
509 size.rheight() *= width / size.width();
510 size.setWidth( width );
511 }
512 return size;
513}
514
516{
517 QSet< QString > referenced;
518
519 if ( !mDiagram )
520 return referenced;
521
522 const auto constDiagramAttributes = diagramAttributes();
523 for ( const QString &att : constDiagramAttributes )
524 {
525 QgsExpression *expression = mDiagram->getExpression( att, context );
526 const auto constReferencedColumns = expression->referencedColumns();
527 for ( const QString &field : constReferencedColumns )
528 {
529 referenced << field;
530 }
531 }
532 return referenced;
533}
534
535void QgsDiagramRenderer::convertSizeToMapUnits( QSizeF &size, const QgsRenderContext &context ) const
536{
537 if ( !size.isValid() )
538 {
539 return;
540 }
541
542 const double pixelToMap = context.scaleFactor() * context.mapToPixel().mapUnitsPerPixel();
543 size.rwidth() *= pixelToMap;
544 size.rheight() *= pixelToMap;
545}
546
547int QgsDiagramRenderer::dpiPaintDevice( const QPainter *painter )
548{
549 if ( painter )
550 {
551 QPaintDevice *device = painter->device();
552 if ( device )
553 {
554 return device->logicalDpiX();
555 }
556 }
557 return -1;
558}
559
560void QgsDiagramRenderer::_readXml( const QDomElement &elem, const QgsReadWriteContext &context )
561{
562 Q_UNUSED( context )
563 mDiagram.reset();
564 const QString diagramType = elem.attribute( QStringLiteral( "diagramType" ) );
565 if ( diagramType == QLatin1String( "Pie" ) )
566 {
567 mDiagram.reset( new QgsPieDiagram() );
568 }
569 else if ( diagramType == QLatin1String( "Text" ) )
570 {
571 mDiagram.reset( new QgsTextDiagram() );
572 }
573 else if ( diagramType == QLatin1String( "Histogram" ) )
574 {
575 mDiagram.reset( new QgsHistogramDiagram() );
576 }
577 else if ( diagramType == QLatin1String( "Stacked" ) )
578 {
579 mDiagram.reset( new QgsStackedBarDiagram() );
580 }
581 else
582 {
583 // unknown diagram type -- default to histograms
584 mDiagram.reset( new QgsHistogramDiagram() );
585 }
586 mShowAttributeLegend = ( elem.attribute( QStringLiteral( "attributeLegend" ), QStringLiteral( "1" ) ) != QLatin1String( "0" ) );
587}
588
589void QgsDiagramRenderer::_writeXml( QDomElement &rendererElem, QDomDocument &doc, const QgsReadWriteContext &context ) const
590{
591 Q_UNUSED( doc )
592 Q_UNUSED( context )
593
594 if ( mDiagram )
595 {
596 rendererElem.setAttribute( QStringLiteral( "diagramType" ), mDiagram->diagramName() );
597 }
598 rendererElem.setAttribute( QStringLiteral( "attributeLegend" ), mShowAttributeLegend );
599}
600
602{
603 return new QgsSingleCategoryDiagramRenderer( *this );
604}
605
607{
608 Q_UNUSED( c )
609 s = mSettings;
610 return true;
611}
612
614{
615 return mDiagram->diagramSize( feature.attributes(), c, mSettings );
616}
617
619{
620 QList<QgsDiagramSettings> settingsList;
621 settingsList.push_back( mSettings );
622 return settingsList;
623}
624
625void QgsSingleCategoryDiagramRenderer::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
626{
627 const QDomElement categoryElem = elem.firstChildElement( QStringLiteral( "DiagramCategory" ) );
628 if ( categoryElem.isNull() )
629 {
630 return;
631 }
632
633 mSettings.readXml( categoryElem, context );
634 _readXml( elem, context );
635}
636
637void QgsSingleCategoryDiagramRenderer::writeXml( QDomElement &layerElem, QDomDocument &doc, const QgsReadWriteContext &context ) const
638{
639 QDomElement rendererElem = doc.createElement( QStringLiteral( "SingleCategoryDiagramRenderer" ) );
640 mSettings.writeXml( rendererElem, doc, context );
641 _writeXml( rendererElem, doc, context );
642 layerElem.appendChild( rendererElem );
643}
644
645
647{
648 mInterpolationSettings.classificationAttributeIsExpression = false;
649}
650
652 : QgsDiagramRenderer( other )
653 , mSettings( other.mSettings )
654 , mInterpolationSettings( other.mInterpolationSettings )
655 , mDataDefinedSizeLegend( other.mDataDefinedSizeLegend ? new QgsDataDefinedSizeLegend( *other.mDataDefinedSizeLegend ) : nullptr )
656{
657}
658
660{
661 delete mDataDefinedSizeLegend;
662}
663
665{
666 if ( &other == this )
667 {
668 return *this;
669 }
670 mSettings = other.mSettings;
671 mInterpolationSettings = other.mInterpolationSettings;
672 delete mDataDefinedSizeLegend;
673 mDataDefinedSizeLegend = new QgsDataDefinedSizeLegend( *other.mDataDefinedSizeLegend );
674 return *this;
675}
676
678{
679 return new QgsLinearlyInterpolatedDiagramRenderer( *this );
680}
681
683{
684 QList<QgsDiagramSettings> settingsList;
685 settingsList.push_back( mSettings );
686 return settingsList;
687}
688
690{
691 s = mSettings;
692 s.size = diagramSize( feature, c );
693 return true;
694}
695
697{
698 return mSettings.categoryAttributes;
699}
700
702{
703 QSet< QString > referenced = QgsDiagramRenderer::referencedFields( context );
704 if ( mInterpolationSettings.classificationAttributeIsExpression )
705 {
706 QgsExpression *expression = mDiagram->getExpression( mInterpolationSettings.classificationAttributeExpression, context );
707 const auto constReferencedColumns = expression->referencedColumns();
708 for ( const QString &field : constReferencedColumns )
709 {
710 referenced << field;
711 }
712 }
713 else
714 {
715 referenced << mInterpolationSettings.classificationField;
716 }
717 return referenced;
718}
719
721{
722 return mDiagram->diagramSize( feature, c, mSettings, mInterpolationSettings );
723}
724
725void QgsLinearlyInterpolatedDiagramRenderer::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
726{
727 mInterpolationSettings.lowerValue = elem.attribute( QStringLiteral( "lowerValue" ) ).toDouble();
728 mInterpolationSettings.upperValue = elem.attribute( QStringLiteral( "upperValue" ) ).toDouble();
729 mInterpolationSettings.lowerSize.setWidth( elem.attribute( QStringLiteral( "lowerWidth" ) ).toDouble() );
730 mInterpolationSettings.lowerSize.setHeight( elem.attribute( QStringLiteral( "lowerHeight" ) ).toDouble() );
731 mInterpolationSettings.upperSize.setWidth( elem.attribute( QStringLiteral( "upperWidth" ) ).toDouble() );
732 mInterpolationSettings.upperSize.setHeight( elem.attribute( QStringLiteral( "upperHeight" ) ).toDouble() );
733 mInterpolationSettings.classificationAttributeIsExpression = elem.hasAttribute( QStringLiteral( "classificationAttributeExpression" ) );
734 if ( mInterpolationSettings.classificationAttributeIsExpression )
735 {
736 mInterpolationSettings.classificationAttributeExpression = elem.attribute( QStringLiteral( "classificationAttributeExpression" ) );
737 }
738 else
739 {
740 mInterpolationSettings.classificationField = elem.attribute( QStringLiteral( "classificationField" ) );
741 }
742 const QDomElement settingsElem = elem.firstChildElement( QStringLiteral( "DiagramCategory" ) );
743 if ( !settingsElem.isNull() )
744 {
745 mSettings.readXml( settingsElem );
746 }
747
748 delete mDataDefinedSizeLegend;
749
750 const QDomElement ddsLegendSizeElem = elem.firstChildElement( QStringLiteral( "data-defined-size-legend" ) );
751 if ( !ddsLegendSizeElem.isNull() )
752 {
753 mDataDefinedSizeLegend = QgsDataDefinedSizeLegend::readXml( ddsLegendSizeElem, context );
754 }
755 else
756 {
757 // pre-3.0 projects
758 if ( elem.attribute( QStringLiteral( "sizeLegend" ), QStringLiteral( "0" ) ) != QLatin1String( "0" ) )
759 {
760 mDataDefinedSizeLegend = new QgsDataDefinedSizeLegend();
761 const QDomElement sizeLegendSymbolElem = elem.firstChildElement( QStringLiteral( "symbol" ) );
762 if ( !sizeLegendSymbolElem.isNull() && sizeLegendSymbolElem.attribute( QStringLiteral( "name" ) ) == QLatin1String( "sizeSymbol" ) )
763 {
764 mDataDefinedSizeLegend->setSymbol( QgsSymbolLayerUtils::loadSymbol<QgsMarkerSymbol>( sizeLegendSymbolElem, context ) );
765 }
766 }
767 else
768 {
769 mDataDefinedSizeLegend = nullptr;
770 }
771 }
772
773 _readXml( elem, context );
774}
775
776void QgsLinearlyInterpolatedDiagramRenderer::writeXml( QDomElement &layerElem, QDomDocument &doc, const QgsReadWriteContext &context ) const
777{
778 QDomElement rendererElem = doc.createElement( QStringLiteral( "LinearlyInterpolatedDiagramRenderer" ) );
779 rendererElem.setAttribute( QStringLiteral( "lowerValue" ), QString::number( mInterpolationSettings.lowerValue ) );
780 rendererElem.setAttribute( QStringLiteral( "upperValue" ), QString::number( mInterpolationSettings.upperValue ) );
781 rendererElem.setAttribute( QStringLiteral( "lowerWidth" ), QString::number( mInterpolationSettings.lowerSize.width() ) );
782 rendererElem.setAttribute( QStringLiteral( "lowerHeight" ), QString::number( mInterpolationSettings.lowerSize.height() ) );
783 rendererElem.setAttribute( QStringLiteral( "upperWidth" ), QString::number( mInterpolationSettings.upperSize.width() ) );
784 rendererElem.setAttribute( QStringLiteral( "upperHeight" ), QString::number( mInterpolationSettings.upperSize.height() ) );
785 if ( mInterpolationSettings.classificationAttributeIsExpression )
786 {
787 rendererElem.setAttribute( QStringLiteral( "classificationAttributeExpression" ), mInterpolationSettings.classificationAttributeExpression );
788 }
789 else
790 {
791 rendererElem.setAttribute( QStringLiteral( "classificationField" ), mInterpolationSettings.classificationField );
792 }
793 mSettings.writeXml( rendererElem, doc );
794
795 if ( mDataDefinedSizeLegend )
796 {
797 QDomElement ddsLegendElem = doc.createElement( QStringLiteral( "data-defined-size-legend" ) );
798 mDataDefinedSizeLegend->writeXml( ddsLegendElem, context );
799 rendererElem.appendChild( ddsLegendElem );
800 }
801
802 _writeXml( rendererElem, doc, context );
803 layerElem.appendChild( rendererElem );
804}
805
806QList< QgsLayerTreeModelLegendNode * > QgsDiagramSettings::legendItems( QgsLayerTreeLayer *nodeLayer ) const
807{
808 QList< QgsLayerTreeModelLegendNode * > list;
809 list.reserve( categoryLabels.size() );
810 for ( int i = 0; i < categoryLabels.size(); ++i )
811 {
812 QPixmap pix( 16, 16 );
813 pix.fill( categoryColors[i] );
814 list << new QgsSimpleLegendNode( nodeLayer, categoryLabels[i], QIcon( pix ), nullptr, QStringLiteral( "diagram_%1" ).arg( QString::number( i ) ) );
815 }
816 return list;
817}
818
820{
821 return mAxisLineSymbol.get();
822}
823
825{
826 if ( axisLineSymbol != mAxisLineSymbol.get() )
827 mAxisLineSymbol.reset( axisLineSymbol );
828}
829
831{
832 return mShowAxis;
833}
834
836{
837 mShowAxis = showAxis;
838}
839
841{
842 return mPaintEffect.get();
843}
844
846{
847 if ( effect != mPaintEffect.get() )
848 mPaintEffect.reset( effect );
849}
850
852 : mAxisLineSymbol( std::make_unique< QgsLineSymbol >() )
853{
854}
855
857
859 : enabled( other.enabled )
860 , font( other.font )
861 , categoryColors( other.categoryColors )
862 , categoryAttributes( other.categoryAttributes )
863 , categoryLabels( other.categoryLabels )
864 , size( other.size )
865 , sizeType( other.sizeType )
866 , sizeScale( other.sizeScale )
867 , lineSizeUnit( other.lineSizeUnit )
868 , lineSizeScale( other.lineSizeScale )
869 , backgroundColor( other.backgroundColor )
870 , penColor( other.penColor )
871 , penWidth( other.penWidth )
872 , labelPlacementMethod( other.labelPlacementMethod )
873 , diagramOrientation( other.diagramOrientation )
874 , barWidth( other.barWidth )
875 , opacity( other.opacity )
876 , scaleByArea( other.scaleByArea )
877 , rotationOffset( other.rotationOffset )
878 , scaleBasedVisibility( other.scaleBasedVisibility )
879 , maximumScale( other.maximumScale )
880 , minimumScale( other.minimumScale )
881 , minimumSize( other.minimumSize )
882 , mSpacing( other.mSpacing )
883 , mSpacingUnit( other.mSpacingUnit )
884 , mSpacingMapUnitScale( other.mSpacingMapUnitScale )
885 , mDirection( other.mDirection )
886 , mShowAxis( other.mShowAxis )
887 , mAxisLineSymbol( other.mAxisLineSymbol ? other.mAxisLineSymbol->clone() : nullptr )
888 , mPaintEffect( other.mPaintEffect ? other.mPaintEffect->clone() : nullptr )
889{
890
891}
892
894{
895 enabled = other.enabled;
896 font = other.font;
900 size = other.size;
901 sizeType = other.sizeType;
902 sizeScale = other.sizeScale;
906 penColor = other.penColor;
907 penWidth = other.penWidth;
910 barWidth = other.barWidth;
911 opacity = other.opacity;
912 scaleByArea = other.scaleByArea;
917 minimumSize = other.minimumSize;
918 mSpacing = other.mSpacing;
919 mSpacingUnit = other.mSpacingUnit;
920 mSpacingMapUnitScale = other.mSpacingMapUnitScale;
921 mDirection = other.mDirection;
922 mAxisLineSymbol.reset( other.mAxisLineSymbol ? other.mAxisLineSymbol->clone() : nullptr );
923 mShowAxis = other.mShowAxis;
924 mPaintEffect.reset( other.mPaintEffect ? other.mPaintEffect->clone() : nullptr );
925 return *this;
926}
927
929{
930 return mDirection;
931}
932
934{
935 mDirection = direction;
936}
937
938QList< QgsLayerTreeModelLegendNode * > QgsDiagramRenderer::legendItems( QgsLayerTreeLayer * ) const
939{
940 return QList< QgsLayerTreeModelLegendNode * >();
941}
942
943QList< QgsLayerTreeModelLegendNode * > QgsSingleCategoryDiagramRenderer::legendItems( QgsLayerTreeLayer *nodeLayer ) const
944{
945 QList< QgsLayerTreeModelLegendNode * > nodes;
947 nodes = mSettings.legendItems( nodeLayer );
948
949 return nodes;
950}
951
952QList< QgsLayerTreeModelLegendNode * > QgsLinearlyInterpolatedDiagramRenderer::legendItems( QgsLayerTreeLayer *nodeLayer ) const
953{
954 QList< QgsLayerTreeModelLegendNode * > nodes;
956 nodes = mSettings.legendItems( nodeLayer );
957
958 if ( mDataDefinedSizeLegend && mDiagram )
959 {
960 // add size legend
961 QgsMarkerSymbol *legendSymbol = mDataDefinedSizeLegend->symbol() ? mDataDefinedSizeLegend->symbol()->clone() : QgsMarkerSymbol::createSimple( QVariantMap() );
962 legendSymbol->setSizeUnit( mSettings.sizeType );
963 legendSymbol->setSizeMapUnitScale( mSettings.sizeScale );
964
965 QgsDataDefinedSizeLegend ddSizeLegend( *mDataDefinedSizeLegend );
966 ddSizeLegend.setSymbol( legendSymbol ); // transfers ownership
967
968 QList<QgsDataDefinedSizeLegend::SizeClass> sizeClasses;
969 if ( ddSizeLegend.classes().isEmpty() )
970 {
971 // automatic class creation if the classes are not defined manually
972 const auto prettyBreaks { QgsSymbolLayerUtils::prettyBreaks( mInterpolationSettings.lowerValue, mInterpolationSettings.upperValue, 4 ) };
973 for ( const double v : prettyBreaks )
974 {
975 const double size = mDiagram->legendSize( v, mSettings, mInterpolationSettings );
976 sizeClasses << QgsDataDefinedSizeLegend::SizeClass( size, QString::number( v ) );
977 }
978 }
979 else
980 {
981 // manual classes need to get size scaled because the QgsSizeScaleTransformer is not used in diagrams :-(
982 const auto constClasses = ddSizeLegend.classes();
983 for ( const QgsDataDefinedSizeLegend::SizeClass &sc : constClasses )
984 {
985 const double size = mDiagram->legendSize( sc.size, mSettings, mInterpolationSettings );
986 sizeClasses << QgsDataDefinedSizeLegend::SizeClass( size, sc.label );
987 }
988 }
989 ddSizeLegend.setClasses( sizeClasses );
990
991 const auto constLegendSymbolList = ddSizeLegend.legendSymbolList();
992 for ( const QgsLegendSymbolItem &si : constLegendSymbolList )
993 {
994 if ( auto *lDataDefinedSizeLegendSettings = si.dataDefinedSizeLegendSettings() )
995 nodes << new QgsDataDefinedSizeLegendNode( nodeLayer, *lDataDefinedSizeLegendSettings );
996 else
997 nodes << new QgsSymbolLegendNode( nodeLayer, si );
998 }
999 }
1000
1001 return nodes;
1002}
1003
1005{
1006 delete mDataDefinedSizeLegend;
1007 mDataDefinedSizeLegend = settings;
1008}
1009
1011{
1012 return mDataDefinedSizeLegend;
1013}
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.
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)
@ StartAngle
Angle offset for pie diagram.
@ Distance
Distance to diagram from feature.
@ IsObstacle
Whether diagram features act as obstacles for other diagrams/labels.
@ PositionX
X-coordinate data defined diagram position.
@ Priority
Diagram priority (between 0 and 10)
@ AlwaysShow
Whether the diagram should always be shown, even if it overlaps other diagrams/labels.
@ Show
Whether to show the diagram.
@ ZIndex
Z-index for diagram ordering.
@ BackgroundColor
Diagram background color.
@ PositionY
Y-coordinate data defined diagram position.
void setRenderer(QgsDiagramRenderer *diagramRenderer)
Sets the diagram renderer associated with the layer.
void readXml(const QDomElement &elem)
Reads the diagram settings from a DOM element.
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the diagram property definitions.
QgsDiagramLayerSettings()
Constructor for QgsDiagramLayerSettings.
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 &features, 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.
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
Constructor for QgsDiagramRenderer.
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.
QgsUnitTypes::RenderUnit sizeType
Diagram size unit.
Direction direction() const
Returns the chart's angular direction.
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.
QList< QString > categoryAttributes
QList< QString > categoryLabels
QgsDiagramSettings()
Constructor for QgsDiagramSettings.
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.
double maximumScale
The maximum map scale (i.e.
void setAxisLineSymbol(QgsLineSymbol *symbol)
Sets the line symbol to use for rendering axis in diagrams.
QgsUnitTypes::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.
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:56
QgsAttributes attributes
Definition: qgsfeature.h:65
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.
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.
Definition: qgslinesymbol.h:30
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)
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.
void setSizeUnit(QgsUnitTypes::RenderUnit unit) const
Sets the size units for the whole symbol (including all symbol layers).
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).
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.
Definition: qgspiediagram.h:39
A grouped map of multiple QgsProperty objects, each referenced by a integer key value.
QSet< QString > referencedFields(const QgsExpressionContext &context=QgsExpressionContext(), bool ignoreContext=false) const override
Returns the set of any fields referenced by the active properties from the collection.
void clear() override
Removes all properties from the collection.
bool hasActiveProperties() const override
Returns true if the collection has any active properties, or false if all properties within the colle...
bool prepare(const QgsExpressionContext &context=QgsExpressionContext()) const override
Prepares the collection against a specified expression context.
Definition for a property.
Definition: qgsproperty.h:46
@ Double
Double value (including negative values)
Definition: qgsproperty.h:56
@ StrokeWidth
Line stroke width.
Definition: qgsproperty.h:71
@ Boolean
Boolean value.
Definition: qgsproperty.h:52
@ Rotation
Rotation (value between 0-360 degrees)
Definition: qgsproperty.h:59
@ ColorWithAlpha
Color with alpha channel.
Definition: qgsproperty.h:63
@ DoublePositive
Positive double value (including 0)
Definition: qgsproperty.h:57
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...
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.
QgsSingleCategoryDiagramRenderer()=default
Constructor for QgsSingleCategoryDiagramRenderer.
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.
A stacked bar chart diagram.
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 QString encodeColor(const QColor &color)
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 Q_INVOKABLE QString encodeUnit(QgsUnitTypes::DistanceUnit unit)
Encodes a distance unit to a string.
static Q_INVOKABLE QgsUnitTypes::RenderUnit decodeRenderUnit(const QString &string, bool *ok=nullptr)
Decodes a render unit from a string.
@ RenderMapUnits
Map units.
Definition: qgsunittypes.h:170
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
const QgsField & field
Definition: qgsfield.h:463
QMap< int, QgsPropertyDefinition > QgsPropertiesDefinition
Definition of available properties.
Definition of one class for the legend.