QGIS API Documentation  2.11.0-Master
qgsrulebasedrendererv2.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsrulebasedrendererv2.cpp - Rule-based renderer (symbology-ng)
3  ---------------------
4  begin : May 2010
5  copyright : (C) 2010 by Martin Dobias
6  email : wonder dot sk at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgsrulebasedrendererv2.h"
17 #include "qgssymbollayerv2.h"
18 #include "qgsexpression.h"
19 #include "qgssymbollayerv2utils.h"
20 #include "qgsrendercontext.h"
21 #include "qgsvectorlayer.h"
22 #include "qgslogger.h"
23 #include "qgsogcutils.h"
27 #include "qgspainteffect.h"
28 #include "qgsdatadefined.h"
29 
30 #include <QSet>
31 
32 #include <QDomDocument>
33 #include <QDomElement>
34 #include <QUuid>
35 
36 
37 QgsRuleBasedRendererV2::Rule::Rule( QgsSymbolV2* symbol, int scaleMinDenom, int scaleMaxDenom, QString filterExp, QString label, QString description, bool elseRule )
38  : mParent( NULL ), mSymbol( symbol )
39  , mScaleMinDenom( scaleMinDenom ), mScaleMaxDenom( scaleMaxDenom )
40  , mFilterExp( filterExp ), mLabel( label ), mDescription( description )
41  , mElseRule( elseRule )
42  , mCheckState( true )
43  , mFilter( NULL )
44 {
46  initFilter();
47 }
48 
50 {
51  delete mSymbol;
52  delete mFilter;
53  qDeleteAll( mChildren );
54  // do NOT delete parent
55 }
56 
58 {
59  if ( mElseRule || mFilterExp.compare( "ELSE", Qt::CaseInsensitive ) == 0 )
60  {
61  mElseRule = true;
62  mFilter = NULL;
63  }
64  else if ( !mFilterExp.isEmpty() )
65  {
66  delete mFilter;
67  mFilter = new QgsExpression( mFilterExp );
68  }
69  else
70  {
71  mFilter = NULL;
72  }
73 }
74 
76 {
77  mChildren.append( rule );
78  rule->mParent = this;
79  updateElseRules();
80 }
81 
83 {
84  mChildren.insert( i, rule );
85  rule->mParent = this;
86  updateElseRules();
87 }
88 
90 {
91  mChildren.removeAll( rule );
92  delete rule;
93  updateElseRules();
94 }
95 
97 {
98  Rule* rule = mChildren[i];
99  mChildren.removeAt( i );
100  delete rule;
101  updateElseRules();
102 }
103 
105 {
106  mChildren.removeAll( rule );
107  rule->mParent = NULL;
108  updateElseRules();
109 }
110 
112 {
113  Rule* rule = mChildren.takeAt( i );
114  rule->mParent = NULL;
115  return rule;
116  // updateElseRules();
117 }
118 
120 {
121  // we could use a hash / map for search if this will be slow...
122 
123  if ( key == mRuleKey )
124  return this;
125 
126  foreach ( Rule* rule, mChildren )
127  {
128  Rule* r = rule->findRuleByKey( key );
129  if ( r )
130  return r;
131  }
132  return 0;
133 }
134 
136 {
137  mElseRules.clear();
138  foreach ( Rule* rule, mChildren )
139  {
140  if ( rule->isElse() )
141  mElseRules << rule;
142  }
143 }
144 
145 
147 {
148  QString off;
149  off.fill( QChar( ' ' ), offset );
150  QString symbolDump = ( mSymbol ? mSymbol->dump() : QString( "[]" ) );
151  QString msg = off + QString( "RULE %1 - scale [%2,%3] - filter %4 - symbol %5\n" )
152  .arg( mLabel ).arg( mScaleMinDenom ).arg( mScaleMaxDenom )
153  .arg( mFilterExp ).arg( symbolDump );
154 
155  QStringList lst;
156  foreach ( Rule* rule, mChildren )
157  {
158  lst.append( rule->dump( offset + 2 ) );
159  }
160  msg += lst.join( "\n" );
161  return msg;
162 }
163 
165 {
166  // attributes needed by this rule
167  QSet<QString> attrs;
168  if ( mFilter )
169  attrs.unite( mFilter->referencedColumns().toSet() );
170  if ( mSymbol )
171  attrs.unite( mSymbol->usedAttributes() );
172 
173  // attributes needed by child rules
174  for ( RuleList::iterator it = mChildren.begin(); it != mChildren.end(); ++it )
175  {
176  Rule* rule = *it;
177  attrs.unite( rule->usedAttributes() );
178  }
179  return attrs;
180 }
181 
183 {
184  QgsSymbolV2List lst;
185  if ( mSymbol )
186  lst.append( mSymbol );
187 
188  for ( RuleList::iterator it = mChildren.begin(); it != mChildren.end(); ++it )
189  {
190  Rule* rule = *it;
191  lst += rule->symbols();
192  }
193  return lst;
194 }
195 
197 {
198  delete mSymbol;
199  mSymbol = sym;
200 }
201 
203 {
205  if ( mSymbol && ( ruleFilter.isEmpty() || mLabel == ruleFilter ) )
206  lst << qMakePair( mLabel, mSymbol );
207 
208  for ( RuleList::iterator it = mChildren.begin(); it != mChildren.end(); ++it )
209  {
210  Rule* rule = *it;
211  if ( scaleDenominator == -1 || rule->isScaleOK( scaleDenominator ) )
212  {
213  lst << rule->legendSymbolItems( scaleDenominator, ruleFilter );
214  }
215  }
216  return lst;
217 }
218 
220 {
222  if ( currentLevel != -1 ) // root rule should not be shown
223  {
224  lst << QgsLegendSymbolItemV2( mSymbol, mLabel, mRuleKey, true, mScaleMinDenom, mScaleMaxDenom, currentLevel, mParent ? mParent->mRuleKey : QString() );
225  }
226 
227  for ( RuleList::const_iterator it = mChildren.constBegin(); it != mChildren.constEnd(); ++it )
228  {
229  Rule* rule = *it;
230  lst << rule->legendSymbolItemsV2( currentLevel + 1 );
231  }
232  return lst;
233 }
234 
235 
237 {
238  if ( ! mFilter || mElseRule )
239  return true;
240 
241  QVariant res = mFilter->evaluate( &f );
242  return res.toInt() != 0;
243 }
244 
245 bool QgsRuleBasedRendererV2::Rule::isScaleOK( double scale ) const
246 {
247  if ( scale == 0 ) // so that we can count features in classes without scale context
248  return true;
249  if ( mScaleMinDenom == 0 && mScaleMaxDenom == 0 )
250  return true;
251  if ( mScaleMinDenom != 0 && mScaleMinDenom > scale )
252  return false;
253  if ( mScaleMaxDenom != 0 && mScaleMaxDenom < scale )
254  return false;
255  return true;
256 }
257 
259 {
260  QgsSymbolV2* sym = mSymbol ? mSymbol->clone() : NULL;
261  Rule* newrule = new Rule( sym, mScaleMinDenom, mScaleMaxDenom, mFilterExp, mLabel, mDescription );
262  newrule->setCheckState( mCheckState );
263  // clone children
264  foreach ( Rule* rule, mChildren )
265  newrule->appendChild( rule->clone() );
266  return newrule;
267 }
268 
270 {
271  QDomElement ruleElem = doc.createElement( "rule" );
272 
273  if ( mSymbol )
274  {
275  int symbolIndex = symbolMap.size();
276  symbolMap[QString::number( symbolIndex )] = mSymbol;
277  ruleElem.setAttribute( "symbol", symbolIndex );
278  }
279  if ( !mFilterExp.isEmpty() )
280  ruleElem.setAttribute( "filter", mFilterExp );
281  if ( mScaleMinDenom != 0 )
282  ruleElem.setAttribute( "scalemindenom", mScaleMinDenom );
283  if ( mScaleMaxDenom != 0 )
284  ruleElem.setAttribute( "scalemaxdenom", mScaleMaxDenom );
285  if ( !mLabel.isEmpty() )
286  ruleElem.setAttribute( "label", mLabel );
287  if ( !mDescription.isEmpty() )
288  ruleElem.setAttribute( "description", mDescription );
289  if ( !mCheckState )
290  ruleElem.setAttribute( "checkstate", 0 );
291  ruleElem.setAttribute( "key", mRuleKey );
292 
293  for ( RuleList::iterator it = mChildren.begin(); it != mChildren.end(); ++it )
294  {
295  Rule* rule = *it;
296  ruleElem.appendChild( rule->save( doc, symbolMap ) );
297  }
298  return ruleElem;
299 }
300 
302 {
303  // do not convert this rule if there are no symbols
304  if ( symbols().isEmpty() )
305  return;
306 
307  if ( !mFilterExp.isEmpty() )
308  {
309  if ( !props.value( "filter", "" ).isEmpty() )
310  props[ "filter" ] += " AND ";
311  props[ "filter" ] += mFilterExp;
312  }
313 
314  if ( mScaleMinDenom != 0 )
315  {
316  bool ok;
317  int parentScaleMinDenom = props.value( "scaleMinDenom", "0" ).toInt( &ok );
318  if ( !ok || parentScaleMinDenom <= 0 )
319  props[ "scaleMinDenom" ] = QString::number( mScaleMinDenom );
320  else
321  props[ "scaleMinDenom" ] = QString::number( qMax( parentScaleMinDenom, mScaleMinDenom ) );
322  }
323 
324  if ( mScaleMaxDenom != 0 )
325  {
326  bool ok;
327  int parentScaleMaxDenom = props.value( "scaleMaxDenom", "0" ).toInt( &ok );
328  if ( !ok || parentScaleMaxDenom <= 0 )
329  props[ "scaleMaxDenom" ] = QString::number( mScaleMaxDenom );
330  else
331  props[ "scaleMaxDenom" ] = QString::number( qMin( parentScaleMaxDenom, mScaleMaxDenom ) );
332  }
333 
334  if ( mSymbol )
335  {
336  QDomElement ruleElem = doc.createElement( "se:Rule" );
337  element.appendChild( ruleElem );
338 
339  //XXX: <se:Name> is the rule identifier, but our the Rule objects
340  // have no properties could be used as identifier. Use the label.
341  QDomElement nameElem = doc.createElement( "se:Name" );
342  nameElem.appendChild( doc.createTextNode( mLabel ) );
343  ruleElem.appendChild( nameElem );
344 
345  if ( !mLabel.isEmpty() || !mDescription.isEmpty() )
346  {
347  QDomElement descrElem = doc.createElement( "se:Description" );
348  if ( !mLabel.isEmpty() )
349  {
350  QDomElement titleElem = doc.createElement( "se:Title" );
351  titleElem.appendChild( doc.createTextNode( mLabel ) );
352  descrElem.appendChild( titleElem );
353  }
354  if ( !mDescription.isEmpty() )
355  {
356  QDomElement abstractElem = doc.createElement( "se:Abstract" );
357  abstractElem.appendChild( doc.createTextNode( mDescription ) );
358  descrElem.appendChild( abstractElem );
359  }
360  ruleElem.appendChild( descrElem );
361  }
362 
363  if ( !props.value( "filter", "" ).isEmpty() )
364  {
365  QgsSymbolLayerV2Utils::createFunctionElement( doc, ruleElem, props.value( "filter", "" ) );
366  }
367 
368  if ( !props.value( "scaleMinDenom", "" ).isEmpty() )
369  {
370  QDomElement scaleMinDenomElem = doc.createElement( "se:MinScaleDenominator" );
371  scaleMinDenomElem.appendChild( doc.createTextNode( props.value( "scaleMinDenom", "" ) ) );
372  ruleElem.appendChild( scaleMinDenomElem );
373  }
374 
375  if ( !props.value( "scaleMaxDenom", "" ).isEmpty() )
376  {
377  QDomElement scaleMaxDenomElem = doc.createElement( "se:MaxScaleDenominator" );
378  scaleMaxDenomElem.appendChild( doc.createTextNode( props.value( "scaleMaxDenom", "" ) ) );
379  ruleElem.appendChild( scaleMaxDenomElem );
380  }
381 
382  mSymbol->toSld( doc, ruleElem, props );
383  }
384 
385  // loop into childern rule list
386  for ( RuleList::iterator it = mChildren.begin(); it != mChildren.end(); ++it )
387  {
388  ( *it )->toSld( doc, element, props );
389  }
390 }
391 
393 {
394  QString filter;
395  return startRender( context, fields, filter );
396 }
397 
399 {
400  mActiveChildren.clear();
401 
402  if ( ! mCheckState )
403  return false;
404 
405  // filter out rules which are not compatible with this scale
406  if ( !isScaleOK( context.rendererScale() ) )
407  return false;
408 
409  // init this rule
410  if ( mFilter )
411  mFilter->prepare( fields );
412  if ( mSymbol )
413  mSymbol->startRender( context, &fields );
414 
415  // init children
416  // build temporary list of active rules (usable with this scale)
417  QStringList subfilters;
418  for ( RuleList::iterator it = mChildren.begin(); it != mChildren.end(); ++it )
419  {
420  QString subfilter;
421  Rule* rule = *it;
422  if ( rule->startRender( context, fields , subfilter ) )
423  {
424  // only add those which are active with current scale
425  mActiveChildren.append( rule );
426  subfilters.append( subfilter );
427  }
428  }
429 
430  // subfilters (on the same level) are joined with OR and finally joined with AND with their parent (this) filter
431  QString sf;
432  if ( subfilters.length() )
433  sf = subfilters.join( ") OR (" ).prepend( "(" ).append( ")" );
434 
435  if ( isElse() )
436  {
437  if ( !sf.length() )
438  filter = "TRUE";
439  else
440  filter = sf;
441  }
442  else if ( mFilterExp.length() && sf.length() )
443  filter = QString( "(%1) AND (%2)" ).arg( mFilterExp ).arg( sf );
444  else if ( mFilterExp.length() )
445  filter = mFilterExp;
446  else
447  filter = sf;
448  return true;
449 }
450 
452 {
453  QSet<int> symbolZLevelsSet;
454 
455  // process this rule
456  if ( mSymbol )
457  {
458  // find out which Z-levels are used
459  for ( int i = 0; i < mSymbol->symbolLayerCount(); i++ )
460  {
461  symbolZLevelsSet.insert( mSymbol->symbolLayer( i )->renderingPass() );
462  }
463  }
464 
465  // process children
467  for ( it = mActiveChildren.begin(); it != mActiveChildren.end(); ++it )
468  {
469  Rule* rule = *it;
470  symbolZLevelsSet.unite( rule->collectZLevels() );
471  }
472  return symbolZLevelsSet;
473 }
474 
476 {
477  if ( mSymbol )
478  {
479  for ( int i = 0; i < mSymbol->symbolLayerCount(); i++ )
480  {
481  int normLevel = zLevelsToNormLevels.value( mSymbol->symbolLayer( i )->renderingPass() );
482  mSymbolNormZLevels.append( normLevel );
483  }
484  }
485 
486  // prepare list of normalized levels for each rule
487  for ( QList<Rule*>::iterator it = mActiveChildren.begin(); it != mActiveChildren.end(); ++it )
488  {
489  Rule* rule = *it;
490  rule->setNormZLevels( zLevelsToNormLevels );
491  }
492 }
493 
494 
496 {
497  if ( !isFilterOK( featToRender.feat ) )
498  return false;
499 
500  bool rendered = false;
501 
502  // create job for this feature and this symbol, add to list of jobs
503  if ( mSymbol )
504  {
505  // add job to the queue: each symbol's zLevel must be added
506  foreach ( int normZLevel, mSymbolNormZLevels )
507  {
508  //QgsDebugMsg(QString("add job at level %1").arg(normZLevel));
509  renderQueue[normZLevel].jobs.append( new RenderJob( featToRender, mSymbol ) );
510  }
511  rendered = true;
512  }
513 
514  bool willrendersomething = false;
515 
516  // process children
517  for ( QList<Rule*>::iterator it = mActiveChildren.begin(); it != mActiveChildren.end(); ++it )
518  {
519  Rule* rule = *it;
520  if ( rule->isElse() )
521  {
522  // Don't process else rules yet
523  continue;
524  }
525  willrendersomething |= rule->renderFeature( featToRender, context, renderQueue );
526  rendered |= willrendersomething;
527  }
528 
529  // If none of the rules passed then we jump into the else rules and process them.
530  if ( !willrendersomething )
531  {
532  foreach ( Rule* rule, mElseRules )
533  {
534  rendered |= rule->renderFeature( featToRender, context, renderQueue );
535  }
536  }
537 
538  return rendered;
539 }
540 
542 {
543  if ( !isFilterOK( feat ) )
544  return false;
545  if ( mSymbol )
546  return true;
547 
548  for ( QList<Rule*>::iterator it = mActiveChildren.begin(); it != mActiveChildren.end(); ++it )
549  {
550  Rule* rule = *it;
551  if ( rule->willRenderFeature( feat ) )
552  return true;
553  }
554  return false;
555 }
556 
558 {
559  QgsSymbolV2List lst;
560  if ( !isFilterOK( feat ) )
561  return lst;
562  if ( mSymbol )
563  lst.append( mSymbol );
564 
565  for ( QList<Rule*>::iterator it = mActiveChildren.begin(); it != mActiveChildren.end(); ++it )
566  {
567  Rule* rule = *it;
568  lst += rule->symbolsForFeature( feat );
569  }
570  return lst;
571 }
572 
574 {
575  RuleList lst;
576  if ( !isFilterOK( feat ) )
577  return lst;
578 
579  if ( mSymbol )
580  lst.append( this );
581 
582  for ( QList<Rule*>::iterator it = mActiveChildren.begin(); it != mActiveChildren.end(); ++it )
583  {
584  Rule* rule = *it;
585  lst += rule->rulesForFeature( feat );
586  }
587  return lst;
588 }
589 
591 {
592  if ( mSymbol )
593  mSymbol->stopRender( context );
594 
595  for ( QList<Rule*>::iterator it = mActiveChildren.begin(); it != mActiveChildren.end(); ++it )
596  {
597  Rule* rule = *it;
598  rule->stopRender( context );
599  }
600 
601  mActiveChildren.clear();
602  mSymbolNormZLevels.clear();
603 }
604 
606 {
607  QString symbolIdx = ruleElem.attribute( "symbol" );
608  QgsSymbolV2* symbol = NULL;
609  if ( !symbolIdx.isEmpty() )
610  {
611  if ( symbolMap.contains( symbolIdx ) )
612  {
613  symbol = symbolMap.take( symbolIdx );
614  }
615  else
616  {
617  QgsDebugMsg( "symbol for rule " + symbolIdx + " not found!" );
618  }
619  }
620 
621  QString filterExp = ruleElem.attribute( "filter" );
622  QString label = ruleElem.attribute( "label" );
623  QString description = ruleElem.attribute( "description" );
624  int scaleMinDenom = ruleElem.attribute( "scalemindenom", "0" ).toInt();
625  int scaleMaxDenom = ruleElem.attribute( "scalemaxdenom", "0" ).toInt();
626  QString ruleKey = ruleElem.attribute( "key" );
627  Rule* rule = new Rule( symbol, scaleMinDenom, scaleMaxDenom, filterExp, label, description );
628 
629  if ( !ruleKey.isEmpty() )
630  rule->mRuleKey = ruleKey;
631 
632  rule->setCheckState( ruleElem.attribute( "checkstate", "1" ).toInt() );
633 
634  QDomElement childRuleElem = ruleElem.firstChildElement( "rule" );
635  while ( !childRuleElem.isNull() )
636  {
637  Rule* childRule = create( childRuleElem, symbolMap );
638  if ( childRule )
639  {
640  rule->appendChild( childRule );
641  }
642  else
643  {
644  QgsDebugMsg( "failed to init a child rule!" );
645  }
646  childRuleElem = childRuleElem.nextSiblingElement( "rule" );
647  }
648 
649  return rule;
650 }
651 
653 {
654  if ( ruleElem.localName() != "Rule" )
655  {
656  QgsDebugMsg( QString( "invalid element: Rule element expected, %1 found!" ).arg( ruleElem.tagName() ) );
657  return NULL;
658  }
659 
660  QString label, description, filterExp;
661  int scaleMinDenom = 0, scaleMaxDenom = 0;
662  QgsSymbolLayerV2List layers;
663 
664  // retrieve the Rule element child nodes
665  QDomElement childElem = ruleElem.firstChildElement();
666  while ( !childElem.isNull() )
667  {
668  if ( childElem.localName() == "Name" )
669  {
670  // <se:Name> tag contains the rule identifier,
671  // so prefer title tag for the label property value
672  if ( label.isEmpty() )
673  label = childElem.firstChild().nodeValue();
674  }
675  else if ( childElem.localName() == "Description" )
676  {
677  // <se:Description> can contains a title and an abstract
678  QDomElement titleElem = childElem.firstChildElement( "Title" );
679  if ( !titleElem.isNull() )
680  {
681  label = titleElem.firstChild().nodeValue();
682  }
683 
684  QDomElement abstractElem = childElem.firstChildElement( "Abstract" );
685  if ( !abstractElem.isNull() )
686  {
687  description = abstractElem.firstChild().nodeValue();
688  }
689  }
690  else if ( childElem.localName() == "Abstract" )
691  {
692  // <sld:Abstract> (v1.0)
693  description = childElem.firstChild().nodeValue();
694  }
695  else if ( childElem.localName() == "Title" )
696  {
697  // <sld:Title> (v1.0)
698  label = childElem.firstChild().nodeValue();
699  }
700  else if ( childElem.localName() == "Filter" )
701  {
703  if ( filter )
704  {
705  if ( filter->hasParserError() )
706  {
707  QgsDebugMsg( "parser error: " + filter->parserErrorString() );
708  }
709  else
710  {
711  filterExp = filter->expression();
712  }
713  delete filter;
714  }
715  }
716  else if ( childElem.localName() == "MinScaleDenominator" )
717  {
718  bool ok;
719  int v = childElem.firstChild().nodeValue().toInt( &ok );
720  if ( ok )
721  scaleMinDenom = v;
722  }
723  else if ( childElem.localName() == "MaxScaleDenominator" )
724  {
725  bool ok;
726  int v = childElem.firstChild().nodeValue().toInt( &ok );
727  if ( ok )
728  scaleMaxDenom = v;
729  }
730  else if ( childElem.localName().endsWith( "Symbolizer" ) )
731  {
732  // create symbol layers for this symbolizer
733  QgsSymbolLayerV2Utils::createSymbolLayerV2ListFromSld( childElem, geomType, layers );
734  }
735 
736  childElem = childElem.nextSiblingElement();
737  }
738 
739  // now create the symbol
740  QgsSymbolV2 *symbol = 0;
741  if ( layers.size() > 0 )
742  {
743  switch ( geomType )
744  {
745  case QGis::Line:
746  symbol = new QgsLineSymbolV2( layers );
747  break;
748 
749  case QGis::Polygon:
750  symbol = new QgsFillSymbolV2( layers );
751  break;
752 
753  case QGis::Point:
754  symbol = new QgsMarkerSymbolV2( layers );
755  break;
756 
757  default:
758  QgsDebugMsg( QString( "invalid geometry type: found %1" ).arg( geomType ) );
759  return NULL;
760  }
761  }
762 
763  // and then create and return the new rule
764  return new Rule( symbol, scaleMinDenom, scaleMaxDenom, filterExp, label, description );
765 }
766 
767 
769 
771  : QgsFeatureRendererV2( "RuleRenderer" ), mRootRule( root )
772 {
773 }
774 
776  : QgsFeatureRendererV2( "RuleRenderer" )
777 {
778  mRootRule = new Rule( NULL ); // root has no symbol, no filter etc - just a container
779  mRootRule->appendChild( new Rule( defaultSymbol ) );
780 }
781 
783 {
784  delete mRootRule;
785 }
786 
787 
789 {
790  // not used at all
791  return 0;
792 }
793 
795  QgsRenderContext& context,
796  int layer,
797  bool selected,
798  bool drawVertexMarker )
799 {
800  Q_UNUSED( layer );
801 
802  int flags = ( selected ? FeatIsSelected : 0 ) | ( drawVertexMarker ? FeatDrawMarkers : 0 );
803  mCurrentFeatures.append( FeatureToRender( feature, flags ) );
804 
805  // check each active rule
806  return mRootRule->renderFeature( mCurrentFeatures.last(), context, mRenderQueue );
807 }
808 
809 
811 {
812  // prepare active children
813  mRootRule->startRender( context, fields, mFilter );
814 
815  QSet<int> symbolZLevelsSet = mRootRule->collectZLevels();
816  QList<int> symbolZLevels = symbolZLevelsSet.toList();
817  qSort( symbolZLevels );
818 
819  // create mapping from unnormalized levels [unlimited range] to normalized levels [0..N-1]
820  // and prepare rendering queue
821  QMap<int, int> zLevelsToNormLevels;
822  int maxNormLevel = -1;
823  foreach ( int zLevel, symbolZLevels )
824  {
825  zLevelsToNormLevels[zLevel] = ++maxNormLevel;
826  mRenderQueue.append( RenderLevel( zLevel ) );
827  QgsDebugMsg( QString( "zLevel %1 -> %2" ).arg( zLevel ).arg( maxNormLevel ) );
828  }
829 
830  mRootRule->setNormZLevels( zLevelsToNormLevels );
831 }
832 
834 {
835  //
836  // do the actual rendering
837  //
838 
839  // go through all levels
840  foreach ( const RenderLevel& level, mRenderQueue )
841  {
842  //QgsDebugMsg(QString("level %1").arg(level.zIndex));
843  // go through all jobs at the level
844  foreach ( const RenderJob* job, level.jobs )
845  {
846  //QgsDebugMsg(QString("job fid %1").arg(job->f->id()));
847  // render feature - but only with symbol layers with specified zIndex
848  QgsSymbolV2* s = job->symbol;
849  int count = s->symbolLayerCount();
850  for ( int i = 0; i < count; i++ )
851  {
852  // TODO: better solution for this
853  // renderFeatureWithSymbol asks which symbol layer to draw
854  // but there are multiple transforms going on!
855  if ( s->symbolLayer( i )->renderingPass() == level.zIndex )
856  {
857  int flags = job->ftr.flags;
858  renderFeatureWithSymbol( job->ftr.feat, job->symbol, context, i, flags & FeatIsSelected, flags & FeatDrawMarkers );
859  }
860  }
861  }
862  }
863 
864  // clean current features
865  mCurrentFeatures.clear();
866 
867  // clean render queue
869 
870  // clean up rules from temporary stuff
871  mRootRule->stopRender( context );
872 }
873 
875 {
876  return mFilter;
877 }
878 
880 {
882  return attrs.values();
883 }
884 
886 {
888 
889  // normally with clone() the individual rules get new keys (UUID), but here we want to keep
890  // the tree of rules intact, so that other components that may use the rule keys work nicely (e.g. visibility presets)
891  clonedRoot->setRuleKey( mRootRule->ruleKey() );
892  RuleList origDescendants = mRootRule->descendants();
893  RuleList clonedDescendants = clonedRoot->descendants();
894  Q_ASSERT( origDescendants.count() == clonedDescendants.count() );
895  for ( int i = 0; i < origDescendants.count(); ++i )
896  clonedDescendants[i]->setRuleKey( origDescendants[i]->ruleKey() );
897 
898  QgsRuleBasedRendererV2* r = new QgsRuleBasedRendererV2( clonedRoot );
899 
901  copyPaintEffect( r );
902  return r;
903 }
904 
906 {
907  mRootRule->toSld( doc, element, QgsStringMap() );
908 }
909 
910 // TODO: ideally this function should be removed in favor of legendSymbol(ogy)Items
912 {
913  return mRootRule->symbols();
914 }
915 
917 {
918  QDomElement rendererElem = doc.createElement( RENDERER_TAG_NAME );
919  rendererElem.setAttribute( "type", "RuleRenderer" );
920  rendererElem.setAttribute( "symbollevels", ( mUsingSymbolLevels ? "1" : "0" ) );
921  rendererElem.setAttribute( "forceraster", ( mForceRaster ? "1" : "0" ) );
922 
924 
925  QDomElement rulesElem = mRootRule->save( doc, symbols );
926  rulesElem.setTagName( "rules" ); // instead of just "rule"
927  rendererElem.appendChild( rulesElem );
928 
929  QDomElement symbolsElem = QgsSymbolLayerV2Utils::saveSymbols( symbols, "symbols", doc );
930  rendererElem.appendChild( symbolsElem );
931 
932  if ( mPaintEffect )
933  mPaintEffect->saveProperties( doc, rendererElem );
934 
935  return rendererElem;
936 }
937 
939 {
942  for ( QgsLegendSymbolList::iterator it = items.begin(); it != items.end(); ++it )
943  {
944  QPair<QString, QgsSymbolV2*> pair = *it;
945  QPixmap pix = QgsSymbolLayerV2Utils::symbolPreviewPixmap( pair.second, iconSize );
946  lst << qMakePair( pair.first, pix );
947  }
948  return lst;
949 }
950 
952 {
953  return true;
954 }
955 
957 {
958  Rule* rule = mRootRule->findRuleByKey( key );
959  return rule ? rule->checkState() : true;
960 }
961 
963 {
964  Rule* rule = mRootRule->findRuleByKey( key );
965  if ( rule )
966  rule->setCheckState( state );
967 }
968 
970 {
971  return mRootRule->legendSymbolItems( scaleDenominator, rule );
972 }
973 
975 {
976  return mRootRule->legendSymbolItemsV2();
977 }
978 
979 
981 {
982  // load symbols
983  QDomElement symbolsElem = element.firstChildElement( "symbols" );
984  if ( symbolsElem.isNull() )
985  return NULL;
986 
987  QgsSymbolV2Map symbolMap = QgsSymbolLayerV2Utils::loadSymbols( symbolsElem );
988 
989  QDomElement rulesElem = element.firstChildElement( "rules" );
990 
991  Rule* root = Rule::create( rulesElem, symbolMap );
992  if ( root == NULL )
993  return NULL;
994 
996 
997  // delete symbols if there are any more
999 
1000  return r;
1001 }
1002 
1004 {
1005  // retrieve child rules
1006  Rule* root = 0;
1007 
1008  QDomElement ruleElem = element.firstChildElement( "Rule" );
1009  while ( !ruleElem.isNull() )
1010  {
1011  Rule *child = Rule::createFromSld( ruleElem, geomType );
1012  if ( child )
1013  {
1014  // create the root rule if not done before
1015  if ( !root )
1016  root = new Rule( 0 );
1017 
1018  root->appendChild( child );
1019  }
1020 
1021  ruleElem = ruleElem.nextSiblingElement( "Rule" );
1022  }
1023 
1024  if ( !root )
1025  {
1026  // no valid rules was found
1027  return NULL;
1028  }
1029 
1030  // create and return the new renderer
1031  return new QgsRuleBasedRendererV2( root );
1032 }
1033 
1036 
1038 {
1039  foreach ( const QgsRendererCategoryV2& cat, r->categories() )
1040  {
1042  QString value;
1043  // not quoting numbers saves a type cast
1044  if ( cat.value().type() == QVariant::Int )
1045  value = cat.value().toString();
1046  else if ( cat.value().type() == QVariant::Double )
1047  // we loose precision here - so we may miss some categories :-(
1048  // TODO: have a possibility to construct expressions directly as a parse tree to avoid loss of precision
1049  value = QString::number( cat.value().toDouble(), 'f', 4 );
1050  else
1051  value = QgsExpression::quotedString( cat.value().toString() );
1052  QString filter = QString( "%1 = %2" ).arg( attr ).arg( value );
1053  QString label = filter;
1054  initialRule->appendChild( new Rule( cat.symbol()->clone(), 0, 0, filter, label ) );
1055  }
1056 }
1057 
1059 {
1060  foreach ( const QgsRendererRangeV2& rng, r->ranges() )
1061  {
1062  // due to the loss of precision in double->string conversion we may miss out values at the limit of the range
1063  // TODO: have a possibility to construct expressions directly as a parse tree to avoid loss of precision
1065  QString filter = QString( "%1 >= %2 AND %1 <= %3" ).arg( attr )
1066  .arg( QString::number( rng.lowerValue(), 'f', 4 ) )
1067  .arg( QString::number( rng.upperValue(), 'f', 4 ) );
1068  QString label = filter;
1069  initialRule->appendChild( new Rule( rng.symbol()->clone(), 0, 0, filter, label ) );
1070  }
1071 }
1072 
1074 {
1075  qSort( scales ); // make sure the scales are in ascending order
1076  int oldScale = initialRule->scaleMinDenom();
1077  int maxDenom = initialRule->scaleMaxDenom();
1078  QgsSymbolV2* symbol = initialRule->symbol();
1079  foreach ( int scale, scales )
1080  {
1081  if ( initialRule->scaleMinDenom() >= scale )
1082  continue; // jump over the first scales out of the interval
1083  if ( maxDenom != 0 && maxDenom <= scale )
1084  break; // ignore the latter scales out of the interval
1085  initialRule->appendChild( new Rule( symbol->clone(), oldScale, scale, QString(), QString( "%1 - %2" ).arg( oldScale ).arg( scale ) ) );
1086  oldScale = scale;
1087  }
1088  // last rule
1089  initialRule->appendChild( new Rule( symbol->clone(), oldScale, maxDenom, QString(), QString( "%1 - %2" ).arg( oldScale ).arg( maxDenom ) ) );
1090 }
1091 
1093 {
1094  QString msg( "Rule-based renderer:\n" );
1095  msg += mRootRule->dump();
1096  return msg;
1097 }
1098 
1100 {
1101  return mRootRule->willRenderFeature( feat );
1102 }
1103 
1105 {
1106  return mRootRule->symbolsForFeature( feat );
1107 }
1108 
1110 {
1111  return mRootRule->symbolsForFeature( feat );
1112 }
1113 
1115 {
1116  if ( renderer->type() == "RuleRenderer" )
1117  {
1118  return dynamic_cast<QgsRuleBasedRendererV2*>( renderer->clone() );
1119  }
1120 
1121  if ( renderer->type() == "singleSymbol" )
1122  {
1123  const QgsSingleSymbolRendererV2* singleSymbolRenderer = dynamic_cast<const QgsSingleSymbolRendererV2*>( renderer );
1124  if ( !singleSymbolRenderer )
1125  return 0;
1126 
1127  QgsSymbolV2* origSymbol = singleSymbolRenderer->symbol()->clone();
1128  convertToDataDefinedSymbology( origSymbol, singleSymbolRenderer->sizeScaleField(), singleSymbolRenderer->rotationField() );
1129  return new QgsRuleBasedRendererV2( origSymbol );
1130  }
1131 
1132  if ( renderer->type() == "categorizedSymbol" )
1133  {
1134  const QgsCategorizedSymbolRendererV2* categorizedRenderer = dynamic_cast<const QgsCategorizedSymbolRendererV2*>( renderer );
1135  if ( !categorizedRenderer )
1136  return 0;
1137 
1139 
1140  QString expression;
1141  QString value;
1142  QgsRendererCategoryV2 category;
1143  for ( int i = 0; i < categorizedRenderer->categories().size(); ++i )
1144  {
1145  category = categorizedRenderer->categories().value( i );
1147 
1148  rule->setLabel( category.label() );
1149 
1150  //We first define the rule corresponding to the category
1151  //If the value is a number, we can use it directly, otherwise we need to quote it in the rule
1152  if ( QVariant( category.value() ).convert( QVariant::Double ) )
1153  {
1154  value = category.value().toString();
1155  }
1156  else
1157  {
1158  value = "'" + category.value().toString() + "'";
1159  }
1160 
1161  //An empty category is equivalent to the ELSE keyword
1162  if ( value == "''" )
1163  {
1164  expression = "ELSE";
1165  }
1166  else
1167  {
1168  expression = categorizedRenderer->classAttribute() + " = " + value;
1169  }
1170  rule->setFilterExpression( expression );
1171 
1172  //Then we construct an equivalent symbol.
1173  //Ideally we could simply copy the symbol, but the categorized renderer allows a separate interface to specify
1174  //data dependent area and rotation, so we need to convert these to obtain the same rendering
1175 
1176  QgsSymbolV2* origSymbol = category.symbol()->clone();
1177  convertToDataDefinedSymbology( origSymbol, categorizedRenderer->sizeScaleField(), categorizedRenderer->rotationField() );
1178  rule->setSymbol( origSymbol );
1179 
1180  rootrule->appendChild( rule );
1181  }
1182 
1183  return new QgsRuleBasedRendererV2( rootrule );
1184  }
1185 
1186  if ( renderer->type() == "graduatedSymbol" )
1187  {
1188 
1189  const QgsGraduatedSymbolRendererV2* graduatedRenderer = dynamic_cast<const QgsGraduatedSymbolRendererV2*>( renderer );
1190  if ( !graduatedRenderer )
1191  return 0;
1192 
1194 
1195  QString expression;
1196  QgsRendererRangeV2 range;
1197  for ( int i = 0; i < graduatedRenderer->ranges().size();++i )
1198  {
1199  range = graduatedRenderer->ranges().value( i );
1201  rule->setLabel( range.label() );
1202  if ( i == 0 )//The lower boundary of the first range is included, while it is excluded for the others
1203  {
1204  expression = graduatedRenderer->classAttribute() + " >= " + QString::number( range.lowerValue(), 'f' ) + " AND " + \
1205  graduatedRenderer->classAttribute() + " <= " + QString::number( range.upperValue(), 'f' );
1206  }
1207  else
1208  {
1209  expression = graduatedRenderer->classAttribute() + " > " + QString::number( range.lowerValue(), 'f' ) + " AND " + \
1210  graduatedRenderer->classAttribute() + " <= " + QString::number( range.upperValue(), 'f' );
1211  }
1212  rule->setFilterExpression( expression );
1213 
1214  //Then we construct an equivalent symbol.
1215  //Ideally we could simply copy the symbol, but the graduated renderer allows a separate interface to specify
1216  //data dependent area and rotation, so we need to convert these to obtain the same rendering
1217 
1218  QgsSymbolV2* symbol = range.symbol()->clone();
1219  convertToDataDefinedSymbology( symbol, graduatedRenderer->sizeScaleField(), graduatedRenderer->rotationField() );
1220 
1221  rule->setSymbol( symbol );
1222 
1223  rootrule->appendChild( rule );
1224  }
1225 
1226  return new QgsRuleBasedRendererV2( rootrule );
1227  }
1228 
1229  if ( renderer->type() == "pointDisplacement" )
1230  {
1231  const QgsPointDisplacementRenderer* pointDisplacementRenderer = dynamic_cast<const QgsPointDisplacementRenderer*>( renderer );
1232  if ( pointDisplacementRenderer )
1233  return convertFromRenderer( pointDisplacementRenderer->embeddedRenderer() );
1234  }
1235  if ( renderer->type() == "invertedPolygonRenderer" )
1236  {
1237  const QgsInvertedPolygonRenderer* invertedPolygonRenderer = dynamic_cast<const QgsInvertedPolygonRenderer*>( renderer );
1238  if ( invertedPolygonRenderer )
1239  return convertFromRenderer( invertedPolygonRenderer->embeddedRenderer() );
1240  }
1241 
1242  return NULL;
1243 }
1244 
1246 {
1247  QString sizeExpression;
1248  switch ( symbol->type() )
1249  {
1250  case QgsSymbolV2::Marker:
1251  for ( int j = 0; j < symbol->symbolLayerCount();++j )
1252  {
1253  QgsMarkerSymbolLayerV2* msl = static_cast<QgsMarkerSymbolLayerV2*>( symbol->symbolLayer( j ) );
1254  if ( ! sizeScaleField.isNull() )
1255  {
1256  sizeExpression = QString( "%1*(%2)" ).arg( msl->size() ).arg( sizeScaleField );
1257  msl->setDataDefinedProperty( "size", new QgsDataDefined( sizeExpression ) );
1258  }
1259  if ( ! rotationField.isNull() )
1260  {
1261  msl->setDataDefinedProperty( "angle", new QgsDataDefined( true, false, QString(), rotationField ) );
1262  }
1263  }
1264  break;
1265  case QgsSymbolV2::Line:
1266  if ( ! sizeScaleField.isNull() )
1267  {
1268  for ( int j = 0; j < symbol->symbolLayerCount();++j )
1269  {
1270  if ( symbol->symbolLayer( j )->layerType() == "SimpleLine" )
1271  {
1272  QgsLineSymbolLayerV2* lsl = static_cast<QgsLineSymbolLayerV2*>( symbol->symbolLayer( j ) );
1273  sizeExpression = QString( "%1*(%2)" ).arg( lsl->width() ).arg( sizeScaleField );
1274  lsl->setDataDefinedProperty( "width", new QgsDataDefined( sizeExpression ) );
1275  }
1276  if ( symbol->symbolLayer( j )->layerType() == "MarkerLine" )
1277  {
1278  QgsSymbolV2* marker = symbol->symbolLayer( j )->subSymbol();
1279  for ( int k = 0; k < marker->symbolLayerCount();++k )
1280  {
1281  QgsMarkerSymbolLayerV2* msl = static_cast<QgsMarkerSymbolLayerV2*>( marker->symbolLayer( k ) );
1282  sizeExpression = QString( "%1*(%2)" ).arg( msl->size() ).arg( sizeScaleField );
1283  msl->setDataDefinedProperty( "size", new QgsDataDefined( sizeExpression ) );
1284  }
1285  }
1286  }
1287  }
1288  break;
1289  default:
1290  break;
1291  }
1292 }
void toSld(QDomDocument &doc, QDomElement &element, QgsStringMap props)
Class for parsing and evaluation of expressions (formerly called "search strings").
Definition: qgsexpression.h:86
void clear()
QgsSymbolV2List symbolsForFeature(QgsFeature &feat)
tell which symbols will be used to render the feature
static QgsSymbolV2Map loadSymbols(QDomElement &element)
void setNormZLevels(const QMap< int, int > &zLevelsToNormLevels)
assign normalized z-levels [0..N-1] for this rule's symbol for quick access during rendering ...
#define RENDERER_TAG_NAME
Definition: qgsrendererv2.h:48
QString & append(QChar ch)
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
Definition: qgsexpression.h:93
A container class for data source field mapping or expression.
const QgsCategoryList & categories() const
bool contains(const Key &key) const
static QString quotedColumnRef(QString name)
return quoted column reference (in double quotes)
virtual double width() const
QString & fill(QChar ch, int size)
virtual QgsSymbolV2List symbols() override
for symbol levels
QSet< int > collectZLevels()
get all used z-levels from this rule and children
QDomNode appendChild(const QDomNode &newChild)
const QString expression() const
Alias for dump()
static QgsFeatureRendererV2 * create(QDomElement &element)
SymbolType type() const
Definition: qgssymbolv2.h:86
QString attribute(const QString &name, const QString &defValue) const
int length() const
void setTagName(const QString &name)
QString nodeValue() const
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
static void convertToDataDefinedSymbology(QgsSymbolV2 *symbol, QString sizeScaleField, QString rotationField)
helper function to convert the size scale and rotation fields present in some other renderers to data...
QString & prepend(QChar ch)
double rendererScale() const
virtual QgsSymbolV2 * clone() const =0
virtual QgsFeatureRendererV2 * clone() const override
static QgsFeatureRendererV2 * createFromSld(QDomElement &element, QGis::GeometryType geomType)
bool isScaleOK(double scale) const
QDomElement nextSiblingElement(const QString &tagName) const
Q_DECL_DEPRECATED bool startRender(QgsRenderContext &context, const QgsFields &fields)
prepare the rule for rendering and its children (build active children array)
Rule * clone() const
clone this rule, return new instance
RuleList rulesForFeature(QgsFeature &feat)
tell which rules will be used to render the feature
Container of fields for a vector layer.
Definition: qgsfield.h:173
void removeChild(Rule *rule)
delete child rule
GeometryType
Definition: qgis.h:155
QString join(const QString &separator) const
const_iterator insert(const T &value)
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:162
virtual bool legendSymbolItemsCheckable() const override
items of symbology items in legend should be checkable
virtual QgsLegendSymbolList legendSymbolItems(double scaleDenominator=-1, QString rule="") override
return a list of item text / symbol
QMap< QString, QString > QgsStringMap
Definition: qgis.h:441
QgsPaintEffect * mPaintEffect
void removeChildAt(int i)
delete child rule
virtual void checkLegendSymbolItem(QString key, bool state=true) override
item in symbology was checked
int size() const
bool isNull() const
QString rotationField() const override
return rotation field name (or empty string if not set or not supported by renderer) ...
T value(int i) const
void renderFeatureWithSymbol(QgsFeature &feature, QgsSymbolV2 *symbol, QgsRenderContext &context, int layer, bool selected, bool drawVertexMarker)
QString type() const
Definition: qgsrendererv2.h:82
static bool createSymbolLayerV2ListFromSld(QDomElement &element, QGis::GeometryType geomType, QgsSymbolLayerV2List &layers)
void stopRender(QgsRenderContext &context)
virtual QgsSymbolV2List originalSymbolsForFeature(QgsFeature &feat) override
Equivalent of originalSymbolsForFeature() call extended to support renderers that may use more symbol...
virtual QgsFeatureRendererV2 * clone() const =0
QString number(int n, int base)
int count(const T &value) const
virtual QDomElement save(QDomDocument &doc) override
store renderer info to XML element
void append(const T &value)
Rule(QgsSymbolV2 *symbol, int scaleMinDenom=0, int scaleMaxDenom=0, QString filterExp=QString(), QString label=QString(), QString description=QString(), bool elseRule=false)
Constructor takes ownership of the symbol.
static void refineRuleCategories(Rule *initialRule, QgsCategorizedSymbolRendererV2 *r)
take a rule and create a list of new rules based on the categories from categorized symbol renderer ...
QString localName() const
int toInt(bool *ok) const
void takeChild(Rule *rule)
take child rule out, set parent as null
QList< T > values() const
virtual void stopRender(QgsRenderContext &context) override
QgsInvertedPolygonRenderer is a polygon-only feature renderer used to display features inverted...
void setAttribute(const QString &name, const QString &value)
static bool createFunctionElement(QDomDocument &doc, QDomElement &element, QString function)
int toInt(bool *ok, int base) const
void appendChild(Rule *rule)
add child rule, take ownership, sets this as parent
static QDomElement saveSymbols(QgsSymbolV2Map &symbols, QString tagName, QDomDocument &doc)
static Rule * create(QDomElement &ruleElem, QgsSymbolV2Map &symbolMap)
bool isEmpty() const
QString rotationField() const override
return rotation field name (or empty string if not set or not supported by renderer) ...
QgsSymbolV2 * symbol() const
QDomElement save(QDomDocument &doc, QgsSymbolV2Map &symbolMap)
bool isFilterOK(QgsFeature &f) const
int symbolLayerCount()
Returns total number of symbol layers contained in the symbol.
Definition: qgssymbolv2.h:113
This class keeps data about a rules for rule-based renderer.
void setRuleKey(const QString &key)
Override the assigned rule key (should be used just internally by rule-based renderer) ...
virtual void toSld(QDomDocument &doc, QDomElement &element) const override
used from subclasses to create SLD Rule elements following SLD v1.1 specs
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const
virtual QgsLegendSymbologyList legendSymbologyItems(QSize iconSize) override
return a list of symbology items for the legend
QgsLegendSymbolList legendSymbolItems(double scaleDenominator=-1, QString rule="")
QString ruleKey() const
Unique rule identifier (for identification of rule within renderer)
Rule * mRootRule
the root node with hierarchical list of rules
virtual bool renderFeature(QgsFeature &feature, QgsRenderContext &context, int layer=-1, bool selected=false, bool drawVertexMarker=false) override
virtual bool willRenderFeature(QgsFeature &feat) override
return whether the renderer will render a feature or not.
static void refineRuleRanges(Rule *initialRule, QgsGraduatedSymbolRendererV2 *r)
take a rule and create a list of new rules based on the ranges from graduated symbol renderer ...
QString dump(int offset=0) const
Rule * takeChildAt(int i)
take child rule out, set parent as null
bool renderFeature(FeatureToRender &featToRender, QgsRenderContext &context, RenderQueue &renderQueue)
virtual bool legendSymbolItemChecked(QString key) override
items of symbology items in legend is checked
QgsFeatureRendererV2 * embeddedRenderer() const
QDomText createTextNode(const QString &value)
iterator end()
QgsLegendSymbolListV2 legendSymbolItemsV2(int currentLevel=-1) const
int renderingPass() const
virtual QString layerType() const =0
A renderer that automatically displaces points with the same position.
bool isNull() const
virtual QgsSymbolV2 * subSymbol()
QgsRuleBasedRendererV2(QgsRuleBasedRendererV2::Rule *root)
Constructs the renderer from given tree of rules (takes ownership)
void setUsingSymbolLevels(bool usingSymbolLevels)
virtual QString dump() const override
for debugging
QString rotationField() const override
return rotation field name (or empty string if not set or not supported by renderer) ...
virtual bool saveProperties(QDomDocument &doc, QDomElement &element) const
Saves the current state of the effect to a DOM element.
Contains information about the context of a rendering operation.
const QgsFeatureRendererV2 * embeddedRenderer() const
QDomNode firstChild() const
void copyPaintEffect(QgsFeatureRendererV2 *destRenderer) const
Copies paint effect of this renderer to another renderer.
QSet< T > & unite(const QSet< T > &other)
const QgsRangeList & ranges() const
When drawing a vector layer with rule-based renderer, it goes through the rules and draws features wi...
static Rule * createFromSld(QDomElement &element, QGis::GeometryType geomType)
QDomElement firstChildElement(const QString &tagName) const
bool usingSymbolLevels() const
static QgsExpression * expressionFromOgcFilter(const QDomElement &element)
Parse XML with OGC filter into QGIS expression.
virtual void startRender(QgsRenderContext &context, const QgsFields &fields) override
Needs to be called when a new render cycle is started.
int length() const
static QString quotedString(QString text)
return quoted string (in single quotes)
virtual QgsLegendSymbolListV2 legendSymbolItemsV2() const override
Return a list of symbology items for the legend.
QList< T > toList() const
static void clearSymbolMap(QgsSymbolV2Map &symbols)
void setSymbol(QgsSymbolV2 *sym)
set a new symbol (or NULL). Deletes old symbol.
virtual QList< QString > usedAttributes() override
double toDouble(bool *ok) const
static QgsRuleBasedRendererV2 * convertFromRenderer(const QgsFeatureRendererV2 *renderer)
creates a QgsRuleBasedRendererV2 from an existing renderer.
QString tagName() const
QgsSymbolLayerV2 * symbolLayer(int layer)
Returns a specific symbol layers contained in the symbol.
virtual QString filter() override
If a renderer does not require all the features this method may be overridden and return an expressio...
void insertChild(int i, Rule *rule)
add child rule, take ownership, sets this as parent
QDomElement createElement(const QString &tagName)
Type type() const
virtual QgsSymbolV2 * symbolForFeature(QgsFeature &feature) override
return symbol for current feature. Should not be used individually: there could be more symbols for a...
static QPixmap symbolPreviewPixmap(QgsSymbolV2 *symbol, QSize size, QgsRenderContext *customContext=0)
bool willRenderFeature(QgsFeature &feat)
only tell whether a feature will be rendered without actually rendering it
QString parserErrorString() const
Returns parser error.
Definition: qgsexpression.h:95
The class stores information about one class/rule of a vector layer renderer in a unified way that ca...
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QString toString() const
QString toString() const
void setFilterExpression(QString filterExp)
iterator begin()
T take(const Key &key)
int size() const
QUuid createUuid()
QList< FeatureToRender > mCurrentFeatures
Rule * findRuleByKey(QString key)
Try to find a rule given its unique key.
static void refineRuleScales(Rule *initialRule, QList< int > scales)
take a rule and create a list of new rules with intervals of scales given by the passed scale denomin...
virtual QgsSymbolV2List symbolsForFeature(QgsFeature &feat) override
return list of symbols used for rendering the feature.
const T value(const Key &key) const
virtual Q_DECL_DEPRECATED void setDataDefinedProperty(const QString &property, const QString &expressionString)
Sets a data defined expression for a property.