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.
This commit is contained in:
Martin Dobias 2014-10-24 12:15:47 +07:00
parent a763594432
commit 8db77fcff7
4 changed files with 35 additions and 3 deletions

View File

@ -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/ );
@ -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/;
@ -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 );

View File

@ -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 )
@ -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;

View File

@ -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 );

View File

@ -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;
@ -949,6 +951,8 @@ QMimeData *QgsRuleBasedRendererV2Model::mimeData( const QModelIndexList &indexes
rootElem.appendChild( symbolsElem );
doc.appendChild( rootElem );
delete rule;
stream << doc.toString( -1 );
}