Skip to content

Commit 8db77fc

Browse files
committed
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.
1 parent a763594 commit 8db77fc

File tree

4 files changed

+35
-3
lines changed

4 files changed

+35
-3
lines changed

python/core/symbology-ng/qgsrulebasedrendererv2.sip

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,15 @@ class QgsRuleBasedRendererV2 : QgsFeatureRendererV2
7676
QgsExpression* filter() const;
7777
QString filterExpression() const;
7878
QString description() const;
79+
//! @note added in 2.6
80+
bool checkState() const;
81+
82+
//! Unique rule identifier (for identification of rule within renderer)
83+
//! @note added in 2.6
84+
QString ruleKey() const;
85+
//! Override the assigned rule key (should be used just internally by rule-based renderer)
86+
//! @note added in 2.6
87+
void setRuleKey( const QString& key );
7988

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

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

149+
//! Try to find a rule given its unique key
150+
//! @note added in 2.6
151+
QgsRuleBasedRendererV2::Rule* findRuleByKey( QString key );
152+
138153
void updateElseRules();
139154

140155
void setIsElse( bool iselse );

src/core/symbology-ng/qgsrulebasedrendererv2.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,6 @@ QgsRuleBasedRendererV2::Rule* QgsRuleBasedRendererV2::Rule::clone() const
257257
{
258258
QgsSymbolV2* sym = mSymbol ? mSymbol->clone() : NULL;
259259
Rule* newrule = new Rule( sym, mScaleMinDenom, mScaleMaxDenom, mFilterExp, mLabel, mDescription );
260-
newrule->mRuleKey = mRuleKey;
261260
newrule->setCheckState( mCheckState );
262261
// clone children
263262
foreach ( Rule* rule, mChildren )
@@ -850,7 +849,18 @@ QList<QString> QgsRuleBasedRendererV2::usedAttributes()
850849

851850
QgsFeatureRendererV2* QgsRuleBasedRendererV2::clone() const
852851
{
853-
QgsRuleBasedRendererV2* r = new QgsRuleBasedRendererV2( mRootRule->clone() );
852+
QgsRuleBasedRendererV2::Rule* clonedRoot = mRootRule->clone();
853+
854+
// normally with clone() the individual rules get new keys (UUID), but here we want to keep
855+
// the tree of rules intact, so that other components that may use the rule keys work nicely (e.g. visibility presets)
856+
clonedRoot->setRuleKey( mRootRule->ruleKey() );
857+
RuleList origDescendants = mRootRule->descendants();
858+
RuleList clonedDescendants = clonedRoot->descendants();
859+
Q_ASSERT( origDescendants.count() == clonedDescendants.count() );
860+
for ( int i = 0; i < origDescendants.count(); ++i )
861+
clonedDescendants[i]->setRuleKey( origDescendants[i]->ruleKey() );
862+
863+
QgsRuleBasedRendererV2* r = new QgsRuleBasedRendererV2( clonedRoot );
854864

855865
r->setUsingSymbolLevels( usingSymbolLevels() );
856866
return r;

src/core/symbology-ng/qgsrulebasedrendererv2.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@ class CORE_EXPORT QgsRuleBasedRendererV2 : public QgsFeatureRendererV2
113113
//! Unique rule identifier (for identification of rule within renderer)
114114
//! @note added in 2.6
115115
QString ruleKey() const { return mRuleKey; }
116+
//! Override the assigned rule key (should be used just internally by rule-based renderer)
117+
//! @note added in 2.6
118+
void setRuleKey( const QString& key ) { mRuleKey = key; }
116119

117120
//! set a new symbol (or NULL). Deletes old symbol.
118121
void setSymbol( QgsSymbolV2* sym );

src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -938,7 +938,9 @@ QMimeData *QgsRuleBasedRendererV2Model::mimeData( const QModelIndexList &indexes
938938
if ( !index.isValid() || index.column() != 0 )
939939
continue;
940940

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

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

954+
delete rule;
955+
952956
stream << doc.toString( -1 );
953957
}
954958

0 commit comments

Comments
 (0)