Quantum GIS API Documentation  1.8
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 "qgsdiagram.h"
00017 #include "qgsrendercontext.h"
00018 #include <QDomElement>
00019 #include <QPainter>
00020 
00021 
00022 void QgsDiagramLayerSettings::readXML( const QDomElement& elem )
00023 {
00024   placement = ( Placement )elem.attribute( "placement" ).toInt();
00025   placementFlags = ( LinePlacementFlags )elem.attribute( "linePlacementFlags" ).toInt();
00026   priority = elem.attribute( "priority" ).toInt();
00027   obstacle = elem.attribute( "obstacle" ).toInt();
00028   dist = elem.attribute( "dist" ).toDouble();
00029   xPosColumn = elem.attribute( "xPosColumn" ).toInt();
00030   yPosColumn = elem.attribute( "yPosColumn" ).toInt();
00031 }
00032 
00033 void QgsDiagramLayerSettings::writeXML( QDomElement& layerElem, QDomDocument& doc ) const
00034 {
00035   QDomElement diagramLayerElem = doc.createElement( "DiagramLayerSettings" );
00036   diagramLayerElem.setAttribute( "placement", placement );
00037   diagramLayerElem.setAttribute( "linePlacementFlags", placementFlags );
00038   diagramLayerElem.setAttribute( "priority", priority );
00039   diagramLayerElem.setAttribute( "obstacle", obstacle );
00040   diagramLayerElem.setAttribute( "dist", QString::number( dist ) );
00041   diagramLayerElem.setAttribute( "xPosColumn", xPosColumn );
00042   diagramLayerElem.setAttribute( "yPosColumn", yPosColumn );
00043   layerElem.appendChild( diagramLayerElem );
00044 }
00045 
00046 void QgsDiagramSettings::readXML( const QDomElement& elem )
00047 {
00048   font.fromString( elem.attribute( "font" ) );
00049   backgroundColor.setNamedColor( elem.attribute( "backgroundColor" ) );
00050   backgroundColor.setAlpha( elem.attribute( "backgroundAlpha" ).toInt() );
00051   size.setWidth( elem.attribute( "width" ).toDouble() );
00052   size.setHeight( elem.attribute( "height" ).toDouble() );
00053   penColor.setNamedColor( elem.attribute( "penColor" ) );
00054   penWidth = elem.attribute( "penWidth" ).toDouble();
00055   minScaleDenominator = elem.attribute( "minScaleDenominator", "-1" ).toDouble();
00056   maxScaleDenominator = elem.attribute( "maxScaleDenominator", "-1" ).toDouble();
00057 
00058   //mm vs map units
00059   if ( elem.attribute( "sizeType" ) == "MM" )
00060   {
00061     sizeType = MM;
00062   }
00063   else
00064   {
00065     sizeType = MapUnits;
00066   }
00067 
00068   //colors
00069   categoryColors.clear();
00070   QStringList colorList = elem.attribute( "colors" ).split( "/" );
00071   QStringList::const_iterator colorIt = colorList.constBegin();
00072   for ( ; colorIt != colorList.constEnd(); ++colorIt )
00073   {
00074     categoryColors.append( QColor( *colorIt ) );
00075   }
00076 
00077   //attribute indices
00078   categoryIndices.clear();
00079   QStringList catList = elem.attribute( "categories" ).split( "/" );
00080   QStringList::const_iterator catIt = catList.constBegin();
00081   for ( ; catIt != catList.constEnd(); ++catIt )
00082   {
00083     categoryIndices.append( catIt->toInt() );
00084   }
00085 }
00086 
00087 void QgsDiagramSettings::writeXML( QDomElement& rendererElem, QDomDocument& doc ) const
00088 {
00089   QDomElement categoryElem = doc.createElement( "DiagramCategory" );
00090   categoryElem.setAttribute( "font", font.toString() );
00091   categoryElem.setAttribute( "backgroundColor", backgroundColor.name() );
00092   categoryElem.setAttribute( "backgroundAlpha", backgroundColor.alpha() );
00093   categoryElem.setAttribute( "width", QString::number( size.width() ) );
00094   categoryElem.setAttribute( "height", QString::number( size.height() ) );
00095   categoryElem.setAttribute( "penColor", penColor.name() );
00096   categoryElem.setAttribute( "penWidth", QString::number( penWidth ) );
00097   categoryElem.setAttribute( "minScaleDenominator", QString::number( minScaleDenominator ) );
00098   categoryElem.setAttribute( "maxScaleDenominator", QString::number( maxScaleDenominator ) );
00099   if ( sizeType == MM )
00100   {
00101     categoryElem.setAttribute( "sizeType", "MM" );
00102   }
00103   else
00104   {
00105     categoryElem.setAttribute( "sizeType", "MapUnits" );
00106   }
00107 
00108   QString colors;
00109   for ( int i = 0; i < categoryColors.size(); ++i )
00110   {
00111     if ( i > 0 )
00112     {
00113       colors.append( "/" );
00114     }
00115     colors.append( categoryColors.at( i ).name() );
00116   }
00117   categoryElem.setAttribute( "colors", colors );
00118 
00119   QString categories;
00120   for ( int i = 0; i < categoryIndices.size(); ++i )
00121   {
00122     if ( i > 0 )
00123     {
00124       categories.append( "/" );
00125     }
00126     categories.append( QString::number( categoryIndices.at( i ) ) );
00127   }
00128   categoryElem.setAttribute( "categories", categories );
00129 
00130   rendererElem.appendChild( categoryElem );
00131 }
00132 
00133 QgsDiagramRendererV2::QgsDiagramRendererV2(): mDiagram( 0 )
00134 {
00135 }
00136 
00137 QgsDiagramRendererV2::~QgsDiagramRendererV2()
00138 {
00139   delete mDiagram;
00140 }
00141 
00142 void QgsDiagramRendererV2::setDiagram( QgsDiagram* d )
00143 {
00144   delete mDiagram;
00145   mDiagram = d;
00146 }
00147 
00148 void QgsDiagramRendererV2::renderDiagram( const QgsAttributeMap& att, QgsRenderContext& c, const QPointF& pos )
00149 {
00150   if ( !mDiagram )
00151   {
00152     return;
00153   }
00154 
00155   QgsDiagramSettings s;
00156   if ( !diagramSettings( att, c, s ) )
00157   {
00158     return;
00159   }
00160 
00161   mDiagram->renderDiagram( att, c, s, pos );
00162 }
00163 
00164 QSizeF QgsDiagramRendererV2::sizeMapUnits( const QgsAttributeMap& attributes, const QgsRenderContext& c )
00165 {
00166   QgsDiagramSettings s;
00167   if ( !diagramSettings( attributes, c, s ) )
00168   {
00169     return QSizeF();
00170   }
00171 
00172   QSizeF size = diagramSize( attributes, c );
00173   if ( s.sizeType == QgsDiagramSettings::MM )
00174   {
00175     convertSizeToMapUnits( size, c );
00176   }
00177   return size;
00178 }
00179 
00180 void QgsDiagramRendererV2::convertSizeToMapUnits( QSizeF& size, const QgsRenderContext& context ) const
00181 {
00182   if ( !size.isValid() )
00183   {
00184     return;
00185   }
00186 
00187   int dpi = dpiPaintDevice( context.constPainter() );
00188   if ( dpi < 0 )
00189   {
00190     return;
00191   }
00192 
00193   double pixelToMap = dpi / 25.4 * context.mapToPixel().mapUnitsPerPixel();
00194   size.rwidth() *= pixelToMap;
00195   size.rheight() *= pixelToMap;
00196 }
00197 
00198 int QgsDiagramRendererV2::dpiPaintDevice( const QPainter* painter )
00199 {
00200   if ( painter )
00201   {
00202     QPaintDevice* device = painter->device();
00203     if ( device )
00204     {
00205       return device->logicalDpiX();
00206     }
00207   }
00208   return -1;
00209 }
00210 
00211 void QgsDiagramRendererV2::_readXML( const QDomElement& elem )
00212 {
00213   delete mDiagram;
00214   QString diagramType = elem.attribute( "diagramType" );
00215   if ( diagramType == "Pie" )
00216   {
00217     mDiagram = new QgsPieDiagram();
00218   }
00219   else if ( diagramType == "Text" )
00220   {
00221     mDiagram = new QgsTextDiagram();
00222   }
00223   else
00224   {
00225     mDiagram = 0;
00226   }
00227 }
00228 
00229 void QgsDiagramRendererV2::_writeXML( QDomElement& rendererElem, QDomDocument& doc ) const
00230 {
00231   Q_UNUSED( doc );
00232   if ( mDiagram )
00233   {
00234     rendererElem.setAttribute( "diagramType", mDiagram->diagramName() );
00235   }
00236 }
00237 
00238 QgsSingleCategoryDiagramRenderer::QgsSingleCategoryDiagramRenderer(): QgsDiagramRendererV2()
00239 {
00240 }
00241 
00242 QgsSingleCategoryDiagramRenderer::~QgsSingleCategoryDiagramRenderer()
00243 {
00244 }
00245 
00246 bool QgsSingleCategoryDiagramRenderer::diagramSettings( const QgsAttributeMap&, const QgsRenderContext& c, QgsDiagramSettings& s )
00247 {
00248   Q_UNUSED( c );
00249   s = mSettings;
00250   return true;
00251 }
00252 
00253 QList<QgsDiagramSettings> QgsSingleCategoryDiagramRenderer::diagramSettings() const
00254 {
00255   QList<QgsDiagramSettings> settingsList;
00256   settingsList.push_back( mSettings );
00257   return settingsList;
00258 }
00259 
00260 void QgsSingleCategoryDiagramRenderer::readXML( const QDomElement& elem )
00261 {
00262   QDomElement categoryElem = elem.firstChildElement( "DiagramCategory" );
00263   if ( categoryElem.isNull() )
00264   {
00265     return;
00266   }
00267 
00268   mSettings.readXML( categoryElem );
00269   _readXML( elem );
00270 }
00271 
00272 void QgsSingleCategoryDiagramRenderer::writeXML( QDomElement& layerElem, QDomDocument& doc ) const
00273 {
00274   QDomElement rendererElem = doc.createElement( "SingleCategoryDiagramRenderer" );
00275   mSettings.writeXML( rendererElem, doc );
00276   _writeXML( rendererElem, doc );
00277   layerElem.appendChild( rendererElem );
00278 }
00279 
00280 
00281 QgsLinearlyInterpolatedDiagramRenderer::QgsLinearlyInterpolatedDiagramRenderer(): QgsDiagramRendererV2()
00282 {
00283 }
00284 
00285 QgsLinearlyInterpolatedDiagramRenderer::~QgsLinearlyInterpolatedDiagramRenderer()
00286 {
00287 }
00288 
00289 QList<QgsDiagramSettings> QgsLinearlyInterpolatedDiagramRenderer::diagramSettings() const
00290 {
00291   QList<QgsDiagramSettings> settingsList;
00292   settingsList.push_back( mSettings );
00293   return settingsList;
00294 }
00295 
00296 bool QgsLinearlyInterpolatedDiagramRenderer::diagramSettings( const QgsAttributeMap& attributes, const QgsRenderContext& c, QgsDiagramSettings& s )
00297 {
00298   s = mSettings;
00299   s.size = diagramSize( attributes, c );
00300   return true;
00301 }
00302 
00303 QList<int> QgsLinearlyInterpolatedDiagramRenderer::diagramAttributes() const
00304 {
00305   QList<int> attributes = mSettings.categoryIndices;
00306   if ( !attributes.contains( mClassificationAttribute ) )
00307   {
00308     attributes.push_back( mClassificationAttribute );
00309   }
00310   return attributes;
00311 }
00312 
00313 QSizeF QgsLinearlyInterpolatedDiagramRenderer::diagramSize( const QgsAttributeMap& attributes, const QgsRenderContext& c )
00314 {
00315   Q_UNUSED( c );
00316   QgsAttributeMap::const_iterator attIt = attributes.find( mClassificationAttribute );
00317   if ( attIt == attributes.constEnd() )
00318   {
00319     return QSizeF(); //zero size if attribute is missing
00320   }
00321   double value = attIt.value().toDouble();
00322 
00323   //interpolate size
00324   double ratio = ( value - mLowerValue ) / ( mUpperValue - mLowerValue );
00325   return QSizeF( mUpperSize.width() * ratio + mLowerSize.width() * ( 1 - ratio ),
00326                  mUpperSize.height() * ratio + mLowerSize.height() * ( 1 - ratio ) );
00327 }
00328 
00329 void QgsLinearlyInterpolatedDiagramRenderer::readXML( const QDomElement& elem )
00330 {
00331   mLowerValue = elem.attribute( "lowerValue" ).toDouble();
00332   mUpperValue = elem.attribute( "upperValue" ).toDouble();
00333   mLowerSize.setWidth( elem.attribute( "lowerWidth" ).toDouble() );
00334   mLowerSize.setHeight( elem.attribute( "lowerHeight" ).toDouble() );
00335   mUpperSize.setWidth( elem.attribute( "upperWidth" ).toDouble() );
00336   mUpperSize.setHeight( elem.attribute( "upperHeight" ).toDouble() );
00337   mClassificationAttribute = elem.attribute( "classificationAttribute" ).toInt();
00338   QDomElement settingsElem = elem.firstChildElement( "DiagramCategory" );
00339   if ( !settingsElem.isNull() )
00340   {
00341     mSettings.readXML( settingsElem );
00342   }
00343   _readXML( elem );
00344 }
00345 
00346 void QgsLinearlyInterpolatedDiagramRenderer::writeXML( QDomElement& layerElem, QDomDocument& doc ) const
00347 {
00348   QDomElement rendererElem = doc.createElement( "LinearlyInterpolatedDiagramRenderer" );
00349   rendererElem.setAttribute( "lowerValue", QString::number( mLowerValue ) );
00350   rendererElem.setAttribute( "upperValue", QString::number( mUpperValue ) );
00351   rendererElem.setAttribute( "lowerWidth", QString::number( mLowerSize.width() ) );
00352   rendererElem.setAttribute( "lowerHeight", QString::number( mLowerSize.height() ) );
00353   rendererElem.setAttribute( "upperWidth", QString::number( mUpperSize.width() ) );
00354   rendererElem.setAttribute( "upperHeight", QString::number( mUpperSize.height() ) );
00355   rendererElem.setAttribute( "classificationAttribute", mClassificationAttribute );
00356   mSettings.writeXML( rendererElem, doc );
00357   _writeXML( rendererElem, doc );
00358   layerElem.appendChild( rendererElem );
00359 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines