00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "qgsrulebasedrendererv2.h"
00017
00018 #include "qgssearchtreenode.h"
00019 #include "qgssymbollayerv2utils.h"
00020 #include "qgsrendercontext.h"
00021 #include "qgsvectorlayer.h"
00022 #include "qgslogger.h"
00023
00024 #include <QSet>
00025
00026 #include <QDomDocument>
00027 #include <QDomElement>
00028
00029
00030
00031 QgsRuleBasedRendererV2::Rule::Rule( QgsSymbolV2* symbol, int scaleMinDenom, int scaleMaxDenom, QString filterExp )
00032 : mSymbol( symbol ),
00033 mScaleMinDenom( scaleMinDenom ), mScaleMaxDenom( scaleMaxDenom ),
00034 mFilterExp( filterExp )
00035 {
00036 initFilter();
00037 }
00038
00039 QgsRuleBasedRendererV2::Rule::Rule( const QgsRuleBasedRendererV2::Rule& other )
00040 : mSymbol( NULL )
00041 {
00042 *this = other;
00043 }
00044
00045 QgsRuleBasedRendererV2::Rule::~Rule()
00046 {
00047 delete mSymbol;
00048 }
00049
00050 void QgsRuleBasedRendererV2::Rule::initFilter()
00051 {
00052 if ( !mFilterExp.isEmpty() )
00053 {
00054 mFilterParsed.setString( mFilterExp );
00055 mFilterTree = mFilterParsed.tree();
00056 }
00057 else
00058 {
00059 mFilterTree = NULL;
00060 }
00061 }
00062
00063 QString QgsRuleBasedRendererV2::Rule::dump() const
00064 {
00065 return QString( "RULE - scale [%1,%2] - filter %3 - symbol %4" )
00066 .arg( mScaleMinDenom ).arg( mScaleMaxDenom )
00067 .arg( mFilterExp ).arg( mSymbol->dump() );
00068
00069 }
00070
00071 QStringList QgsRuleBasedRendererV2::Rule::needsFields() const
00072 {
00073 if ( ! mFilterTree )
00074 return QStringList();
00075
00076 return mFilterTree->referencedColumns();
00077 }
00078
00079 bool QgsRuleBasedRendererV2::Rule::isFilterOK( const QgsFieldMap& fields, QgsFeature& f ) const
00080 {
00081 if ( ! mFilterTree )
00082 return true;
00083
00084 bool res = mFilterTree->checkAgainst( fields, f );
00085
00086 return res;
00087 }
00088
00089 bool QgsRuleBasedRendererV2::Rule::isScaleOK( double scale ) const
00090 {
00091 if ( mScaleMinDenom == 0 && mScaleMaxDenom == 0 )
00092 return true;
00093 if ( mScaleMinDenom != 0 && mScaleMinDenom > scale )
00094 return false;
00095 if ( mScaleMaxDenom != 0 && mScaleMaxDenom < scale )
00096 return false;
00097 return true;
00098 }
00099
00100 QgsRuleBasedRendererV2::Rule& QgsRuleBasedRendererV2::Rule::operator=( const QgsRuleBasedRendererV2::Rule & other )
00101 {
00102 if ( this != &other )
00103 {
00104 delete mSymbol;
00105 mSymbol = other.mSymbol->clone();
00106
00107 mScaleMinDenom = other.mScaleMinDenom;
00108 mScaleMaxDenom = other.mScaleMaxDenom;
00109 mFilterExp = other.mFilterExp;
00110 initFilter();
00111 }
00112 return *this;
00113 }
00114
00116
00117 QgsRuleBasedRendererV2::QgsRuleBasedRendererV2( QgsSymbolV2* defaultSymbol )
00118 : QgsFeatureRendererV2( "RuleRenderer" )
00119 {
00120 mDefaultSymbol = defaultSymbol;
00121
00122
00123 mRules << Rule( defaultSymbol->clone() );
00124 }
00125
00126
00127 QgsSymbolV2* QgsRuleBasedRendererV2::symbolForFeature( QgsFeature& feature )
00128 {
00129 return mCurrentSymbol;
00130 }
00131
00132 void QgsRuleBasedRendererV2::renderFeature( QgsFeature& feature,
00133 QgsRenderContext& context,
00134 int layer,
00135 bool selected,
00136 bool drawVertexMarker )
00137 {
00138 for ( QList<Rule*>::iterator it = mCurrentRules.begin(); it != mCurrentRules.end(); ++it )
00139 {
00140 Rule* rule = *it;
00141 if ( rule->isFilterOK( mCurrentFields, feature ) )
00142 {
00143 mCurrentSymbol = rule->symbol();
00144
00145 QgsFeatureRendererV2::renderFeature( feature, context, layer, selected, drawVertexMarker );
00146 }
00147 }
00148 }
00149
00150
00151 void QgsRuleBasedRendererV2::startRender( QgsRenderContext& context, const QgsVectorLayer *vlayer )
00152 {
00153 double currentScale = context.rendererScale();
00154
00155
00156 mCurrentRules.clear();
00157 for ( QList<Rule>::iterator it = mRules.begin(); it != mRules.end(); ++it )
00158 {
00159 Rule& rule = *it;
00160 if ( rule.isScaleOK( currentScale ) )
00161 mCurrentRules.append( &rule );
00162 }
00163
00164 mCurrentFields = vlayer->pendingFields();
00165
00166 for ( QList<Rule*>::iterator it = mCurrentRules.begin(); it != mCurrentRules.end(); ++it )
00167 {
00168 Rule* rule = *it;
00169 rule->symbol()->startRender( context );
00170 }
00171 }
00172
00173 void QgsRuleBasedRendererV2::stopRender( QgsRenderContext& context )
00174 {
00175 for ( QList<Rule*>::iterator it = mCurrentRules.begin(); it != mCurrentRules.end(); ++it )
00176 {
00177 Rule* rule = *it;
00178 rule->symbol()->stopRender( context );
00179 }
00180
00181 mCurrentRules.clear();
00182 mCurrentFields.clear();
00183 }
00184
00185 QList<QString> QgsRuleBasedRendererV2::usedAttributes()
00186 {
00187 QSet<QString> attrs;
00188 for ( QList<Rule>::iterator it = mRules.begin(); it != mRules.end(); ++it )
00189 {
00190 Rule& rule = *it;
00191 attrs.unite( rule.needsFields().toSet() );
00192 }
00193 return attrs.values();
00194 }
00195
00196 QgsFeatureRendererV2* QgsRuleBasedRendererV2::clone()
00197 {
00198 QgsSymbolV2* s = mDefaultSymbol->clone();
00199 QgsRuleBasedRendererV2* r = new QgsRuleBasedRendererV2( s );
00200 r->mRules = mRules;
00201 return r;
00202 }
00203
00204 QgsSymbolV2List QgsRuleBasedRendererV2::symbols()
00205 {
00206 QgsSymbolV2List lst;
00207 for ( QList<Rule>::iterator it = mRules.begin(); it != mRules.end(); ++it )
00208 {
00209 Rule& rule = *it;
00210 lst.append( rule.symbol() );
00211 }
00212
00213 return lst;
00214 }
00215
00216 QDomElement QgsRuleBasedRendererV2::save( QDomDocument& doc )
00217 {
00218 QDomElement rendererElem = doc.createElement( RENDERER_TAG_NAME );
00219 rendererElem.setAttribute( "type", "RuleRenderer" );
00220
00221 QDomElement rulesElem = doc.createElement( "rules" );
00222
00223 QgsSymbolV2Map symbols;
00224 symbols["default"] = mDefaultSymbol;
00225
00226 int i = 0;
00227 for ( QList<Rule>::iterator it = mRules.begin(); it != mRules.end(); ++i, ++it )
00228 {
00229 Rule& rule = *it;
00230 symbols[QString::number( i )] = rule.symbol();
00231 QDomElement ruleElem = doc.createElement( "rule" );
00232 ruleElem.setAttribute( "symbol", i );
00233 ruleElem.setAttribute( "filter", rule.filterExpression() );
00234 ruleElem.setAttribute( "scalemindenom", rule.scaleMinDenom() );
00235 ruleElem.setAttribute( "scalemaxdenom", rule.scaleMaxDenom() );
00236 rulesElem.appendChild( ruleElem );
00237 }
00238 rendererElem.appendChild( rulesElem );
00239
00240 QDomElement symbolsElem = QgsSymbolLayerV2Utils::saveSymbols( symbols, "symbols", doc );
00241 rendererElem.appendChild( symbolsElem );
00242
00243 return rendererElem;
00244 }
00245
00246
00247 QgsLegendSymbologyList QgsRuleBasedRendererV2::legendSymbologyItems( QSize iconSize )
00248 {
00249 QgsLegendSymbologyList lst;
00250 for ( QList<Rule>::iterator it = mRules.begin(); it != mRules.end(); ++it )
00251 {
00252 QPixmap pix = QgsSymbolLayerV2Utils::symbolPreviewPixmap( it->symbol(), iconSize );
00253 lst << qMakePair( it->filterExpression(), pix );
00254 }
00255 return lst;
00256 }
00257
00258 QgsLegendSymbolList QgsRuleBasedRendererV2::legendSymbolItems()
00259 {
00260 QgsLegendSymbolList lst;
00261 for ( QList<Rule>::iterator it = mRules.begin(); it != mRules.end(); ++it )
00262 {
00263 lst << qMakePair( it->filterExpression(), it->symbol() );
00264 }
00265 return lst;
00266 }
00267
00268
00269 QgsFeatureRendererV2* QgsRuleBasedRendererV2::create( QDomElement& element )
00270 {
00271
00272 QDomElement symbolsElem = element.firstChildElement( "symbols" );
00273 if ( symbolsElem.isNull() )
00274 return NULL;
00275
00276 QgsSymbolV2Map symbolMap = QgsSymbolLayerV2Utils::loadSymbols( symbolsElem );
00277
00278 if ( !symbolMap.contains( "default" ) )
00279 {
00280 QgsDebugMsg( "default symbol not found!" );
00281 return NULL;
00282 }
00283
00284 QgsRuleBasedRendererV2* r = new QgsRuleBasedRendererV2( symbolMap.take( "default" ) );
00285 r->mRules.clear();
00286
00287 QDomElement rulesElem = element.firstChildElement( "rules" );
00288 QDomElement ruleElem = rulesElem.firstChildElement( "rule" );
00289 while ( !ruleElem.isNull() )
00290 {
00291 QString symbolIdx = ruleElem.attribute( "symbol" );
00292 if ( symbolMap.contains( symbolIdx ) )
00293 {
00294 QString filterExp = ruleElem.attribute( "filter" );
00295 int scaleMinDenom = ruleElem.attribute( "scalemindenom", "0" ).toInt();
00296 int scaleMaxDenom = ruleElem.attribute( "scalemaxdenom", "0" ).toInt();
00297 r->mRules.append( Rule( symbolMap.take( symbolIdx ), scaleMinDenom, scaleMaxDenom, filterExp ) );
00298 }
00299 else
00300 {
00301 QgsDebugMsg( "symbol for rule " + symbolIdx + " not found! (skipping)" );
00302 }
00303 ruleElem = ruleElem.nextSiblingElement( "rule" );
00304 }
00305
00306
00307 QgsSymbolLayerV2Utils::clearSymbolMap( symbolMap );
00308
00309 return r;
00310 }
00311
00312
00313 int QgsRuleBasedRendererV2::ruleCount()
00314 {
00315 return mRules.count();
00316 }
00317
00318 QgsRuleBasedRendererV2::Rule& QgsRuleBasedRendererV2::ruleAt( int index )
00319 {
00320 return mRules[index];
00321 }
00322
00323 void QgsRuleBasedRendererV2::addRule( const QgsRuleBasedRendererV2::Rule& rule )
00324 {
00325 mRules.append( rule );
00326 }
00327
00328 void QgsRuleBasedRendererV2::insertRule( int index, const QgsRuleBasedRendererV2::Rule& rule )
00329 {
00330 mRules.insert( index, rule );
00331 }
00332
00333 void QgsRuleBasedRendererV2::updateRuleAt( int index, const QgsRuleBasedRendererV2::Rule& rule )
00334 {
00335 mRules[index] = rule;
00336 }
00337
00338 void QgsRuleBasedRendererV2::removeRuleAt( int index )
00339 {
00340 mRules.removeAt( index );
00341 }
00342
00343 #include "qgscategorizedsymbolrendererv2.h"
00344 #include "qgsgraduatedsymbolrendererv2.h"
00345
00346 QList<QgsRuleBasedRendererV2::Rule> QgsRuleBasedRendererV2::refineRuleCategories( QgsRuleBasedRendererV2::Rule& initialRule, QgsCategorizedSymbolRendererV2* r )
00347 {
00348 QList<Rule> rules;
00349 foreach( const QgsRendererCategoryV2& cat, r->categories() )
00350 {
00351 QString newfilter = QString( "%1 = '%2'" ).arg( r->classAttribute() ).arg( cat.value().toString() );
00352 QString filter = initialRule.filterExpression();
00353 if ( filter.isEmpty() )
00354 filter = newfilter;
00355 else
00356 filter = QString( "(%1) AND (%2)" ).arg( filter ).arg( newfilter );
00357 rules.append( Rule( cat.symbol()->clone(), initialRule.scaleMinDenom(), initialRule.scaleMaxDenom(), filter ) );
00358 }
00359 return rules;
00360 }
00361
00362 QList<QgsRuleBasedRendererV2::Rule> QgsRuleBasedRendererV2::refineRuleRanges( QgsRuleBasedRendererV2::Rule& initialRule, QgsGraduatedSymbolRendererV2* r )
00363 {
00364 QList<Rule> rules;
00365 foreach( const QgsRendererRangeV2& rng, r->ranges() )
00366 {
00367 QString newfilter = QString( "%1 >= '%2' AND %1 <= '%3'" ).arg( r->classAttribute() ).arg( rng.lowerValue() ).arg( rng.upperValue() );
00368 QString filter = initialRule.filterExpression();
00369 if ( filter.isEmpty() )
00370 filter = newfilter;
00371 else
00372 filter = QString( "(%1) AND (%2)" ).arg( filter ).arg( newfilter );
00373 rules.append( Rule( rng.symbol()->clone(), initialRule.scaleMinDenom(), initialRule.scaleMaxDenom(), filter ) );
00374 }
00375 return rules;
00376 }
00377
00378 QList<QgsRuleBasedRendererV2::Rule> QgsRuleBasedRendererV2::refineRuleScales( QgsRuleBasedRendererV2::Rule& initialRule, QList<int> scales )
00379 {
00380 qSort( scales );
00381 QList<Rule> rules;
00382 int oldScale = initialRule.scaleMinDenom();
00383 int maxDenom = initialRule.scaleMaxDenom();
00384 foreach( int scale, scales )
00385 {
00386 if ( initialRule.scaleMinDenom() >= scale )
00387 continue;
00388 if ( maxDenom != 0 && maxDenom <= scale )
00389 break;
00390 rules.append( Rule( initialRule.symbol()->clone(), oldScale, scale, initialRule.filterExpression() ) );
00391 oldScale = scale;
00392 }
00393
00394 rules.append( Rule( initialRule.symbol()->clone(), oldScale, maxDenom, initialRule.filterExpression() ) );
00395 return rules;
00396 }