Quantum GIS API Documentation  1.7.4
src/core/renderer/qgsuniquevaluerenderer.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002                          qgsuniquevaluerenderer.cpp  -  description
00003                              -------------------
00004     begin                : July 2004
00005     copyright            : (C) 2004 by Marco Hugentobler
00006     email                : [email protected]
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 /* $Id: qgsuniquevaluerenderer.cpp 5371 2006-04-25 01:52:13Z wonder $ */
00018 
00019 #include "qgsuniquevaluerenderer.h"
00020 #include "qgsfeature.h"
00021 #include "qgsvectordataprovider.h"
00022 #include "qgsvectorlayer.h"
00023 #include "qgsrendercontext.h"
00024 #include "qgssymbol.h"
00025 #include "qgssymbologyutils.h"
00026 #include "qgslogger.h"
00027 #include <cmath>
00028 #include <QDomNode>
00029 #include <QPainter>
00030 #include <QImage>
00031 #include <vector>
00032 
00033 QgsUniqueValueRenderer::QgsUniqueValueRenderer( QGis::GeometryType type ): mClassificationField( 0 )
00034 {
00035   mGeometryType = type;
00036   mSymbolAttributesDirty = false;
00037 }
00038 
00039 QgsUniqueValueRenderer::QgsUniqueValueRenderer( const QgsUniqueValueRenderer& other )
00040 {
00041   mGeometryType = other.mGeometryType;
00042   mClassificationField = other.mClassificationField;
00043   QMap<QString, QgsSymbol*> s = other.mSymbols;
00044   for ( QMap<QString, QgsSymbol*>::iterator it = s.begin(); it != s.end(); ++it )
00045   {
00046     QgsSymbol* s = new QgsSymbol( * it.value() );
00047     insertValue( it.key(), s );
00048   }
00049   updateSymbolAttributes();
00050 }
00051 
00052 QgsUniqueValueRenderer& QgsUniqueValueRenderer::operator=( const QgsUniqueValueRenderer & other )
00053 {
00054   if ( this != &other )
00055   {
00056     mGeometryType = other.mGeometryType;
00057     mClassificationField = other.mClassificationField;
00058     clearValues();
00059     for ( QMap<QString, QgsSymbol*>::iterator it = mSymbols.begin(); it != mSymbols.end(); ++it )
00060     {
00061       QgsSymbol* s = new QgsSymbol( *it.value() );
00062       insertValue( it.key(), s );
00063     }
00064     updateSymbolAttributes();
00065   }
00066   return *this;
00067 }
00068 
00069 QgsUniqueValueRenderer::~QgsUniqueValueRenderer()
00070 {
00071   for ( QMap<QString, QgsSymbol*>::iterator it = mSymbols.begin(); it != mSymbols.end(); ++it )
00072   {
00073     delete it.value();
00074   }
00075 }
00076 
00077 void QgsUniqueValueRenderer::insertValue( QString name, QgsSymbol* symbol )
00078 {
00079   mSymbols.insert( name, symbol );
00080   mSymbolAttributesDirty = true;
00081 }
00082 
00083 void QgsUniqueValueRenderer::setClassificationField( int field )
00084 {
00085   mClassificationField = field;
00086 }
00087 
00088 int QgsUniqueValueRenderer::classificationField() const
00089 {
00090   return mClassificationField;
00091 }
00092 
00093 bool QgsUniqueValueRenderer::willRenderFeature( QgsFeature *f )
00094 {
00095   return ( symbolForFeature( f ) != 0 );
00096 }
00097 
00098 void QgsUniqueValueRenderer::renderFeature( QgsRenderContext &renderContext, QgsFeature& f, QImage* img, bool selected, double opacity )
00099 {
00100   QPainter *p = renderContext.painter();
00101   QgsSymbol* symbol = symbolForFeature( &f );
00102   if ( !symbol ) //no matching symbol
00103   {
00104     if ( img && mGeometryType == QGis::Point )
00105     {
00106       img->fill( 0 );
00107     }
00108     else if ( mGeometryType != QGis::Point )
00109     {
00110       p->setPen( Qt::NoPen );
00111       p->setBrush( Qt::NoBrush );
00112     }
00113     return;
00114   }
00115 
00116   // Point
00117   if ( img && mGeometryType == QGis::Point )
00118   {
00119     double fieldScale = 1.0;
00120     double rotation = 0.0;
00121 
00122     if ( symbol->scaleClassificationField() >= 0 )
00123     {
00124       //first find out the value for the scale classification attribute
00125       const QgsAttributeMap& attrs = f.attributeMap();
00126       fieldScale = sqrt( qAbs( attrs[symbol->scaleClassificationField()].toDouble() ) );
00127     }
00128     if ( symbol->rotationClassificationField() >= 0 )
00129     {
00130       const QgsAttributeMap& attrs = f.attributeMap();
00131       rotation = attrs[symbol->rotationClassificationField()].toDouble();
00132     }
00133 
00134     QString oldName;
00135 
00136     if ( symbol->symbolField() >= 0 )
00137     {
00138       const QgsAttributeMap& attrs = f.attributeMap();
00139       QString name = attrs[symbol->symbolField()].toString();
00140       oldName = symbol->pointSymbolName();
00141       symbol->setNamedPointSymbol( name );
00142     }
00143 
00144     double scale = renderContext.scaleFactor();
00145 
00146     if ( symbol->pointSizeUnits() )
00147     {
00148       scale = 1.0 / renderContext.mapToPixel().mapUnitsPerPixel();
00149     }
00150 
00151     *img = symbol->getPointSymbolAsImage( scale, selected, mSelectionColor,
00152                                           fieldScale, rotation, renderContext.rasterScaleFactor(),
00153                                           opacity );
00154     if ( !oldName.isNull() )
00155     {
00156       symbol->setNamedPointSymbol( oldName );
00157     }
00158   }
00159   // Line, polygon
00160   else if ( mGeometryType != QGis::Point )
00161   {
00162     if ( !selected )
00163     {
00164       QPen pen = symbol->pen();
00165       pen.setWidthF( renderContext.scaleFactor() * pen.widthF() );
00166       p->setPen( pen );
00167       if ( mGeometryType == QGis::Polygon )
00168       {
00169         QBrush brush = symbol->brush();
00170         scaleBrush( brush, renderContext.rasterScaleFactor() ); //scale brush content for printout
00171         p->setBrush( brush );
00172       }
00173     }
00174     else
00175     {
00176       QPen pen = symbol->pen();
00177       pen.setWidthF( renderContext.scaleFactor() * pen.widthF() );
00178       if ( mGeometryType == QGis::Polygon )
00179       {
00180         QBrush brush = symbol->brush();
00181         scaleBrush( brush, renderContext.rasterScaleFactor() ); //scale brush content for printout
00182         brush.setColor( mSelectionColor );
00183         p->setBrush( brush );
00184       }
00185       else //don't draw outlines of polygons in selection color otherwise they appear merged
00186       {
00187         pen.setColor( mSelectionColor );
00188       }
00189       p->setPen( pen );
00190     }
00191   }
00192 }
00193 
00194 QgsSymbol *QgsUniqueValueRenderer::symbolForFeature( const QgsFeature *f )
00195 {
00196   //first find out the value
00197   const QgsAttributeMap& attrs = f->attributeMap();
00198   QString value = attrs[mClassificationField].toString();
00199 
00200   QMap<QString, QgsSymbol*>::iterator it = mSymbols.find( value );
00201   if ( it == mSymbols.end() )
00202   {
00203     it = mSymbols.find( QString::null );
00204   }
00205 
00206   if ( it == mSymbols.end() )
00207   {
00208     return 0;
00209   }
00210   else
00211   {
00212     return it.value();
00213   }
00214 }
00215 
00216 int QgsUniqueValueRenderer::readXML( const QDomNode& rnode, QgsVectorLayer& vl )
00217 {
00218   mGeometryType = vl.geometryType();
00219   QDomNode classnode = rnode.namedItem( "classificationfield" );
00220   QString classificationField = classnode.toElement().text();
00221 
00222   QgsVectorDataProvider* theProvider = vl.dataProvider();
00223   if ( !theProvider )
00224   {
00225     return 1;
00226   }
00227 
00228   int classificationId = theProvider->fieldNameIndex( classificationField );
00229   if ( classificationId == -1 )
00230   {
00231     //go on. Because with joins, it might be the joined layer is not loaded yet
00232   }
00233   setClassificationField( classificationId );
00234 
00235   QDomNode symbolnode = rnode.namedItem( "symbol" );
00236   while ( !symbolnode.isNull() )
00237   {
00238     QgsSymbol* msy = new QgsSymbol( mGeometryType );
00239     msy->readXML( symbolnode, &vl );
00240     insertValue( msy->lowerValue(), msy );
00241     symbolnode = symbolnode.nextSibling();
00242   }
00243   updateSymbolAttributes();
00244   vl.setRenderer( this );
00245   return 0;
00246 }
00247 
00248 void QgsUniqueValueRenderer::clearValues()
00249 {
00250   for ( QMap<QString, QgsSymbol*>::iterator it = mSymbols.begin(); it != mSymbols.end(); ++it )
00251   {
00252     delete it.value();
00253   }
00254   mSymbols.clear();
00255   updateSymbolAttributes();
00256 }
00257 
00258 void QgsUniqueValueRenderer::updateSymbolAttributes()
00259 {
00260   mSymbolAttributesDirty = false;
00261 
00262   mSymbolAttributes.clear();
00263 
00264   QMap<QString, QgsSymbol*>::iterator it;
00265   for ( it = mSymbols.begin(); it != mSymbols.end(); ++it )
00266   {
00267     int rotationField = ( *it )->rotationClassificationField();
00268     if ( rotationField >= 0 && !( mSymbolAttributes.contains( rotationField ) ) )
00269     {
00270       mSymbolAttributes.append( rotationField );
00271     }
00272     int scaleField = ( *it )->scaleClassificationField();
00273     if ( scaleField >= 0 && !( mSymbolAttributes.contains( scaleField ) ) )
00274     {
00275       mSymbolAttributes.append( scaleField );
00276     }
00277     int symbolField = ( *it )->symbolField();
00278     if ( symbolField >= 0 && !mSymbolAttributes.contains( symbolField ) )
00279     {
00280       mSymbolAttributes.append( symbolField );
00281     }
00282   }
00283 }
00284 
00285 QString QgsUniqueValueRenderer::name() const
00286 {
00287   return "Unique Value";
00288 }
00289 
00290 QgsAttributeList QgsUniqueValueRenderer::classificationAttributes() const
00291 {
00292   QgsAttributeList list( mSymbolAttributes );
00293   if ( ! list.contains( mClassificationField ) )
00294   {
00295     list.append( mClassificationField );
00296   }
00297   return list;
00298 }
00299 
00300 bool QgsUniqueValueRenderer::writeXML( QDomNode & layer_node, QDomDocument & document, const QgsVectorLayer& vl ) const
00301 {
00302   const QgsVectorDataProvider* theProvider = vl.dataProvider();
00303   if ( !theProvider )
00304   {
00305     return false;
00306   }
00307 
00308   QString classificationFieldName;
00309   QgsFieldMap::const_iterator field_it = theProvider->fields().find( mClassificationField );
00310   if ( field_it != theProvider->fields().constEnd() )
00311   {
00312     classificationFieldName = field_it.value().name();
00313   }
00314 
00315   bool returnval = true;
00316   QDomElement uniquevalue = document.createElement( "uniquevalue" );
00317   layer_node.appendChild( uniquevalue );
00318   QDomElement classificationfield = document.createElement( "classificationfield" );
00319   QDomText classificationfieldtxt = document.createTextNode( classificationFieldName );
00320   classificationfield.appendChild( classificationfieldtxt );
00321   uniquevalue.appendChild( classificationfield );
00322   for ( QMap<QString, QgsSymbol*>::const_iterator it = mSymbols.begin(); it != mSymbols.end(); ++it )
00323   {
00324     if ( !( it.value()->writeXML( uniquevalue, document, &vl ) ) )
00325     {
00326       returnval = false;
00327     }
00328   }
00329   return returnval;
00330 }
00331 
00332 QgsRenderer* QgsUniqueValueRenderer::clone() const
00333 {
00334   QgsUniqueValueRenderer* r = new QgsUniqueValueRenderer( *this );
00335   return r;
00336 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines