Quantum GIS API Documentation  1.8
src/core/symbology-ng/qgssinglesymbolrendererv2.cpp
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines