Skip to content

Commit

Permalink
Added support for check states to rule-based renderer
Browse files Browse the repository at this point in the history
  • Loading branch information
wonder-sk committed Sep 1, 2014
1 parent cf95582 commit fb7901c
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 4 deletions.
68 changes: 66 additions & 2 deletions src/core/symbology-ng/qgsrulebasedrendererv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,18 @@

#include <QDomDocument>
#include <QDomElement>

#include <QUuid>


QgsRuleBasedRendererV2::Rule::Rule( QgsSymbolV2* symbol, int scaleMinDenom, int scaleMaxDenom, QString filterExp, QString label, QString description , bool elseRule )
: mParent( NULL ), mSymbol( symbol )
, mScaleMinDenom( scaleMinDenom ), mScaleMaxDenom( scaleMaxDenom )
, mFilterExp( filterExp ), mLabel( label ), mDescription( description )
, mElseRule( elseRule ), mFilter( NULL )
, mElseRule( elseRule )
, mCheckState( true )
, mFilter( NULL )
{
mRuleKey = QUuid::createUuid().toString();
initFilter();
}

Expand Down Expand Up @@ -108,6 +111,22 @@ QgsRuleBasedRendererV2::Rule* QgsRuleBasedRendererV2::Rule::takeChildAt( int i )
// updateElseRules();
}

QgsRuleBasedRendererV2::Rule* QgsRuleBasedRendererV2::Rule::findRuleByKey( QString key )
{
// we could use a hash / map for search if this will be slow...

if ( key == mRuleKey )
return this;

foreach ( Rule* rule, mChildren )
{
Rule* r = rule->findRuleByKey( key );
if ( r )
return r;
}
return 0;
}

