21 changes: 17 additions & 4 deletions src/core/symbology-ng/qgscategorizedsymbolrendererv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,14 +197,18 @@ QgsSymbolV2* QgsCategorizedSymbolRendererV2::symbolForValue( QVariant value )
QgsSymbolV2* QgsCategorizedSymbolRendererV2::symbolForFeature( QgsFeature& feature )
{
const QgsAttributes& attrs = feature.attributes();
QVariant value;
if ( mAttrNum < 0 || mAttrNum >= attrs.count() )
{
QgsDebugMsg( "attribute '" + mAttrName + "' (index " + QString::number( mAttrNum ) + ") required by renderer not found" );
return NULL;
value = mExpression->evaluate( &feature );
}
else
{
value = attrs[mAttrNum];
}

// find the right symbol for the category
QgsSymbolV2* symbol = symbolForValue( attrs[mAttrNum] );
QgsSymbolV2* symbol = symbolForValue( value );
if ( symbol == NULL )
{
// if no symbol found use default one
Expand Down Expand Up @@ -361,6 +365,11 @@ void QgsCategorizedSymbolRendererV2::startRender( QgsRenderContext& context, con

// find out classification attribute index from name
mAttrNum = vlayer ? vlayer->fieldNameIndex( mAttrName ) : -1;
if ( mAttrNum == -1 )
{
mExpression = new QgsExpression( mAttrName );
mExpression->prepare( vlayer->pendingFields() );
}

mRotationFieldIdx = ( mRotationField.isEmpty() ? -1 : vlayer->fieldNameIndex( mRotationField ) );
mSizeScaleFieldIdx = ( mSizeScaleField.isEmpty() ? -1 : vlayer->fieldNameIndex( mSizeScaleField ) );
Expand Down Expand Up @@ -401,7 +410,11 @@ void QgsCategorizedSymbolRendererV2::stopRender( QgsRenderContext& context )
QList<QString> QgsCategorizedSymbolRendererV2::usedAttributes()
{
QSet<QString> attributes;
attributes.insert( mAttrName );
QgsExpression exp( mAttrName );
foreach (QString attr, exp.referencedColumns() )
{
attributes << attr;
}
if ( !mRotationField.isEmpty() )
{
attributes.insert( mRotationField );
Expand Down
2 changes: 2 additions & 0 deletions src/core/symbology-ng/qgscategorizedsymbolrendererv2.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include "qgssymbolv2.h"
#include "qgsrendererv2.h"
#include "qgsexpression.h"

#include <QHash>

Expand Down Expand Up @@ -155,6 +156,7 @@ class CORE_EXPORT QgsCategorizedSymbolRendererV2 : public QgsFeatureRendererV2
QString mRotationField;
QString mSizeScaleField;
QgsSymbolV2::ScaleMethod mScaleMethod;
QgsExpression* mExpression;

//! attribute index (derived from attribute name in startRender)
int mAttrNum;
Expand Down
50 changes: 41 additions & 9 deletions src/core/symbology-ng/qgsgraduatedsymbolrendererv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
#include "qgsvectorlayer.h"
#include "qgslogger.h"
#include "qgsvectordataprovider.h"

#include "qgsexpression.h"
#include <QDomDocument>
#include <QDomElement>
#include <QSettings> // for legend
Expand Down Expand Up @@ -184,18 +184,22 @@ QgsSymbolV2* QgsGraduatedSymbolRendererV2::symbolForValue( double value )
QgsSymbolV2* QgsGraduatedSymbolRendererV2::symbolForFeature( QgsFeature& feature )
{
const QgsAttributes& attrs = feature.attributes();
QVariant value;
if ( mAttrNum < 0 || mAttrNum >= attrs.count() )
{
QgsDebugMsg( "attribute required by renderer not found: " + mAttrName + "(index " + QString::number( mAttrNum ) + ")" );
return NULL;
value = mExpression->evaluate( &feature );
}
else
{
value = attrs[mAttrNum];
}

// Null values should not be categorized
if ( attrs[mAttrNum].isNull() )
if ( value.isNull() )
return NULL;

// find the right category
QgsSymbolV2* symbol = symbolForValue( attrs[mAttrNum].toDouble() );
QgsSymbolV2* symbol = symbolForValue( value.toDouble() );
if ( symbol == NULL )
return NULL;

Expand Down Expand Up @@ -237,6 +241,12 @@ void QgsGraduatedSymbolRendererV2::startRender( QgsRenderContext& context, const
// find out classification attribute index from name
mAttrNum = vlayer ? vlayer->fieldNameIndex( mAttrName ) : -1;

if ( mAttrNum == -1 )
{
mExpression = new QgsExpression( mAttrName );
mExpression->prepare( vlayer->pendingFields() );
}

mRotationFieldIdx = ( mRotationField.isEmpty() ? -1 : vlayer->fieldNameIndex( mRotationField ) );
mSizeScaleFieldIdx = ( mSizeScaleField.isEmpty() ? -1 : vlayer->fieldNameIndex( mSizeScaleField ) );

Expand Down Expand Up @@ -279,7 +289,11 @@ void QgsGraduatedSymbolRendererV2::stopRender( QgsRenderContext& context )
QList<QString> QgsGraduatedSymbolRendererV2::usedAttributes()
{
QSet<QString> attributes;
attributes.insert( mAttrName );
QgsExpression exp( mAttrName );
foreach (QString attr, exp.referencedColumns() )
{
attributes << attr;
}
if ( !mRotationField.isEmpty() )
{
attributes.insert( mRotationField );
Expand Down Expand Up @@ -780,11 +794,29 @@ QgsGraduatedSymbolRendererV2* QgsGraduatedSymbolRendererV2::createRenderer(
return NULL;

int attrNum = vlayer->fieldNameIndex( attrName );
double minimum;
double maximum;
if ( attrNum == -1 )
{
QList<double> values;
QgsFeatureIterator fit = vlayer->getFeatures();
QgsFeature feature;
QgsExpression expression( attrName );
while ( fit.nextFeature( feature ) )
{
values << expression.evaluate( feature ).toDouble();
}
qSort( values );
minimum = values.first();
maximum = values.last();
}
else
{
minimum = vlayer->minimumValue( attrNum ).toDouble();
maximum = vlayer->maximumValue( attrNum ).toDouble();
}

double minimum = vlayer->minimumValue( attrNum ).toDouble();
double maximum = vlayer->maximumValue( attrNum ).toDouble();
QgsDebugMsg( QString( "min %1 // max %2" ).arg( minimum ).arg( maximum ) );

QList<double> breaks;
QList<int> labels;
if ( mode == EqualInterval )
Expand Down
3 changes: 2 additions & 1 deletion src/core/symbology-ng/qgsgraduatedsymbolrendererv2.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include "qgssymbolv2.h"
#include "qgsrendererv2.h"
#include "qgsexpression.h"

class CORE_EXPORT QgsRendererRangeV2
{
Expand Down Expand Up @@ -177,7 +178,7 @@ class CORE_EXPORT QgsGraduatedSymbolRendererV2 : public QgsFeatureRendererV2
QString mRotationField;
QString mSizeScaleField;
QgsSymbolV2::ScaleMethod mScaleMethod;

QgsExpression* mExpression;
//! attribute index (derived from attribute name in startRender)
int mAttrNum;
int mRotationFieldIdx, mSizeScaleFieldIdx;
Expand Down
46 changes: 44 additions & 2 deletions src/gui/symbology-ng/qgscategorizedsymbolrendererv2widget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@
#include "qgsstylev2.h"

#include "qgssymbolv2selectordialog.h"
#include "qgsexpressionbuilderdialog.h"

#include "qgsvectorlayer.h"

#include "qgsproject.h"
#include "qgsexpression.h"

#include <QMenu>
#include <QMessageBox>
Expand Down Expand Up @@ -387,6 +389,7 @@ QgsCategorizedSymbolRendererV2Widget::QgsCategorizedSymbolRendererV2Widget( QgsV
connect( btnDeleteAllCategories, SIGNAL( clicked() ), this, SLOT( deleteAllCategories() ) );
connect( btnAddCategory, SIGNAL( clicked() ), this, SLOT( addCategory() ) );

connect( btnExpression, SIGNAL( clicked() ), this, SLOT( setExpression() ) );
// update GUI from renderer
updateUiFromRenderer();

Expand Down Expand Up @@ -420,7 +423,12 @@ void QgsCategorizedSymbolRendererV2Widget::updateUiFromRenderer()
QString attrName = mRenderer->classAttribute();
mOldClassificationAttribute = attrName;
int idx = cboCategorizedColumn->findText( attrName, Qt::MatchExactly );
cboCategorizedColumn->setCurrentIndex( idx >= 0 ? idx : 0 );
if ( idx == -1 )
{
cboCategorizedColumn->addItem( attrName );
idx = cboCategorizedColumn->count() - 1;
}
cboCategorizedColumn->setCurrentIndex( idx );
connect( cboCategorizedColumn, SIGNAL( currentIndexChanged( int ) ), this, SLOT( categoryColumnChanged() ) );

// set source symbol
Expand Down Expand Up @@ -590,7 +598,25 @@ void QgsCategorizedSymbolRendererV2Widget::addCategories()
QString attrName = cboCategorizedColumn->currentText();
int idx = mLayer->fieldNameIndex( attrName );
QList<QVariant> unique_vals;
mLayer->uniqueValues( idx, unique_vals );
if ( idx == -1 )
{
// Lets assume it's an expression
QgsExpression* expression = new QgsExpression( attrName );
expression->prepare( mLayer->pendingFields() );
QgsFeatureIterator fit = mLayer->getFeatures();
QgsFeature feature;
while ( fit.nextFeature( feature ) )
{
QVariant value = expression->evaluate( feature ) ;
if ( unique_vals.contains( value ) )
continue;
unique_vals << value;
}
}
else
{
mLayer->uniqueValues( idx, unique_vals );
}

// ask to abort if too many classes
if ( unique_vals.size() >= 1000 )
Expand Down Expand Up @@ -733,6 +759,22 @@ void QgsCategorizedSymbolRendererV2Widget::deleteAllCategories()
mModel->removeAllRows();
}

void QgsCategorizedSymbolRendererV2Widget::setExpression()
{
QgsExpressionBuilderDialog dlg( mLayer, cboCategorizedColumn->currentText(), this );
dlg.setWindowTitle( "Set column expression" );
if ( dlg.exec() )
{
QString expression = dlg.expressionText();
if ( !expression.isEmpty() )
{
cboCategorizedColumn->addItem( expression );
cboCategorizedColumn->setCurrentIndex( cboCategorizedColumn->count() - 1 );
}
}

}

void QgsCategorizedSymbolRendererV2Widget::addCategory()
{
if ( !mModel ) return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ class GUI_EXPORT QgsCategorizedSymbolRendererV2Widget : public QgsRendererV2Widg
void addCategories();
void deleteCategories();
void deleteAllCategories();
void setExpression();

void rotationFieldChanged( QString fldName );
void sizeScaleFieldChanged( QString fldName );
Expand Down
25 changes: 24 additions & 1 deletion src/gui/symbology-ng/qgsgraduatedsymbolrendererv2widget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "qgsvectorlayer.h"

#include "qgssymbolv2selectordialog.h"
#include "qgsexpressionbuilderdialog.h"

#include "qgsludialog.h"

Expand Down Expand Up @@ -359,6 +360,7 @@ QgsGraduatedSymbolRendererV2Widget::QgsGraduatedSymbolRendererV2Widget( QgsVecto
mGraduatedSymbol = QgsSymbolV2::defaultSymbol( mLayer->geometryType() );

connect( cboGraduatedColumn, SIGNAL( currentIndexChanged( int ) ), this, SLOT( graduatedColumnChanged() ) );
connect( btnExpression, SIGNAL( clicked() ), this, SLOT( setExpression() ) );
connect( viewGraduated, SIGNAL( doubleClicked( const QModelIndex & ) ), this, SLOT( rangesDoubleClicked( const QModelIndex & ) ) );
connect( viewGraduated, SIGNAL( clicked( const QModelIndex & ) ), this, SLOT( rangesClicked( const QModelIndex & ) ) );
connect( viewGraduated, SIGNAL( customContextMenuRequested( const QPoint& ) ), this, SLOT( contextMenuViewCategories( const QPoint& ) ) );
Expand Down Expand Up @@ -417,7 +419,12 @@ void QgsGraduatedSymbolRendererV2Widget::updateUiFromRenderer()
disconnect( cboGraduatedColumn, SIGNAL( currentIndexChanged( int ) ), this, SLOT( graduatedColumnChanged() ) );
QString attrName = mRenderer->classAttribute();
int idx = cboGraduatedColumn->findText( attrName, Qt::MatchExactly );
cboGraduatedColumn->setCurrentIndex( idx >= 0 ? idx : 0 );
if ( idx == -1 )
{
cboGraduatedColumn->addItem( attrName );
idx = cboGraduatedColumn->count() - 1;
}
cboGraduatedColumn->setCurrentIndex( idx );
connect( cboGraduatedColumn, SIGNAL( currentIndexChanged( int ) ), this, SLOT( graduatedColumnChanged() ) );

// set source symbol
Expand Down Expand Up @@ -453,6 +460,22 @@ void QgsGraduatedSymbolRendererV2Widget::graduatedColumnChanged()
}


void QgsGraduatedSymbolRendererV2Widget::setExpression()
{
QgsExpressionBuilderDialog dlg( mLayer, cboGraduatedColumn->currentText(), this );
dlg.setWindowTitle( "Set column expression" );
if ( dlg.exec() )
{
QString expression = dlg.expressionText();
if ( !expression.isEmpty() )
{
cboGraduatedColumn->addItem( expression );
cboGraduatedColumn->setCurrentIndex( cboGraduatedColumn->count() - 1 );
}
}

}

void QgsGraduatedSymbolRendererV2Widget::classifyGraduated()
{
QString attrName = cboGraduatedColumn->currentText();
Expand Down
1 change: 1 addition & 0 deletions src/gui/symbology-ng/qgsgraduatedsymbolrendererv2widget.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ class GUI_EXPORT QgsGraduatedSymbolRendererV2Widget : public QgsRendererV2Widget
public slots:
void changeGraduatedSymbol();
void graduatedColumnChanged();
void setExpression();
void classifyGraduated();
void reapplyColorRamp();
void rangesDoubleClicked( const QModelIndex & idx );
Expand Down
30 changes: 29 additions & 1 deletion src/ui/qgscategorizedsymbolrendererv2widget.ui
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,32 @@
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>300</width>
<height>16777215</height>
</size>
</property>
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnExpression">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/mIconExpressionEditorOpen.svg</normaloff>:/images/themes/default/mIconExpressionEditorOpen.svg</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>16</height>
</size>
</property>
</widget>
</item>
<item>
Expand Down Expand Up @@ -207,6 +233,8 @@
<tabstop>btnDeleteAllCategories</tabstop>
<tabstop>btnJoinCategories</tabstop>
</tabstops>
<resources/>
<resources>
<include location="../../images/images.qrc"/>
</resources>
<connections/>
</ui>
Loading