Quantum GIS API Documentation  1.7.5-Wroclaw
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
qgsuniquevaluerenderer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsuniquevaluerenderer.cpp - description
3  -------------------
4  begin : July 2004
5  copyright : (C) 2004 by Marco Hugentobler
6  email : marco.hugentobler@autoform.ch
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 /* $Id: qgsuniquevaluerenderer.cpp 5371 2006-04-25 01:52:13Z wonder $ */
18 
19 #include "qgsuniquevaluerenderer.h"
20 #include "qgsfeature.h"
21 #include "qgsvectordataprovider.h"
22 #include "qgsvectorlayer.h"
23 #include "qgsrendercontext.h"
24 #include "qgssymbol.h"
25 #include "qgssymbologyutils.h"
26 #include "qgslogger.h"
27 #include <cmath>
28 #include <QDomNode>
29 #include <QPainter>
30 #include <QImage>
31 #include <vector>
32 
34 {
35  mGeometryType = type;
36  mSymbolAttributesDirty = false;
37 }
38 
40 {
43  QMap<QString, QgsSymbol*> s = other.mSymbols;
44  for ( QMap<QString, QgsSymbol*>::iterator it = s.begin(); it != s.end(); ++it )
45  {
46  QgsSymbol* s = new QgsSymbol( * it.value() );
47  insertValue( it.key(), s );
48  }
50 }
51 
53 {
54  if ( this != &other )
55  {
58  clearValues();
59  for ( QMap<QString, QgsSymbol*>::iterator it = mSymbols.begin(); it != mSymbols.end(); ++it )
60  {
61  QgsSymbol* s = new QgsSymbol( *it.value() );
62  insertValue( it.key(), s );
63  }
65  }
66  return *this;
67 }
68 
70 {
71  for ( QMap<QString, QgsSymbol*>::iterator it = mSymbols.begin(); it != mSymbols.end(); ++it )
72  {
73  delete it.value();
74  }
75 }
76 
77 void QgsUniqueValueRenderer::insertValue( QString name, QgsSymbol* symbol )
78 {
79  mSymbols.insert( name, symbol );
81 }
82 
84 {
85  mClassificationField = field;
86 }
87 
89 {
90  return mClassificationField;
91 }
92 
94 {
95  return ( symbolForFeature( f ) != 0 );
96 }
97 
98 void QgsUniqueValueRenderer::renderFeature( QgsRenderContext &renderContext, QgsFeature& f, QImage* img, bool selected, double opacity )
99 {
100  QPainter *p = renderContext.painter();
101  QgsSymbol* symbol = symbolForFeature( &f );
102  if ( !symbol ) //no matching symbol
103  {
104  if ( img && mGeometryType == QGis::Point )
105  {
106  img->fill( 0 );
107  }
108  else if ( mGeometryType != QGis::Point )
109  {
110  p->setPen( Qt::NoPen );
111  p->setBrush( Qt::NoBrush );
112  }
113  return;
114  }
115 
116  // Point
117  if ( img && mGeometryType == QGis::Point )
118  {
119  double fieldScale = 1.0;
120  double rotation = 0.0;
121 
122  if ( symbol->scaleClassificationField() >= 0 )
123  {
124  //first find out the value for the scale classification attribute
125  const QgsAttributeMap& attrs = f.attributeMap();
126  fieldScale = sqrt( qAbs( attrs[symbol->scaleClassificationField()].toDouble() ) );
127  }
128  if ( symbol->rotationClassificationField() >= 0 )
129  {
130  const QgsAttributeMap& attrs = f.attributeMap();
131  rotation = attrs[symbol->rotationClassificationField()].toDouble();
132  }
133 
134  QString oldName;
135 
136  if ( symbol->symbolField() >= 0 )
137  {
138  const QgsAttributeMap& attrs = f.attributeMap();
139  QString name = attrs[symbol->symbolField()].toString();
140  oldName = symbol->pointSymbolName();
141  symbol->setNamedPointSymbol( name );
142  }
143 
144  double scale = renderContext.scaleFactor();
145 
146  if ( symbol->pointSizeUnits() )
147  {
148  scale = 1.0 / renderContext.mapToPixel().mapUnitsPerPixel();
149  }
150 
151  *img = symbol->getPointSymbolAsImage( scale, selected, mSelectionColor,
152  fieldScale, rotation, renderContext.rasterScaleFactor(),
153  opacity );
154  if ( !oldName.isNull() )
155  {
156  symbol->setNamedPointSymbol( oldName );
157  }
158  }
159  // Line, polygon
160  else if ( mGeometryType != QGis::Point )
161  {
162  if ( !selected )
163  {
164  QPen pen = symbol->pen();
165  pen.setWidthF( renderContext.scaleFactor() * pen.widthF() );
166  p->setPen( pen );
167  if ( mGeometryType == QGis::Polygon )
168  {
169  QBrush brush = symbol->brush();
170  scaleBrush( brush, renderContext.rasterScaleFactor() ); //scale brush content for printout
171  p->setBrush( brush );
172  }
173  }
174  else
175  {
176  QPen pen = symbol->pen();
177  pen.setWidthF( renderContext.scaleFactor() * pen.widthF() );
178  if ( mGeometryType == QGis::Polygon )
179  {
180  QBrush brush = symbol->brush();
181  scaleBrush( brush, renderContext.rasterScaleFactor() ); //scale brush content for printout
182  brush.setColor( mSelectionColor );
183  p->setBrush( brush );
184  }
185  else //don't draw outlines of polygons in selection color otherwise they appear merged
186  {
187  pen.setColor( mSelectionColor );
188  }
189  p->setPen( pen );
190  }
191  }
192 }
193 
195 {
196  //first find out the value
197  const QgsAttributeMap& attrs = f->attributeMap();
198  QString value = attrs[mClassificationField].toString();
199 
200  QMap<QString, QgsSymbol*>::iterator it = mSymbols.find( value );
201  if ( it == mSymbols.end() )
202  {
203  it = mSymbols.find( QString::null );
204  }
205 
206  if ( it == mSymbols.end() )
207  {
208  return 0;
209  }
210  else
211  {
212  return it.value();
213  }
214 }
215 
216 int QgsUniqueValueRenderer::readXML( const QDomNode& rnode, QgsVectorLayer& vl )
217 {
219  QDomNode classnode = rnode.namedItem( "classificationfield" );
220  QString classificationField = classnode.toElement().text();
221 
222  QgsVectorDataProvider* theProvider = vl.dataProvider();
223  if ( !theProvider )
224  {
225  return 1;
226  }
227 
228  int classificationId = theProvider->fieldNameIndex( classificationField );
229  if ( classificationId == -1 )
230  {
231  //go on. Because with joins, it might be the joined layer is not loaded yet
232  }
233  setClassificationField( classificationId );
234 
235  QDomNode symbolnode = rnode.namedItem( "symbol" );
236  while ( !symbolnode.isNull() )
237  {
238  QgsSymbol* msy = new QgsSymbol( mGeometryType );
239  msy->readXML( symbolnode, &vl );
240  insertValue( msy->lowerValue(), msy );
241  symbolnode = symbolnode.nextSibling();
242  }
244  vl.setRenderer( this );
245  return 0;
246 }
247 
249 {
250  for ( QMap<QString, QgsSymbol*>::iterator it = mSymbols.begin(); it != mSymbols.end(); ++it )
251  {
252  delete it.value();
253  }
254  mSymbols.clear();
256 }
257 
259 {
260  mSymbolAttributesDirty = false;
261 
262  mSymbolAttributes.clear();
263 
264  QMap<QString, QgsSymbol*>::iterator it;
265  for ( it = mSymbols.begin(); it != mSymbols.end(); ++it )
266  {
267  int rotationField = ( *it )->rotationClassificationField();
268  if ( rotationField >= 0 && !( mSymbolAttributes.contains( rotationField ) ) )
269  {
270  mSymbolAttributes.append( rotationField );
271  }
272  int scaleField = ( *it )->scaleClassificationField();
273  if ( scaleField >= 0 && !( mSymbolAttributes.contains( scaleField ) ) )
274  {
275  mSymbolAttributes.append( scaleField );
276  }
277  int symbolField = ( *it )->symbolField();
278  if ( symbolField >= 0 && !mSymbolAttributes.contains( symbolField ) )
279  {
280  mSymbolAttributes.append( symbolField );
281  }
282  }
283 }
284 
286 {
287  return "Unique Value";
288 }
289 
291 {
293  if ( ! list.contains( mClassificationField ) )
294  {
295  list.append( mClassificationField );
296  }
297  return list;
298 }
299 
300 bool QgsUniqueValueRenderer::writeXML( QDomNode & layer_node, QDomDocument & document, const QgsVectorLayer& vl ) const
301 {
302  const QgsVectorDataProvider* theProvider = vl.dataProvider();
303  if ( !theProvider )
304  {
305  return false;
306  }
307 
308  QString classificationFieldName;
309  QgsFieldMap::const_iterator field_it = theProvider->fields().find( mClassificationField );
310  if ( field_it != theProvider->fields().constEnd() )
311  {
312  classificationFieldName = field_it.value().name();
313  }
314 
315  bool returnval = true;
316  QDomElement uniquevalue = document.createElement( "uniquevalue" );
317  layer_node.appendChild( uniquevalue );
318  QDomElement classificationfield = document.createElement( "classificationfield" );
319  QDomText classificationfieldtxt = document.createTextNode( classificationFieldName );
320  classificationfield.appendChild( classificationfieldtxt );
321  uniquevalue.appendChild( classificationfield );
322  for ( QMap<QString, QgsSymbol*>::const_iterator it = mSymbols.begin(); it != mSymbols.end(); ++it )
323  {
324  if ( !( it.value()->writeXML( uniquevalue, document, &vl ) ) )
325  {
326  returnval = false;
327  }
328  }
329  return returnval;
330 }
331 
333 {
335  return r;
336 }