void QgsRuleBasedRendererV2::Rule::updateElseRules()
{
mElseRules.clear();
Expand Down Expand Up @@ -192,6 +211,24 @@ QgsLegendSymbolList QgsRuleBasedRendererV2::Rule::legendSymbolItems( double scal
return lst;
}

QgsLegendSymbolListV2 QgsRuleBasedRendererV2::Rule::legendSymbolItemsV2() const
{
QgsLegendSymbolListV2 lst;
if ( mSymbol )
{
lst << QgsLegendSymbolItemV2( mSymbol->clone(), mLabel, mRuleKey );
lst.last().scaleDenomMin = mScaleMinDenom;
lst.last().scaleDenomMax = mScaleMaxDenom;
}

for ( RuleList::const_iterator it = mChildren.constBegin(); it != mChildren.constEnd(); ++it )
{
Rule* rule = *it;
lst << rule->legendSymbolItemsV2();
}
return lst;
}


bool QgsRuleBasedRendererV2::Rule::isFilterOK( QgsFeature& f ) const
{
Expand Down Expand Up @@ -219,6 +256,7 @@ QgsRuleBasedRendererV2::Rule* QgsRuleBasedRendererV2::Rule::clone() const
{
QgsSymbolV2* sym = mSymbol ? mSymbol->clone() : NULL;
Rule* newrule = new Rule( sym, mScaleMinDenom, mScaleMaxDenom, mFilterExp, mLabel, mDescription );
newrule->setCheckState( mCheckState );
// clone children
foreach ( Rule* rule, mChildren )
newrule->appendChild( rule->clone() );
Expand Down Expand Up @@ -349,6 +387,9 @@ bool QgsRuleBasedRendererV2::Rule::startRender( QgsRenderContext& context, const
{
mActiveChildren.clear();

if ( ! mCheckState )
return false;

// filter out rules which are not compatible with this scale
if ( !isScaleOK( context.rendererScale() ) )
return false;
Expand Down Expand Up @@ -847,11 +888,34 @@ QgsLegendSymbologyList QgsRuleBasedRendererV2::legendSymbologyItems( QSize iconS
return lst;
}

bool QgsRuleBasedRendererV2::legendSymbolItemsCheckable() const
{
return true;
}

bool QgsRuleBasedRendererV2::legendSymbolItemChecked( QString key )
{
Rule* rule = mRootRule->findRuleByKey( key );
return rule ? rule->checkState() : true;
}

void QgsRuleBasedRendererV2::checkLegendSymbolItem( QString key, bool state )
{
Rule* rule = mRootRule->findRuleByKey( key );
if ( rule )
rule->setCheckState( state );
}

QgsLegendSymbolList QgsRuleBasedRendererV2::legendSymbolItems( double scaleDenominator, QString rule )
{
return mRootRule->legendSymbolItems( scaleDenominator, rule );
}

QgsLegendSymbolListV2 QgsRuleBasedRendererV2::legendSymbolItemsV2() const
{
return mRootRule->legendSymbolItemsV2();
}


QgsFeatureRendererV2* QgsRuleBasedRendererV2::create( QDomElement& element )
{
Expand Down
34 changes: 34 additions & 0 deletions src/core/symbology-ng/qgsrulebasedrendererv2.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ class CORE_EXPORT QgsRuleBasedRendererV2 : public QgsFeatureRendererV2
QgsSymbolV2List symbols();
//! @note not available in python bindings
QgsLegendSymbolList legendSymbolItems( double scaleDenominator = -1, QString rule = "" );
//! @note added in 2.6
QgsLegendSymbolListV2 legendSymbolItemsV2() const;
bool isFilterOK( QgsFeature& f ) const;
bool isScaleOK( double scale ) const;

Expand All @@ -105,6 +107,12 @@ class CORE_EXPORT QgsRuleBasedRendererV2 : public QgsFeatureRendererV2
QgsExpression* filter() const { return mFilter; }
QString filterExpression() const { return mFilterExp; }
QString description() const { return mDescription; }
//! @note added in 2.6
bool checkState() const { return mCheckState; }

//! Unique rule identifier (for identification of rule within renderer)
//! @note added in 2.6
QString ruleKey() const { return mRuleKey; }

//! set a new symbol (or NULL). Deletes old symbol.
void setSymbol( QgsSymbolV2* sym );
Expand All @@ -113,6 +121,8 @@ class CORE_EXPORT QgsRuleBasedRendererV2 : public QgsFeatureRendererV2
void setScaleMaxDenom( int scaleMaxDenom ) { mScaleMaxDenom = scaleMaxDenom; }
void setFilterExpression( QString filterExp ) { mFilterExp = filterExp; initFilter(); }
void setDescription( QString description ) { mDescription = description; }
//! @note added in 2.6
void setCheckState( bool state ) { mCheckState = state; }

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

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

void updateElseRules();

void setIsElse( bool iselse ) { mElseRule = iselse; }
Expand All @@ -179,6 +193,9 @@ class CORE_EXPORT QgsRuleBasedRendererV2 : public QgsFeatureRendererV2
bool mElseRule;
RuleList mChildren;
RuleList mElseRules;
bool mCheckState; // whether it is enabled or not

QString mRuleKey; // string used for unique identification of rule within renderer

// temporary
QgsExpression* mFilter;
Expand Down Expand Up @@ -223,11 +240,28 @@ class CORE_EXPORT QgsRuleBasedRendererV2 : public QgsFeatureRendererV2
//! return a list of symbology items for the legend
virtual QgsLegendSymbologyList legendSymbologyItems( QSize iconSize );

//! items of symbology items in legend should be checkable
//! @note added in 2.5
virtual bool legendSymbolItemsCheckable() const;

//! items of symbology items in legend is checked
//! @note added in 2.5
virtual bool legendSymbolItemChecked( QString key );

//! item in symbology was checked
//! @note added in 2.5
virtual void checkLegendSymbolItem( QString key, bool state = true );

//! return a list of item text / symbol
//! @note: this method was added in version 1.5
//! @note not available in python bindings
virtual QgsLegendSymbolList legendSymbolItems( double scaleDenominator = -1, QString rule = "" );

//! Return a list of symbology items for the legend. Better choice than legendSymbolItems().
//! Default fallback implementation just uses legendSymbolItems() implementation
//! @node added in 2.6
virtual QgsLegendSymbolListV2 legendSymbolItemsV2() const;

//! for debugging
virtual QString dump() const;

Expand Down
22 changes: 20 additions & 2 deletions src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -704,8 +704,10 @@ Qt::ItemFlags QgsRuleBasedRendererV2Model::flags( const QModelIndex &index ) con
// allow drop only at first column
Qt::ItemFlag drop = ( index.column() == 0 ? Qt::ItemIsDropEnabled : Qt::NoItemFlags );

Qt::ItemFlag checkable = ( index.column() == 0 ? Qt::ItemIsUserCheckable : Qt::NoItemFlags );

return Qt::ItemIsEnabled | Qt::ItemIsSelectable |
Qt::ItemIsEditable |
Qt::ItemIsEditable | checkable |
Qt::ItemIsDragEnabled | drop;
}

Expand Down Expand Up @@ -797,6 +799,12 @@ QVariant QgsRuleBasedRendererV2Model::data( const QModelIndex &index, int role )
default: return QVariant();
}
}
else if ( role == Qt::CheckStateRole )
{
if ( index.column() != 0 )
return QVariant();
return rule->checkState() ? Qt::Checked : Qt::Unchecked;
}
else
return QVariant();
}
Expand Down Expand Up @@ -868,11 +876,21 @@ QModelIndex QgsRuleBasedRendererV2Model::parent( const QModelIndex &index ) cons

bool QgsRuleBasedRendererV2Model::setData( const QModelIndex & index, const QVariant & value, int role )
{
if ( !index.isValid() || role != Qt::EditRole )
if ( !index.isValid() )
return false;

QgsRuleBasedRendererV2::Rule* rule = ruleForIndex( index );

if ( role == Qt::CheckStateRole )
{
rule->setCheckState( value.toInt() == Qt::Checked );
emit dataChanged( index, index );
return true;
}

if ( role != Qt::EditRole )
return false;

switch ( index.column() )
{
case 0: // label
Expand Down

0 comments on commit fb7901c

Please sign in to comment.