Skip to content

Commit 245e76d

Browse files
committed
Model/view-based tree of rules. Added basic unit test, GUI renderer test
1 parent 83ec810 commit 245e76d

13 files changed

+556
-539
lines changed

python/core/symbology-ng-core.sip

+4-14
Original file line numberDiff line numberDiff line change
@@ -430,8 +430,10 @@ class QgsRuleBasedRendererV2 : QgsFeatureRendererV2
430430

431431
static QgsFeatureRendererV2* create( QDomElement& element ) /Factory/;
432432

433-
//! Constructor. Takes ownership of the defult symbol.
434-
QgsRuleBasedRendererV2( QgsSymbolV2* defaultSymbol /Transfer/ = NULL );
433+
//! Constructs the renderer from given tree of rules
434+
QgsRuleBasedRendererV2( QgsRuleBasedRendererV2::Rule* root /Transfer/ );
435+
//! Constructor for convenience. Creates a root rule and adds a default rule with symbol
436+
QgsRuleBasedRendererV2( QgsSymbolV2* defaultSymbol /Transfer/ );
435437

436438
//! return symbol for current feature. Should not be used individually: there could be more symbols for a feature
437439
virtual QgsSymbolV2* symbolForFeature( QgsFeature& feature );
@@ -456,18 +458,6 @@ class QgsRuleBasedRendererV2 : QgsFeatureRendererV2
456458

457459
/////
458460

459-
//! return the total number of rules
460-
int ruleCount();
461-
//! get reference to rule at index (valid indexes: 0...count-1)
462-
QgsRuleBasedRendererV2::Rule* ruleAt( int index );
463-
//! add rule to the end of the list of rules
464-
void addRule( QgsRuleBasedRendererV2::Rule* rule );
465-
//! insert rule to a specific position of the list of rules
466-
void insertRule( int index, QgsRuleBasedRendererV2::Rule* rule );
467-
//! modify the rule at a specific position of the list of rules
468-
void updateRuleAt( int index, QgsRuleBasedRendererV2::Rule* rule );
469-
//! remove the rule at the specified index
470-
void removeRuleAt( int index );
471461

472462
//////
473463

src/core/symbology-ng/qgsrulebasedrendererv2.cpp

+24-72
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929

3030

3131
QgsRuleBasedRendererV2::Rule::Rule( QgsSymbolV2* symbol, int scaleMinDenom, int scaleMaxDenom, QString filterExp, QString label, QString description )
32-
: mSymbol( symbol ),
32+
: mParent( NULL ), mSymbol( symbol ),
3333
mScaleMinDenom( scaleMinDenom ), mScaleMaxDenom( scaleMaxDenom ),
3434
mFilterExp( filterExp ), mLabel( label ), mDescription( description ),
3535
mFilter( NULL )
@@ -41,6 +41,8 @@ QgsRuleBasedRendererV2::Rule::~Rule()
4141
{
4242
delete mSymbol;
4343
delete mFilter;
44+
qDeleteAll( mChildren );
45+
// do NOT delete parent
4446
}
4547

4648
void QgsRuleBasedRendererV2::Rule::initFilter()
@@ -145,9 +147,7 @@ QgsRuleBasedRendererV2::Rule* QgsRuleBasedRendererV2::Rule::clone() const
145147
Rule* newrule = new Rule( sym, mScaleMinDenom, mScaleMaxDenom, mFilterExp, mLabel, mDescription );
146148
// clone children
147149
foreach( Rule* rule, mChildren )
148-
{
149-
newrule->mChildren.append( rule->clone() );
150-
}
150+
newrule->appendChild( rule->clone() );
151151
return newrule;
152152
}
153153

