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
Expand Up @@ -26,15 +26,18 @@


#include <QDomDocument> #include <QDomDocument>
#include <QDomElement> #include <QDomElement>

#include <QUuid>




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


Expand Down Expand Up @@ -108,6 +111,22 @@ QgsRuleBasedRendererV2::Rule* QgsRuleBasedRendererV2::Rule::takeChildAt( int i )
// updateElseRules(); // 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() void QgsRuleBasedRendererV2::Rule::updateElseRules()
{ {
mElseRules.clear(); mElseRules.clear();
Expand Down Expand Up @@ -192,6 +211,24 @@ QgsLegendSymbolList QgsRuleBasedRendererV2::Rule::legendSymbolItems( double scal
return lst; 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 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; QgsSymbolV2* sym = mSymbol ? mSymbol->clone() : NULL;
Rule* newrule = new Rule( sym, mScaleMinDenom, mScaleMaxDenom, mFilterExp, mLabel, mDescription ); Rule* newrule = new Rule( sym, mScaleMinDenom, mScaleMaxDenom, mFilterExp, mLabel, mDescription );
newrule->setCheckState( mCheckState );
// clone children // clone children
foreach ( Rule* rule, mChildren ) foreach ( Rule* rule, mChildren )
newrule->appendChild( rule->clone() ); newrule->appendChild( rule->clone() );
Expand Down Expand Up @@ -349,6 +387,9 @@ bool QgsRuleBasedRendererV2::Rule::startRender( QgsRenderContext& context, const
{ {
mActiveChildren.clear(); mActiveChildren.clear();


if ( ! mCheckState )
return false;

// filter out rules which are not compatible with this scale // filter out rules which are not compatible with this scale
if ( !isScaleOK( context.rendererScale() ) ) if ( !isScaleOK( context.rendererScale() ) )
return false; return false;
Expand Down Expand Up @@ -847,11 +888,34 @@ QgsLegendSymbologyList QgsRuleBasedRendererV2::legendSymbologyItems( QSize iconS
return lst; 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 ) QgsLegendSymbolList QgsRuleBasedRendererV2::legendSymbolItems( double scaleDenominator, QString rule )
{ {
return mRootRule->legendSymbolItems( scaleDenominator, rule ); return mRootRule->legendSymbolItems( scaleDenominator, rule );
} }


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



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


Expand All @@ -105,6 +107,12 @@ class CORE_EXPORT QgsRuleBasedRendererV2 : public QgsFeatureRendererV2
QgsExpression* filter() const { return mFilter; } QgsExpression* filter() const { return mFilter; }
QString filterExpression() const { return mFilterExp; } QString filterExpression() const { return mFilterExp; }
QString description() const { return mDescription; } 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. //! set a new symbol (or NULL). Deletes old symbol.
void setSymbol( QgsSymbolV2* sym ); void setSymbol( QgsSymbolV2* sym );
Expand All @@ -113,6 +121,8 @@ class CORE_EXPORT QgsRuleBasedRendererV2 : public QgsFeatureRendererV2
void setScaleMaxDenom( int scaleMaxDenom ) { mScaleMaxDenom = scaleMaxDenom; } void setScaleMaxDenom( int scaleMaxDenom ) { mScaleMaxDenom = scaleMaxDenom; }
void setFilterExpression( QString filterExp ) { mFilterExp = filterExp; initFilter(); } void setFilterExpression( QString filterExp ) { mFilterExp = filterExp; initFilter(); }
void setDescription( QString description ) { mDescription = description; } void setDescription( QString description ) { mDescription = description; }
//! @note added in 2.6
void setCheckState( bool state ) { mCheckState = state; }


//! clone this rule, return new instance //! clone this rule, return new instance
Rule* clone() const; 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 //! take child rule out, set parent as null
Rule* takeChildAt( int i ); 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 updateElseRules();


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

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


// temporary // temporary
QgsExpression* mFilter; 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 //! return a list of symbology items for the legend
virtual QgsLegendSymbologyList legendSymbologyItems( QSize iconSize ); 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 //! return a list of item text / symbol
//! @note: this method was added in version 1.5 //! @note: this method was added in version 1.5
//! @note not available in python bindings //! @note not available in python bindings
virtual QgsLegendSymbolList legendSymbolItems( double scaleDenominator = -1, QString rule = "" ); 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 //! for debugging
virtual QString dump() const; virtual QString dump() const;


Expand Down
22 changes: 20 additions & 2 deletions src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp
Expand Up @@ -704,8 +704,10 @@ Qt::ItemFlags QgsRuleBasedRendererV2Model::flags( const QModelIndex &index ) con
// allow drop only at first column // allow drop only at first column
Qt::ItemFlag drop = ( index.column() == 0 ? Qt::ItemIsDropEnabled : Qt::NoItemFlags ); 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 | return Qt::ItemIsEnabled | Qt::ItemIsSelectable |
Qt::ItemIsEditable | Qt::ItemIsEditable | checkable |
Qt::ItemIsDragEnabled | drop; Qt::ItemIsDragEnabled | drop;
} }


Expand Down Expand Up @@ -797,6 +799,12 @@ QVariant QgsRuleBasedRendererV2Model::data( const QModelIndex &index, int role )
default: return QVariant(); default: return QVariant();
} }
} }
else if ( role == Qt::CheckStateRole )
{
if ( index.column() != 0 )
return QVariant();
return rule->checkState() ? Qt::Checked : Qt::Unchecked;
}
else else
return QVariant(); 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 ) bool QgsRuleBasedRendererV2Model::setData( const QModelIndex & index, const QVariant & value, int role )
{ {
if ( !index.isValid() || role != Qt::EditRole ) if ( !index.isValid() )
return false; return false;


QgsRuleBasedRendererV2::Rule* rule = ruleForIndex( index ); 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() ) switch ( index.column() )
{ {
case 0: // label case 0: // label
Expand Down

0 comments on commit fb7901c

Please sign in to comment.