Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fix Andreas' problem with checkboxes in legend + update SIP bindings
The problem was that rule-based renderer allowed cloned rules to have the same unique rule key.
That in turn created the confusion with checkboxes in legend. Now rules always have new rule key
when cloned. The only exception is when the whole renderer is cloned - in such case we preserve
their rule keys, so that other components (legend / visibility presets) can still keep using
the original rule keys.

Projects where this problem appears need to be fixed - the easiest way is to select all rules,
copy&paste them and remove the previous rules.
  • Loading branch information
wonder-sk committed Oct 24, 2014
1 parent a763594 commit 8db77fc
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 3 deletions.
15 changes: 15 additions & 0 deletions python/core/symbology-ng/qgsrulebasedrendererv2.sip
Expand Up @@ -76,6 +76,15 @@ class QgsRuleBasedRendererV2 : QgsFeatureRendererV2
QgsExpression* filter() const;
QString filterExpression() const;
QString description() const;
//! @note added in 2.6
bool checkState() const;

//! Unique rule identifier (for identification of rule within renderer)
//! @note added in 2.6
QString ruleKey() const;
//! Override the assigned rule key (should be used just internally by rule-based renderer)
//! @note added in 2.6
void setRuleKey( const QString& key );

//! set a new symbol (or NULL). Deletes old symbol.
void setSymbol( QgsSymbolV2* sym /Transfer/ );
Expand All @@ -84,6 +93,8 @@ class QgsRuleBasedRendererV2 : QgsFeatureRendererV2
void setScaleMaxDenom( int scaleMaxDenom );
void setFilterExpression( QString filterExp );
void setDescription( QString description );
//! @note added in 2.6
void setCheckState( bool state );

//! clone this rule, return new instance
QgsRuleBasedRendererV2::Rule* clone() const /Factory/;
Expand Down Expand Up @@ -135,6 +146,10 @@ class QgsRuleBasedRendererV2 : QgsFeatureRendererV2
//! take child rule out, set parent as null
QgsRuleBasedRendererV2::Rule* takeChildAt( int i ) /TransferBack/;

//! Try to find a rule given its unique key
//! @note added in 2.6
QgsRuleBasedRendererV2::Rule* findRuleByKey( QString key );

void updateElseRules();

void setIsElse( bool iselse );
Expand Down
14 changes: 12 additions & 2 deletions src/core/symbology-ng/qgsrulebasedrendererv2.cpp
Expand Up @@ -257,7 +257,6 @@ QgsRuleBasedRendererV2::Rule* QgsRuleBasedRendererV2::Rule::clone() const
{
QgsSymbolV2* sym = mSymbol ? mSymbol->clone() : NULL;
Rule* newrule = new Rule( sym, mScaleMinDenom, mScaleMaxDenom, mFilterExp, mLabel, mDescription );
newrule->mRuleKey = mRuleKey;
newrule->setCheckState( mCheckState );
// clone children
foreach ( Rule* rule, mChildren )
Expand Down Expand Up @@ -850,7 +849,18 @@ QList<QString> QgsRuleBasedRendererV2::usedAttributes()

QgsFeatureRendererV2* QgsRuleBasedRendererV2::clone() const
{
QgsRuleBasedRendererV2* r = new QgsRuleBasedRendererV2( mRootRule->clone() );
QgsRuleBasedRendererV2::Rule* clonedRoot = mRootRule->clone();

// normally with clone() the individual rules get new keys (UUID), but here we want to keep
// the tree of rules intact, so that other components that may use the rule keys work nicely (e.g. visibility presets)
clonedRoot->setRuleKey( mRootRule->ruleKey() );
RuleList origDescendants = mRootRule->descendants();
RuleList clonedDescendants = clonedRoot->descendants();
Q_ASSERT( origDescendants.count() == clonedDescendants.count() );
for ( int i = 0; i < origDescendants.count(); ++i )
clonedDescendants[i]->setRuleKey( origDescendants[i]->ruleKey() );

QgsRuleBasedRendererV2* r = new QgsRuleBasedRendererV2( clonedRoot );

r->setUsingSymbolLevels( usingSymbolLevels() );
return r;
Expand Down
3 changes: 3 additions & 0 deletions src/core/symbology-ng/qgsrulebasedrendererv2.h
Expand Up @@ -113,6 +113,9 @@ class CORE_EXPORT QgsRuleBasedRendererV2 : public QgsFeatureRendererV2
//! Unique rule identifier (for identification of rule within renderer)
//! @note added in 2.6
QString ruleKey() const { return mRuleKey; }
//! Override the assigned rule key (should be used just internally by rule-based renderer)
//! @note added in 2.6
void setRuleKey( const QString& key ) { mRuleKey = key; }

//! set a new symbol (or NULL). Deletes old symbol.
void setSymbol( QgsSymbolV2* sym );
Expand Down
6 changes: 5 additions & 1 deletion src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp
Expand Up @@ -938,7 +938,9 @@ QMimeData *QgsRuleBasedRendererV2Model::mimeData( const QModelIndexList &indexes
if ( !index.isValid() || index.column() != 0 )
continue;

QgsRuleBasedRendererV2::Rule* rule = ruleForIndex( index );
// we use a clone of the existing rule because it has a new unique rule key
// non-unique rule keys would confuse other components using them (e.g. legend)
QgsRuleBasedRendererV2::Rule* rule = ruleForIndex( index )->clone();
QDomDocument doc;
QgsSymbolV2Map symbols;

Expand All @@ -949,6 +951,8 @@ QMimeData *QgsRuleBasedRendererV2Model::mimeData( const QModelIndexList &indexes
rootElem.appendChild( symbolsElem );
doc.appendChild( rootElem );

delete rule;

stream << doc.toString( -1 );
}

Expand Down

0 comments on commit 8db77fc

Please sign in to comment.