QGIS API Documentation  2.0.1-Dufour
 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  font.fromString( elem.attribute( "font" ) );
56  backgroundColor.setNamedColor( elem.attribute( "backgroundColor" ) );
57  backgroundColor.setAlpha( elem.attribute( "backgroundAlpha" ).toInt() );
58  size.setWidth( elem.attribute( "width" ).toDouble() );
59  size.setHeight( elem.attribute( "height" ).toDouble() );
60  transparency = elem.attribute( "transparency", "0" ).toInt();
61  penColor.setNamedColor( elem.attribute( "penColor" ) );
62  int penAlpha = elem.attribute( "penAlpha", "255" ).toInt();
63  penColor.setAlpha( penAlpha );
64  penWidth = elem.attribute( "penWidth" ).toDouble();
65 
66  minScaleDenominator = elem.attribute( "minScaleDenominator", "-1" ).toDouble();
67  maxScaleDenominator = elem.attribute( "maxScaleDenominator", "-1" ).toDouble();
68 
69  //mm vs map units
70  if ( elem.attribute( "sizeType" ) == "MM" )
71  {
72  sizeType = MM;
73  }
74  else
75  {
77  }
78 
79  //label placement method
80  if ( elem.attribute( "labelPlacementMethod" ) == "Height" )
81  {
83  }
84  else
85  {
87  }
88 
89  // orientation
90  if ( elem.attribute( "diagramOrientation" ) == "Left" )
91  {
93  }
94  else if ( elem.attribute( "diagramOrientation" ) == "Right" )
95  {
97  }
98  else if ( elem.attribute( "diagramOrientation" ) == "Down" )
99  {
101  }
102  else
103  {
105  }
106 
107  // scale dependency
108  if ( elem.attribute( "scaleDependency" ) == "Diameter" )
109  {
110  scaleByArea = false;
111  }
112  else
113  {
114  scaleByArea = true;
115  }
116 
117  barWidth = elem.attribute( "barWidth" ).toDouble();
118 
119  angleOffset = elem.attribute( "angleOffset" ).toInt();
120 
121  minimumSize = elem.attribute( "minimumSize" ).toDouble();
122 
123  //colors
124  categoryColors.clear();
125  QDomNodeList attributes = elem.elementsByTagName( "attribute" );
126 
127  if ( attributes.length() > 0 )
128  {
129  for ( uint i = 0; i < attributes.length(); i++ )
130  {
131  QDomElement attrElem = attributes.at( i ).toElement();
132  QColor newColor( attrElem.attribute( "color" ) );
133  newColor.setAlpha( 255 - transparency );
134  categoryColors.append( newColor );
135  categoryIndices.append( layer->fieldNameIndex( attrElem.attribute( "field" ) ) );
136  }
137  }
138  else
139  {
140  // Restore old format attributes and colors
141 
142  QStringList colorList = elem.attribute( "colors" ).split( "/" );
143  QStringList::const_iterator colorIt = colorList.constBegin();
144  for ( ; colorIt != colorList.constEnd(); ++colorIt )
145  {
146  QColor newColor( *colorIt );
147  newColor.setAlpha( 255 - transparency );
148  categoryColors.append( QColor( newColor ) );
149  }
150 
151  //attribute indices
152  categoryIndices.clear();
153  QStringList catList = elem.attribute( "categories" ).split( "/" );
154  QStringList::const_iterator catIt = catList.constBegin();
155  for ( ; catIt != catList.constEnd(); ++catIt )
156  {
157  categoryIndices.append( catIt->toInt() );
158  }
159  }
160 }
161 
162 void QgsDiagramSettings::writeXML( QDomElement& rendererElem, QDomDocument& doc, const QgsVectorLayer* layer ) const
163 {
164  QDomElement categoryElem = doc.createElement( "DiagramCategory" );
165  categoryElem.setAttribute( "font", font.toString() );
166  categoryElem.setAttribute( "backgroundColor", backgroundColor.name() );
167  categoryElem.setAttribute( "backgroundAlpha", backgroundColor.alpha() );
168  categoryElem.setAttribute( "width", QString::number( size.width() ) );
169  categoryElem.setAttribute( "height", QString::number( size.height() ) );
170  categoryElem.setAttribute( "penColor", penColor.name() );
171  categoryElem.setAttribute( "penAlpha", penColor.alpha() );
172  categoryElem.setAttribute( "penWidth", QString::number( penWidth ) );
173  categoryElem.setAttribute( "minScaleDenominator", QString::number( minScaleDenominator ) );
174  categoryElem.setAttribute( "maxScaleDenominator", QString::number( maxScaleDenominator ) );
175  categoryElem.setAttribute( "transparency", QString::number( transparency ) );
176 
177  // site type (mm vs. map units)
178  if ( sizeType == MM )
179  {
180  categoryElem.setAttribute( "sizeType", "MM" );
181  }
182  else
183  {
184  categoryElem.setAttribute( "sizeType", "MapUnits" );
185  }
186 
187  // label placement method (text diagram)
188  if ( labelPlacementMethod == Height )
189  {
190  categoryElem.setAttribute( "labelPlacementMethod", "Height" );
191  }
192  else
193  {
194  categoryElem.setAttribute( "labelPlacementMethod", "XHeight" );
195  }
196 
197  if ( scaleByArea )
198  {
199  categoryElem.setAttribute( "scaleDependency", "Area" );
200  }
201  else
202  {
203  categoryElem.setAttribute( "scaleDependency", "Diameter" );
204  }
205 
206  // orientation (histogram)
207  switch ( diagramOrientation )
208  {
209  case Left:
210  categoryElem.setAttribute( "diagramOrientation", "Left" );
211  break;
212 
213  case Right:
214  categoryElem.setAttribute( "diagramOrientation", "Right" );
215  break;
216 
217  case Down:
218  categoryElem.setAttribute( "diagramOrientation", "Down" );
219  break;
220 
221  case Up:
222  categoryElem.setAttribute( "diagramOrientation", "Up" );
223  break;
224 
225  default:
226  categoryElem.setAttribute( "diagramOrientation", "Up" );
227  break;
228  }
229 
230  categoryElem.setAttribute( "barWidth", QString::number( barWidth ) );
231  categoryElem.setAttribute( "minimumSize", QString::number( minimumSize ) );
232  categoryElem.setAttribute( "angleOffset", QString::number( angleOffset ) );
233 
234  QString colors;
235  int nCats = qMin( categoryColors.size(), categoryIndices.size() );
236  for ( int i = 0; i < nCats; ++i )
237  {
238  QDomElement attributeElem = doc.createElement( "attribute" );
239 
240  attributeElem.setAttribute( "field", layer->pendingFields().at( categoryIndices.at( i ) ).name() );
241  attributeElem.setAttribute( "color", categoryColors.at( i ).name() );
242  categoryElem.appendChild( attributeElem );
243  }
244 
245  rendererElem.appendChild( categoryElem );
246 }
247 
249 {
250 }
251 
253 {
254  delete mDiagram;
255 }
256 
257 void QgsDiagramRendererV2::setDiagram( QgsDiagram* d )
258 {
259  delete mDiagram;
260  mDiagram = d;
261 }
262 
263 void QgsDiagramRendererV2::renderDiagram( const QgsAttributes& att, QgsRenderContext& c, const QPointF& pos )
264 {
265  if ( !mDiagram )
266  {
267  return;
268  }
269 
271  if ( !diagramSettings( att, c, s ) )
272  {
273  return;
274  }
275 
276  mDiagram->renderDiagram( att, c, s, pos );
277 }
278 
280 {
282  if ( !diagramSettings( attributes, c, s ) )
283  {
284  return QSizeF();
285  }
286 
287  QSizeF size = diagramSize( attributes, c );
288  if ( s.sizeType == QgsDiagramSettings::MM )
289  {
290  convertSizeToMapUnits( size, c );
291  }
292  return size;
293 }
294 
296 {
297  if ( !size.isValid() )
298  {
299  return;
300  }
301 
302  double pixelToMap = context.scaleFactor() * context.mapToPixel().mapUnitsPerPixel();
303  size.rwidth() *= pixelToMap;
304  size.rheight() *= pixelToMap;
305 }
306 
307 int QgsDiagramRendererV2::dpiPaintDevice( const QPainter* painter )
308 {
309  if ( painter )
310  {
311  QPaintDevice* device = painter->device();
312  if ( device )
313  {
314  return device->logicalDpiX();
315  }
316  }
317  return -1;
318 }
319 
320 void QgsDiagramRendererV2::_readXML( const QDomElement& elem, const QgsVectorLayer* layer )
321 {
322  Q_UNUSED( layer )
323 
324  delete mDiagram;
325  QString diagramType = elem.attribute( "diagramType" );
326  if ( diagramType == "Pie" )
327  {
328  mDiagram = new QgsPieDiagram();
329  }
330  else if ( diagramType == "Text" )
331  {
332  mDiagram = new QgsTextDiagram();
333  }
334  else if ( diagramType == "Histogram" )
335  {
336  mDiagram = new QgsHistogramDiagram();
337  }
338  else
339  {
340  mDiagram = 0;
341  }
342 }
343 
344 void QgsDiagramRendererV2::_writeXML( QDomElement& rendererElem, QDomDocument& doc, const QgsVectorLayer* layer ) const
345 {
346  Q_UNUSED( doc );
347  Q_UNUSED( layer )
348 
349  if ( mDiagram )
350  {
351  rendererElem.setAttribute( "diagramType", mDiagram->diagramName() );
352  }
353 }
354 
356 {
357 }
358 
360 {
361 }
362 
364 {
365  Q_UNUSED( c );
366  s = mSettings;
367  return true;
368 }
369 
371 {
372  return mDiagram->diagramSize( attributes, c, mSettings );
373 }
374 
375 QList<QgsDiagramSettings> QgsSingleCategoryDiagramRenderer::diagramSettings() const
376 {
377  QList<QgsDiagramSettings> settingsList;
378  settingsList.push_back( mSettings );
379  return settingsList;
380 }
381 
382 void QgsSingleCategoryDiagramRenderer::readXML( const QDomElement& elem, const QgsVectorLayer* layer )
383 {
384  QDomElement categoryElem = elem.firstChildElement( "DiagramCategory" );
385  if ( categoryElem.isNull() )
386  {
387  return;
388  }
389 
390  mSettings.readXML( categoryElem, layer );
391  _readXML( elem, layer );
392 }
393 
394 void QgsSingleCategoryDiagramRenderer::writeXML( QDomElement& layerElem, QDomDocument& doc, const QgsVectorLayer* layer ) const
395 {
396  QDomElement rendererElem = doc.createElement( "SingleCategoryDiagramRenderer" );
397  mSettings.writeXML( rendererElem, doc, layer );
398  _writeXML( rendererElem, doc , layer );
399  layerElem.appendChild( rendererElem );
400 }
401 
402 
404 {
405 }
406 
408 {
409 }
410 
412 {
413  QList<QgsDiagramSettings> settingsList;
414  settingsList.push_back( mSettings );
415  return settingsList;
416 }
417 
419 {
420  s = mSettings;
421  s.size = diagramSize( attributes, c );
422  return true;
423 }
424 
426 {
427  QList<int> attributes = mSettings.categoryIndices;
428  if ( !attributes.contains( mInterpolationSettings.classificationAttribute ) )
429  {
430  attributes.push_back( mInterpolationSettings.classificationAttribute );
431  }
432  return attributes;
433 }
434 
436 {
437  return mDiagram->diagramSize( attributes, 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.classificationAttribute = elem.attribute( "classificationAttribute" ).toInt();
449  QDomElement settingsElem = elem.firstChildElement( "DiagramCategory" );
450  if ( !settingsElem.isNull() )
451  {
452  mSettings.readXML( settingsElem, layer );
453  }
454  _readXML( elem, layer );
455 }
456 
457 void QgsLinearlyInterpolatedDiagramRenderer::writeXML( QDomElement& layerElem, QDomDocument& doc, const QgsVectorLayer* layer ) const
458 {
459  QDomElement rendererElem = doc.createElement( "LinearlyInterpolatedDiagramRenderer" );
460  rendererElem.setAttribute( "lowerValue", QString::number( mInterpolationSettings.lowerValue ) );
461  rendererElem.setAttribute( "upperValue", QString::number( mInterpolationSettings.upperValue ) );
462  rendererElem.setAttribute( "lowerWidth", QString::number( mInterpolationSettings.lowerSize.width() ) );
463  rendererElem.setAttribute( "lowerHeight", QString::number( mInterpolationSettings.lowerSize.height() ) );
464  rendererElem.setAttribute( "upperWidth", QString::number( mInterpolationSettings.upperSize.width() ) );
465  rendererElem.setAttribute( "upperHeight", QString::number( mInterpolationSettings.upperSize.height() ) );
466  rendererElem.setAttribute( "classificationAttribute", mInterpolationSettings.classificationAttribute );
467  mSettings.writeXML( rendererElem, doc, layer );
468  _writeXML( rendererElem, doc, layer );
469  layerElem.appendChild( rendererElem );
470 }