Quantum GIS API Documentation
1.8
|
00001 /*************************************************************************** 00002 qgssinglesymbolrendererv2.cpp 00003 --------------------- 00004 begin : November 2009 00005 copyright : (C) 2009 by Martin Dobias 00006 email : wonder.sk at gmail.com 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 00016 #include "qgssinglesymbolrendererv2.h" 00017 00018 #include "qgssymbolv2.h" 00019 #include "qgssymbollayerv2utils.h" 00020 00021 #include "qgslogger.h" 00022 #include "qgsfeature.h" 00023 #include "qgsvectorlayer.h" 00024 #include "qgssymbollayerv2.h" 00025 00026 #include <QDomDocument> 00027 #include <QDomElement> 00028 00029 QgsSingleSymbolRendererV2::QgsSingleSymbolRendererV2( QgsSymbolV2* symbol ) 00030 : QgsFeatureRendererV2( "singleSymbol" ), mRotationFieldIdx( -1 ), mSizeScaleFieldIdx( -1 ), mTempSymbol( NULL ) 00031 { 00032 Q_ASSERT( symbol ); 00033 mSymbol = symbol; 00034 } 00035 00036 QgsSingleSymbolRendererV2::~QgsSingleSymbolRendererV2() 00037 { 00038 delete mSymbol; 00039 } 00040 00041 QgsSymbolV2* QgsSingleSymbolRendererV2::symbolForFeature( QgsFeature& feature ) 00042 { 00043 if ( mRotationFieldIdx == -1 && mSizeScaleFieldIdx == -1 ) 00044 return mSymbol; 00045 00046 double rotation = 0; 00047 double sizeScale = 1; 00048 if ( mRotationFieldIdx != -1 ) 00049 { 00050 rotation = feature.attributeMap()[mRotationFieldIdx].toDouble(); 00051 } 00052 if ( mSizeScaleFieldIdx != -1 ) 00053 { 00054 sizeScale = feature.attributeMap()[mSizeScaleFieldIdx].toDouble(); 00055 } 00056 00057 if ( mTempSymbol->type() == QgsSymbolV2::Marker ) 00058 { 00059 QgsMarkerSymbolV2* markerSymbol = static_cast<QgsMarkerSymbolV2*>( mTempSymbol ); 00060 if ( mRotationFieldIdx != -1 ) 00061 markerSymbol->setAngle( rotation ); 00062 if ( mSizeScaleFieldIdx != -1 ) 00063 markerSymbol->setSize( sizeScale * mOrigSize ); 00064 } 00065 else if ( mTempSymbol->type() == QgsSymbolV2::Line ) 00066 { 00067 QgsLineSymbolV2* lineSymbol = static_cast<QgsLineSymbolV2*>( mTempSymbol ); 00068 if ( mSizeScaleFieldIdx != -1 ) 00069 lineSymbol->setWidth( sizeScale * mOrigSize ); 00070 } 00071 else if ( mTempSymbol->type() == QgsSymbolV2::Fill ) 00072 { 00073 QgsFillSymbolV2* fillSymbol = static_cast<QgsFillSymbolV2*>( mTempSymbol ); 00074 if ( mRotationFieldIdx != -1 ) 00075 fillSymbol->setAngle( rotation ); 00076 } 00077 00078 return mTempSymbol; 00079 } 00080 00081 void QgsSingleSymbolRendererV2::startRender( QgsRenderContext& context, const QgsVectorLayer *vlayer ) 00082 { 00083 if ( !mSymbol ) 00084 { 00085 return; 00086 } 00087 mRotationFieldIdx = mRotationField.isEmpty() ? -1 : vlayer->fieldNameIndex( mRotationField ); 00088 mSizeScaleFieldIdx = mSizeScaleField.isEmpty() ? -1 : vlayer->fieldNameIndex( mSizeScaleField ); 00089 00090 mSymbol->startRender( context, vlayer ); 00091 00092 if ( mRotationFieldIdx != -1 || mSizeScaleFieldIdx != -1 ) 00093 { 00094 // we are going to need a temporary symbol 00095 mTempSymbol = mSymbol->clone(); 00096 00097 int hints = 0; 00098 if ( mRotationFieldIdx != -1 ) 00099 hints |= QgsSymbolV2::DataDefinedRotation; 00100 if ( mSizeScaleFieldIdx != -1 ) 00101 hints |= QgsSymbolV2::DataDefinedSizeScale; 00102 mTempSymbol->setRenderHints( hints ); 00103 00104 mTempSymbol->startRender( context, vlayer ); 00105 00106 if ( mSymbol->type() == QgsSymbolV2::Marker ) 00107 { 00108 mOrigSize = static_cast<QgsMarkerSymbolV2*>( mSymbol )->size(); 00109 } 00110 else if ( mSymbol->type() == QgsSymbolV2::Line ) 00111 { 00112 mOrigSize = static_cast<QgsLineSymbolV2*>( mSymbol )->width(); 00113 } 00114 else 00115 { 00116 mOrigSize = 0; 00117 } 00118 } 00119 } 00120 00121 void QgsSingleSymbolRendererV2::stopRender( QgsRenderContext& context ) 00122 { 00123 if ( !mSymbol ) 00124 { 00125 return; 00126 } 00127 mSymbol->stopRender( context ); 00128 00129 if ( mRotationFieldIdx != -1 || mSizeScaleFieldIdx != -1 ) 00130 { 00131 // we are going to need a temporary symbol 00132 mTempSymbol->stopRender( context ); 00133 delete mTempSymbol; 00134 mTempSymbol = NULL; 00135 } 00136 } 00137 00138 QList<QString> QgsSingleSymbolRendererV2::usedAttributes() 00139 { 00140 QSet<QString> attributes; 00141 if ( mSymbol ) 00142 { 00143 attributes.unite( mSymbol->usedAttributes() ); 00144 } 00145 if ( !mRotationField.isEmpty() ) 00146 { 00147 attributes.insert( mRotationField ); 00148 } 00149 if ( !mSizeScaleField.isEmpty() ) 00150 { 00151 attributes.insert( mSizeScaleField ); 00152 } 00153 return attributes.toList(); 00154 } 00155 00156 QgsSymbolV2* QgsSingleSymbolRendererV2::symbol() const 00157 { 00158 return mSymbol; 00159 } 00160 00161 void QgsSingleSymbolRendererV2::setSymbol( QgsSymbolV2* s ) 00162 { 00163 Q_ASSERT( s ); 00164 delete mSymbol; 00165 mSymbol = s; 00166 } 00167 00168 QString QgsSingleSymbolRendererV2::dump() 00169 { 00170 if ( mSymbol ) 00171 { 00172 return QString( "SINGLE: %1" ).arg( mSymbol->dump() ); 00173 } 00174 else 00175 { 00176 return ""; 00177 } 00178 } 00179 00180 QgsFeatureRendererV2* QgsSingleSymbolRendererV2::clone() 00181 { 00182 QgsSingleSymbolRendererV2* r = new QgsSingleSymbolRendererV2( mSymbol->clone() ); 00183 r->setUsingSymbolLevels( usingSymbolLevels() ); 00184 r->setRotationField( rotationField() ); 00185 r->setSizeScaleField( sizeScaleField() ); 00186 return r; 00187 } 00188 00189 void QgsSingleSymbolRendererV2::toSld( QDomDocument& doc, QDomElement &element ) const 00190 { 00191 QgsStringMap props; 00192 if ( !mRotationField.isEmpty() ) 00193 props[ "angle" ] = QString( mRotationField ).append( "\"" ).prepend( "\"" ); 00194 if ( !mSizeScaleField.isEmpty() ) 00195 props[ "scale" ] = QString( mSizeScaleField ).append( "\"" ).prepend( "\"" ); 00196 00197 QDomElement ruleElem = doc.createElement( "se:Rule" ); 00198 element.appendChild( ruleElem ); 00199 00200 QDomElement nameElem = doc.createElement( "se:Name" ); 00201 nameElem.appendChild( doc.createTextNode( "Single symbol" ) ); 00202 ruleElem.appendChild( nameElem ); 00203 00204 mSymbol->toSld( doc, ruleElem, props ); 00205 } 00206 00207 QgsSymbolV2List QgsSingleSymbolRendererV2::symbols() 00208 { 00209 QgsSymbolV2List lst; 00210 lst.append( mSymbol ); 00211 return lst; 00212 } 00213 00214 QgsFeatureRendererV2* QgsSingleSymbolRendererV2::create( QDomElement& element ) 00215 { 00216 QDomElement symbolsElem = element.firstChildElement( "symbols" ); 00217 if ( symbolsElem.isNull() ) 00218 return NULL; 00219 00220 QgsSymbolV2Map symbolMap = QgsSymbolLayerV2Utils::loadSymbols( symbolsElem ); 00221 00222 if ( !symbolMap.contains( "0" ) ) 00223 return NULL; 00224 00225 QgsSingleSymbolRendererV2* r = new QgsSingleSymbolRendererV2( symbolMap.take( "0" ) ); 00226 00227 // delete symbols if there are any more 00228 QgsSymbolLayerV2Utils::clearSymbolMap( symbolMap ); 00229 00230 QDomElement rotationElem = element.firstChildElement( "rotation" ); 00231 if ( !rotationElem.isNull() ) 00232 r->setRotationField( rotationElem.attribute( "field" ) ); 00233 00234 QDomElement sizeScaleElem = element.firstChildElement( "sizescale" ); 00235 if ( !sizeScaleElem.isNull() ) 00236 r->setSizeScaleField( sizeScaleElem.attribute( "field" ) ); 00237 00238 // TODO: symbol levels 00239 return r; 00240 } 00241 00242 QgsFeatureRendererV2* QgsSingleSymbolRendererV2::createFromSld( QDomElement& element, QGis::GeometryType geomType ) 00243 { 00244 // XXX this renderer can handle only one Rule! 00245 00246 // get the first Rule element 00247 QDomElement ruleElem = element.firstChildElement( "Rule" ); 00248 if ( ruleElem.isNull() ) 00249 { 00250 QgsDebugMsg( "no Rule elements found!" ); 00251 return NULL; 00252 } 00253 00254 QString label, description; 00255 QgsSymbolLayerV2List layers; 00256 00257 // retrieve the Rule element child nodes 00258 QDomElement childElem = ruleElem.firstChildElement(); 00259 while ( !childElem.isNull() ) 00260 { 00261 if ( childElem.localName() == "Name" ) 00262 { 00263 label = childElem.firstChild().nodeValue(); 00264 } 00265 else if ( childElem.localName() == "Description" || childElem.localName() == "Abstract" ) 00266 { 00267 description = childElem.firstChild().nodeValue(); 00268 } 00269 else if ( childElem.localName().endsWith( "Symbolizer" ) ) 00270 { 00271 // create symbol layers for this symbolizer 00272 QgsSymbolLayerV2Utils::createSymbolLayerV2ListFromSld( childElem, geomType, layers ); 00273 } 00274 00275 childElem = childElem.nextSiblingElement(); 00276 } 00277 00278 // now create the symbol 00279 QgsSymbolV2 *symbol = 0; 00280 if ( layers.size() > 0 ) 00281 { 00282 switch ( geomType ) 00283 { 00284 case QGis::Line: 00285 symbol = new QgsLineSymbolV2( layers ); 00286 break; 00287 00288 case QGis::Polygon: 00289 symbol = new QgsFillSymbolV2( layers ); 00290 break; 00291 00292 case QGis::Point: 00293 symbol = new QgsMarkerSymbolV2( layers ); 00294 break; 00295 00296 default: 00297 QgsDebugMsg( QString( "invalid geometry type: found %1" ).arg( geomType ) ); 00298 return NULL; 00299 } 00300 } 00301 00302 // and finally return the new renderer 00303 return new QgsSingleSymbolRendererV2( symbol ); 00304 } 00305 00306 QDomElement QgsSingleSymbolRendererV2::save( QDomDocument& doc ) 00307 { 00308 QDomElement rendererElem = doc.createElement( RENDERER_TAG_NAME ); 00309 rendererElem.setAttribute( "type", "singleSymbol" ); 00310 rendererElem.setAttribute( "symbollevels", ( mUsingSymbolLevels ? "1" : "0" ) ); 00311 00312 QgsSymbolV2Map symbols; 00313 symbols["0"] = mSymbol; 00314 QDomElement symbolsElem = QgsSymbolLayerV2Utils::saveSymbols( symbols, "symbols", doc ); 00315 rendererElem.appendChild( symbolsElem ); 00316 00317 QDomElement rotationElem = doc.createElement( "rotation" ); 00318 rotationElem.setAttribute( "field", mRotationField ); 00319 rendererElem.appendChild( rotationElem ); 00320 00321 QDomElement sizeScaleElem = doc.createElement( "sizescale" ); 00322 sizeScaleElem.setAttribute( "field", mSizeScaleField ); 00323 rendererElem.appendChild( sizeScaleElem ); 00324 00325 return rendererElem; 00326 } 00327 00328 QgsLegendSymbologyList QgsSingleSymbolRendererV2::legendSymbologyItems( QSize iconSize ) 00329 { 00330 QgsLegendSymbologyList lst; 00331 if ( mSymbol ) 00332 { 00333 QPixmap pix = QgsSymbolLayerV2Utils::symbolPreviewPixmap( mSymbol, iconSize ); 00334 lst << qMakePair( QString(), pix ); 00335 } 00336 return lst; 00337 } 00338 00339 QgsLegendSymbolList QgsSingleSymbolRendererV2::legendSymbolItems() 00340 { 00341 QgsLegendSymbolList lst; 00342 lst << qMakePair( QString(), mSymbol ); 00343 return lst; 00344 }