|
QGIS API Documentation
master-6164ace
|
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 }