QGIS API Documentation  master-3f58142
src/core/qgsdiagramrendererv2.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002     qgsdiagramrendererv2.cpp
00003     ---------------------
00004     begin                : March 2011
00005     copyright            : (C) 2011 by Marco Hugentobler
00006     email                : marco dot hugentobler at sourcepole dot ch
00007  ***************************************************************************
00008  *                                                                         *
00009  *   This program is free software; you can redistribute it and/or modify  *
00010  *   it under the terms of the GNU General Public License as published by  *
00011  *   the Free Software Foundation; either version 2 of the License, or     *
00012  *   (at your option) any later version.                                   *
00013  *                                                                         *
00014  ***************************************************************************/
00015 #include "qgsdiagramrendererv2.h"
00016 #include "diagram/qgstextdiagram.h"
00017 #include "diagram/qgspiediagram.h"
00018 #include "diagram/qgshistogramdiagram.h"
00019 #include "qgsrendercontext.h"
00020 #include <QDomElement>
00021 #include <QPainter>
00022 
00023 
00024 void QgsDiagramLayerSettings::readXML( const QDomElement& elem )
00025 {
00026   placement = ( Placement )elem.attribute( "placement" ).toInt();
00027   placementFlags = ( LinePlacementFlags )elem.attribute( "linePlacementFlags" ).toInt();
00028   priority = elem.attribute( "priority" ).toInt();
00029   obstacle = elem.attribute( "obstacle" ).toInt();
00030   dist = elem.attribute( "dist" ).toDouble();
00031   xPosColumn = elem.attribute( "xPosColumn" ).toInt();
00032   yPosColumn = elem.attribute( "yPosColumn" ).toInt();
00033 }
00034 
00035 void QgsDiagramLayerSettings::writeXML( QDomElement& layerElem, QDomDocument& doc ) const
00036 {
00037   QDomElement diagramLayerElem = doc.createElement( "DiagramLayerSettings" );
00038   diagramLayerElem.setAttribute( "placement", placement );
00039   diagramLayerElem.setAttribute( "linePlacementFlags", placementFlags );
00040   diagramLayerElem.setAttribute( "priority", priority );
00041   diagramLayerElem.setAttribute( "obstacle", obstacle );
00042   diagramLayerElem.setAttribute( "dist", QString::number( dist ) );
00043   diagramLayerElem.setAttribute( "xPosColumn", xPosColumn );
00044   diagramLayerElem.setAttribute( "yPosColumn", yPosColumn );
00045   layerElem.appendChild( diagramLayerElem );
00046 }
00047 
00048 void QgsDiagramSettings::readXML( const QDomElement& elem )
00049 {
00050   font.fromString( elem.attribute( "font" ) );
00051   backgroundColor.setNamedColor( elem.attribute( "backgroundColor" ) );
00052   backgroundColor.setAlpha( elem.attribute( "backgroundAlpha" ).toInt() );
00053   size.setWidth( elem.attribute( "width" ).toDouble() );
00054   size.setHeight( elem.attribute( "height" ).toDouble() );
00055   transparency = elem.attribute( "transparency", "0" ).toInt();
00056   penColor.setNamedColor( elem.attribute( "penColor" ) );
00057   int penAlpha = elem.attribute( "penAlpha", "255" ).toInt();
00058   penColor.setAlpha( penAlpha );
00059   penWidth = elem.attribute( "penWidth" ).toDouble();
00060 
00061   minScaleDenominator = elem.attribute( "minScaleDenominator", "-1" ).toDouble();
00062   maxScaleDenominator = elem.attribute( "maxScaleDenominator", "-1" ).toDouble();
00063 
00064   //mm vs map units
00065   if ( elem.attribute( "sizeType" ) == "MM" )
00066   {
00067     sizeType = MM;
00068   }
00069   else
00070   {
00071     sizeType = MapUnits;
00072   }
00073 
00074   //label placement method
00075   if ( elem.attribute( "labelPlacementMethod" ) == "Height" )
00076   {
00077     labelPlacementMethod = Height;
00078   }
00079   else
00080   {
00081     labelPlacementMethod = XHeight;
00082   }
00083 
00084   // orientation
00085   if ( elem.attribute( "diagramOrientation" ) == "Left" )
00086   {
00087     diagramOrientation = Left;
00088   }
00089   else if ( elem.attribute( "diagramOrientation" ) == "Right" )
00090   {
00091     diagramOrientation = Right;
00092   }
00093   else if ( elem.attribute( "diagramOrientation" ) == "Down" )
00094   {
00095     diagramOrientation = Down;
00096   }
00097   else
00098   {
00099     diagramOrientation = Up;
00100   }
00101 
00102   // scale dependency
00103   if ( elem.attribute( "scaleDependency" ) == "Diameter" )
00104   {
00105     scaleByArea = false;
00106   }
00107   else
00108   {
00109     scaleByArea = true;
00110   }
00111 
00112   barWidth = elem.attribute( "barWidth" ).toDouble();
00113 
00114   angleOffset = elem.attribute( "angleOffset" ).toInt();
00115 
00116   minimumSize = elem.attribute( "minimumSize" ).toDouble();
00117 
00118   //colors
00119   categoryColors.clear();
00120   QStringList colorList = elem.attribute( "colors" ).split( "/" );
00121   QStringList::const_iterator colorIt = colorList.constBegin();
00122   for ( ; colorIt != colorList.constEnd(); ++colorIt )
00123   {
00124     QColor newColor( *colorIt );
00125     newColor.setAlpha( 255 - transparency );
00126     categoryColors.append( QColor( newColor ) );
00127   }
00128 
00129   //attribute indices
00130   categoryIndices.clear();
00131   QStringList catList = elem.attribute( "categories" ).split( "/" );
00132   QStringList::const_iterator catIt = catList.constBegin();
00133   for ( ; catIt != catList.constEnd(); ++catIt )
00134   {
00135     categoryIndices.append( catIt->toInt() );
00136   }
00137 }
00138 
00139 void QgsDiagramSettings::writeXML( QDomElement& rendererElem, QDomDocument& doc ) const
00140 {
00141   QDomElement categoryElem = doc.createElement( "DiagramCategory" );
00142   categoryElem.setAttribute( "font", font.toString() );
00143   categoryElem.setAttribute( "backgroundColor", backgroundColor.name() );
00144   categoryElem.setAttribute( "backgroundAlpha", backgroundColor.alpha() );
00145   categoryElem.setAttribute( "width", QString::number( size.width() ) );
00146   categoryElem.setAttribute( "height", QString::number( size.height() ) );
00147   categoryElem.setAttribute( "penColor", penColor.name() );
00148   categoryElem.setAttribute( "penAlpha", penColor.alpha() );
00149   categoryElem.setAttribute( "penWidth", QString::number( penWidth ) );
00150   categoryElem.setAttribute( "minScaleDenominator", QString::number( minScaleDenominator ) );
00151   categoryElem.setAttribute( "maxScaleDenominator", QString::number( maxScaleDenominator ) );
00152   categoryElem.setAttribute( "transparency", QString::number( transparency ) );
00153 
00154   // site type (mm vs. map units)
00155   if ( sizeType == MM )
00156   {
00157     categoryElem.setAttribute( "sizeType", "MM" );
00158   }
00159   else
00160   {
00161     categoryElem.setAttribute( "sizeType", "MapUnits" );
00162   }
00163 
00164   // label placement method (text diagram)
00165   if ( labelPlacementMethod == Height )
00166   {
00167     categoryElem.setAttribute( "labelPlacementMethod", "Height" );
00168   }
00169   else
00170   {
00171     categoryElem.setAttribute( "labelPlacementMethod", "XHeight" );
00172   }
00173 
00174   if ( scaleByArea )
00175   {
00176     categoryElem.setAttribute( "scaleDependency", "Area" );
00177   }
00178   else
00179   {
00180     categoryElem.setAttribute( "scaleDependency", "Diameter" );
00181   }
00182 
00183   // orientation (histogram)
00184   switch ( diagramOrientation )
00185   {
00186     case Left:
00187       categoryElem.setAttribute( "diagramOrientation", "Left" );
00188       break;
00189 
00190     case Right:
00191       categoryElem.setAttribute( "diagramOrientation", "Right" );
00192       break;
00193 
00194     case Down:
00195       categoryElem.setAttribute( "diagramOrientation", "Down" );
00196       break;
00197 
00198     case Up:
00199       categoryElem.setAttribute( "diagramOrientation", "Up" );
00200       break;
00201 
00202     default:
00203       categoryElem.setAttribute( "diagramOrientation", "Up" );
00204       break;
00205   }
00206 
00207   categoryElem.setAttribute( "barWidth", QString::number( barWidth ) );
00208   categoryElem.setAttribute( "minimumSize", QString::number( minimumSize ) );
00209   categoryElem.setAttribute( "angleOffset", QString::number( angleOffset ) );
00210 
00211   QString colors;
00212   for ( int i = 0; i < categoryColors.size(); ++i )
00213   {
00214     if ( i > 0 )
00215     {
00216       colors.append( "/" );
00217     }
00218     colors.append( categoryColors.at( i ).name() );
00219   }
00220   categoryElem.setAttribute( "colors", colors );
00221 
00222   QString categories;
00223   for ( int i = 0; i < categoryIndices.size(); ++i )
00224   {
00225     if ( i > 0 )
00226     {
00227       categories.append( "/" );
00228     }
00229     categories.append( QString::number( categoryIndices.at( i ) ) );
00230   }
00231   categoryElem.setAttribute( "categories", categories );
00232 
00233   rendererElem.appendChild( categoryElem );
00234 }
00235 
00236 QgsDiagramRendererV2::QgsDiagramRendererV2(): mDiagram( 0 )
00237 {
00238 }
00239 
00240 QgsDiagramRendererV2::~QgsDiagramRendererV2()
00241 {
00242   delete mDiagram;
00243 }
00244 
00245 void QgsDiagramRendererV2::setDiagram( QgsDiagram* d )
00246 {
00247   delete mDiagram;
00248   mDiagram = d;
00249 }
00250 
00251 void QgsDiagramRendererV2::renderDiagram( const QgsAttributes& att, QgsRenderContext& c, const QPointF& pos )
00252 {
00253   if ( !mDiagram )
00254   {
00255     return;
00256   }
00257 
00258   QgsDiagramSettings s;
00259   if ( !diagramSettings( att, c, s ) )
00260   {
00261     return;
00262   }
00263 
00264   mDiagram->renderDiagram( att, c, s, pos );
00265 }
00266 
00267 QSizeF QgsDiagramRendererV2::sizeMapUnits( const QgsAttributes& attributes, const QgsRenderContext& c )
00268 {
00269   QgsDiagramSettings s;
00270   if ( !diagramSettings( attributes, c, s ) )
00271   {
00272     return QSizeF();
00273   }
00274 
00275   QSizeF size = diagramSize( attributes, c );
00276   if ( s.sizeType == QgsDiagramSettings::MM )
00277   {
00278     convertSizeToMapUnits( size, c );
00279   }
00280   return size;
00281 }
00282 
00283 void QgsDiagramRendererV2::convertSizeToMapUnits( QSizeF& size, const QgsRenderContext& context ) const
00284 {
00285   if ( !size.isValid() )
00286   {
00287     return;
00288   }
00289 
00290   double pixelToMap = context.scaleFactor() * context.mapToPixel().mapUnitsPerPixel();
00291   size.rwidth() *= pixelToMap;
00292   size.rheight() *= pixelToMap;
00293 }
00294 
00295 int QgsDiagramRendererV2::dpiPaintDevice( const QPainter* painter )
00296 {
00297   if ( painter )
00298   {
00299     QPaintDevice* device = painter->device();
00300     if ( device )
00301     {
00302       return device->logicalDpiX();
00303     }
00304   }
00305   return -1;
00306 }
00307 
00308 void QgsDiagramRendererV2::_readXML( const QDomElement& elem )
00309 {
00310   delete mDiagram;
00311   QString diagramType = elem.attribute( "diagramType" );
00312   if ( diagramType == "Pie" )
00313   {
00314     mDiagram = new QgsPieDiagram();
00315   }
00316   else if ( diagramType == "Text" )
00317   {
00318     mDiagram = new QgsTextDiagram();
00319   }
00320   else if ( diagramType == "Histogram" )
00321   {
00322     mDiagram = new QgsHistogramDiagram();
00323   }
00324   else
00325   {
00326     mDiagram = 0;
00327   }
00328 }
00329 
00330 void QgsDiagramRendererV2::_writeXML( QDomElement& rendererElem, QDomDocument& doc ) const
00331 {
00332   Q_UNUSED( doc );
00333   if ( mDiagram )
00334   {
00335     rendererElem.setAttribute( "diagramType", mDiagram->diagramName() );
00336   }
00337 }
00338 
00339 QgsSingleCategoryDiagramRenderer::QgsSingleCategoryDiagramRenderer(): QgsDiagramRendererV2()
00340 {
00341 }
00342 
00343 QgsSingleCategoryDiagramRenderer::~QgsSingleCategoryDiagramRenderer()
00344 {
00345 }
00346 
00347 bool QgsSingleCategoryDiagramRenderer::diagramSettings( const QgsAttributes&, const QgsRenderContext& c, QgsDiagramSettings& s )
00348 {
00349   Q_UNUSED( c );
00350   s = mSettings;
00351   return true;
00352 }
00353 
00354 QSizeF QgsSingleCategoryDiagramRenderer::diagramSize( const QgsAttributes &attributes, const QgsRenderContext &c )
00355 {
00356   return mDiagram->diagramSize( attributes, c, mSettings );
00357 }
00358 
00359 QList<QgsDiagramSettings> QgsSingleCategoryDiagramRenderer::diagramSettings() const
00360 {
00361   QList<QgsDiagramSettings> settingsList;
00362   settingsList.push_back( mSettings );
00363   return settingsList;
00364 }
00365 
00366 void QgsSingleCategoryDiagramRenderer::readXML( const QDomElement& elem )
00367 {
00368   QDomElement categoryElem = elem.firstChildElement( "DiagramCategory" );
00369   if ( categoryElem.isNull() )
00370   {
00371     return;
00372   }
00373 
00374   mSettings.readXML( categoryElem );
00375   _readXML( elem );
00376 }
00377 
00378 void QgsSingleCategoryDiagramRenderer::writeXML( QDomElement& layerElem, QDomDocument& doc ) const
00379 {
00380   QDomElement rendererElem = doc.createElement( "SingleCategoryDiagramRenderer" );
00381   mSettings.writeXML( rendererElem, doc );
00382   _writeXML( rendererElem, doc );
00383   layerElem.appendChild( rendererElem );
00384 }
00385 
00386 
00387 QgsLinearlyInterpolatedDiagramRenderer::QgsLinearlyInterpolatedDiagramRenderer(): QgsDiagramRendererV2()
00388 {
00389 }
00390 
00391 QgsLinearlyInterpolatedDiagramRenderer::~QgsLinearlyInterpolatedDiagramRenderer()
00392 {
00393 }
00394 
00395 QList<QgsDiagramSettings> QgsLinearlyInterpolatedDiagramRenderer::diagramSettings() const
00396 {
00397   QList<QgsDiagramSettings> settingsList;
00398   settingsList.push_back( mSettings );
00399   return settingsList;
00400 }
00401 
00402 bool QgsLinearlyInterpolatedDiagramRenderer::diagramSettings( const QgsAttributes& attributes, const QgsRenderContext& c, QgsDiagramSettings& s )
00403 {
00404   s = mSettings;
00405   s.size = diagramSize( attributes, c );
00406   return true;
00407 }
00408 
00409 QList<int> QgsLinearlyInterpolatedDiagramRenderer::diagramAttributes() const
00410 {
00411   QList<int> attributes = mSettings.categoryIndices;
00412   if ( !attributes.contains( mInterpolationSettings.classificationAttribute ) )
00413   {
00414     attributes.push_back( mInterpolationSettings.classificationAttribute );
00415   }
00416   return attributes;
00417 }
00418 
00419 QSizeF QgsLinearlyInterpolatedDiagramRenderer::diagramSize( const QgsAttributes& attributes, const QgsRenderContext& c )
00420 {
00421   return mDiagram->diagramSize( attributes, c, mSettings, mInterpolationSettings );
00422 }
00423 
00424 void QgsLinearlyInterpolatedDiagramRenderer::readXML( const QDomElement& elem )
00425 {
00426   mInterpolationSettings.lowerValue = elem.attribute( "lowerValue" ).toDouble();
00427   mInterpolationSettings.upperValue = elem.attribute( "upperValue" ).toDouble();
00428   mInterpolationSettings.lowerSize.setWidth( elem.attribute( "lowerWidth" ).toDouble() );
00429   mInterpolationSettings.lowerSize.setHeight( elem.attribute( "lowerHeight" ).toDouble() );
00430   mInterpolationSettings.upperSize.setWidth( elem.attribute( "upperWidth" ).toDouble() );
00431   mInterpolationSettings.upperSize.setHeight( elem.attribute( "upperHeight" ).toDouble() );
00432   mInterpolationSettings.classificationAttribute = elem.attribute( "classificationAttribute" ).toInt();
00433   QDomElement settingsElem = elem.firstChildElement( "DiagramCategory" );
00434   if ( !settingsElem.isNull() )
00435   {
00436     mSettings.readXML( settingsElem );
00437   }
00438   _readXML( elem );
00439 }
00440 
00441 void QgsLinearlyInterpolatedDiagramRenderer::writeXML( QDomElement& layerElem, QDomDocument& doc ) const
00442 {
00443   QDomElement rendererElem = doc.createElement( "LinearlyInterpolatedDiagramRenderer" );
00444   rendererElem.setAttribute( "lowerValue", QString::number( mInterpolationSettings.lowerValue ) );
00445   rendererElem.setAttribute( "upperValue", QString::number( mInterpolationSettings.upperValue ) );
00446   rendererElem.setAttribute( "lowerWidth", QString::number( mInterpolationSettings.lowerSize.width() ) );
00447   rendererElem.setAttribute( "lowerHeight", QString::number( mInterpolationSettings.lowerSize.height() ) );
00448   rendererElem.setAttribute( "upperWidth", QString::number( mInterpolationSettings.upperSize.width() ) );
00449   rendererElem.setAttribute( "upperHeight", QString::number( mInterpolationSettings.upperSize.height() ) );
00450   rendererElem.setAttribute( "classificationAttribute", mInterpolationSettings.classificationAttribute );
00451   mSettings.writeXML( rendererElem, doc );
00452   _writeXML( rendererElem, doc );
00453   layerElem.appendChild( rendererElem );
00454 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines