QGIS API Documentation  3.12.1-BucureČ™ti (121cc00ff0)
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 
31 #include <QDomElement>
32 #include <QPainter>
33 
34 QgsPropertiesDefinition QgsDiagramLayerSettings::sPropertyDefinitions;
35 
36 void QgsDiagramLayerSettings::initPropertyDefinitions()
37 {
38  if ( !sPropertyDefinitions.isEmpty() )
39  return;
40 
41  const QString origin = QStringLiteral( "diagram" );
42 
43  sPropertyDefinitions = QgsPropertiesDefinition
44  {
45  { QgsDiagramLayerSettings::BackgroundColor, QgsPropertyDefinition( "backgroundColor", QObject::tr( "Background color" ), QgsPropertyDefinition::ColorWithAlpha, origin ) },
46  { QgsDiagramLayerSettings::StrokeColor, QgsPropertyDefinition( "strokeColor", QObject::tr( "Stroke color" ), QgsPropertyDefinition::ColorWithAlpha, origin ) },
47  { QgsDiagramLayerSettings::StrokeWidth, QgsPropertyDefinition( "strokeWidth", QObject::tr( "Stroke width" ), QgsPropertyDefinition::StrokeWidth, origin ) },
48  { QgsDiagramLayerSettings::PositionX, QgsPropertyDefinition( "positionX", QObject::tr( "Position (X)" ), QgsPropertyDefinition::Double, origin ) },
49  { QgsDiagramLayerSettings::PositionY, QgsPropertyDefinition( "positionY", QObject::tr( "Position (Y)" ), QgsPropertyDefinition::Double, origin ) },
50  { QgsDiagramLayerSettings::Distance, QgsPropertyDefinition( "distance", QObject::tr( "Placement distance" ), QgsPropertyDefinition::DoublePositive, origin ) },
51  { QgsDiagramLayerSettings::Priority, QgsPropertyDefinition( "priority", QObject::tr( "Placement priority" ), QgsPropertyDefinition::DoublePositive, origin ) },
52  { QgsDiagramLayerSettings::ZIndex, QgsPropertyDefinition( "zIndex", QObject::tr( "Placement z-index" ), QgsPropertyDefinition::Double, origin ) },
53  { QgsDiagramLayerSettings::IsObstacle, QgsPropertyDefinition( "isObstacle", QObject::tr( "Diagram is an obstacle" ), QgsPropertyDefinition::Boolean, origin ) },
54  { QgsDiagramLayerSettings::Show, QgsPropertyDefinition( "show", QObject::tr( "Show diagram" ), QgsPropertyDefinition::Boolean, origin ) },
55  { QgsDiagramLayerSettings::AlwaysShow, QgsPropertyDefinition( "alwaysShow", QObject::tr( "Always show diagram" ), QgsPropertyDefinition::Boolean, origin ) },
56  { QgsDiagramLayerSettings::StartAngle, QgsPropertyDefinition( "startAngle", QObject::tr( "Pie chart start angle" ), QgsPropertyDefinition::Rotation, origin ) },
57  };
58 }
59 
61 {
62  initPropertyDefinitions();
63  return sPropertyDefinitions;
64 }
65 
67 {
68  initPropertyDefinitions();
69 }
70 
72  : mCt( rh.mCt )
73  , mPlacement( rh.mPlacement )
74  , mPlacementFlags( rh.mPlacementFlags )
75  , mPriority( rh.mPriority )
76  , mZIndex( rh.mZIndex )
77  , mObstacle( rh.mObstacle )
78  , mDistance( rh.mDistance )
79  , mRenderer( rh.mRenderer ? rh.mRenderer->clone() : nullptr )
80  , mShowAll( rh.mShowAll )
81  , mDataDefinedProperties( rh.mDataDefinedProperties )
82 {
83  initPropertyDefinitions();
84 }
85 
87 {
88  mPlacement = rh.mPlacement;
89  mPlacementFlags = rh.mPlacementFlags;
90  mPriority = rh.mPriority;
91  mZIndex = rh.mZIndex;
92  mObstacle = rh.mObstacle;
93  mDistance = rh.mDistance;
94  mRenderer = rh.mRenderer ? rh.mRenderer->clone() : nullptr;
95  mCt = rh.mCt;
96  mShowAll = rh.mShowAll;
97  mDataDefinedProperties = rh.mDataDefinedProperties;
98  return *this;
99 }
100 
102 {
103  delete mRenderer;
104 }
105 
107 {
108  if ( diagramRenderer == mRenderer )
109  return;
110 
111  delete mRenderer;
112  mRenderer = diagramRenderer;
113 }
114 
116 {
117  mCt = transform;
118 }
119 
120 void QgsDiagramLayerSettings::readXml( const QDomElement &elem )
121 {
122  QDomNodeList propertyElems = elem.elementsByTagName( QStringLiteral( "properties" ) );
123  if ( !propertyElems.isEmpty() )
124  {
125  ( void )mDataDefinedProperties.readXml( propertyElems.at( 0 ).toElement(), sPropertyDefinitions );
126  }
127  else
128  {
129  mDataDefinedProperties.clear();
130  }
131 
132  mPlacement = static_cast< Placement >( elem.attribute( QStringLiteral( "placement" ) ).toInt() );
133  mPlacementFlags = static_cast< LinePlacementFlag >( elem.attribute( QStringLiteral( "linePlacementFlags" ) ).toInt() );
134  mPriority = elem.attribute( QStringLiteral( "priority" ) ).toInt();
135  mZIndex = elem.attribute( QStringLiteral( "zIndex" ) ).toDouble();
136  mObstacle = elem.attribute( QStringLiteral( "obstacle" ) ).toInt();
137  mDistance = elem.attribute( QStringLiteral( "dist" ) ).toDouble();
138  mShowAll = ( elem.attribute( QStringLiteral( "showAll" ), QStringLiteral( "0" ) ) != QLatin1String( "0" ) );
139 }
140 
141 void QgsDiagramLayerSettings::writeXml( QDomElement &layerElem, QDomDocument &doc ) const
142 {
143  QDomElement diagramLayerElem = doc.createElement( QStringLiteral( "DiagramLayerSettings" ) );
144  QDomElement propertiesElem = doc.createElement( QStringLiteral( "properties" ) );
145  ( void )mDataDefinedProperties.writeXml( propertiesElem, sPropertyDefinitions );
146  diagramLayerElem.appendChild( propertiesElem );
147  diagramLayerElem.setAttribute( QStringLiteral( "placement" ), mPlacement );
148  diagramLayerElem.setAttribute( QStringLiteral( "linePlacementFlags" ), mPlacementFlags );
149  diagramLayerElem.setAttribute( QStringLiteral( "priority" ), mPriority );
150  diagramLayerElem.setAttribute( QStringLiteral( "zIndex" ), mZIndex );
151  diagramLayerElem.setAttribute( QStringLiteral( "obstacle" ), mObstacle );
152  diagramLayerElem.setAttribute( QStringLiteral( "dist" ), QString::number( mDistance ) );
153  diagramLayerElem.setAttribute( QStringLiteral( "showAll" ), mShowAll );
154  layerElem.appendChild( diagramLayerElem );
155 }
156 
158 {
159  return mDataDefinedProperties.prepare( context );
160 }
161 
163 {
164  QSet< QString > referenced;
165  if ( mRenderer )
166  referenced = mRenderer->referencedFields( context );
167 
168  //add the ones needed for data defined settings
169  referenced.unite( mDataDefinedProperties.referencedFields( context ) );
170 
171  return referenced;
172 }
173 
174 void QgsDiagramSettings::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
175 {
176  enabled = ( elem.attribute( QStringLiteral( "enabled" ), QStringLiteral( "1" ) ) != QLatin1String( "0" ) );
177  if ( !QgsFontUtils::setFromXmlChildNode( font, elem, QStringLiteral( "fontProperties" ) ) )
178  {
179  font.fromString( elem.attribute( QStringLiteral( "font" ) ) );
180  }
181  backgroundColor.setNamedColor( elem.attribute( QStringLiteral( "backgroundColor" ) ) );
182  backgroundColor.setAlpha( elem.attribute( QStringLiteral( "backgroundAlpha" ) ).toInt() );
183  size.setWidth( elem.attribute( QStringLiteral( "width" ) ).toDouble() );
184  size.setHeight( elem.attribute( QStringLiteral( "height" ) ).toDouble() );
185  if ( elem.hasAttribute( QStringLiteral( "transparency" ) ) )
186  {
187  opacity = 1 - elem.attribute( QStringLiteral( "transparency" ), QStringLiteral( "0" ) ).toInt() / 255.0;
188  }
189  else
190  {
191  opacity = elem.attribute( QStringLiteral( "opacity" ), QStringLiteral( "1.00" ) ).toDouble();
192  }
193 
194  penColor.setNamedColor( elem.attribute( QStringLiteral( "penColor" ) ) );
195  int penAlpha = elem.attribute( QStringLiteral( "penAlpha" ), QStringLiteral( "255" ) ).toInt();
196  penColor.setAlpha( penAlpha );
197  penWidth = elem.attribute( QStringLiteral( "penWidth" ) ).toDouble();
198 
199  mDirection = static_cast< Direction >( elem.attribute( QStringLiteral( "direction" ), QStringLiteral( "1" ) ).toInt() );
200 
201  maximumScale = elem.attribute( QStringLiteral( "minScaleDenominator" ), QStringLiteral( "-1" ) ).toDouble();
202  minimumScale = elem.attribute( QStringLiteral( "maxScaleDenominator" ), QStringLiteral( "-1" ) ).toDouble();
203  if ( elem.hasAttribute( QStringLiteral( "scaleBasedVisibility" ) ) )
204  {
205  scaleBasedVisibility = ( elem.attribute( QStringLiteral( "scaleBasedVisibility" ), QStringLiteral( "1" ) ) != QLatin1String( "0" ) );
206  }
207  else
208  {
209  scaleBasedVisibility = maximumScale >= 0 && minimumScale >= 0;
210  }
211 
212  //diagram size unit type and scale
213  if ( elem.attribute( QStringLiteral( "sizeType" ) ) == QLatin1String( "MapUnits" ) )
214  {
215  //compatibility with pre-2.16 project files
216  sizeType = QgsUnitTypes::RenderMapUnits;
217  }
218  else
219  {
220  sizeType = QgsUnitTypes::decodeRenderUnit( elem.attribute( QStringLiteral( "sizeType" ) ) );
221  }
222  sizeScale = QgsSymbolLayerUtils::decodeMapUnitScale( elem.attribute( QStringLiteral( "sizeScale" ) ) );
223 
224  //line width unit type and scale
225  lineSizeUnit = QgsUnitTypes::decodeRenderUnit( elem.attribute( QStringLiteral( "lineSizeType" ) ) );
226  lineSizeScale = QgsSymbolLayerUtils::decodeMapUnitScale( elem.attribute( QStringLiteral( "lineSizeScale" ) ) );
227 
228  mSpacing = elem.attribute( QStringLiteral( "spacing" ) ).toDouble();
229  mSpacingUnit = QgsUnitTypes::decodeRenderUnit( elem.attribute( QStringLiteral( "spacingUnit" ) ) );
230  mSpacingMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( elem.attribute( QStringLiteral( "spacingUnitScale" ) ) );
231 
232  //label placement method
233  if ( elem.attribute( QStringLiteral( "labelPlacementMethod" ) ) == QLatin1String( "Height" ) )
234  {
235  labelPlacementMethod = Height;
236  }
237  else
238  {
239  labelPlacementMethod = XHeight;
240  }
241 
242  // orientation
243  if ( elem.attribute( QStringLiteral( "diagramOrientation" ) ) == QLatin1String( "Left" ) )
244  {
245  diagramOrientation = Left;
246  }
247  else if ( elem.attribute( QStringLiteral( "diagramOrientation" ) ) == QLatin1String( "Right" ) )
248  {
249  diagramOrientation = Right;
250  }
251  else if ( elem.attribute( QStringLiteral( "diagramOrientation" ) ) == QLatin1String( "Down" ) )
252  {
253  diagramOrientation = Down;
254  }
255  else
256  {
257  diagramOrientation = Up;
258  }
259 
260  // scale dependency
261  if ( elem.attribute( QStringLiteral( "scaleDependency" ) ) == QLatin1String( "Diameter" ) )
262  {
263  scaleByArea = false;
264  }
265  else
266  {
267  scaleByArea = true;
268  }
269 
270  barWidth = elem.attribute( QStringLiteral( "barWidth" ) ).toDouble();
271 
272  if ( elem.hasAttribute( QStringLiteral( "angleOffset" ) ) )
273  rotationOffset = std::fmod( 360.0 - elem.attribute( QStringLiteral( "angleOffset" ) ).toInt() / 16.0, 360.0 );
274  else
275  rotationOffset = elem.attribute( QStringLiteral( "rotationOffset" ) ).toDouble();
276 
277  minimumSize = elem.attribute( QStringLiteral( "minimumSize" ) ).toDouble();
278 
279  QDomNodeList axisSymbolNodes = elem.elementsByTagName( QStringLiteral( "axisSymbol" ) );
280  if ( axisSymbolNodes.count() > 0 )
281  {
282  QDomElement axisSymbolElem = axisSymbolNodes.at( 0 ).toElement().firstChildElement();
283  mAxisLineSymbol.reset( QgsSymbolLayerUtils::loadSymbol<QgsLineSymbol>( axisSymbolElem, context ) );
284  }
285  else
286  {
287  mAxisLineSymbol = qgis::make_unique< QgsLineSymbol >();
288  }
289 
290  mShowAxis = elem.attribute( QStringLiteral( "showAxis" ), QStringLiteral( "0" ) ).toInt();
291 
292  //colors
293  categoryColors.clear();
294  QDomNodeList attributes = elem.elementsByTagName( QStringLiteral( "attribute" ) );
295 
296 
297  if ( attributes.length() > 0 )
298  {
299  for ( int i = 0; i < attributes.size(); i++ )
300  {
301  QDomElement attrElem = attributes.at( i ).toElement();
302  QColor newColor( attrElem.attribute( QStringLiteral( "color" ) ) );
303  newColor.setAlphaF( opacity );
304  categoryColors.append( newColor );
305  categoryAttributes.append( attrElem.attribute( QStringLiteral( "field" ) ) );
306  categoryLabels.append( attrElem.attribute( QStringLiteral( "label" ) ) );
307  if ( categoryLabels.constLast().isEmpty() )
308  {
309  categoryLabels.back() = categoryAttributes.back();
310  }
311  }
312  }
313  else
314  {
315  // Restore old format attributes and colors
316 
317  QStringList colorList = elem.attribute( QStringLiteral( "colors" ) ).split( '/' );
318  QStringList::const_iterator colorIt = colorList.constBegin();
319  for ( ; colorIt != colorList.constEnd(); ++colorIt )
320  {
321  QColor newColor( *colorIt );
322  newColor.setAlphaF( opacity );
323  categoryColors.append( QColor( newColor ) );
324  }
325 
326  //attribute indices
327  categoryAttributes.clear();
328  QStringList catList = elem.attribute( QStringLiteral( "categories" ) ).split( '/' );
329  QStringList::const_iterator catIt = catList.constBegin();
330  for ( ; catIt != catList.constEnd(); ++catIt )
331  {
332  categoryAttributes.append( *catIt );
333  categoryLabels.append( *catIt );
334  }
335  }
336 
337  QDomElement effectElem = elem.firstChildElement( QStringLiteral( "effect" ) );
338  if ( !effectElem.isNull() )
339  setPaintEffect( QgsApplication::paintEffectRegistry()->createEffect( effectElem ) );
340  else
341  setPaintEffect( QgsApplication::paintEffectRegistry()->defaultStack() );
342 }
343 
344 void QgsDiagramSettings::writeXml( QDomElement &rendererElem, QDomDocument &doc, const QgsReadWriteContext &context ) const
345 {
346  QDomElement categoryElem = doc.createElement( QStringLiteral( "DiagramCategory" ) );
347  categoryElem.setAttribute( QStringLiteral( "enabled" ), enabled );
348  categoryElem.appendChild( QgsFontUtils::toXmlElement( font, doc, QStringLiteral( "fontProperties" ) ) );
349  categoryElem.setAttribute( QStringLiteral( "backgroundColor" ), backgroundColor.name() );
350  categoryElem.setAttribute( QStringLiteral( "backgroundAlpha" ), backgroundColor.alpha() );
351  categoryElem.setAttribute( QStringLiteral( "width" ), QString::number( size.width() ) );
352  categoryElem.setAttribute( QStringLiteral( "height" ), QString::number( size.height() ) );
353  categoryElem.setAttribute( QStringLiteral( "penColor" ), penColor.name() );
354  categoryElem.setAttribute( QStringLiteral( "penAlpha" ), penColor.alpha() );
355  categoryElem.setAttribute( QStringLiteral( "penWidth" ), QString::number( penWidth ) );
356  categoryElem.setAttribute( QStringLiteral( "scaleBasedVisibility" ), scaleBasedVisibility );
357  categoryElem.setAttribute( QStringLiteral( "minScaleDenominator" ), QString::number( maximumScale ) );
358  categoryElem.setAttribute( QStringLiteral( "maxScaleDenominator" ), QString::number( minimumScale ) );
359  categoryElem.setAttribute( QStringLiteral( "opacity" ), QString::number( opacity ) );
360  categoryElem.setAttribute( QStringLiteral( "spacing" ), QString::number( mSpacing ) );
361  categoryElem.setAttribute( QStringLiteral( "spacingUnit" ), QgsUnitTypes::encodeUnit( mSpacingUnit ) );
362  categoryElem.setAttribute( QStringLiteral( "spacingUnitScale" ), QgsSymbolLayerUtils::encodeMapUnitScale( mSpacingMapUnitScale ) );
363  categoryElem.setAttribute( QStringLiteral( "direction" ), QString::number( mDirection ) );
364 
365  //diagram size unit type and scale
366  categoryElem.setAttribute( QStringLiteral( "sizeType" ), QgsUnitTypes::encodeUnit( sizeType ) );
367  categoryElem.setAttribute( QStringLiteral( "sizeScale" ), QgsSymbolLayerUtils::encodeMapUnitScale( sizeScale ) );
368 
369  //line width unit type and scale
370  categoryElem.setAttribute( QStringLiteral( "lineSizeType" ), QgsUnitTypes::encodeUnit( lineSizeUnit ) );
371  categoryElem.setAttribute( QStringLiteral( "lineSizeScale" ), QgsSymbolLayerUtils::encodeMapUnitScale( lineSizeScale ) );
372 
373  // label placement method (text diagram)
374  if ( labelPlacementMethod == Height )
375  {
376  categoryElem.setAttribute( QStringLiteral( "labelPlacementMethod" ), QStringLiteral( "Height" ) );
377  }
378  else
379  {
380  categoryElem.setAttribute( QStringLiteral( "labelPlacementMethod" ), QStringLiteral( "XHeight" ) );
381  }
382 
383  if ( scaleByArea )
384  {
385  categoryElem.setAttribute( QStringLiteral( "scaleDependency" ), QStringLiteral( "Area" ) );
386  }
387  else
388  {
389  categoryElem.setAttribute( QStringLiteral( "scaleDependency" ), QStringLiteral( "Diameter" ) );
390  }
391 
392  // orientation (histogram)
393  switch ( diagramOrientation )
394  {
395  case Left:
396  categoryElem.setAttribute( QStringLiteral( "diagramOrientation" ), QStringLiteral( "Left" ) );
397  break;
398 
399  case Right:
400  categoryElem.setAttribute( QStringLiteral( "diagramOrientation" ), QStringLiteral( "Right" ) );
401  break;
402 
403  case Down:
404  categoryElem.setAttribute( QStringLiteral( "diagramOrientation" ), QStringLiteral( "Down" ) );
405  break;
406 
407  case Up:
408  categoryElem.setAttribute( QStringLiteral( "diagramOrientation" ), QStringLiteral( "Up" ) );
409  break;
410  }
411 
412  categoryElem.setAttribute( QStringLiteral( "barWidth" ), QString::number( barWidth ) );
413  categoryElem.setAttribute( QStringLiteral( "minimumSize" ), QString::number( minimumSize ) );
414  categoryElem.setAttribute( QStringLiteral( "rotationOffset" ), QString::number( rotationOffset ) );
415 
416  int nCats = std::min( categoryColors.size(), categoryAttributes.size() );
417  for ( int i = 0; i < nCats; ++i )
418  {
419  QDomElement attributeElem = doc.createElement( QStringLiteral( "attribute" ) );
420 
421  attributeElem.setAttribute( QStringLiteral( "field" ), categoryAttributes.at( i ) );
422  attributeElem.setAttribute( QStringLiteral( "color" ), categoryColors.at( i ).name() );
423  attributeElem.setAttribute( QStringLiteral( "label" ), categoryLabels.at( i ) );
424  categoryElem.appendChild( attributeElem );
425  }
426 
427  categoryElem.setAttribute( QStringLiteral( "showAxis" ), mShowAxis ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
428  QDomElement axisSymbolElem = doc.createElement( QStringLiteral( "axisSymbol" ) );
429  QDomElement symbolElem = QgsSymbolLayerUtils::saveSymbol( QString(), mAxisLineSymbol.get(), doc, context );
430  axisSymbolElem.appendChild( symbolElem );
431  categoryElem.appendChild( axisSymbolElem );
432 
433  if ( mPaintEffect && !QgsPaintEffectRegistry::isDefaultStack( mPaintEffect.get() ) )
434  mPaintEffect->saveProperties( doc, categoryElem );
435 
436  rendererElem.appendChild( categoryElem );
437 }
438 
440 {
441  if ( mDiagram.get() == d )
442  return;
443 
444  mDiagram.reset( d );
445 }
446 
448  : mDiagram( other.mDiagram ? other.mDiagram->clone() : nullptr )
449  , mShowAttributeLegend( other.mShowAttributeLegend )
450 {
451 }
452 
454 {
455  mDiagram.reset( other.mDiagram ? other.mDiagram->clone() : nullptr );
457  return *this;
458 }
459 
460 void QgsDiagramRenderer::renderDiagram( const QgsFeature &feature, QgsRenderContext &c, QPointF pos, const QgsPropertyCollection &properties ) const
461 {
462  if ( !mDiagram )
463  {
464  return;
465  }
466 
468  if ( !diagramSettings( feature, c, s ) )
469  {
470  return;
471  }
472 
473  if ( properties.hasActiveProperties() )
474  {
483  }
484 
485  QgsPaintEffect *effect = s.paintEffect();
486  std::unique_ptr< QgsEffectPainter > effectPainter;
487  if ( effect && effect->enabled() )
488  {
489  effectPainter = qgis::make_unique< QgsEffectPainter >( c, effect );
490  }
491 
492  mDiagram->renderDiagram( feature, c, s, pos );
493 }
494 
495 QSizeF QgsDiagramRenderer::sizeMapUnits( const QgsFeature &feature, const QgsRenderContext &c ) const
496 {
498  if ( !diagramSettings( feature, c, s ) )
499  {
500  return QSizeF();
501  }
502 
503  QSizeF size = diagramSize( feature, c );
504  if ( size.isValid() )
505  {
506  double width = c.convertToMapUnits( size.width(), s.sizeType, s.sizeScale );
507  size.rheight() *= width / size.width();
508  size.setWidth( width );
509  }
510  return size;
511 }
512 
513 QSet<QString> QgsDiagramRenderer::referencedFields( const QgsExpressionContext &context ) const
514 {
515  QSet< QString > referenced;
516 
517  if ( !mDiagram )
518  return referenced;
519 
520  const auto constDiagramAttributes = diagramAttributes();
521  for ( const QString &att : constDiagramAttributes )
522  {
523  QgsExpression *expression = mDiagram->getExpression( att, context );
524  const auto constReferencedColumns = expression->referencedColumns();
525  for ( const QString &field : constReferencedColumns )
526  {
527  referenced << field;
528  }
529  }
530  return referenced;
531 }
532 
533 void QgsDiagramRenderer::convertSizeToMapUnits( QSizeF &size, const QgsRenderContext &context ) const
534 {
535  if ( !size.isValid() )
536  {
537  return;
538  }
539 
540  double pixelToMap = context.scaleFactor() * context.mapToPixel().mapUnitsPerPixel();
541  size.rwidth() *= pixelToMap;
542  size.rheight() *= pixelToMap;
543 }
544 
545 int QgsDiagramRenderer::dpiPaintDevice( const QPainter *painter )
546 {
547  if ( painter )
548  {
549  QPaintDevice *device = painter->device();
550  if ( device )
551  {
552  return device->logicalDpiX();
553  }
554  }
555  return -1;
556 }
557 
558 void QgsDiagramRenderer::_readXml( const QDomElement &elem, const QgsReadWriteContext &context )
559 {
560  Q_UNUSED( context )
561  mDiagram.reset();
562  QString diagramType = elem.attribute( QStringLiteral( "diagramType" ) );
563  if ( diagramType == QLatin1String( "Pie" ) )
564  {
565  mDiagram.reset( new QgsPieDiagram() );
566  }
567  else if ( diagramType == QLatin1String( "Text" ) )
568  {
569  mDiagram.reset( new QgsTextDiagram() );
570  }
571  else if ( diagramType == QLatin1String( "Histogram" ) )
572  {
573  mDiagram.reset( new QgsHistogramDiagram() );
574  }
575  else if ( diagramType == QLatin1String( "Stacked" ) )
576  {
577  mDiagram.reset( new QgsStackedBarDiagram() );
578  }
579  else
580  {
581  // unknown diagram type -- default to histograms
582  mDiagram.reset( new QgsHistogramDiagram() );
583  }
584  mShowAttributeLegend = ( elem.attribute( QStringLiteral( "attributeLegend" ), QStringLiteral( "1" ) ) != QLatin1String( "0" ) );
585 }
586 
587 void QgsDiagramRenderer::_writeXml( QDomElement &rendererElem, QDomDocument &doc, const QgsReadWriteContext &context ) const
588 {
589  Q_UNUSED( doc )
590  Q_UNUSED( context )
591 
592  if ( mDiagram )
593  {
594  rendererElem.setAttribute( QStringLiteral( "diagramType" ), mDiagram->diagramName() );
595  }
596  rendererElem.setAttribute( QStringLiteral( "attributeLegend" ), mShowAttributeLegend );
597 }
598 
600 {
601  return new QgsSingleCategoryDiagramRenderer( *this );
602 }
603 
605 {
606  Q_UNUSED( c )
607  s = mSettings;
608  return true;
609 }
610 
612 {
613  return mDiagram->diagramSize( feature.attributes(), c, mSettings );
614 }
615 
616 QList<QgsDiagramSettings> QgsSingleCategoryDiagramRenderer::diagramSettings() const
617 {
618  QList<QgsDiagramSettings> settingsList;
619  settingsList.push_back( mSettings );
620  return settingsList;
621 }
622 
623 void QgsSingleCategoryDiagramRenderer::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
624 {
625  QDomElement categoryElem = elem.firstChildElement( QStringLiteral( "DiagramCategory" ) );
626  if ( categoryElem.isNull() )
627  {
628  return;
629  }
630 
631  mSettings.readXml( categoryElem, context );
632  _readXml( elem, context );
633 }
634 
635 void QgsSingleCategoryDiagramRenderer::writeXml( QDomElement &layerElem, QDomDocument &doc, const QgsReadWriteContext &context ) const
636 {
637  QDomElement rendererElem = doc.createElement( QStringLiteral( "SingleCategoryDiagramRenderer" ) );
638  mSettings.writeXml( rendererElem, doc, context );
639  _writeXml( rendererElem, doc, context );
640  layerElem.appendChild( rendererElem );
641 }
642 
643 
645 {
646  mInterpolationSettings.classificationAttributeIsExpression = false;
647 }
648 
650  : QgsDiagramRenderer( other )
651  , mSettings( other.mSettings )
652  , mInterpolationSettings( other.mInterpolationSettings )
653  , mDataDefinedSizeLegend( other.mDataDefinedSizeLegend ? new QgsDataDefinedSizeLegend( *other.mDataDefinedSizeLegend ) : nullptr )
654 {
655 }
656 
658 {
659  delete mDataDefinedSizeLegend;
660 }
661 
663 {
664  return new QgsLinearlyInterpolatedDiagramRenderer( *this );
665 }
666 
668 {
669  QList<QgsDiagramSettings> settingsList;
670  settingsList.push_back( mSettings );
671  return settingsList;
672 }
673 
675 {
676  s = mSettings;
677  s.size = diagramSize( feature, c );
678  return true;
679 }
680 
682 {
683  return mSettings.categoryAttributes;
684 }
685 
687 {
688  QSet< QString > referenced = QgsDiagramRenderer::referencedFields( context );
689  if ( mInterpolationSettings.classificationAttributeIsExpression )
690  {
691  QgsExpression *expression = mDiagram->getExpression( mInterpolationSettings.classificationAttributeExpression, context );
692  const auto constReferencedColumns = expression->referencedColumns();
693  for ( const QString &field : constReferencedColumns )
694  {
695  referenced << field;
696  }
697  }
698  else
699  {
700  referenced << mInterpolationSettings.classificationField;
701  }
702  return referenced;
703 }
704 
706 {
707  return mDiagram->diagramSize( feature, c, mSettings, mInterpolationSettings );
708 }
709 
710 void QgsLinearlyInterpolatedDiagramRenderer::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
711 {
712  mInterpolationSettings.lowerValue = elem.attribute( QStringLiteral( "lowerValue" ) ).toDouble();
713  mInterpolationSettings.upperValue = elem.attribute( QStringLiteral( "upperValue" ) ).toDouble();
714  mInterpolationSettings.lowerSize.setWidth( elem.attribute( QStringLiteral( "lowerWidth" ) ).toDouble() );
715  mInterpolationSettings.lowerSize.setHeight( elem.attribute( QStringLiteral( "lowerHeight" ) ).toDouble() );
716  mInterpolationSettings.upperSize.setWidth( elem.attribute( QStringLiteral( "upperWidth" ) ).toDouble() );
717  mInterpolationSettings.upperSize.setHeight( elem.attribute( QStringLiteral( "upperHeight" ) ).toDouble() );
718  mInterpolationSettings.classificationAttributeIsExpression = elem.hasAttribute( QStringLiteral( "classificationAttributeExpression" ) );
719  if ( mInterpolationSettings.classificationAttributeIsExpression )
720  {
721  mInterpolationSettings.classificationAttributeExpression = elem.attribute( QStringLiteral( "classificationAttributeExpression" ) );
722  }
723  else
724  {
725  mInterpolationSettings.classificationField = elem.attribute( QStringLiteral( "classificationField" ) );
726  }
727  QDomElement settingsElem = elem.firstChildElement( QStringLiteral( "DiagramCategory" ) );
728  if ( !settingsElem.isNull() )
729  {
730  mSettings.readXml( settingsElem );
731  }
732 
733  delete mDataDefinedSizeLegend;
734 
735  QDomElement ddsLegendSizeElem = elem.firstChildElement( QStringLiteral( "data-defined-size-legend" ) );
736  if ( !ddsLegendSizeElem.isNull() )
737  {
738  mDataDefinedSizeLegend = QgsDataDefinedSizeLegend::readXml( ddsLegendSizeElem, context );
739  }
740  else
741  {
742  // pre-3.0 projects
743  if ( elem.attribute( QStringLiteral( "sizeLegend" ), QStringLiteral( "0" ) ) != QLatin1String( "0" ) )
744  {
745  mDataDefinedSizeLegend = new QgsDataDefinedSizeLegend();
746  QDomElement sizeLegendSymbolElem = elem.firstChildElement( QStringLiteral( "symbol" ) );
747  if ( !sizeLegendSymbolElem.isNull() && sizeLegendSymbolElem.attribute( QStringLiteral( "name" ) ) == QLatin1String( "sizeSymbol" ) )
748  {
749  mDataDefinedSizeLegend->setSymbol( QgsSymbolLayerUtils::loadSymbol<QgsMarkerSymbol>( sizeLegendSymbolElem, context ) );
750  }
751  }
752  else
753  {
754  mDataDefinedSizeLegend = nullptr;
755  }
756  }
757 
758  _readXml( elem, context );
759 }
760 
761 void QgsLinearlyInterpolatedDiagramRenderer::writeXml( QDomElement &layerElem, QDomDocument &doc, const QgsReadWriteContext &context ) const
762 {
763  QDomElement rendererElem = doc.createElement( QStringLiteral( "LinearlyInterpolatedDiagramRenderer" ) );
764  rendererElem.setAttribute( QStringLiteral( "lowerValue" ), QString::number( mInterpolationSettings.lowerValue ) );
765  rendererElem.setAttribute( QStringLiteral( "upperValue" ), QString::number( mInterpolationSettings.upperValue ) );
766  rendererElem.setAttribute( QStringLiteral( "lowerWidth" ), QString::number( mInterpolationSettings.lowerSize.width() ) );
767  rendererElem.setAttribute( QStringLiteral( "lowerHeight" ), QString::number( mInterpolationSettings.lowerSize.height() ) );
768  rendererElem.setAttribute( QStringLiteral( "upperWidth" ), QString::number( mInterpolationSettings.upperSize.width() ) );
769  rendererElem.setAttribute( QStringLiteral( "upperHeight" ), QString::number( mInterpolationSettings.upperSize.height() ) );
770  if ( mInterpolationSettings.classificationAttributeIsExpression )
771  {
772  rendererElem.setAttribute( QStringLiteral( "classificationAttributeExpression" ), mInterpolationSettings.classificationAttributeExpression );
773  }
774  else
775  {
776  rendererElem.setAttribute( QStringLiteral( "classificationField" ), mInterpolationSettings.classificationField );
777  }
778  mSettings.writeXml( rendererElem, doc );
779 
780  if ( mDataDefinedSizeLegend )
781  {
782  QDomElement ddsLegendElem = doc.createElement( QStringLiteral( "data-defined-size-legend" ) );
783  mDataDefinedSizeLegend->writeXml( ddsLegendElem, context );
784  rendererElem.appendChild( ddsLegendElem );
785  }
786 
787  _writeXml( rendererElem, doc, context );
788  layerElem.appendChild( rendererElem );
789 }
790 
791 QList< QgsLayerTreeModelLegendNode * > QgsDiagramSettings::legendItems( QgsLayerTreeLayer *nodeLayer ) const
792 {
793  QList< QgsLayerTreeModelLegendNode * > list;
794  list.reserve( categoryLabels.size() );
795  for ( int i = 0; i < categoryLabels.size(); ++i )
796  {
797  QPixmap pix( 16, 16 );
798  pix.fill( categoryColors[i] );
799  list << new QgsSimpleLegendNode( nodeLayer, categoryLabels[i], QIcon( pix ), nullptr, QStringLiteral( "diagram_%1" ).arg( QString::number( i ) ) );
800  }
801  return list;
802 }
803 
805 {
806  return mAxisLineSymbol.get();
807 }
808 
810 {
811  if ( axisLineSymbol != mAxisLineSymbol.get() )
812  mAxisLineSymbol.reset( axisLineSymbol );
813 }
814 
816 {
817  return mShowAxis;
818 }
819 
820 void QgsDiagramSettings::setShowAxis( bool showAxis )
821 {
822  mShowAxis = showAxis;
823 }
824 
826 {
827  return mPaintEffect.get();
828 }
829 
831 {
832  if ( effect != mPaintEffect.get() )
833  mPaintEffect.reset( effect );
834 }
835 
837  : mAxisLineSymbol( qgis::make_unique< QgsLineSymbol >() )
838 {
839 }
840 
842 
844  : enabled( other.enabled )
845  , font( other.font )
846  , categoryColors( other.categoryColors )
848  , categoryLabels( other.categoryLabels )
849  , size( other.size )
850  , sizeType( other.sizeType )
851  , sizeScale( other.sizeScale )
852  , lineSizeUnit( other.lineSizeUnit )
853  , lineSizeScale( other.lineSizeScale )
855  , penColor( other.penColor )
856  , penWidth( other.penWidth )
859  , barWidth( other.barWidth )
860  , opacity( other.opacity )
861  , scaleByArea( other.scaleByArea )
862  , rotationOffset( other.rotationOffset )
864  , maximumScale( other.maximumScale )
865  , minimumScale( other.minimumScale )
866  , minimumSize( other.minimumSize )
867  , mSpacing( other.mSpacing )
868  , mSpacingUnit( other.mSpacingUnit )
869  , mSpacingMapUnitScale( other.mSpacingMapUnitScale )
870  , mDirection( other.mDirection )
871  , mShowAxis( other.mShowAxis )
872  , mAxisLineSymbol( other.mAxisLineSymbol ? other.mAxisLineSymbol->clone() : nullptr )
873  , mPaintEffect( other.mPaintEffect ? other.mPaintEffect->clone() : nullptr )
874 {
875 
876 }
877 
879 {
880  enabled = other.enabled;
881  font = other.font;
885  size = other.size;
886  sizeType = other.sizeType;
887  sizeScale = other.sizeScale;
888  lineSizeUnit = other.lineSizeUnit;
891  penColor = other.penColor;
892  penWidth = other.penWidth;
895  barWidth = other.barWidth;
896  opacity = other.opacity;
897  scaleByArea = other.scaleByArea;
900  maximumScale = other.maximumScale;
901  minimumScale = other.minimumScale;
902  minimumSize = other.minimumSize;
903  mSpacing = other.mSpacing;
904  mSpacingUnit = other.mSpacingUnit;
905  mSpacingMapUnitScale = other.mSpacingMapUnitScale;
906  mDirection = other.mDirection;
907  mAxisLineSymbol.reset( other.mAxisLineSymbol ? other.mAxisLineSymbol->clone() : nullptr );
908  mShowAxis = other.mShowAxis;
909  mPaintEffect.reset( other.mPaintEffect ? other.mPaintEffect->clone() : nullptr );
910  return *this;
911 }
912 
914 {
915  return mDirection;
916 }
917 
919 {
920  mDirection = direction;
921 }
922 
923 QList< QgsLayerTreeModelLegendNode * > QgsDiagramRenderer::legendItems( QgsLayerTreeLayer * ) const
924 {
925  return QList< QgsLayerTreeModelLegendNode * >();
926 }
927 
928 QList< QgsLayerTreeModelLegendNode * > QgsSingleCategoryDiagramRenderer::legendItems( QgsLayerTreeLayer *nodeLayer ) const
929 {
930  QList< QgsLayerTreeModelLegendNode * > nodes;
931  if ( mShowAttributeLegend )
932  nodes = mSettings.legendItems( nodeLayer );
933 
934  return nodes;
935 }
936 
937 QList< QgsLayerTreeModelLegendNode * > QgsLinearlyInterpolatedDiagramRenderer::legendItems( QgsLayerTreeLayer *nodeLayer ) const
938 {
939  QList< QgsLayerTreeModelLegendNode * > nodes;
940  if ( mShowAttributeLegend )
941  nodes = mSettings.legendItems( nodeLayer );
942 
943  if ( mDataDefinedSizeLegend && mDiagram )
944  {
945  // add size legend
946  QgsMarkerSymbol *legendSymbol = mDataDefinedSizeLegend->symbol() ? mDataDefinedSizeLegend->symbol()->clone() : QgsMarkerSymbol::createSimple( QgsStringMap() );
947  legendSymbol->setSizeUnit( mSettings.sizeType );
948  legendSymbol->setSizeMapUnitScale( mSettings.sizeScale );
949 
950  QgsDataDefinedSizeLegend ddSizeLegend( *mDataDefinedSizeLegend );
951  ddSizeLegend.setSymbol( legendSymbol ); // transfers ownership
952 
953  QList<QgsDataDefinedSizeLegend::SizeClass> sizeClasses;
954  if ( ddSizeLegend.classes().isEmpty() )
955  {
956  // automatic class creation if the classes are not defined manually
957  const auto prettyBreaks { QgsSymbolLayerUtils::prettyBreaks( mInterpolationSettings.lowerValue, mInterpolationSettings.upperValue, 4 ) };
958  for ( double v : prettyBreaks )
959  {
960  double size = mDiagram->legendSize( v, mSettings, mInterpolationSettings );
961  sizeClasses << QgsDataDefinedSizeLegend::SizeClass( size, QString::number( v ) );
962  }
963  }
964  else
965  {
966  // manual classes need to get size scaled because the QgsSizeScaleTransformer is not used in diagrams :-(
967  const auto constClasses = ddSizeLegend.classes();
968  for ( const QgsDataDefinedSizeLegend::SizeClass &sc : constClasses )
969  {
970  double size = mDiagram->legendSize( sc.size, mSettings, mInterpolationSettings );
971  sizeClasses << QgsDataDefinedSizeLegend::SizeClass( size, sc.label );
972  }
973  }
974  ddSizeLegend.setClasses( sizeClasses );
975 
976  const auto constLegendSymbolList = ddSizeLegend.legendSymbolList();
977  for ( const QgsLegendSymbolItem &si : constLegendSymbolList )
978  {
979  if ( si.dataDefinedSizeLegendSettings() )
980  nodes << new QgsDataDefinedSizeLegendNode( nodeLayer, *si.dataDefinedSizeLegendSettings() );
981  else
982  nodes << new QgsSymbolLegendNode( nodeLayer, si );
983  }
984  }
985 
986  return nodes;
987 }
988 
990 {
991  delete mDataDefinedSizeLegend;
992  mDataDefinedSizeLegend = settings;
993 }
994 
996 {
997  return mDataDefinedSizeLegend;
998 }
void _writeXml(QDomElement &rendererElem, QDomDocument &doc, const QgsReadWriteContext &context) const
Writes internal QgsDiagramRenderer diagram state to a DOM element.
Class for parsing and evaluation of expressions (formerly called "search strings").
static int dpiPaintDevice(const QPainter *)
Returns the paint device dpi (or -1 in case of error.
The class is used as a container of context for various read/write operations on other objects...
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...
QgsUnitTypes::RenderUnit lineSizeUnit
Line unit index.
double minimumSize
Scale diagrams smaller than mMinimumSize to mMinimumSize.
void setCoordinateTransform(const QgsCoordinateTransform &transform)
Sets the coordinate transform associated with the layer.
double convertToMapUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale()) const
Converts a size from the specified units to map units.
Distance to diagram from feature.
void writeXml(QDomElement &layerElem, QDomDocument &doc, const QgsReadWriteContext &context) const override
Writes diagram state to a DOM element.
QSet< QString > referencedFields(const QgsExpressionContext &context=QgsExpressionContext()) const override
Returns the set of any fields required for diagram rendering.
void setPaintEffect(QgsPaintEffect *effect)
Sets the paint effect to use while rendering diagrams.
QgsSingleCategoryDiagramRenderer * clone() const override
Returns new instance that is equivalent to this one.
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...
void setShowAxis(bool showAxis)
Sets whether the diagram axis should be shown.
void setAxisLineSymbol(QgsLineSymbol *symbol)
Sets the line symbol to use for rendering axis in diagrams.
Definition of one class for the legend.
A stacked bar chart diagram.
virtual bool readXml(const QDomElement &collectionElem, const QgsPropertiesDefinition &definitions)
Reads property collection state from an XML element.
double opacity
Opacity, from 0 (transparent) to 1.0 (opaque)
Renders the diagrams for all features with the same settings.
QList< QString > categoryAttributes
QgsDiagramRenderer()=default
Constructor for QgsDiagramRenderer.
virtual QList< QgsLayerTreeModelLegendNode *> legendItems(QgsLayerTreeLayer *nodeLayer) const
Returns list of legend nodes for the diagram.
Produces legend node with a marker symbol.
virtual QList< QString > diagramAttributes() const =0
Returns attribute indices needed for diagram rendering.
static bool isDefaultStack(QgsPaintEffect *effect)
Tests whether a paint effect matches the default effects stack.
void writeXml(QDomElement &layerElem, QDomDocument &doc) const
Writes the diagram settings to a DOM element.
Base class for visual effects which can be applied to QPicture drawings.
void setSizeMapUnitScale(const QgsMapUnitScale &scale)
Sets the size map unit scale for the whole symbol (including all symbol layers).
Definition: qgssymbol.cpp:1537
Implementation of legend node interface for displaying preview of vector symbols and their labels and...
Angle offset for pie diagram.
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
Color with alpha channel.
Definition: qgsproperty.h:64
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
QSet< QString > referencedFields(const QgsExpressionContext &context=QgsExpressionContext()) const
Returns the set of any fields referenced by the layer&#39;s diagrams.
QSet< QString > referencedColumns() const
Gets list of columns referenced by the expression.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
Positive double value (including 0)
Definition: qgsproperty.h:58
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...
QgsLegendSymbolList legendSymbolList() const
Generates legend symbol items according to the configuration.
Whether diagram features act as obstacles for other diagrams/labels.
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.
bool mShowAttributeLegend
Whether to show an attribute legend for the diagrams.
QMap< QString, QString > QgsStringMap
Definition: qgis.h:694
double rotationOffset
Rotation offset, in degrees clockwise from horizontal.
Rotation (value between 0-360 degrees)
Definition: qgsproperty.h:60
A marker symbol type, for rendering Point and MultiPoint geometries.
Definition: qgssymbol.h:895
QgsDiagramSettings()
Constructor for QgsDiagramSettings.
void setDiagram(QgsDiagram *d)
A line symbol type, for rendering LineString and MultiLineString geometries.
Definition: qgssymbol.h:1095
QList< QgsDiagramSettings > diagramSettings() const override
Returns list with all diagram settings in the renderer.
static QgsPaintEffectRegistry * paintEffectRegistry()
Returns the application&#39;s paint effect registry, used for managing paint effects. ...
static QString encodeColor(const QColor &color)
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
Direction direction() const
Returns the chart&#39;s angular direction.
void readXml(const QDomElement &elem, const QgsReadWriteContext &context=QgsReadWriteContext())
Reads diagram settings from XML.
bool prepare(const QgsExpressionContext &context=QgsExpressionContext()) const override
Prepares the collection against a specified expression context.
DiagramOrientation diagramOrientation
Z-index for diagram ordering.
double maximumScale
The maximum map scale (i.e.
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...
Evaluates and returns the diagram settings relating to a diagram for a specific feature.
double minimumScale
The minimum map scale (i.e.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
bool prepare(const QgsExpressionContext &context=QgsExpressionContext()) const
Prepares the diagrams for a specified expression context.
void readXml(const QDomElement &elem)
Reads the diagram settings from a DOM element.
void convertSizeToMapUnits(QSizeF &size, const QgsRenderContext &context) const
Converts size from mm to map units.
QgsDiagramLayerSettings()
Constructor for QgsDiagramLayerSettings.
QgsMapUnitScale sizeScale
Diagram size unit scale.
void readXml(const QDomElement &elem, const QgsReadWriteContext &context) override
Reads diagram state from a DOM element.
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.
Y-coordinate data defined diagram position.
bool enabled() const
Returns whether the effect is enabled.
Implementation of legend node interface for displaying arbitrary label with icon. ...
void clear() override
Removes all properties from the collection.
static Q_INVOKABLE QgsUnitTypes::RenderUnit decodeRenderUnit(const QString &string, bool *ok=nullptr)
Decodes a render unit from a string.
double mapUnitsPerPixel() const
Returns current map units per pixel.
Whether to show the diagram.
void writeXml(QDomElement &rendererElem, QDomDocument &doc, const QgsReadWriteContext &context=QgsReadWriteContext()) const
Writes diagram settings to XML.
Double value (including negative values)
Definition: qgsproperty.h:57
QList< QgsLayerTreeModelLegendNode *> legendItems(QgsLayerTreeLayer *nodeLayer) const
Returns list of legend nodes for the diagram.
std::unique_ptr< QgsDiagram > mDiagram
Reference to the object that does the real diagram rendering.
void setSizeUnit(QgsUnitTypes::RenderUnit unit)
Sets the size units for the whole symbol (including all symbol layers).
Definition: qgssymbol.cpp:1499
void writeXml(QDomElement &elem, const QgsReadWriteContext &context) const
Writes configuration to the given XML element.
void writeXml(QDomElement &layerElem, QDomDocument &doc, const QgsReadWriteContext &context) const override
Writes diagram state to a DOM element.
void setDirection(Direction direction)
Sets the chart&#39;s angular direction.
Definition for a property.
Definition: qgsproperty.h:46
Base class for all diagram types.
Definition: qgsdiagram.h:38
QgsLinearlyInterpolatedDiagramRenderer * clone() const override
Returns new instance that is equivalent to this one.
QMap< int, QgsPropertyDefinition > QgsPropertiesDefinition
Definition of available properties.
QgsUnitTypes::RenderUnit sizeType
Diagram size unit.
QgsLineSymbol * axisLineSymbol() const
Returns the line symbol to use for rendering axis in diagrams.
void setRenderer(QgsDiagramRenderer *diagramRenderer)
Sets the diagram renderer associated with the layer.
static Q_INVOKABLE QString encodeUnit(QgsUnitTypes::DistanceUnit unit)
Encodes a distance unit to a string.
QgsExpressionContext & expressionContext()
Gets the expression context.
Stores the settings for rendering of all diagrams for a layer.
Direction
Angular directions.
static QList< double > prettyBreaks(double minimum, double maximum, int classes)
Computes a sequence of about &#39;classes&#39; equally spaced round values which cover the range of values fr...
QSet< QString > referencedFields(const QgsExpressionContext &context=QgsExpressionContext()) const override
Returns the set of any fields referenced by the active properties from the collection.
QgsDiagramSettings & operator=(const QgsDiagramSettings &other)
The class stores information about one class/rule of a vector layer renderer in a unified way that ca...
Contains information about the context of a rendering operation.
X-coordinate data defined diagram position.
QgsDataDefinedSizeLegend * dataDefinedSizeLegend() const
Returns configuration of appearance of legend.
virtual QSet< QString > referencedFields(const QgsExpressionContext &context=QgsExpressionContext()) const
Returns the set of any fields required for diagram rendering.
const QgsMapToPixel & mapToPixel() const
Returns the context&#39;s map to pixel transform, which transforms between map coordinates and device coo...
QList< QgsLayerTreeModelLegendNode *> legendItems(QgsLayerTreeLayer *nodeLayer) const override
Returns list of legend nodes for the diagram.
virtual QSizeF diagramSize(const QgsFeature &features, const QgsRenderContext &c) const =0
Returns size of the diagram (in painter units) or an invalid size in case of error.
Diagram priority (between 0 and 10)
void setSymbol(QgsMarkerSymbol *symbol SIP_TRANSFER)
Sets marker symbol that will be used to draw markers in legend.
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the diagram property definitions.
QList< QString > diagramAttributes() const override
Returns attribute indices needed for diagram rendering.
QgsDiagramRenderer & operator=(const QgsDiagramRenderer &other)
virtual QList< QgsDiagramSettings > diagramSettings() const =0
Returns list with all diagram settings in the renderer.
QString classificationField
Name of the field for classification.
Class for doing transforms between two map coordinate systems.
A grouped map of multiple QgsProperty objects, each referenced by a integer key value.
QList< QString > categoryLabels
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
Whether the diagram should always be shown, even if it overlaps other diagrams/labels.
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...
bool hasActiveProperties() const override
Returns true if the collection has any active properties, or false if all properties within the colle...
static QgsMarkerSymbol * createSimple(const QgsStringMap &properties)
Create a marker symbol with one symbol layer: SimpleMarker with specified properties.
Definition: qgssymbol.cpp:1288
static QDomElement toXmlElement(const QFont &font, QDomDocument &document, const QString &elementName)
Returns a DOM element containing the properties of the font.
LinePlacementFlag
Line placement flags for controlling line based placements.
QgsMapUnitScale lineSizeScale
Line unit scale.
QgsPaintEffect * createEffect(const QString &name, const QgsStringMap &properties=QgsStringMap()) const
Creates a new paint effect given the effect name and properties map.
void readXml(const QDomElement &elem, const QgsReadWriteContext &context) override
Reads diagram state from a DOM element.
QList< QgsLayerTreeModelLegendNode *> legendItems(QgsLayerTreeLayer *nodeLayer) const override
Returns list of legend nodes for the diagram.
double scaleFactor() const
Returns the scaling factor for the render to convert painter units to physical sizes.
Object that keeps configuration of appearance of marker symbol&#39;s data-defined size in legend...
virtual bool writeXml(QDomElement &collectionElem, const QgsPropertiesDefinition &definitions) const
Writes the current state of the property collection into an XML element.
void setDataDefinedSizeLegend(QgsDataDefinedSizeLegend *settings)
Configures appearance of legend.
QList< QColor > categoryColors
void setOriginalValueVariable(const QVariant &value)
Sets the original value variable value for the context.
QgsPaintEffect * paintEffect() const
Returns the paint effect to use while rendering diagrams.
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...
QList< QgsDiagramSettings > diagramSettings() const override
Returns list with all diagram settings in the renderer.
QgsDiagramLayerSettings & operator=(const QgsDiagramLayerSettings &rh)
void _readXml(const QDomElement &elem, const QgsReadWriteContext &context)
Reads internal QgsDiagramRenderer state from a DOM element.
Stores the settings for rendering a single diagram.
QgsAttributes attributes
Definition: qgsfeature.h:65
bool showAxis() const
Returns true if the diagram axis should be shown.
QgsMarkerSymbol * clone() const override
Returns a deep copy of this symbol.
Definition: qgssymbol.cpp:1766
LabelPlacementMethod labelPlacementMethod
virtual QgsDiagramRenderer * clone() const =0
Returns new instance that is equivalent to this one.
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...
Layer tree node points to a map layer.
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.