QGIS API Documentation  2.2.0-Valmiera
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
qgsdiagramrendererv2.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsdiagramrendererv2.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 "qgsdiagramrendererv2.h"
16 #include "qgsvectorlayer.h"
17 #include "diagram/qgstextdiagram.h"
18 #include "diagram/qgspiediagram.h"
19 #include "diagram/qgshistogramdiagram.h"
20 #include "qgsrendercontext.h"
21 #include <QDomElement>
22 #include <QPainter>
23 
24 
25 void QgsDiagramLayerSettings::readXML( const QDomElement& elem, const QgsVectorLayer* layer )
26 {
27  Q_UNUSED( layer )
28 
29  placement = ( Placement )elem.attribute( "placement" ).toInt();
30  placementFlags = ( LinePlacementFlags )elem.attribute( "linePlacementFlags" ).toInt();
31  priority = elem.attribute( "priority" ).toInt();
32  obstacle = elem.attribute( "obstacle" ).toInt();
33  dist = elem.attribute( "dist" ).toDouble();
34  xPosColumn = elem.attribute( "xPosColumn" ).toInt();
35  yPosColumn = elem.attribute( "yPosColumn" ).toInt();
36 }
37 
38 void QgsDiagramLayerSettings::writeXML( QDomElement& layerElem, QDomDocument& doc, const QgsVectorLayer* layer ) const
39 {
40  Q_UNUSED( layer )
41 
42  QDomElement diagramLayerElem = doc.createElement( "DiagramLayerSettings" );
43  diagramLayerElem.setAttribute( "placement", placement );
44  diagramLayerElem.setAttribute( "linePlacementFlags", placementFlags );
45  diagramLayerElem.setAttribute( "priority", priority );
46  diagramLayerElem.setAttribute( "obstacle", obstacle );
47  diagramLayerElem.setAttribute( "dist", QString::number( dist ) );
48  diagramLayerElem.setAttribute( "xPosColumn", xPosColumn );
49  diagramLayerElem.setAttribute( "yPosColumn", yPosColumn );
50  layerElem.appendChild( diagramLayerElem );
51 }
52 
53 void QgsDiagramSettings::readXML( const QDomElement& elem, const QgsVectorLayer* layer )
54 {
55  Q_UNUSED( layer );
56 
57  font.fromString( elem.attribute( "font" ) );
58  backgroundColor.setNamedColor( elem.attribute( "backgroundColor" ) );
59  backgroundColor.setAlpha( elem.attribute( "backgroundAlpha" ).toInt() );
60  size.setWidth( elem.attribute( "width" ).toDouble() );
61  size.setHeight( elem.attribute( "height" ).toDouble() );
62  transparency = elem.attribute( "transparency", "0" ).toInt();
63  penColor.setNamedColor( elem.attribute( "penColor" ) );
64  int penAlpha = elem.attribute( "penAlpha", "255" ).toInt();
65  penColor.setAlpha( penAlpha );
66  penWidth = elem.attribute( "penWidth" ).toDouble();
67 
68  minScaleDenominator = elem.attribute( "minScaleDenominator", "-1" ).toDouble();
69  maxScaleDenominator = elem.attribute( "maxScaleDenominator", "-1" ).toDouble();
70 
71  //mm vs map units
72  if ( elem.attribute( "sizeType" ) == "MM" )
73  {
74  sizeType = MM;
75  }
76  else
77  {
79  }
80 
81  //label placement method
82  if ( elem.attribute( "labelPlacementMethod" ) == "Height" )
83  {
85  }
86  else
87  {
89  }
90 
91  // orientation
92  if ( elem.attribute( "diagramOrientation" ) == "Left" )
93  {
95  }
96  else if ( elem.attribute( "diagramOrientation" ) == "Right" )
97  {
99  }
100  else if ( elem.attribute( "diagramOrientation" ) == "Down" )
101  {
103  }
104  else
105  {
107  }
108 
109  // scale dependency
110  if ( elem.attribute( "scaleDependency" ) == "Diameter" )
111  {
112  scaleByArea = false;
113  }
114  else
115  {
116  scaleByArea = true;
117  }
118 
119  barWidth = elem.attribute( "barWidth" ).toDouble();
120 
121  angleOffset = elem.attribute( "angleOffset" ).toInt();
122 
123  minimumSize = elem.attribute( "minimumSize" ).toDouble();
124 
125  //colors
126  categoryColors.clear();
127  QDomNodeList attributes = elem.elementsByTagName( "attribute" );
128 
129  if ( attributes.length() > 0 )
130  {
131  for ( uint i = 0; i < attributes.length(); i++ )
132  {
133  QDomElement attrElem = attributes.at( i ).toElement();
134  QColor newColor( attrElem.attribute( "color" ) );
135  newColor.setAlpha( 255 - transparency );
136  categoryColors.append( newColor );
137  categoryAttributes.append( attrElem.attribute( "field" ) );
138  }
139  }
140  else
141  {
142  // Restore old format attributes and colors
143 
144  QStringList colorList = elem.attribute( "colors" ).split( "/" );
145  QStringList::const_iterator colorIt = colorList.constBegin();
146  for ( ; colorIt != colorList.constEnd(); ++colorIt )
147  {
148  QColor newColor( *colorIt );
149  newColor.setAlpha( 255 - transparency );
150  categoryColors.append( QColor( newColor ) );
151  }
152 
153  //attribute indices
154  categoryAttributes.clear();
155  QStringList catList = elem.attribute( "categories" ).split( "/" );
156  QStringList::const_iterator catIt = catList.constBegin();
157  for ( ; catIt != catList.constEnd(); ++catIt )
158  {
159  categoryAttributes.append( *catIt );
160  }
161  }
162 }
163 
164 void QgsDiagramSettings::writeXML( QDomElement& rendererElem, QDomDocument& doc, const QgsVectorLayer* layer ) const
165 {
166  Q_UNUSED( layer );
167 
168  QDomElement categoryElem = doc.createElement( "DiagramCategory" );
169  categoryElem.setAttribute( "font", font.toString() );
170  categoryElem.setAttribute( "backgroundColor", backgroundColor.name() );
171  categoryElem.setAttribute( "backgroundAlpha", backgroundColor.alpha() );
172  categoryElem.setAttribute( "width", QString::number( size.width() ) );
173  categoryElem.setAttribute( "height", QString::number( size.height() ) );
174  categoryElem.setAttribute( "penColor", penColor.name() );
175  categoryElem.setAttribute( "penAlpha", penColor.alpha() );
176  categoryElem.setAttribute( "penWidth", QString::number( penWidth ) );
177  categoryElem.setAttribute( "minScaleDenominator", QString::number( minScaleDenominator ) );
178  categoryElem.setAttribute( "maxScaleDenominator", QString::number( maxScaleDenominator ) );
179  categoryElem.setAttribute( "transparency", QString::number( transparency ) );
180 
181  // site type (mm vs. map units)
182  if ( sizeType == MM )
183  {
184  categoryElem.setAttribute( "sizeType", "MM" );
185  }
186  else
187  {
188  categoryElem.setAttribute( "sizeType", "MapUnits" );
189  }
190 
191  // label placement method (text diagram)
192  if ( labelPlacementMethod == Height )
193  {
194  categoryElem.setAttribute( "labelPlacementMethod", "Height" );
195  }
196  else
197  {
198  categoryElem.setAttribute( "labelPlacementMethod", "XHeight" );
199  }
200 
201  if ( scaleByArea )
202  {
203  categoryElem.setAttribute( "scaleDependency", "Area" );
204  }
205  else
206  {
207  categoryElem.setAttribute( "scaleDependency", "Diameter" );
208  }
209 
210  // orientation (histogram)
211  switch ( diagramOrientation )
212  {
213  case Left:
214  categoryElem.setAttribute( "diagramOrientation", "Left" );
215  break;
216 
217  case Right:
218  categoryElem.setAttribute( "diagramOrientation", "Right" );
219  break;
220 
221  case Down:
222  categoryElem.setAttribute( "diagramOrientation", "Down" );
223  break;
224 
225  case Up:
226  categoryElem.setAttribute( "diagramOrientation", "Up" );
227  break;
228 
229  default:
230  categoryElem.setAttribute( "diagramOrientation", "Up" );
231  break;
232  }
233 
234  categoryElem.setAttribute( "barWidth", QString::number( barWidth ) );
235  categoryElem.setAttribute( "minimumSize", QString::number( minimumSize ) );
236  categoryElem.setAttribute( "angleOffset", QString::number( angleOffset ) );
237 
238  QString colors;
239  int nCats = qMin( categoryColors.size(), categoryAttributes.size() );
240  for ( int i = 0; i < nCats; ++i )
241  {
242  QDomElement attributeElem = doc.createElement( "attribute" );
243 
244  attributeElem.setAttribute( "field", categoryAttributes.at( i ) );
245  attributeElem.setAttribute( "color", categoryColors.at( i ).name() );
246  categoryElem.appendChild( attributeElem );
247  }
248 
249  rendererElem.appendChild( categoryElem );
250 }
251 
253 {
254 }
255 
257 {
258  delete mDiagram;
259 }
260 
261 void QgsDiagramRendererV2::setDiagram( QgsDiagram* d )
262 {
263  delete mDiagram;
264  mDiagram = d;
265 }
266 
267 void QgsDiagramRendererV2::renderDiagram( const QgsFeature& feature, QgsRenderContext& c, const QPointF& pos )
268 {
269  if ( !mDiagram )
270  {
271  return;
272  }
273 
275  if ( !diagramSettings( feature, c, s ) )
276  {
277  return;
278  }
279 
280  mDiagram->renderDiagram( feature, c, s, pos );
281 }
282 
284 {
286  if ( !diagramSettings( feature, c, s ) )
287  {
288  return QSizeF();
289  }
290 
291  QSizeF size = diagramSize( feature, c );
292  if ( s.sizeType == QgsDiagramSettings::MM )
293  {
294  convertSizeToMapUnits( size, c );
295  }
296  return size;
297 }
298 
300 {
301  if ( !size.isValid() )
302  {
303  return;
304  }
305 
306  double pixelToMap = context.scaleFactor() * context.mapToPixel().mapUnitsPerPixel();
307  size.rwidth() *= pixelToMap;
308  size.rheight() *= pixelToMap;
309 }
310 
311 int QgsDiagramRendererV2::dpiPaintDevice( const QPainter* painter )
312 {
313  if ( painter )
314  {
315  QPaintDevice* device = painter->device();
316  if ( device )
317  {
318  return device->logicalDpiX();
319  }
320  }
321  return -1;
322 }
323 
324 void QgsDiagramRendererV2::_readXML( const QDomElement& elem, const QgsVectorLayer* layer )
325 {
326  Q_UNUSED( layer )
327 
328  delete mDiagram;
329  QString diagramType = elem.attribute( "diagramType" );
330  if ( diagramType == "Pie" )
331  {
332  mDiagram = new QgsPieDiagram();
333  }
334  else if ( diagramType == "Text" )
335  {
336  mDiagram = new QgsTextDiagram();
337  }
338  else if ( diagramType == "Histogram" )
339  {
340  mDiagram = new QgsHistogramDiagram();
341  }
342  else
343  {
344  mDiagram = 0;
345  }
346 }
347 
348 void QgsDiagramRendererV2::_writeXML( QDomElement& rendererElem, QDomDocument& doc, const QgsVectorLayer* layer ) const
349 {
350  Q_UNUSED( doc );
351  Q_UNUSED( layer )
352 
353  if ( mDiagram )
354  {
355  rendererElem.setAttribute( "diagramType", mDiagram->diagramName() );
356  }
357 }
358 
360 {
361 }
362 
364 {
365 }
366 
368 {
369  Q_UNUSED( c );
370  s = mSettings;
371  return true;
372 }
373 
375 {
376  return mDiagram->diagramSize( feature.attributes(), c, mSettings );
377 }
378 
379 QList<QgsDiagramSettings> QgsSingleCategoryDiagramRenderer::diagramSettings() const
380 {
381  QList<QgsDiagramSettings> settingsList;
382  settingsList.push_back( mSettings );
383  return settingsList;
384 }
385 
386 void QgsSingleCategoryDiagramRenderer::readXML( const QDomElement& elem, const QgsVectorLayer* layer )
387 {
388  QDomElement categoryElem = elem.firstChildElement( "DiagramCategory" );
389  if ( categoryElem.isNull() )
390  {
391  return;
392  }
393 
394  mSettings.readXML( categoryElem, layer );
395  _readXML( elem, layer );
396 }
397 
398 void QgsSingleCategoryDiagramRenderer::writeXML( QDomElement& layerElem, QDomDocument& doc, const QgsVectorLayer* layer ) const
399 {
400  QDomElement rendererElem = doc.createElement( "SingleCategoryDiagramRenderer" );
401  mSettings.writeXML( rendererElem, doc, layer );
402  _writeXML( rendererElem, doc , layer );
403  layerElem.appendChild( rendererElem );
404 }
405 
406 
408 {
410 }
411 
413 {
414 }
415 
417 {
418  QList<QgsDiagramSettings> settingsList;
419  settingsList.push_back( mSettings );
420  return settingsList;
421 }
422 
424 {
425  s = mSettings;
426  s.size = diagramSize( feature, c );
427  return true;
428 }
429 
431 {
433 }
434 
436 {
437  return mDiagram->diagramSize( feature, c, mSettings, mInterpolationSettings );
438 }
439 
440 void QgsLinearlyInterpolatedDiagramRenderer::readXML( const QDomElement& elem, const QgsVectorLayer* layer )
441 {
442  mInterpolationSettings.lowerValue = elem.attribute( "lowerValue" ).toDouble();
443  mInterpolationSettings.upperValue = elem.attribute( "upperValue" ).toDouble();
444  mInterpolationSettings.lowerSize.setWidth( elem.attribute( "lowerWidth" ).toDouble() );
445  mInterpolationSettings.lowerSize.setHeight( elem.attribute( "lowerHeight" ).toDouble() );
446  mInterpolationSettings.upperSize.setWidth( elem.attribute( "upperWidth" ).toDouble() );
447  mInterpolationSettings.upperSize.setHeight( elem.attribute( "upperHeight" ).toDouble() );
448  mInterpolationSettings.classificationAttributeIsExpression = elem.hasAttribute( "classificationAttributeExpression" );
450  {
451  mInterpolationSettings.classificationAttributeExpression = elem.attribute( "classificationAttributeExpression" );
452  }
453  else
454  {
455  mInterpolationSettings.classificationAttribute = elem.attribute( "classificationAttribute" ).toInt();
456  }
457  QDomElement settingsElem = elem.firstChildElement( "DiagramCategory" );
458  if ( !settingsElem.isNull() )
459  {
460  mSettings.readXML( settingsElem, layer );
461  }
462  _readXML( elem, layer );
463 }
464 
465 void QgsLinearlyInterpolatedDiagramRenderer::writeXML( QDomElement& layerElem, QDomDocument& doc, const QgsVectorLayer* layer ) const
466 {
467  QDomElement rendererElem = doc.createElement( "LinearlyInterpolatedDiagramRenderer" );
468  rendererElem.setAttribute( "lowerValue", QString::number( mInterpolationSettings.lowerValue ) );
469  rendererElem.setAttribute( "upperValue", QString::number( mInterpolationSettings.upperValue ) );
470  rendererElem.setAttribute( "lowerWidth", QString::number( mInterpolationSettings.lowerSize.width() ) );
471  rendererElem.setAttribute( "lowerHeight", QString::number( mInterpolationSettings.lowerSize.height() ) );
472  rendererElem.setAttribute( "upperWidth", QString::number( mInterpolationSettings.upperSize.width() ) );
473  rendererElem.setAttribute( "upperHeight", QString::number( mInterpolationSettings.upperSize.height() ) );
475  {
476  rendererElem.setAttribute( "classificationAttributeExpression", mInterpolationSettings.classificationAttributeExpression );
477  }
478  else
479  {
480  rendererElem.setAttribute( "classificationAttribute", mInterpolationSettings.classificationAttribute );
481  }
482  mSettings.writeXML( rendererElem, doc, layer );
483  _writeXML( rendererElem, doc, layer );
484  layerElem.appendChild( rendererElem );
485 }