@@ -320,7 +320,7 @@ QgsRuleBasedRendererV2::Rule* QgsRuleBasedRendererV2::Rule::create( QDomElement&
320320
{
321321
Rule* childRule = create( childRuleElem, symbolMap );
322322
if ( childRule )
323-
rule->mChildren.append( childRule );
323+
rule->appendChild( childRule );
324324
else
325325
QgsDebugMsg( "failed to init a child rule!" );
326326
childRuleElem = childRuleElem.nextSiblingElement( "rule" );
@@ -332,16 +332,16 @@ QgsRuleBasedRendererV2::Rule* QgsRuleBasedRendererV2::Rule::create( QDomElement&
332332

333333
/////////////////////
334334

335+
QgsRuleBasedRendererV2::QgsRuleBasedRendererV2( QgsRuleBasedRendererV2::Rule* root )
336+
: QgsFeatureRendererV2( "RuleRenderer" ), mRootRule( root )
337+
{
338+
}
339+
335340
QgsRuleBasedRendererV2::QgsRuleBasedRendererV2( QgsSymbolV2* defaultSymbol )
336341
: QgsFeatureRendererV2( "RuleRenderer" )
337342
{
338-
mRootRule = new Rule( NULL );
339-
340-
if ( defaultSymbol )
341-
{
342-
// add the default rule
343-
mRootRule->children().append( new Rule( defaultSymbol ) );
344-
}
343+
mRootRule = new Rule( NULL ); // root has no symbol, no filter etc - just a container
344+
mRootRule->appendChild( new Rule( defaultSymbol ) );
345345
}
346346

347347
QgsRuleBasedRendererV2::~QgsRuleBasedRendererV2()
@@ -454,9 +454,7 @@ QList<QString> QgsRuleBasedRendererV2::usedAttributes()
454454

455455
QgsFeatureRendererV2* QgsRuleBasedRendererV2::clone()
456456
{
457-
QgsRuleBasedRendererV2* r = new QgsRuleBasedRendererV2();
458-
delete r->mRootRule;
459-
r->mRootRule = mRootRule->clone();
457+
QgsRuleBasedRendererV2* r = new QgsRuleBasedRendererV2( mRootRule->clone() );
460458

461459
r->setUsingSymbolLevels( usingSymbolLevels() );
462460
setUsingSymbolLevels( usingSymbolLevels() );
@@ -477,8 +475,8 @@ QDomElement QgsRuleBasedRendererV2::save( QDomDocument& doc )
477475

478476
QgsSymbolV2Map symbols;
479477

480-
QDomElement rulesElem = doc.createElement( "rules" );
481-
rulesElem.appendChild( mRootRule->save( doc, symbols ) );
478+
QDomElement rulesElem = mRootRule->save( doc, symbols );
479+
rulesElem.setTagName( "rules" ); // instead of just "rule"
482480
rendererElem.appendChild( rulesElem );
483481

484482
QDomElement symbolsElem = QgsSymbolLayerV2Utils::saveSymbols( symbols, "symbols", doc );
@@ -518,14 +516,11 @@ QgsFeatureRendererV2* QgsRuleBasedRendererV2::create( QDomElement& element )
518516

519517
QDomElement rulesElem = element.firstChildElement( "rules" );
520518

521-
QDomElement rootRuleElem = rulesElem.firstChildElement( "rule" );
522-
Rule* root = Rule::create( rootRuleElem, symbolMap );
519+
Rule* root = Rule::create( rulesElem, symbolMap );
523520
if ( root == NULL )
524521
return NULL;
525522

526-
QgsRuleBasedRendererV2* r = new QgsRuleBasedRendererV2();
527-
delete r->mRootRule;
528-
r->mRootRule = root;
523+
QgsRuleBasedRendererV2* r = new QgsRuleBasedRendererV2( root );
529524

530525
// delete symbols if there are any more
531526
QgsSymbolLayerV2Utils::clearSymbolMap( symbolMap );
@@ -534,48 +529,10 @@ QgsFeatureRendererV2* QgsRuleBasedRendererV2::create( QDomElement& element )
534529
}
535530

536531

537-
int QgsRuleBasedRendererV2::ruleCount()
538-
{
539-
return mRootRule->children().count();
540-
}
541-
542-
QgsRuleBasedRendererV2::Rule* QgsRuleBasedRendererV2::ruleAt( int index )
543-
{
544-
return mRootRule->children()[index];
545-
}
546-
547-
void QgsRuleBasedRendererV2::addRule( QgsRuleBasedRendererV2::Rule* rule )
548-
{
549-
mRootRule->children().append( rule );
550-
}
551-
552-
void QgsRuleBasedRendererV2::insertRule( int index, QgsRuleBasedRendererV2::Rule* rule )
553-
{
554-
mRootRule->children().insert( index, rule );
555-
}
556-
557-
void QgsRuleBasedRendererV2::updateRuleAt( int index, QgsRuleBasedRendererV2::Rule* rule )
558-
{
559-
RuleList& rules = mRootRule->children();
560-
delete rules[index]; // delete previous
561-
rules[index] = rule;
562-
}
563-
564-
void QgsRuleBasedRendererV2::removeRuleAt( int index )
565-
{
566-
delete mRootRule->children().takeAt( index );
567-
}
568-
569-
void QgsRuleBasedRendererV2::swapRules( int index1, int index2 )
570-
{
571-
mRootRule->children().swap( index1, index2 );
572-
}
573-
574-
575532
#include "qgscategorizedsymbolrendererv2.h"
576533
#include "qgsgraduatedsymbolrendererv2.h"
577534

578-
QgsRuleBasedRendererV2::RuleList QgsRuleBasedRendererV2::refineRuleCategories( QgsRuleBasedRendererV2::Rule* initialRule, QgsCategorizedSymbolRendererV2* r )
535+
void QgsRuleBasedRendererV2::refineRuleCategories( QgsRuleBasedRendererV2::Rule* initialRule, QgsCategorizedSymbolRendererV2* r )
579536
{
580537
RuleList rules;
581538
foreach( const QgsRendererCategoryV2& cat, r->categories() )
@@ -588,14 +545,12 @@ QgsRuleBasedRendererV2::RuleList QgsRuleBasedRendererV2::refineRuleCategories( Q
588545
filter = newfilter;
589546
else
590547
filter = QString( "(%1) AND (%2)" ).arg( filter ).arg( newfilter );
591-
rules.append( new Rule( cat.symbol()->clone(), initialRule->scaleMinDenom(), initialRule->scaleMaxDenom(), filter, label, description ) );
548+
initialRule->appendChild( new Rule( cat.symbol()->clone(), initialRule->scaleMinDenom(), initialRule->scaleMaxDenom(), filter, label, description ) );
592549
}
593-
return rules;
594550
}
595551

596-
QgsRuleBasedRendererV2::RuleList QgsRuleBasedRendererV2::refineRuleRanges( QgsRuleBasedRendererV2::Rule* initialRule, QgsGraduatedSymbolRendererV2* r )
552+
void QgsRuleBasedRendererV2::refineRuleRanges( QgsRuleBasedRendererV2::Rule* initialRule, QgsGraduatedSymbolRendererV2* r )
597553
{
598-
RuleList rules;
599554
foreach( const QgsRendererRangeV2& rng, r->ranges() )
600555
{
601556
QString newfilter = QString( "%1 >= '%2' AND %1 <= '%3'" ).arg( r->classAttribute() ).arg( rng.lowerValue() ).arg( rng.upperValue() );
@@ -606,15 +561,13 @@ QgsRuleBasedRendererV2::RuleList QgsRuleBasedRendererV2::refineRuleRanges( QgsRu
606561
filter = newfilter;
607562
else
608563
filter = QString( "(%1) AND (%2)" ).arg( filter ).arg( newfilter );
609-
rules.append( new Rule( rng.symbol()->clone(), initialRule->scaleMinDenom(), initialRule->scaleMaxDenom(), filter, label, description ) );
564+
initialRule->appendChild( new Rule( rng.symbol()->clone(), initialRule->scaleMinDenom(), initialRule->scaleMaxDenom(), filter, label, description ) );
610565
}
611-
return rules;
612566
}
613567

614-
QgsRuleBasedRendererV2::RuleList QgsRuleBasedRendererV2::refineRuleScales( QgsRuleBasedRendererV2::Rule* initialRule, QList<int> scales )
568+
void QgsRuleBasedRendererV2::refineRuleScales( QgsRuleBasedRendererV2::Rule* initialRule, QList<int> scales )
615569
{
616570
qSort( scales ); // make sure the scales are in ascending order
617-
RuleList rules;
618571
int oldScale = initialRule->scaleMinDenom();
619572
int maxDenom = initialRule->scaleMaxDenom();
620573
QString filter = initialRule->filterExpression();
@@ -627,12 +580,11 @@ QgsRuleBasedRendererV2::RuleList QgsRuleBasedRendererV2::refineRuleScales( QgsRu
627580
continue; // jump over the first scales out of the interval
628581
if ( maxDenom != 0 && maxDenom <= scale )
629582
break; // ignore the latter scales out of the interval
630-
rules.append( new Rule( symbol->clone(), oldScale, scale, filter, label, description ) );
583+
initialRule->appendChild( new Rule( symbol->clone(), oldScale, scale, filter, label, description ) );
631584
oldScale = scale;
632585
}
633586
// last rule
634-
rules.append( new Rule( symbol->clone(), oldScale, maxDenom, filter, label, description ) );
635-
return rules;
587+
initialRule->appendChild( new Rule( symbol->clone(), oldScale, maxDenom, filter, label, description ) );
636588
}
637589

638590
QString QgsRuleBasedRendererV2::dump()

src/core/symbology-ng/qgsrulebasedrendererv2.h

+18-22
Original file line numberDiff line numberDiff line change
@@ -119,11 +119,22 @@ class CORE_EXPORT QgsRuleBasedRendererV2 : public QgsFeatureRendererV2
119119
static Rule* create( QDomElement& ruleElem, QgsSymbolV2Map& symbolMap );
120120

121121
RuleList& children() { return mChildren; }
122+
Rule* parent() { return mParent; }
123+
124+
//! add child rule, take ownership, sets this as parent
125+
void appendChild( Rule* rule ) { mChildren.append( rule ); rule->mParent = this; }
126+
//! add child rule, take ownership, sets this as parent
127+
void insertChild( int i, Rule* rule ) { mChildren.insert( i, rule ); rule->mParent = this; }
128+
//! delete child rule
129+
void removeChild( Rule* rule ) { mChildren.removeAll( rule ); delete rule; }
130+
//! take child rule out, set parent as null
131+
void takeChild( Rule* rule ) { mChildren.removeAll( rule ); rule->mParent = NULL; }
122132

123133
protected:
124134

125135
void initFilter();
126136

137+
Rule* mParent; // parent rule (NULL only for root rule)
127138
QgsSymbolV2* mSymbol;
128139
int mScaleMinDenom, mScaleMaxDenom;
129140
QString mFilterExp, mLabel, mDescription;
@@ -141,8 +152,10 @@ class CORE_EXPORT QgsRuleBasedRendererV2 : public QgsFeatureRendererV2
141152

142153
static QgsFeatureRendererV2* create( QDomElement& element );
143154

144-
//! Constructor. Adds default rule if the symbol is not null (and takes ownership of it)
145-
QgsRuleBasedRendererV2( QgsSymbolV2* defaultSymbol = NULL );
155+
//! Constructs the renderer from given tree of rules (takes ownership)
156+
QgsRuleBasedRendererV2( QgsRuleBasedRendererV2::Rule* root );
157+
//! Constructor for convenience. Creates a root rule and adds a default rule with symbol (takes ownership)
158+
QgsRuleBasedRendererV2( QgsSymbolV2* defaultSymbol );
146159

147160
~QgsRuleBasedRendererV2();
148161

@@ -178,31 +191,14 @@ class CORE_EXPORT QgsRuleBasedRendererV2 : public QgsFeatureRendererV2
178191

179192
Rule* rootRule() { return mRootRule; }
180193

181-
182-
//! return the total number of rules
183-
int ruleCount();
184-
//! get reference to rule at index (valid indexes: 0...count-1)
185-
Rule* ruleAt( int index );
186-
//! add rule to the end of the list of rules. takes ownership
187-
void addRule( Rule* rule );
188-
//! insert rule to a specific position of the list of rules. takes ownership
189-
void insertRule( int index, Rule* rule );
190-
//! modify the rule at a specific position of the list of rules. takes ownership
191-
void updateRuleAt( int index, Rule* rule );
192-
//! remove the rule at the specified index
193-
void removeRuleAt( int index );
194-
//! swap the two rules specified by the indices
195-
void swapRules( int index1, int index2 );
196-
197-
198194
//////
199195

200196
//! take a rule and create a list of new rules based on the categories from categorized symbol renderer
201-
static RuleList refineRuleCategories( Rule* initialRule, QgsCategorizedSymbolRendererV2* r );
197+
static void refineRuleCategories( Rule* initialRule, QgsCategorizedSymbolRendererV2* r );
202198
//! take a rule and create a list of new rules based on the ranges from graduated symbol renderer
203-
static RuleList refineRuleRanges( Rule* initialRule, QgsGraduatedSymbolRendererV2* r );
199+
static void refineRuleRanges( Rule* initialRule, QgsGraduatedSymbolRendererV2* r );
204200
//! take a rule and create a list of new rules with intervals of scales given by the passed scale denominators
205-
static RuleList refineRuleScales( Rule* initialRule, QList<int> scales );
201+
static void refineRuleScales( Rule* initialRule, QList<int> scales );
206202

207203
protected:
208204
//! the root node with hierarchical list of rules

0 commit comments

Comments
 (0)