QGIS API Documentation  3.21.0-Master (5b68dc587e)
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"
19 #include "diagram/qgstextdiagram.h"
20 #include "diagram/qgspiediagram.h"
23 #include "qgsrendercontext.h"
25 #include "qgsfontutils.h"
26 #include "qgssymbollayerutils.h"
27 #include "qgspainteffectregistry.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 
36 QgsPropertiesDefinition QgsDiagramLayerSettings::sPropertyDefinitions;
37 
38 void 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 
122 void 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 
143 void 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 
176 void 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( opacity );
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  newColor.setAlphaF( opacity );
325  categoryColors.append( QColor( newColor ) );
326  }
327 
328  //attribute indices
329  categoryAttributes.clear();
330  const QStringList catList = elem.attribute( QStringLiteral( "categories" ) ).split( '/' );
331  QStringList::const_iterator catIt = catList.constBegin();
332  for ( ; catIt != catList.constEnd(); ++catIt )
333  {
334  categoryAttributes.append( *catIt );
335  categoryLabels.append( *catIt );
336  }
337  }
338 
339  const QDomElement effectElem = elem.firstChildElement( QStringLiteral( "effect" ) );
340  if ( !effectElem.isNull() )
341  setPaintEffect( QgsApplication::paintEffectRegistry()->createEffect( effectElem ) );
342  else
344 }
345 
346 void QgsDiagramSettings::writeXml( QDomElement &rendererElem, QDomDocument &doc, const QgsReadWriteContext &context ) const
347 {
348  QDomElement categoryElem = doc.createElement( QStringLiteral( "DiagramCategory" ) );
349  categoryElem.setAttribute( QStringLiteral( "enabled" ), enabled );
350  categoryElem.appendChild( QgsFontUtils::toXmlElement( font, doc, QStringLiteral( "fontProperties" ) ) );
351  categoryElem.setAttribute( QStringLiteral( "backgroundColor" ), backgroundColor.name() );
352  categoryElem.setAttribute( QStringLiteral( "backgroundAlpha" ), backgroundColor.alpha() );
353  categoryElem.setAttribute( QStringLiteral( "width" ), QString::number( size.width() ) );
354  categoryElem.setAttribute( QStringLiteral( "height" ), QString::number( size.height() ) );
355  categoryElem.setAttribute( QStringLiteral( "penColor" ), penColor.name() );
356  categoryElem.setAttribute( QStringLiteral( "penAlpha" ), penColor.alpha() );
357  categoryElem.setAttribute( QStringLiteral( "penWidth" ), QString::number( penWidth ) );
358  categoryElem.setAttribute( QStringLiteral( "scaleBasedVisibility" ), scaleBasedVisibility );
359  categoryElem.setAttribute( QStringLiteral( "minScaleDenominator" ), QString::number( maximumScale ) );
360  categoryElem.setAttribute( QStringLiteral( "maxScaleDenominator" ), QString::number( minimumScale ) );
361  categoryElem.setAttribute( QStringLiteral( "opacity" ), QString::number( opacity ) );
362  categoryElem.setAttribute( QStringLiteral( "spacing" ), QString::number( mSpacing ) );
363  categoryElem.setAttribute( QStringLiteral( "spacingUnit" ), QgsUnitTypes::encodeUnit( mSpacingUnit ) );
364  categoryElem.setAttribute( QStringLiteral( "spacingUnitScale" ), QgsSymbolLayerUtils::encodeMapUnitScale( mSpacingMapUnitScale ) );
365  categoryElem.setAttribute( QStringLiteral( "direction" ), QString::number( mDirection ) );
366 
367  //diagram size unit type and scale
368  categoryElem.setAttribute( QStringLiteral( "sizeType" ), QgsUnitTypes::encodeUnit( sizeType ) );
369  categoryElem.setAttribute( QStringLiteral( "sizeScale" ), QgsSymbolLayerUtils::encodeMapUnitScale( sizeScale ) );
370 
371  //line width unit type and scale
372  categoryElem.setAttribute( QStringLiteral( "lineSizeType" ), QgsUnitTypes::encodeUnit( lineSizeUnit ) );
373  categoryElem.setAttribute( QStringLiteral( "lineSizeScale" ), QgsSymbolLayerUtils::encodeMapUnitScale( lineSizeScale ) );
374 
375  // label placement method (text diagram)
376  if ( labelPlacementMethod == Height )
377  {
378  categoryElem.setAttribute( QStringLiteral( "labelPlacementMethod" ), QStringLiteral( "Height" ) );
379  }
380  else
381  {
382  categoryElem.setAttribute( QStringLiteral( "labelPlacementMethod" ), QStringLiteral( "XHeight" ) );
383  }
384 
385  if ( scaleByArea )
386  {
387  categoryElem.setAttribute( QStringLiteral( "scaleDependency" ), QStringLiteral( "Area" ) );
388  }
389  else
390  {
391  categoryElem.setAttribute( QStringLiteral( "scaleDependency" ), QStringLiteral( "Diameter" ) );
392  }
393 
394  // orientation (histogram)
395  switch ( diagramOrientation )
396  {
397  case Left:
398  categoryElem.setAttribute( QStringLiteral( "diagramOrientation" ), QStringLiteral( "Left" ) );
399  break;
400 
401  case Right:
402  categoryElem.setAttribute( QStringLiteral( "diagramOrientation" ), QStringLiteral( "Right" ) );
403  break;
404 
405  case Down:
406  categoryElem.setAttribute( QStringLiteral( "diagramOrientation" ), QStringLiteral( "Down" ) );
407  break;
408 
409  case Up:
410  categoryElem.setAttribute( QStringLiteral( "diagramOrientation" ), QStringLiteral( "Up" ) );
411  break;
412  }
413 
414  categoryElem.setAttribute( QStringLiteral( "barWidth" ), QString::number( barWidth ) );
415  categoryElem.setAttribute( QStringLiteral( "minimumSize" ), QString::number( minimumSize ) );
416  categoryElem.setAttribute( QStringLiteral( "rotationOffset" ), QString::number( rotationOffset ) );
417 
418  const int nCats = std::min( categoryColors.size(), categoryAttributes.size() );
419  for ( int i = 0; i < nCats; ++i )
420  {
421  QDomElement attributeElem = doc.createElement( QStringLiteral( "attribute" ) );
422 
423  attributeElem.setAttribute( QStringLiteral( "field" ), categoryAttributes.at( i ) );
424  attributeElem.setAttribute( QStringLiteral( "color" ), categoryColors.at( i ).name() );
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 
462 void 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 
497 QSizeF 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 
515 QSet<QString> QgsDiagramRenderer::referencedFields( const QgsExpressionContext &context ) const
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 
535 void 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 
547 int 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 
560 void 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 
589 void 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 
618 QList<QgsDiagramSettings> QgsSingleCategoryDiagramRenderer::diagramSettings() const
619 {
620  QList<QgsDiagramSettings> settingsList;
621  settingsList.push_back( mSettings );
622  return settingsList;
623 }
624 
625 void 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 
637 void 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 
725 void 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 
776 void 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 
806 QList< 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 
835 void QgsDiagramSettings::setShowAxis( bool showAxis )
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;
903  lineSizeUnit = other.lineSizeUnit;
906  penColor = other.penColor;
907  penWidth = other.penWidth;
910  barWidth = other.barWidth;
911  opacity = other.opacity;
912  scaleByArea = other.scaleByArea;
915  maximumScale = other.maximumScale;
916  minimumScale = other.minimumScale;
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 
938 QList< QgsLayerTreeModelLegendNode * > QgsDiagramRenderer::legendItems( QgsLayerTreeLayer * ) const
939 {
940  return QList< QgsLayerTreeModelLegendNode * >();
941 }
942 
943 QList< QgsLayerTreeModelLegendNode * > QgsSingleCategoryDiagramRenderer::legendItems( QgsLayerTreeLayer *nodeLayer ) const
944 {
945  QList< QgsLayerTreeModelLegendNode * > nodes;
946  if ( mShowAttributeLegend )
947  nodes = mSettings.legendItems( nodeLayer );
948 
949  return nodes;
950 }
951 
952 QList< QgsLayerTreeModelLegendNode * > QgsLinearlyInterpolatedDiagramRenderer::legendItems( QgsLayerTreeLayer *nodeLayer ) const
953 {
954  QList< QgsLayerTreeModelLegendNode * > nodes;
955  if ( mShowAttributeLegend )
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 QgsDiagramRenderer * clone() const =0
Returns new instance that is equivalent to this one.
virtual QList< QString > diagramAttributes() const =0
Returns attribute indices needed for diagram rendering.
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.
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)
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)
Sets the size units for the whole symbol (including all symbol layers).
void setSizeMapUnitScale(const QgsMapUnitScale &scale)
Sets the size map unit scale for the whole symbol (including all symbol layers).
QgsMarkerSymbol * clone() const override
Returns a deep copy of this symbol.
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:48
@ Double
Double value (including negative values)
Definition: qgsproperty.h:58
@ StrokeWidth
Line stroke width.
Definition: qgsproperty.h:73
@ Boolean
Boolean value.
Definition: qgsproperty.h:54
@ Rotation
Rotation (value between 0-360 degrees)
Definition: qgsproperty.h:61
@ ColorWithAlpha
Color with alpha channel.
Definition: qgsproperty.h:65
@ DoublePositive
Positive double value (including 0)
Definition: qgsproperty.h:59
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.