QGIS API Documentation  3.20.0-Odense (decaadbb31)
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  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  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  QDomNodeList axisSymbolNodes = elem.elementsByTagName( QStringLiteral( "axisSymbol" ) );
282  if ( axisSymbolNodes.count() > 0 )
283  {
284  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  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  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  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  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  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  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  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  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  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  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  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  return new QgsLinearlyInterpolatedDiagramRenderer( *this );
667 }
668 
670 {
671  QList<QgsDiagramSettings> settingsList;
672  settingsList.push_back( mSettings );
673  return settingsList;
674 }
675 
677 {
678  s = mSettings;
679  s.size = diagramSize( feature, c );
680  return true;
681 }
682 
684 {
685  return mSettings.categoryAttributes;
686 }
687 
689 {
690  QSet< QString > referenced = QgsDiagramRenderer::referencedFields( context );
691  if ( mInterpolationSettings.classificationAttributeIsExpression )
692  {
693  QgsExpression *expression = mDiagram->getExpression( mInterpolationSettings.classificationAttributeExpression, context );
694  const auto constReferencedColumns = expression->referencedColumns();
695  for ( const QString &field : constReferencedColumns )
696  {
697  referenced << field;
698  }
699  }
700  else
701  {
702  referenced << mInterpolationSettings.classificationField;
703  }
704  return referenced;
705 }
706 
708 {
709  return mDiagram->diagramSize( feature, c, mSettings, mInterpolationSettings );
710 }
711 
712 void QgsLinearlyInterpolatedDiagramRenderer::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
713 {
714  mInterpolationSettings.lowerValue = elem.attribute( QStringLiteral( "lowerValue" ) ).toDouble();
715  mInterpolationSettings.upperValue = elem.attribute( QStringLiteral( "upperValue" ) ).toDouble();
716  mInterpolationSettings.lowerSize.setWidth( elem.attribute( QStringLiteral( "lowerWidth" ) ).toDouble() );
717  mInterpolationSettings.lowerSize.setHeight( elem.attribute( QStringLiteral( "lowerHeight" ) ).toDouble() );
718  mInterpolationSettings.upperSize.setWidth( elem.attribute( QStringLiteral( "upperWidth" ) ).toDouble() );
719  mInterpolationSettings.upperSize.setHeight( elem.attribute( QStringLiteral( "upperHeight" ) ).toDouble() );
720  mInterpolationSettings.classificationAttributeIsExpression = elem.hasAttribute( QStringLiteral( "classificationAttributeExpression" ) );
721  if ( mInterpolationSettings.classificationAttributeIsExpression )
722  {
723  mInterpolationSettings.classificationAttributeExpression = elem.attribute( QStringLiteral( "classificationAttributeExpression" ) );
724  }
725  else
726  {
727  mInterpolationSettings.classificationField = elem.attribute( QStringLiteral( "classificationField" ) );
728  }
729  QDomElement settingsElem = elem.firstChildElement( QStringLiteral( "DiagramCategory" ) );
730  if ( !settingsElem.isNull() )
731  {
732  mSettings.readXml( settingsElem );
733  }
734 
735  delete mDataDefinedSizeLegend;
736 
737  QDomElement ddsLegendSizeElem = elem.firstChildElement( QStringLiteral( "data-defined-size-legend" ) );
738  if ( !ddsLegendSizeElem.isNull() )
739  {
740  mDataDefinedSizeLegend = QgsDataDefinedSizeLegend::readXml( ddsLegendSizeElem, context );
741  }
742  else
743  {
744  // pre-3.0 projects
745  if ( elem.attribute( QStringLiteral( "sizeLegend" ), QStringLiteral( "0" ) ) != QLatin1String( "0" ) )
746  {
747  mDataDefinedSizeLegend = new QgsDataDefinedSizeLegend();
748  QDomElement sizeLegendSymbolElem = elem.firstChildElement( QStringLiteral( "symbol" ) );
749  if ( !sizeLegendSymbolElem.isNull() && sizeLegendSymbolElem.attribute( QStringLiteral( "name" ) ) == QLatin1String( "sizeSymbol" ) )
750  {
751  mDataDefinedSizeLegend->setSymbol( QgsSymbolLayerUtils::loadSymbol<QgsMarkerSymbol>( sizeLegendSymbolElem, context ) );
752  }
753  }
754  else
755  {
756  mDataDefinedSizeLegend = nullptr;
757  }
758  }
759 
760  _readXml( elem, context );
761 }
762 
763 void QgsLinearlyInterpolatedDiagramRenderer::writeXml( QDomElement &layerElem, QDomDocument &doc, const QgsReadWriteContext &context ) const
764 {
765  QDomElement rendererElem = doc.createElement( QStringLiteral( "LinearlyInterpolatedDiagramRenderer" ) );
766  rendererElem.setAttribute( QStringLiteral( "lowerValue" ), QString::number( mInterpolationSettings.lowerValue ) );
767  rendererElem.setAttribute( QStringLiteral( "upperValue" ), QString::number( mInterpolationSettings.upperValue ) );
768  rendererElem.setAttribute( QStringLiteral( "lowerWidth" ), QString::number( mInterpolationSettings.lowerSize.width() ) );
769  rendererElem.setAttribute( QStringLiteral( "lowerHeight" ), QString::number( mInterpolationSettings.lowerSize.height() ) );
770  rendererElem.setAttribute( QStringLiteral( "upperWidth" ), QString::number( mInterpolationSettings.upperSize.width() ) );
771  rendererElem.setAttribute( QStringLiteral( "upperHeight" ), QString::number( mInterpolationSettings.upperSize.height() ) );
772  if ( mInterpolationSettings.classificationAttributeIsExpression )
773  {
774  rendererElem.setAttribute( QStringLiteral( "classificationAttributeExpression" ), mInterpolationSettings.classificationAttributeExpression );
775  }
776  else
777  {
778  rendererElem.setAttribute( QStringLiteral( "classificationField" ), mInterpolationSettings.classificationField );
779  }
780  mSettings.writeXml( rendererElem, doc );
781 
782  if ( mDataDefinedSizeLegend )
783  {
784  QDomElement ddsLegendElem = doc.createElement( QStringLiteral( "data-defined-size-legend" ) );
785  mDataDefinedSizeLegend->writeXml( ddsLegendElem, context );
786  rendererElem.appendChild( ddsLegendElem );
787  }
788 
789  _writeXml( rendererElem, doc, context );
790  layerElem.appendChild( rendererElem );
791 }
792 
793 QList< QgsLayerTreeModelLegendNode * > QgsDiagramSettings::legendItems( QgsLayerTreeLayer *nodeLayer ) const
794 {
795  QList< QgsLayerTreeModelLegendNode * > list;
796  list.reserve( categoryLabels.size() );
797  for ( int i = 0; i < categoryLabels.size(); ++i )
798  {
799  QPixmap pix( 16, 16 );
800  pix.fill( categoryColors[i] );
801  list << new QgsSimpleLegendNode( nodeLayer, categoryLabels[i], QIcon( pix ), nullptr, QStringLiteral( "diagram_%1" ).arg( QString::number( i ) ) );
802  }
803  return list;
804 }
805 
807 {
808  return mAxisLineSymbol.get();
809 }
810 
812 {
813  if ( axisLineSymbol != mAxisLineSymbol.get() )
814  mAxisLineSymbol.reset( axisLineSymbol );
815 }
816 
818 {
819  return mShowAxis;
820 }
821 
822 void QgsDiagramSettings::setShowAxis( bool showAxis )
823 {
824  mShowAxis = showAxis;
825 }
826 
828 {
829  return mPaintEffect.get();
830 }
831 
833 {
834  if ( effect != mPaintEffect.get() )
835  mPaintEffect.reset( effect );
836 }
837 
839  : mAxisLineSymbol( std::make_unique< QgsLineSymbol >() )
840 {
841 }
842 
844 
846  : enabled( other.enabled )
847  , font( other.font )
848  , categoryColors( other.categoryColors )
849  , categoryAttributes( other.categoryAttributes )
850  , categoryLabels( other.categoryLabels )
851  , size( other.size )
852  , sizeType( other.sizeType )
853  , sizeScale( other.sizeScale )
854  , lineSizeUnit( other.lineSizeUnit )
855  , lineSizeScale( other.lineSizeScale )
856  , backgroundColor( other.backgroundColor )
857  , penColor( other.penColor )
858  , penWidth( other.penWidth )
859  , labelPlacementMethod( other.labelPlacementMethod )
860  , diagramOrientation( other.diagramOrientation )
861  , barWidth( other.barWidth )
862  , opacity( other.opacity )
863  , scaleByArea( other.scaleByArea )
864  , rotationOffset( other.rotationOffset )
865  , scaleBasedVisibility( other.scaleBasedVisibility )
866  , maximumScale( other.maximumScale )
867  , minimumScale( other.minimumScale )
868  , minimumSize( other.minimumSize )
869  , mSpacing( other.mSpacing )
870  , mSpacingUnit( other.mSpacingUnit )
871  , mSpacingMapUnitScale( other.mSpacingMapUnitScale )
872  , mDirection( other.mDirection )
873  , mShowAxis( other.mShowAxis )
874  , mAxisLineSymbol( other.mAxisLineSymbol ? other.mAxisLineSymbol->clone() : nullptr )
875  , mPaintEffect( other.mPaintEffect ? other.mPaintEffect->clone() : nullptr )
876 {
877 
878 }
879 
881 {
882  enabled = other.enabled;
883  font = other.font;
887  size = other.size;
888  sizeType = other.sizeType;
889  sizeScale = other.sizeScale;
890  lineSizeUnit = other.lineSizeUnit;
893  penColor = other.penColor;
894  penWidth = other.penWidth;
897  barWidth = other.barWidth;
898  opacity = other.opacity;
899  scaleByArea = other.scaleByArea;
902  maximumScale = other.maximumScale;
903  minimumScale = other.minimumScale;
904  minimumSize = other.minimumSize;
905  mSpacing = other.mSpacing;
906  mSpacingUnit = other.mSpacingUnit;
907  mSpacingMapUnitScale = other.mSpacingMapUnitScale;
908  mDirection = other.mDirection;
909  mAxisLineSymbol.reset( other.mAxisLineSymbol ? other.mAxisLineSymbol->clone() : nullptr );
910  mShowAxis = other.mShowAxis;
911  mPaintEffect.reset( other.mPaintEffect ? other.mPaintEffect->clone() : nullptr );
912  return *this;
913 }
914 
916 {
917  return mDirection;
918 }
919 
921 {
922  mDirection = direction;
923 }
924 
925 QList< QgsLayerTreeModelLegendNode * > QgsDiagramRenderer::legendItems( QgsLayerTreeLayer * ) const
926 {
927  return QList< QgsLayerTreeModelLegendNode * >();
928 }
929 
930 QList< QgsLayerTreeModelLegendNode * > QgsSingleCategoryDiagramRenderer::legendItems( QgsLayerTreeLayer *nodeLayer ) const
931 {
932  QList< QgsLayerTreeModelLegendNode * > nodes;
933  if ( mShowAttributeLegend )
934  nodes = mSettings.legendItems( nodeLayer );
935 
936  return nodes;
937 }
938 
939 QList< QgsLayerTreeModelLegendNode * > QgsLinearlyInterpolatedDiagramRenderer::legendItems( QgsLayerTreeLayer *nodeLayer ) const
940 {
941  QList< QgsLayerTreeModelLegendNode * > nodes;
942  if ( mShowAttributeLegend )
943  nodes = mSettings.legendItems( nodeLayer );
944 
945  if ( mDataDefinedSizeLegend && mDiagram )
946  {
947  // add size legend
948  QgsMarkerSymbol *legendSymbol = mDataDefinedSizeLegend->symbol() ? mDataDefinedSizeLegend->symbol()->clone() : QgsMarkerSymbol::createSimple( QVariantMap() );
949  legendSymbol->setSizeUnit( mSettings.sizeType );
950  legendSymbol->setSizeMapUnitScale( mSettings.sizeScale );
951 
952  QgsDataDefinedSizeLegend ddSizeLegend( *mDataDefinedSizeLegend );
953  ddSizeLegend.setSymbol( legendSymbol ); // transfers ownership
954 
955  QList<QgsDataDefinedSizeLegend::SizeClass> sizeClasses;
956  if ( ddSizeLegend.classes().isEmpty() )
957  {
958  // automatic class creation if the classes are not defined manually
959  const auto prettyBreaks { QgsSymbolLayerUtils::prettyBreaks( mInterpolationSettings.lowerValue, mInterpolationSettings.upperValue, 4 ) };
960  for ( double v : prettyBreaks )
961  {
962  double size = mDiagram->legendSize( v, mSettings, mInterpolationSettings );
963  sizeClasses << QgsDataDefinedSizeLegend::SizeClass( size, QString::number( v ) );
964  }
965  }
966  else
967  {
968  // manual classes need to get size scaled because the QgsSizeScaleTransformer is not used in diagrams :-(
969  const auto constClasses = ddSizeLegend.classes();
970  for ( const QgsDataDefinedSizeLegend::SizeClass &sc : constClasses )
971  {
972  double size = mDiagram->legendSize( sc.size, mSettings, mInterpolationSettings );
973  sizeClasses << QgsDataDefinedSizeLegend::SizeClass( size, sc.label );
974  }
975  }
976  ddSizeLegend.setClasses( sizeClasses );
977 
978  const auto constLegendSymbolList = ddSizeLegend.legendSymbolList();
979  for ( const QgsLegendSymbolItem &si : constLegendSymbolList )
980  {
981  if ( auto *lDataDefinedSizeLegendSettings = si.dataDefinedSizeLegendSettings() )
982  nodes << new QgsDataDefinedSizeLegendNode( nodeLayer, *lDataDefinedSizeLegendSettings );
983  else
984  nodes << new QgsSymbolLegendNode( nodeLayer, si );
985  }
986  }
987 
988  return nodes;
989 }
990 
992 {
993  delete mDataDefinedSizeLegend;
994  mDataDefinedSizeLegend = settings;
995 }
996 
998 {
999  return mDataDefinedSizeLegend;
1000 }
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.
double mapUnitsPerPixel() const
Returns 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.