Skip to content

Commit a0911d6

Browse files
sbrunnerm-kuhn
authored andcommittedJan 10, 2014
[diagram] Add expression for diagram attributes and size
1 parent 443a416 commit a0911d6

25 files changed

+610
-116
lines changed
 

‎python/core/diagram/qgsdiagram.sip

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,16 @@ class QgsDiagram
66
public:
77
virtual ~QgsDiagram();
88
/**Draws the diagram at the given position (in pixel coordinates)*/
9-
virtual void renderDiagram( const QgsAttributes& att, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position ) = 0;
9+
virtual void renderDiagram( const QgsAttributes& att, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position ) /Deprecated/;
10+
/**Draws the diagram at the given position (in pixel coordinates)*/
11+
virtual void renderDiagram( const QgsFeature& feature, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position ) = 0;
1012
virtual QString diagramName() const = 0;
1113
/**Returns the size in map units the diagram will use to render.*/
1214
virtual QSizeF diagramSize( const QgsAttributes& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s ) = 0;
1315
/**Returns the size in map units the diagram will use to render. Interpolate size*/
14-
virtual QSizeF diagramSize( const QgsAttributes& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is ) = 0;
16+
virtual QSizeF diagramSize( const QgsAttributes& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is ) /Deprecated/;
17+
/**Returns the size in map units the diagram will use to render. Interpolate size*/
18+
virtual QSizeF diagramSize( const QgsFeature& feature, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is ) = 0;
1519

1620
protected:
1721
/** Changes the pen width to match the current settings and rendering context

‎python/core/diagram/qgshistogramdiagram.sip

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ class QgsHistogramDiagram: QgsDiagram
77
QgsHistogramDiagram();
88
~QgsHistogramDiagram();
99

10-
void renderDiagram( const QgsAttributes& att, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position );
10+
void renderDiagram( const QgsFeature& feature, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position );
1111
QSizeF diagramSize( const QgsAttributes& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s );
12-
QSizeF diagramSize( const QgsAttributes& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is );
12+
QSizeF diagramSize( const QgsFeature& feature, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is );
1313
QString diagramName() const;
1414
};

‎python/core/diagram/qgspiediagram.sip

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ class QgsPieDiagram: QgsDiagram
77
QgsPieDiagram();
88
~QgsPieDiagram();
99

10-
void renderDiagram( const QgsAttributes& att, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position );
10+
void renderDiagram( const QgsFeature& feature, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position );
1111
QSizeF diagramSize( const QgsAttributes& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s );
12-
QSizeF diagramSize( const QgsAttributes& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is );
12+
QSizeF diagramSize( const QgsFeature& feature, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is );
1313
QString diagramName() const;
1414
};

‎python/core/diagram/qgstextdiagram.sip

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ class QgsTextDiagram: QgsDiagram
2020

2121
QgsTextDiagram();
2222
~QgsTextDiagram();
23-
void renderDiagram( const QgsAttributes& att, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position );
23+
void renderDiagram( const QgsFeature& feature, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position );
2424
QSizeF diagramSize( const QgsAttributes& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s );
25-
QSizeF diagramSize( const QgsAttributes& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is );
25+
QSizeF diagramSize( const QgsFeature& feature, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is );
2626

2727
QString diagramName() const;
2828
};

‎python/core/qgsdiagramrendererv2.sip

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ class QgsDiagramSettings
6969
QgsDiagramSettings();
7070
QFont font;
7171
QList< QColor > categoryColors;
72-
QList< int > categoryIndices;
72+
QList< QString > categoryAttributes;
7373
QSizeF size; //size
7474
SizeType sizeType; //mm or map units
7575
QColor backgroundColor;
@@ -119,14 +119,14 @@ class QgsDiagramRendererV2
119119
virtual ~QgsDiagramRendererV2();
120120

121121
/**Returns size of the diagram for feature f in map units. Returns an invalid QSizeF in case of error*/
122-
virtual QSizeF sizeMapUnits( const QgsAttributes& attributes, const QgsRenderContext& c );
122+
virtual QSizeF sizeMapUnits( const QgsFeature& feature, const QgsRenderContext& c );
123123

124124
virtual QString rendererName() const = 0;
125125

126126
/**Returns attribute indices needed for diagram rendering*/
127-
virtual QList<int> diagramAttributes() const = 0;
127+
virtual QList<QString> diagramAttributes() const = 0;
128128

129-
void renderDiagram( const QgsAttributes& att, QgsRenderContext& c, const QPointF& pos );
129+
void renderDiagram( const QgsFeature& feature, QgsRenderContext& c, const QPointF& pos );
130130

131131
void setDiagram( QgsDiagram* d /Transfer/ );
132132
const QgsDiagram* diagram() const;
@@ -144,10 +144,10 @@ class QgsDiagramRendererV2
144144
* @param c render context
145145
* @param s out: diagram settings for the feature
146146
*/
147-
virtual bool diagramSettings( const QgsAttributes& att, const QgsRenderContext& c, QgsDiagramSettings& s ) = 0;
147+
virtual bool diagramSettings( const QgsFeature& feature, const QgsRenderContext& c, QgsDiagramSettings& s ) = 0;
148148

149149
/**Returns size of the diagram (in painter units) or an invalid size in case of error*/
150-
virtual QSizeF diagramSize( const QgsAttributes& attributes, const QgsRenderContext& c ) = 0;
150+
virtual QSizeF diagramSize( const QgsFeature& feature, const QgsRenderContext& c ) = 0;
151151

152152
/**Converts size from mm to map units*/
153153
void convertSizeToMapUnits( QSizeF& size, const QgsRenderContext& context ) const;
@@ -173,7 +173,7 @@ class QgsSingleCategoryDiagramRenderer : QgsDiagramRendererV2
173173

174174
QString rendererName() const;
175175

176-
QList<int> diagramAttributes() const;
176+
QList<QString> diagramAttributes() const;
177177

178178
void setDiagramSettings( const QgsDiagramSettings& s );
179179

@@ -183,9 +183,9 @@ class QgsSingleCategoryDiagramRenderer : QgsDiagramRendererV2
183183
void writeXML( QDomElement& layerElem, QDomDocument& doc, const QgsVectorLayer* layer ) const;
184184

185185
protected:
186-
bool diagramSettings( const QgsAttributes&, const QgsRenderContext& c, QgsDiagramSettings& s );
186+
bool diagramSettings( const QgsFeature& feature, const QgsRenderContext& c, QgsDiagramSettings& s );
187187

188-
QSizeF diagramSize( const QgsAttributes& attributes, const QgsRenderContext& c );
188+
QSizeF diagramSize( const QgsFeature& feature, const QgsRenderContext& c );
189189
};
190190

191191
class QgsLinearlyInterpolatedDiagramRenderer : QgsDiagramRendererV2
@@ -203,7 +203,7 @@ class QgsLinearlyInterpolatedDiagramRenderer : QgsDiagramRendererV2
203203

204204
void setDiagramSettings( const QgsDiagramSettings& s );
205205

206-
QList<int> diagramAttributes() const;
206+
QList<QString> diagramAttributes() const;
207207

208208
QString rendererName() const;
209209

@@ -226,7 +226,7 @@ class QgsLinearlyInterpolatedDiagramRenderer : QgsDiagramRendererV2
226226
void writeXML( QDomElement& layerElem, QDomDocument& doc, const QgsVectorLayer* layer ) const;
227227

228228
protected:
229-
bool diagramSettings( const QgsAttributes&, const QgsRenderContext& c, QgsDiagramSettings& s );
229+
bool diagramSettings( const QgsFeature& feature, const QgsRenderContext& c, QgsDiagramSettings& s );
230230

231-
QSizeF diagramSize( const QgsAttributes& attributes, const QgsRenderContext& c );
231+
QSizeF diagramSize( const QgsFeature& feature, const QgsRenderContext& c );
232232
};

‎src/app/qgsdiagramproperties.cpp

Lines changed: 130 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,15 @@
2020
#include "diagram/qgstextdiagram.h"
2121

2222
#include "qgisapp.h"
23+
#include "qgsproject.h"
2324
#include "qgsapplication.h"
2425
#include "qgsdiagramproperties.h"
2526
#include "qgsdiagramrendererv2.h"
2627
#include "qgslabelengineconfigdialog.h"
2728
#include "qgsmessagebar.h"
2829
#include "qgsvectorlayerproperties.h"
2930
#include "qgsvectordataprovider.h"
31+
#include "qgsfeatureiterator.h"
3032

3133
#include <QColorDialog>
3234
#include <QFontDialog>
@@ -127,8 +129,9 @@ QgsDiagramProperties::QgsDiagramProperties( QgsVectorLayer* layer, QWidget* pare
127129
for ( int idx = 0; idx < layerFields.count(); ++idx )
128130
{
129131
QTreeWidgetItem *newItem = new QTreeWidgetItem( mAttributesTreeWidget );
130-
newItem->setText( 0, layerFields[idx].name() );
131-
newItem->setData( 0, Qt::UserRole, idx );
132+
QString name = QString( "\"%1\"" ).arg( layerFields[idx].name() );
133+
newItem->setText( 0, name );
134+
newItem->setData( 0, Qt::UserRole, name );
132135
newItem->setFlags( newItem->flags() & ~Qt::ItemIsDropEnabled );
133136
if ( layerFields[idx].type() != QVariant::String )
134137
{
@@ -138,6 +141,7 @@ QgsDiagramProperties::QgsDiagramProperties( QgsVectorLayer* layer, QWidget* pare
138141
mDataDefinedXComboBox->addItem( layerFields[idx].name(), idx );
139142
mDataDefinedYComboBox->addItem( layerFields[idx].name(), idx );
140143
}
144+
mAvailableAttributes = mSizeAttributeComboBox->count();
141145

142146
const QgsDiagramRendererV2* dr = layer->diagramRenderer();
143147
if ( !dr ) //no diagram renderer yet, insert reasonable default
@@ -250,13 +254,13 @@ QgsDiagramProperties::QgsDiagramProperties( QgsVectorLayer* layer, QWidget* pare
250254
}
251255

252256
QList< QColor > categoryColors = settingList.at( 0 ).categoryColors;
253-
QList< int > categoryIndices = settingList.at( 0 ).categoryIndices;
254-
QList< int >::const_iterator catIt = categoryIndices.constBegin();
257+
QList< QString > categoryAttributes = settingList.at( 0 ).categoryAttributes;
258+
QList< QString >::const_iterator catIt = categoryAttributes.constBegin();
255259
QList< QColor >::const_iterator coIt = categoryColors.constBegin();
256-
for ( ;catIt != categoryIndices.constEnd(); ++catIt, ++coIt )
260+
for ( ; catIt != categoryAttributes.constEnd(); ++catIt, ++coIt )
257261
{
258262
QTreeWidgetItem *newItem = new QTreeWidgetItem( mDiagramAttributesTreeWidget );
259-
newItem->setText( 0, layer->pendingFields()[*catIt].name() );
263+
newItem->setText( 0, *catIt );
260264
newItem->setData( 0, Qt::UserRole, *catIt );
261265
newItem->setFlags( newItem->flags() & ~Qt::ItemIsDropEnabled );
262266
QColor col( *coIt );
@@ -273,7 +277,15 @@ QgsDiagramProperties::QgsDiagramProperties( QgsVectorLayer* layer, QWidget* pare
273277
mDiagramSizeSpinBox->setEnabled( false );
274278
mValueLineEdit->setText( QString::number( lidr->upperValue(), 'f' ) );
275279
mSizeSpinBox->setValue(( lidr->upperSize().width() + lidr->upperSize().height() ) / 2 );
276-
mSizeAttributeComboBox->setCurrentIndex( mSizeAttributeComboBox->findData( lidr->classificationAttribute() ) );
280+
if ( lidr->classificationAttributeIsExpression() )
281+
{
282+
mSizeAttributeComboBox->addItem( lidr->classificationAttributeExpression() );
283+
mSizeAttributeComboBox->setCurrentIndex( mSizeAttributeComboBox->count() - 1 );
284+
}
285+
else
286+
{
287+
mSizeAttributeComboBox->setCurrentIndex( mSizeAttributeComboBox->findData( lidr->classificationAttribute() ) );
288+
}
277289
}
278290
}
279291

@@ -307,6 +319,9 @@ QgsDiagramProperties::QgsDiagramProperties( QgsVectorLayer* layer, QWidget* pare
307319

308320
// Trigger a clicked event, so all the items get properly enabled and disabled
309321
on_mDisplayDiagramsGroupBox_toggled( mDisplayDiagramsGroupBox->isChecked() );
322+
323+
connect( mSizeAttributeExpression, SIGNAL( clicked() ), this, SLOT( showSizeAttributeExpressionDialog() ) );
324+
connect( mAddAttributeExpression, SIGNAL( clicked() ), this, SLOT( showAddAttributeExpressionDialog() ) );
310325
}
311326

312327
void QgsDiagramProperties::on_mDiagramTypeComboBox_currentIndexChanged( int index )
@@ -433,7 +448,30 @@ void QgsDiagramProperties::on_mFindMaximumValueButton_clicked()
433448
QgsVectorDataProvider* provider = mLayer->dataProvider();
434449
if ( provider )
435450
{
436-
mValueLineEdit->setText( provider->maximumValue( mSizeAttributeComboBox->itemData( mSizeAttributeComboBox->currentIndex() ).toInt() ).toString() );
451+
float maxValue = 0;
452+
if ( mSizeAttributeComboBox->currentIndex() >= mAvailableAttributes )
453+
{
454+
QgsExpression exp( mSizeAttributeComboBox->currentText() );
455+
exp.prepare( mLayer->pendingFields() );
456+
if ( exp.hasEvalError() )
457+
{
458+
QgsDebugMsgLevel( "Prepare error:" + exp.evalErrorString(), 4 );
459+
}
460+
else
461+
{
462+
QgsFeature feature;
463+
QgsFeatureIterator features = mLayer->getFeatures();
464+
while ( features.nextFeature( *&feature ) )
465+
{
466+
maxValue = qMax( maxValue, exp.evaluate( &feature ).toFloat() );
467+
}
468+
}
469+
}
470+
else
471+
{
472+
maxValue = provider->maximumValue( mSizeAttributeComboBox->itemData( mSizeAttributeComboBox->currentIndex() ).toInt() ).toFloat();
473+
}
474+
mValueLineEdit->setText( QString( "%1" ).arg( maxValue ) );
437475
}
438476
}
439477
}
@@ -551,16 +589,16 @@ void QgsDiagramProperties::apply()
551589
ds.transparency = mTransparencySlider->value();
552590

553591
QList<QColor> categoryColors;
554-
QList<int> categoryAttributes;
592+
QList<QString> categoryAttributes;
555593
for ( int i = 0; i < mDiagramAttributesTreeWidget->topLevelItemCount(); ++i )
556594
{
557595
QColor color = mDiagramAttributesTreeWidget->topLevelItem( i )->background( 1 ).color();
558596
color.setAlpha( 255 - ds.transparency );
559597
categoryColors.append( color );
560-
categoryAttributes.append( mDiagramAttributesTreeWidget->topLevelItem( i )->data( 0, Qt::UserRole ).toInt() );
598+
categoryAttributes.append( mDiagramAttributesTreeWidget->topLevelItem( i )->data( 0, Qt::UserRole ).toString() );
561599
}
562600
ds.categoryColors = categoryColors;
563-
ds.categoryIndices = categoryAttributes;
601+
ds.categoryAttributes = categoryAttributes;
564602
ds.size = QSizeF( mDiagramSizeSpinBox->value(), mDiagramSizeSpinBox->value() );
565603
ds.sizeType = static_cast<QgsDiagramSettings::SizeType>( mDiagramUnitComboBox->itemData( mDiagramUnitComboBox->currentIndex() ).toInt() );
566604
ds.labelPlacementMethod = static_cast<QgsDiagramSettings::LabelPlacementMethod>( mLabelPlacementComboBox->itemData( mLabelPlacementComboBox->currentIndex() ).toInt() );
@@ -611,7 +649,16 @@ void QgsDiagramProperties::apply()
611649
dr->setLowerSize( QSizeF( 0.0, 0.0 ) );
612650
dr->setUpperValue( mValueLineEdit->text().toDouble() );
613651
dr->setUpperSize( QSizeF( mSizeSpinBox->value(), mSizeSpinBox->value() ) );
614-
dr->setClassificationAttribute( mSizeAttributeComboBox->itemData( mSizeAttributeComboBox->currentIndex() ).toInt() );
652+
bool isExpression = mSizeAttributeComboBox->currentIndex() >= mAvailableAttributes;
653+
dr->setClassificationAttributeIsExpression( isExpression );
654+
if ( isExpression )
655+
{
656+
dr->setClassificationAttributeExpression( mSizeAttributeComboBox->currentText() );
657+
}
658+
else
659+
{
660+
dr->setClassificationAttribute( mSizeAttributeComboBox->itemData( mSizeAttributeComboBox->currentIndex() ).toInt() );
661+
}
615662
dr->setDiagram( diagram );
616663
dr->setDiagramSettings( ds );
617664
mLayer->setDiagramRenderer( dr );
@@ -638,3 +685,74 @@ void QgsDiagramProperties::apply()
638685
mLayer->setDiagramLayerSettings( dls );
639686
}
640687
}
688+
689+
void QgsDiagramProperties::showSizeAttributeExpressionDialog()
690+
{
691+
QString current = mSizeAttributeComboBox->currentText();
692+
if ( mSizeAttributeComboBox->currentIndex() < mAvailableAttributes )
693+
{
694+
current = QString( "\"%1\"" ).arg( current );
695+
}
696+
QgsExpressionBuilderDialog dlg( mLayer, current, this );
697+
698+
dlg.setWindowTitle( tr( "Expression based attribute" ) );
699+
700+
QgsDistanceArea myDa;
701+
myDa.setSourceCrs( mLayer->crs().srsid() );
702+
myDa.setEllipsoidalMode( QgisApp::instance()->mapCanvas()->mapRenderer()->hasCrsTransformEnabled() );
703+
myDa.setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ) );
704+
dlg.setGeomCalculator( myDa );
705+
706+
if ( dlg.exec() == QDialog::Accepted )
707+
{
708+
QString expression = dlg.expressionText();
709+
//Only add the expression if the user has entered some text.
710+
if ( !expression.isEmpty() )
711+
{
712+
mSizeAttributeComboBox->addItem( expression );
713+
mSizeAttributeComboBox->setCurrentIndex( mSizeAttributeComboBox->count() - 1 );
714+
}
715+
}
716+
activateWindow(); // set focus back parent
717+
}
718+
719+
void QgsDiagramProperties::showAddAttributeExpressionDialog()
720+
{
721+
QString expression;
722+
QList<QTreeWidgetItem *> selections = mAttributesTreeWidget->selectedItems();
723+
if ( !selections.empty() )
724+
{
725+
expression = selections[0]->text( 0 );
726+
}
727+
QgsExpressionBuilderDialog dlg( mLayer, expression, this );
728+
dlg.setWindowTitle( tr( "Expression based attribute" ) );
729+
730+
QgsDistanceArea myDa;
731+
myDa.setSourceCrs( mLayer->crs().srsid() );
732+
myDa.setEllipsoidalMode( QgisApp::instance()->mapCanvas()->mapRenderer()->hasCrsTransformEnabled() );
733+
myDa.setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ) );
734+
dlg.setGeomCalculator( myDa );
735+
736+
if ( dlg.exec() == QDialog::Accepted )
737+
{
738+
QString expression = dlg.expressionText();
739+
//Only add the expression if the user has entered some text.
740+
if ( !expression.isEmpty() )
741+
{
742+
QTreeWidgetItem *newItem = new QTreeWidgetItem( mDiagramAttributesTreeWidget );
743+
744+
newItem->setText( 0, expression );
745+
newItem->setData( 0, Qt::UserRole, expression );
746+
newItem->setFlags( newItem->flags() & ~Qt::ItemIsDropEnabled );
747+
748+
//set initial color for diagram category
749+
int red = 1 + ( int )( 255.0 * rand() / ( RAND_MAX + 1.0 ) );
750+
int green = 1 + ( int )( 255.0 * rand() / ( RAND_MAX + 1.0 ) );
751+
int blue = 1 + ( int )( 255.0 * rand() / ( RAND_MAX + 1.0 ) );
752+
QColor randomColor( red, green, blue );
753+
newItem->setBackground( 1, QBrush( randomColor ) );
754+
mDiagramAttributesTreeWidget->addTopLevelItem( newItem );
755+
}
756+
}
757+
activateWindow(); // set focus back parent
758+
}

‎src/app/qgsdiagramproperties.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,16 @@ class APP_EXPORT QgsDiagramProperties : public QWidget, private Ui::QgsDiagramPr
4444
void on_mDiagramFontButton_clicked();
4545
void on_mDiagramAttributesTreeWidget_itemDoubleClicked( QTreeWidgetItem * item, int column );
4646
void on_mEngineSettingsButton_clicked();
47+
void showSizeAttributeExpressionDialog();
48+
void showAddAttributeExpressionDialog();
4749

4850
protected:
4951
QFont mDiagramFont;
5052

5153
QgsVectorLayer* mLayer;
5254

5355
private:
56+
int mAvailableAttributes;
5457
};
5558

5659
#endif // QGSDIAGRAMPROPERTIES_H

‎src/core/diagram/qgsdiagram.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,33 @@
1515
#include "qgsdiagram.h"
1616
#include "qgsdiagramrendererv2.h"
1717
#include "qgsrendercontext.h"
18+
#include "qgsexpression.h"
1819

1920
#include <QPainter>
2021

22+
23+
void QgsDiagram::clearCache()
24+
{
25+
QMapIterator<QString, QgsExpression*> i( mExpressions );
26+
while ( i.hasNext() )
27+
{
28+
i.next();
29+
delete i.value();
30+
}
31+
mExpressions.clear();
32+
}
33+
34+
QgsExpression* QgsDiagram::getExpression( const QString& expression, const QgsFields* fields )
35+
{
36+
if ( !mExpressions.contains( expression ) )
37+
{
38+
QgsExpression* expr = new QgsExpression( expression );
39+
expr->prepare( *fields );
40+
mExpressions[expression] = expr;
41+
}
42+
return mExpressions[expression];
43+
}
44+
2145
void QgsDiagram::setPenWidth( QPen& pen, const QgsDiagramSettings& s, const QgsRenderContext& c )
2246
{
2347
if ( s.sizeType == QgsDiagramSettings::MM )
@@ -69,3 +93,17 @@ QFont QgsDiagram::scaledFont( const QgsDiagramSettings& s, const QgsRenderContex
6993

7094
return f;
7195
}
96+
97+
void QgsDiagram::renderDiagram( const QgsAttributes& attributes, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position )
98+
{
99+
QgsFeature feature;
100+
feature.setAttributes( attributes );
101+
renderDiagram( feature, c, s, position );
102+
}
103+
104+
QSizeF QgsDiagram::diagramSize( const QgsAttributes& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is )
105+
{
106+
QgsFeature feature;
107+
feature.setAttributes( attributes );
108+
return diagramSize( feature, c, s, is );
109+
}

‎src/core/diagram/qgsdiagram.h

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,28 @@ class QgsDiagramInterpolationSettings;
2626

2727
class QgsRenderContext;
2828

29+
class QgsExpression;
30+
2931

3032

3133
/**Base class for all diagram types*/
3234
class CORE_EXPORT QgsDiagram
3335
{
3436
public:
35-
virtual ~QgsDiagram() {}
37+
virtual ~QgsDiagram() { clearCache(); }
38+
void clearCache();
39+
QgsExpression* getExpression( const QString& expression, const QgsFields* fields );
40+
/** @deprecated `void renderDiagram( const QgsFeature& feature, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position )` should be used instead */
41+
virtual Q_DECL_DEPRECATED void renderDiagram( const QgsAttributes& att, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position );
3642
/**Draws the diagram at the given position (in pixel coordinates)*/
37-
virtual void renderDiagram( const QgsAttributes& att, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position ) = 0;
43+
virtual void renderDiagram( const QgsFeature& feature, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position ) = 0;
3844
virtual QString diagramName() const = 0;
3945
/**Returns the size in map units the diagram will use to render.*/
4046
virtual QSizeF diagramSize( const QgsAttributes& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s ) = 0;
47+
/** @deprecated `QSizeF diagramSize( const QgsFeature& feature, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is )` should be used instead */
48+
virtual Q_DECL_DEPRECATED QSizeF diagramSize( const QgsAttributes& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is );
4149
/**Returns the size in map units the diagram will use to render. Interpolate size*/
42-
virtual QSizeF diagramSize( const QgsAttributes& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is ) = 0;
50+
virtual QSizeF diagramSize( const QgsFeature& feature, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is ) = 0;
4351

4452
protected:
4553
/** Changes the pen width to match the current settings and rendering context
@@ -74,6 +82,9 @@ class CORE_EXPORT QgsDiagram
7482
* @return The properly scaled font for rendering
7583
*/
7684
QFont scaledFont( const QgsDiagramSettings& s, const QgsRenderContext& c );
85+
86+
private:
87+
QMap<QString, QgsExpression*> mExpressions;
7788
};
7889

7990
#endif // QGSDIAGRAM_H

‎src/core/diagram/qgshistogramdiagram.cpp

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "qgshistogramdiagram.h"
1616
#include "qgsdiagramrendererv2.h"
1717
#include "qgsrendercontext.h"
18+
#include "qgsexpression.h"
1819

1920
#include <QPainter>
2021

@@ -29,20 +30,21 @@ QgsHistogramDiagram::~QgsHistogramDiagram()
2930
{
3031
}
3132

32-
QSizeF QgsHistogramDiagram::diagramSize( const QgsAttributes& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is )
33+
QSizeF QgsHistogramDiagram::diagramSize( const QgsFeature& feature, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is )
3334
{
3435
Q_UNUSED( c );
3536
QSizeF size;
36-
if ( attributes.count() == 0 )
37+
if ( feature.attributes().count() == 0 )
3738
{
3839
return size; //zero size if no attributes
3940
}
4041

4142
double maxValue = 0;
4243

43-
foreach ( int cat, s.categoryIndices )
44+
foreach ( QString cat, s.categoryAttributes )
4445
{
45-
maxValue = qMax( attributes[cat].toDouble(), maxValue );
46+
QgsExpression* expression = getExpression( cat, feature.fields() );
47+
maxValue = qMax( expression->evaluate( feature ).toDouble(), maxValue );
4648
}
4749

4850
// Scale, if extension is smaller than the specified minimum
@@ -56,13 +58,13 @@ QSizeF QgsHistogramDiagram::diagramSize( const QgsAttributes& attributes, const
5658
case QgsDiagramSettings::Up:
5759
case QgsDiagramSettings::Down:
5860
mScaleFactor = (( is.upperSize.width() - is.lowerSize.height() ) / ( is.upperValue - is.lowerValue ) );
59-
size.scale( s.barWidth * s.categoryIndices.size(), maxValue * mScaleFactor, Qt::IgnoreAspectRatio );
61+
size.scale( s.barWidth * s.categoryAttributes.size(), maxValue * mScaleFactor, Qt::IgnoreAspectRatio );
6062
break;
6163

6264
case QgsDiagramSettings::Right:
6365
case QgsDiagramSettings::Left:
6466
mScaleFactor = (( is.upperSize.width() - is.lowerSize.width() ) / ( is.upperValue - is.lowerValue ) );
65-
size.scale( maxValue * mScaleFactor, s.barWidth * s.categoryIndices.size(), Qt::IgnoreAspectRatio );
67+
size.scale( maxValue * mScaleFactor, s.barWidth * s.categoryAttributes.size(), Qt::IgnoreAspectRatio );
6668
break;
6769
}
6870

@@ -105,7 +107,7 @@ QSizeF QgsHistogramDiagram::diagramSize( const QgsAttributes& attributes, const
105107
return size;
106108
}
107109

108-
void QgsHistogramDiagram::renderDiagram( const QgsAttributes& att, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position )
110+
void QgsHistogramDiagram::renderDiagram( const QgsFeature& feature, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position )
109111
{
110112
QPainter* p = c.painter();
111113
if ( !p )
@@ -116,9 +118,10 @@ void QgsHistogramDiagram::renderDiagram( const QgsAttributes& att, QgsRenderCont
116118
QList<double> values;
117119
double maxValue = 0;
118120

119-
foreach ( int cat, s.categoryIndices )
121+
foreach ( QString cat, s.categoryAttributes )
120122
{
121-
double currentVal = att[cat].toDouble();
123+
QgsExpression* expression = getExpression( cat, feature.fields() );
124+
double currentVal = expression->evaluate( feature ).toDouble();
122125
values.push_back( currentVal );
123126
maxValue = qMax( currentVal, maxValue );
124127
}

‎src/core/diagram/qgshistogramdiagram.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ class CORE_EXPORT QgsHistogramDiagram: public QgsDiagram
3737
QgsHistogramDiagram();
3838
~QgsHistogramDiagram();
3939

40-
void renderDiagram( const QgsAttributes& att, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position );
40+
void renderDiagram( const QgsFeature& feature, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position );
4141
QSizeF diagramSize( const QgsAttributes& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s );
42-
QSizeF diagramSize( const QgsAttributes& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is );
42+
QSizeF diagramSize( const QgsFeature& feature, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is );
4343
QString diagramName() const { return DIAGRAM_NAME_HISTOGRAM; }
4444

4545
private:

‎src/core/diagram/qgspiediagram.cpp

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "qgspiediagram.h"
1616
#include "qgsdiagramrendererv2.h"
1717
#include "qgsrendercontext.h"
18+
#include "qgsexpression.h"
1819

1920
#include <QPainter>
2021

@@ -29,10 +30,21 @@ QgsPieDiagram::~QgsPieDiagram()
2930
{
3031
}
3132

32-
QSizeF QgsPieDiagram::diagramSize( const QgsAttributes& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is )
33+
QSizeF QgsPieDiagram::diagramSize( const QgsFeature& feature, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is )
3334
{
3435
Q_UNUSED( c );
35-
QVariant attrVal = attributes[is.classificationAttribute];
36+
37+
QVariant attrVal;
38+
if ( is.classificationAttributeIsExpression )
39+
{
40+
QgsExpression* expression = getExpression( is.classificationAttributeExpression, feature.fields() );
41+
attrVal = expression->evaluate( feature );
42+
}
43+
else
44+
{
45+
attrVal = feature.attributes()[is.classificationAttribute];
46+
}
47+
3648
if ( !attrVal.isValid() )
3749
{
3850
return QSizeF(); //zero size if attribute is missing
@@ -90,7 +102,7 @@ QSizeF QgsPieDiagram::diagramSize( const QgsAttributes& attributes, const QgsRen
90102

91103
int QgsPieDiagram::sCount = 0;
92104

93-
void QgsPieDiagram::renderDiagram( const QgsAttributes& att, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position )
105+
void QgsPieDiagram::renderDiagram( const QgsFeature& feature, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position )
94106
{
95107
QPainter* p = c.painter();
96108
if ( !p )
@@ -104,10 +116,11 @@ void QgsPieDiagram::renderDiagram( const QgsAttributes& att, QgsRenderContext& c
104116
double valSum = 0;
105117
int valCount = 0;
106118

107-
QList<int>::const_iterator catIt = s.categoryIndices.constBegin();
108-
for ( ; catIt != s.categoryIndices.constEnd(); ++catIt )
119+
QList<QString>::const_iterator catIt = s.categoryAttributes.constBegin();
120+
for ( ; catIt != s.categoryAttributes.constEnd(); ++catIt )
109121
{
110-
currentVal = att[*catIt].toDouble();
122+
QgsExpression* expression = getExpression( *catIt, feature.fields() );
123+
currentVal = expression->evaluate( feature ).toDouble();
111124
values.push_back( currentVal );
112125
valSum += currentVal;
113126
if ( currentVal ) valCount++;

‎src/core/diagram/qgspiediagram.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@ class CORE_EXPORT QgsPieDiagram: public QgsDiagram
3535
QgsPieDiagram();
3636
~QgsPieDiagram();
3737

38-
void renderDiagram( const QgsAttributes& att, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position );
38+
void renderDiagram( const QgsFeature& feature, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position );
3939
QSizeF diagramSize( const QgsAttributes& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s );
40-
QSizeF diagramSize( const QgsAttributes& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is );
40+
QSizeF diagramSize( const QgsFeature& feature, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is );
4141
QString diagramName() const { return DIAGRAM_NAME_PIE; }
4242

4343
private:

‎src/core/diagram/qgstextdiagram.cpp

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "qgstextdiagram.h"
1616
#include "qgsdiagramrendererv2.h"
1717
#include "qgsrendercontext.h"
18+
#include "qgsexpression.h"
1819

1920
#include <QPainter>
2021

@@ -30,11 +31,20 @@ QgsTextDiagram::~QgsTextDiagram()
3031
{
3132
}
3233

33-
QSizeF QgsTextDiagram::diagramSize( const QgsAttributes& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is )
34+
QSizeF QgsTextDiagram::diagramSize( const QgsFeature& feature, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is )
3435
{
3536
Q_UNUSED( c );
3637

37-
QVariant attrVal = attributes[is.classificationAttribute];
38+
QVariant attrVal;
39+
if ( is.classificationAttributeIsExpression )
40+
{
41+
QgsExpression* expression = getExpression( is.classificationAttributeExpression, feature.fields() );
42+
attrVal = expression->evaluate( feature );
43+
}
44+
else
45+
{
46+
attrVal = feature.attributes()[is.classificationAttribute];
47+
}
3848

3949
if ( !attrVal.isValid() )
4050
{
@@ -84,8 +94,10 @@ QSizeF QgsTextDiagram::diagramSize( const QgsAttributes& attributes, const QgsRe
8494
return s.size;
8595
}
8696

87-
void QgsTextDiagram::renderDiagram( const QgsAttributes& att, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position )
97+
void QgsTextDiagram::renderDiagram( const QgsFeature& feature, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position )
8898
{
99+
Q_UNUSED( feature );
100+
89101
QPainter* p = c.painter();
90102
if ( !p )
91103
{
@@ -108,7 +120,7 @@ void QgsTextDiagram::renderDiagram( const QgsAttributes& att, QgsRenderContext&
108120
double baseY = position.y() - h;
109121

110122
QList<QPointF> textPositions; //midpoints for text placement
111-
int nCategories = s.categoryIndices.size();
123+
int nCategories = s.categoryAttributes.size();
112124
for ( int i = 0; i < nCategories; ++i )
113125
{
114126
if ( mOrientation == Horizontal )
@@ -210,7 +222,9 @@ void QgsTextDiagram::renderDiagram( const QgsAttributes& att, QgsRenderContext&
210222

211223
for ( int i = 0; i < textPositions.size(); ++i )
212224
{
213-
QString val = att[ s.categoryIndices.at( i )].toString();
225+
QgsExpression* expression = getExpression( s.categoryAttributes.at( i ), feature.fields() );
226+
QString val = expression->evaluate( feature ).toString();
227+
214228
//find out dimesions
215229
double textWidth = fontMetrics.width( val );
216230
double textHeight = fontMetrics.height();

‎src/core/diagram/qgstextdiagram.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,9 @@ class CORE_EXPORT QgsTextDiagram: public QgsDiagram
4848

4949
QgsTextDiagram();
5050
~QgsTextDiagram();
51-
void renderDiagram( const QgsAttributes& att, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position );
51+
void renderDiagram( const QgsFeature& feature, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position );
5252
QSizeF diagramSize( const QgsAttributes& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s );
53-
QSizeF diagramSize( const QgsAttributes& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is );
53+
QSizeF diagramSize( const QgsFeature& feature, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is );
5454

5555
QString diagramName() const { return DIAGRAM_NAME_TEXT; }
5656

‎src/core/qgsdiagramrendererv2.cpp

Lines changed: 42 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ void QgsDiagramLayerSettings::writeXML( QDomElement& layerElem, QDomDocument& do
5252

5353
void QgsDiagramSettings::readXML( const QDomElement& elem, const QgsVectorLayer* layer )
5454
{
55+
Q_UNUSED( layer );
56+
5557
font.fromString( elem.attribute( "font" ) );
5658
backgroundColor.setNamedColor( elem.attribute( "backgroundColor" ) );
5759
backgroundColor.setAlpha( elem.attribute( "backgroundAlpha" ).toInt() );
@@ -132,7 +134,7 @@ void QgsDiagramSettings::readXML( const QDomElement& elem, const QgsVectorLayer*
132134
QColor newColor( attrElem.attribute( "color" ) );
133135
newColor.setAlpha( 255 - transparency );
134136
categoryColors.append( newColor );
135-
categoryIndices.append( layer->fieldNameIndex( attrElem.attribute( "field" ) ) );
137+
categoryAttributes.append( attrElem.attribute( "field" ) );
136138
}
137139
}
138140
else
@@ -149,18 +151,20 @@ void QgsDiagramSettings::readXML( const QDomElement& elem, const QgsVectorLayer*
149151
}
150152

151153
//attribute indices
152-
categoryIndices.clear();
154+
categoryAttributes.clear();
153155
QStringList catList = elem.attribute( "categories" ).split( "/" );
154156
QStringList::const_iterator catIt = catList.constBegin();
155157
for ( ; catIt != catList.constEnd(); ++catIt )
156158
{
157-
categoryIndices.append( catIt->toInt() );
159+
categoryAttributes.append( *catIt );
158160
}
159161
}
160162
}
161163

162164
void QgsDiagramSettings::writeXML( QDomElement& rendererElem, QDomDocument& doc, const QgsVectorLayer* layer ) const
163165
{
166+
Q_UNUSED( layer );
167+
164168
QDomElement categoryElem = doc.createElement( "DiagramCategory" );
165169
categoryElem.setAttribute( "font", font.toString() );
166170
categoryElem.setAttribute( "backgroundColor", backgroundColor.name() );
@@ -232,12 +236,12 @@ void QgsDiagramSettings::writeXML( QDomElement& rendererElem, QDomDocument& doc,
232236
categoryElem.setAttribute( "angleOffset", QString::number( angleOffset ) );
233237

234238
QString colors;
235-
int nCats = qMin( categoryColors.size(), categoryIndices.size() );
239+
int nCats = qMin( categoryColors.size(), categoryAttributes.size() );
236240
for ( int i = 0; i < nCats; ++i )
237241
{
238242
QDomElement attributeElem = doc.createElement( "attribute" );
239243

240-
attributeElem.setAttribute( "field", layer->pendingFields().at( categoryIndices.at( i ) ).name() );
244+
attributeElem.setAttribute( "field", categoryAttributes.at( i ) );
241245
attributeElem.setAttribute( "color", categoryColors.at( i ).name() );
242246
categoryElem.appendChild( attributeElem );
243247
}
@@ -260,31 +264,31 @@ void QgsDiagramRendererV2::setDiagram( QgsDiagram* d )
260264
mDiagram = d;
261265
}
262266

263-
void QgsDiagramRendererV2::renderDiagram( const QgsAttributes& att, QgsRenderContext& c, const QPointF& pos )
267+
void QgsDiagramRendererV2::renderDiagram( const QgsFeature& feature, QgsRenderContext& c, const QPointF& pos )
264268
{
265269
if ( !mDiagram )
266270
{
267271
return;
268272
}
269273

270274
QgsDiagramSettings s;
271-
if ( !diagramSettings( att, c, s ) )
275+
if ( !diagramSettings( feature, c, s ) )
272276
{
273277
return;
274278
}
275279

276-
mDiagram->renderDiagram( att, c, s, pos );
280+
mDiagram->renderDiagram( feature, c, s, pos );
277281
}
278282

279-
QSizeF QgsDiagramRendererV2::sizeMapUnits( const QgsAttributes& attributes, const QgsRenderContext& c )
283+
QSizeF QgsDiagramRendererV2::sizeMapUnits( const QgsFeature& feature, const QgsRenderContext& c )
280284
{
281285
QgsDiagramSettings s;
282-
if ( !diagramSettings( attributes, c, s ) )
286+
if ( !diagramSettings( feature, c, s ) )
283287
{
284288
return QSizeF();
285289
}
286290

287-
QSizeF size = diagramSize( attributes, c );
291+
QSizeF size = diagramSize( feature, c );
288292
if ( s.sizeType == QgsDiagramSettings::MM )
289293
{
290294
convertSizeToMapUnits( size, c );
@@ -360,16 +364,16 @@ QgsSingleCategoryDiagramRenderer::~QgsSingleCategoryDiagramRenderer()
360364
{
361365
}
362366

363-
bool QgsSingleCategoryDiagramRenderer::diagramSettings( const QgsAttributes&, const QgsRenderContext& c, QgsDiagramSettings& s )
367+
bool QgsSingleCategoryDiagramRenderer::diagramSettings( const QgsFeature&, const QgsRenderContext& c, QgsDiagramSettings& s )
364368
{
365369
Q_UNUSED( c );
366370
s = mSettings;
367371
return true;
368372
}
369373

370-
QSizeF QgsSingleCategoryDiagramRenderer::diagramSize( const QgsAttributes &attributes, const QgsRenderContext &c )
374+
QSizeF QgsSingleCategoryDiagramRenderer::diagramSize( const QgsFeature &feature, const QgsRenderContext &c )
371375
{
372-
return mDiagram->diagramSize( attributes, c, mSettings );
376+
return mDiagram->diagramSize( feature.attributes(), c, mSettings );
373377
}
374378

375379
QList<QgsDiagramSettings> QgsSingleCategoryDiagramRenderer::diagramSettings() const
@@ -402,6 +406,7 @@ void QgsSingleCategoryDiagramRenderer::writeXML( QDomElement& layerElem, QDomDoc
402406

403407
QgsLinearlyInterpolatedDiagramRenderer::QgsLinearlyInterpolatedDiagramRenderer(): QgsDiagramRendererV2()
404408
{
409+
mInterpolationSettings.classificationAttributeIsExpression = false;
405410
}
406411

407412
QgsLinearlyInterpolatedDiagramRenderer::~QgsLinearlyInterpolatedDiagramRenderer()
@@ -415,26 +420,21 @@ QList<QgsDiagramSettings> QgsLinearlyInterpolatedDiagramRenderer::diagramSetting
415420
return settingsList;
416421
}
417422

418-
bool QgsLinearlyInterpolatedDiagramRenderer::diagramSettings( const QgsAttributes& attributes, const QgsRenderContext& c, QgsDiagramSettings& s )
423+
bool QgsLinearlyInterpolatedDiagramRenderer::diagramSettings( const QgsFeature& feature, const QgsRenderContext& c, QgsDiagramSettings& s )
419424
{
420425
s = mSettings;
421-
s.size = diagramSize( attributes, c );
426+
s.size = diagramSize( feature, c );
422427
return true;
423428
}
424429

425-
QList<int> QgsLinearlyInterpolatedDiagramRenderer::diagramAttributes() const
430+
QList<QString> QgsLinearlyInterpolatedDiagramRenderer::diagramAttributes() const
426431
{
427-
QList<int> attributes = mSettings.categoryIndices;
428-
if ( !attributes.contains( mInterpolationSettings.classificationAttribute ) )
429-
{
430-
attributes.push_back( mInterpolationSettings.classificationAttribute );
431-
}
432-
return attributes;
432+
return mSettings.categoryAttributes;
433433
}
434434

435-
QSizeF QgsLinearlyInterpolatedDiagramRenderer::diagramSize( const QgsAttributes& attributes, const QgsRenderContext& c )
435+
QSizeF QgsLinearlyInterpolatedDiagramRenderer::diagramSize( const QgsFeature& feature, const QgsRenderContext& c )
436436
{
437-
return mDiagram->diagramSize( attributes, c, mSettings, mInterpolationSettings );
437+
return mDiagram->diagramSize( feature, c, mSettings, mInterpolationSettings );
438438
}
439439

440440
void QgsLinearlyInterpolatedDiagramRenderer::readXML( const QDomElement& elem, const QgsVectorLayer* layer )
@@ -445,7 +445,15 @@ void QgsLinearlyInterpolatedDiagramRenderer::readXML( const QDomElement& elem, c
445445
mInterpolationSettings.lowerSize.setHeight( elem.attribute( "lowerHeight" ).toDouble() );
446446
mInterpolationSettings.upperSize.setWidth( elem.attribute( "upperWidth" ).toDouble() );
447447
mInterpolationSettings.upperSize.setHeight( elem.attribute( "upperHeight" ).toDouble() );
448-
mInterpolationSettings.classificationAttribute = elem.attribute( "classificationAttribute" ).toInt();
448+
mInterpolationSettings.classificationAttributeIsExpression = elem.hasAttribute( "classificationAttributeExpression" );
449+
if ( mInterpolationSettings.classificationAttributeIsExpression )
450+
{
451+
mInterpolationSettings.classificationAttributeExpression = elem.attribute( "classificationAttributeExpression" );
452+
}
453+
else
454+
{
455+
mInterpolationSettings.classificationAttribute = elem.attribute( "classificationAttribute" ).toInt();
456+
}
449457
QDomElement settingsElem = elem.firstChildElement( "DiagramCategory" );
450458
if ( !settingsElem.isNull() )
451459
{
@@ -463,7 +471,14 @@ void QgsLinearlyInterpolatedDiagramRenderer::writeXML( QDomElement& layerElem, Q
463471
rendererElem.setAttribute( "lowerHeight", QString::number( mInterpolationSettings.lowerSize.height() ) );
464472
rendererElem.setAttribute( "upperWidth", QString::number( mInterpolationSettings.upperSize.width() ) );
465473
rendererElem.setAttribute( "upperHeight", QString::number( mInterpolationSettings.upperSize.height() ) );
466-
rendererElem.setAttribute( "classificationAttribute", mInterpolationSettings.classificationAttribute );
474+
if ( mInterpolationSettings.classificationAttributeIsExpression )
475+
{
476+
rendererElem.setAttribute( "classificationAttributeExpression", mInterpolationSettings.classificationAttributeExpression );
477+
}
478+
else
479+
{
480+
rendererElem.setAttribute( "classificationAttribute", mInterpolationSettings.classificationAttribute );
481+
}
467482
mSettings.writeXML( rendererElem, doc, layer );
468483
_writeXML( rendererElem, doc, layer );
469484
layerElem.appendChild( rendererElem );

‎src/core/qgsdiagramrendererv2.h

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ class CORE_EXPORT QgsDiagramSettings
123123
{}
124124
QFont font;
125125
QList< QColor > categoryColors;
126-
QList< int > categoryIndices;
126+
QList< QString > categoryAttributes;
127127
QSizeF size; //size
128128
SizeType sizeType; //mm or map units
129129
QColor backgroundColor;
@@ -157,6 +157,8 @@ class CORE_EXPORT QgsDiagramInterpolationSettings
157157
double upperValue;
158158
/**Index of the classification attribute*/
159159
int classificationAttribute;
160+
QString classificationAttributeExpression;
161+
bool classificationAttributeIsExpression;
160162
};
161163

162164
/**Returns diagram settings for a feature*/
@@ -167,18 +169,18 @@ class CORE_EXPORT QgsDiagramRendererV2
167169
QgsDiagramRendererV2();
168170
virtual ~QgsDiagramRendererV2();
169171

170-
/**Returns size of the diagram for feature f in map units. Returns an invalid QSizeF in case of error*/
171-
virtual QSizeF sizeMapUnits( const QgsAttributes& attributes, const QgsRenderContext& c );
172+
/**Returns size of the diagram for a feature in map units. Returns an invalid QSizeF in case of error*/
173+
virtual QSizeF sizeMapUnits( const QgsFeature& feature, const QgsRenderContext& c );
172174

173175
virtual QString rendererName() const = 0;
174176

175177
/**Returns attribute indices needed for diagram rendering*/
176-
virtual QList<int> diagramAttributes() const = 0;
178+
virtual QList<QString> diagramAttributes() const = 0;
177179

178-
void renderDiagram( const QgsAttributes& att, QgsRenderContext& c, const QPointF& pos );
180+
void renderDiagram( const QgsFeature& feature, QgsRenderContext& c, const QPointF& pos );
179181

180182
void setDiagram( QgsDiagram* d );
181-
const QgsDiagram* diagram() const { return mDiagram; }
183+
QgsDiagram* diagram() const { return mDiagram; }
182184

183185
/**Returns list with all diagram settings in the renderer*/
184186
virtual QList<QgsDiagramSettings> diagramSettings() const = 0;
@@ -189,14 +191,14 @@ class CORE_EXPORT QgsDiagramRendererV2
189191
protected:
190192

191193
/**Returns diagram settings for a feature (or false if the diagram for the feature is not to be rendered). Used internally within renderDiagram()
192-
* @param att attribute map
194+
* @param feature the feature
193195
* @param c render context
194196
* @param s out: diagram settings for the feature
195197
*/
196-
virtual bool diagramSettings( const QgsAttributes& att, const QgsRenderContext& c, QgsDiagramSettings& s ) = 0;
198+
virtual bool diagramSettings( const QgsFeature&, const QgsRenderContext& c, QgsDiagramSettings& s ) = 0;
197199

198200
/**Returns size of the diagram (in painter units) or an invalid size in case of error*/
199-
virtual QSizeF diagramSize( const QgsAttributes& attributes, const QgsRenderContext& c ) = 0;
201+
virtual QSizeF diagramSize( const QgsFeature& features, const QgsRenderContext& c ) = 0;
200202

201203
/**Converts size from mm to map units*/
202204
void convertSizeToMapUnits( QSizeF& size, const QgsRenderContext& context ) const;
@@ -221,7 +223,7 @@ class CORE_EXPORT QgsSingleCategoryDiagramRenderer : public QgsDiagramRendererV2
221223

222224
QString rendererName() const { return "SingleCategory"; }
223225

224-
QList<int> diagramAttributes() const { return mSettings.categoryIndices; }
226+
QList<QString> diagramAttributes() const { return mSettings.categoryAttributes; }
225227

226228
void setDiagramSettings( const QgsDiagramSettings& s ) { mSettings = s; }
227229

@@ -231,9 +233,9 @@ class CORE_EXPORT QgsSingleCategoryDiagramRenderer : public QgsDiagramRendererV2
231233
void writeXML( QDomElement& layerElem, QDomDocument& doc, const QgsVectorLayer* layer ) const;
232234

233235
protected:
234-
bool diagramSettings( const QgsAttributes&, const QgsRenderContext& c, QgsDiagramSettings& s );
236+
bool diagramSettings( const QgsFeature&, const QgsRenderContext& c, QgsDiagramSettings& s );
235237

236-
QSizeF diagramSize( const QgsAttributes& attributes, const QgsRenderContext& c );
238+
QSizeF diagramSize( const QgsFeature&, const QgsRenderContext& c );
237239

238240
private:
239241
QgsDiagramSettings mSettings;
@@ -250,7 +252,7 @@ class CORE_EXPORT QgsLinearlyInterpolatedDiagramRenderer : public QgsDiagramRend
250252

251253
void setDiagramSettings( const QgsDiagramSettings& s ) { mSettings = s; }
252254

253-
QList<int> diagramAttributes() const;
255+
QList<QString> diagramAttributes() const;
254256

255257
QString rendererName() const { return "LinearlyInterpolated"; }
256258

@@ -269,13 +271,19 @@ class CORE_EXPORT QgsLinearlyInterpolatedDiagramRenderer : public QgsDiagramRend
269271
int classificationAttribute() const { return mInterpolationSettings.classificationAttribute; }
270272
void setClassificationAttribute( int index ) { mInterpolationSettings.classificationAttribute = index; }
271273

274+
QString classificationAttributeExpression() const { return mInterpolationSettings.classificationAttributeExpression; }
275+
void setClassificationAttributeExpression( QString expression ) { mInterpolationSettings.classificationAttributeExpression = expression; }
276+
277+
bool classificationAttributeIsExpression() const { return mInterpolationSettings.classificationAttributeIsExpression; }
278+
void setClassificationAttributeIsExpression( bool isExpression ) { mInterpolationSettings.classificationAttributeIsExpression = isExpression; }
279+
272280
void readXML( const QDomElement& elem, const QgsVectorLayer* layer );
273281
void writeXML( QDomElement& layerElem, QDomDocument& doc, const QgsVectorLayer* layer ) const;
274282

275283
protected:
276-
bool diagramSettings( const QgsAttributes&, const QgsRenderContext& c, QgsDiagramSettings& s );
284+
bool diagramSettings( const QgsFeature&, const QgsRenderContext& c, QgsDiagramSettings& s );
277285

278-
QSizeF diagramSize( const QgsAttributes& attributes, const QgsRenderContext& c );
286+
QSizeF diagramSize( const QgsFeature&, const QgsRenderContext& c );
279287

280288
private:
281289
QgsDiagramSettings mSettings;

‎src/core/qgspallabeling.cpp

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ class QgsPalGeometry : public PalGeometry
7676
, mWordSpacing( wordSpacing )
7777
, mCurvedLabeling( curvedLabeling )
7878
{
79-
mStrId = FID_TO_STRING( id ).toAscii();
79+
mStrId = FID_TO_STRING( mId ).toAscii();
8080
mDefinedFont = QFont();
8181
}
8282

@@ -172,9 +172,17 @@ class QgsPalGeometry : public PalGeometry
172172

173173
QFontMetricsF* getLabelFontMetrics() { return mFontMetrics; }
174174

175-
void setDiagramAttributes( const QgsAttributes& attrs ) { mDiagramAttributes = attrs; }
175+
void setDiagramAttributes( const QgsAttributes& attrs, const QgsFields* fields ) { mDiagramAttributes = attrs; mDiagramFields = fields; }
176176
const QgsAttributes& diagramAttributes() { return mDiagramAttributes; }
177177

178+
void feature( QgsFeature& feature )
179+
{
180+
feature.setFeatureId( mId );
181+
feature.setFields( mDiagramFields, false );
182+
feature.setAttributes( mDiagramAttributes );
183+
feature.setValid( true );
184+
}
185+
178186
protected:
179187
GEOSGeometry* mG;
180188
QString mText;
@@ -193,6 +201,7 @@ class QgsPalGeometry : public PalGeometry
193201

194202
/**Stores attribute values for diagram rendering*/
195203
QgsAttributes mDiagramAttributes;
204+
const QgsFields* mDiagramFields;
196205
};
197206

198207
// -------------
@@ -3357,15 +3366,15 @@ void QgsPalLabeling::registerDiagramFeature( QgsVectorLayer* layer, QgsFeature&
33573366
QgsDiagramRendererV2* dr = layerIt.value().renderer;
33583367
if ( dr )
33593368
{
3360-
QSizeF diagSize = dr->sizeMapUnits( feat.attributes(), context );
3369+
QSizeF diagSize = dr->sizeMapUnits( feat, context );
33613370
if ( diagSize.isValid() )
33623371
{
33633372
diagramWidth = diagSize.width();
33643373
diagramHeight = diagSize.height();
33653374
}
33663375

33673376
//append the diagram attributes to lbl
3368-
lbl->setDiagramAttributes( feat.attributes() );
3377+
lbl->setDiagramAttributes( feat.attributes(), feat.fields() );
33693378
}
33703379

33713380
// feature to the layer
@@ -3866,14 +3875,16 @@ void QgsPalLabeling::drawLabeling( QgsRenderContext& context )
38663875
QString layerName = QString::fromUtf8(( *it )->getLayerName() );
38673876
if ( palGeometry->isDiagram() )
38683877
{
3878+
QgsFeature feature;
38693879
//render diagram
38703880
QHash<QgsVectorLayer*, QgsDiagramLayerSettings>::iterator dit = mActiveDiagramLayers.begin();
38713881
for ( dit = mActiveDiagramLayers.begin(); dit != mActiveDiagramLayers.end(); ++dit )
38723882
{
38733883
if ( dit.key() && dit.key()->id().append( "d" ) == layerName )
38743884
{
3885+
palGeometry->feature( feature );
38753886
QgsPoint outPt = xform->transform(( *it )->getX(), ( *it )->getY() );
3876-
dit.value().renderer->renderDiagram( palGeometry->diagramAttributes(), context, QPointF( outPt.x(), outPt.y() ) );
3887+
dit.value().renderer->renderDiagram( feature, context, QPointF( outPt.x(), outPt.y() ) );
38773888
}
38783889
}
38793890

‎src/core/qgsvectorlayer.cpp

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@
7777

7878
#include "qgsmaptopixelgeometrysimplifier.h"
7979

80+
#include "diagram/qgsdiagram.h"
81+
8082
#ifdef TESTPROVIDERLIB
8183
#include <dlfcn.h>
8284
#endif
@@ -3611,15 +3613,49 @@ void QgsVectorLayer::prepareLabelingAndDiagrams( QgsRenderContext& rendererConte
36113613
mDiagramLayerSettings->renderer = mDiagramRenderer;
36123614
rendererContext.labelingEngine()->addDiagramLayer( this, mDiagramLayerSettings );
36133615
//add attributes needed by the diagram renderer
3614-
QList<int> att = mDiagramRenderer->diagramAttributes();
3615-
QList<int>::const_iterator attIt = att.constBegin();
3616+
QList<QString> att = mDiagramRenderer->diagramAttributes();
3617+
QList<QString>::const_iterator attIt = att.constBegin();
36163618
for ( ; attIt != att.constEnd(); ++attIt )
36173619
{
3618-
if ( !attributes.contains( *attIt ) )
3620+
QgsExpression* expression = mDiagramRenderer->diagram()->getExpression( *attIt, &pendingFields() );
3621+
QStringList columns = expression->referencedColumns();
3622+
QStringList::const_iterator columnsIterator = columns.constBegin();
3623+
for ( ; columnsIterator != columns.constEnd(); ++columnsIterator )
36193624
{
3620-
attributes << *attIt;
3625+
int index = fieldNameIndex( *columnsIterator );
3626+
if ( !attributes.contains( index ) )
3627+
{
3628+
attributes << index;
3629+
}
3630+
}
3631+
}
3632+
3633+
QgsLinearlyInterpolatedDiagramRenderer* mLinearlyInterpolatedDiagramRenderer = dynamic_cast<QgsLinearlyInterpolatedDiagramRenderer*>( mDiagramRenderer );
3634+
if ( mLinearlyInterpolatedDiagramRenderer != NULL )
3635+
{
3636+
if ( mLinearlyInterpolatedDiagramRenderer->classificationAttributeIsExpression() )
3637+
{
3638+
QgsExpression* expression = mDiagramRenderer->diagram()->getExpression( mLinearlyInterpolatedDiagramRenderer->classificationAttributeExpression(), &pendingFields() );
3639+
QStringList columns = expression->referencedColumns();
3640+
QStringList::const_iterator columnsIterator = columns.constBegin();
3641+
for ( ; columnsIterator != columns.constEnd(); ++columnsIterator )
3642+
{
3643+
int index = fieldNameIndex( *columnsIterator );
3644+
if ( !attributes.contains( index ) )
3645+
{
3646+
attributes << index;
3647+
}
3648+
}
3649+
}
3650+
else
3651+
{
3652+
if ( !attributes.contains( mLinearlyInterpolatedDiagramRenderer->classificationAttribute() ) )
3653+
{
3654+
attributes << mLinearlyInterpolatedDiagramRenderer->classificationAttribute();
3655+
}
36213656
}
36223657
}
3658+
36233659
//and the ones needed for data defined diagram positions
36243660
if ( mDiagramLayerSettings->xPosColumn >= 0 && !attributes.contains( mDiagramLayerSettings->xPosColumn ) )
36253661
{

‎src/ui/qgsdiagrampropertiesbase.ui

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,26 @@
418418
</property>
419419
</widget>
420420
</item>
421+
<item>
422+
<widget class="QPushButton" name="mSizeAttributeExpression">
423+
<property name="enabled">
424+
<bool>true</bool>
425+
</property>
426+
<property name="toolTip">
427+
<string>Edit expression</string>
428+
</property>
429+
<property name="icon">
430+
<iconset resource="../../images/images.qrc">
431+
<normaloff>:/images/themes/default/mIconExpressionEditorOpen.svg</normaloff>:/images/themes/default/mIconExpressionEditorOpen.svg</iconset>
432+
</property>
433+
<property name="iconSize">
434+
<size>
435+
<width>24</width>
436+
<height>16</height>
437+
</size>
438+
</property>
439+
</widget>
440+
</item>
421441
<item>
422442
<widget class="QPushButton" name="mFindMaximumValueButton">
423443
<property name="text">
@@ -837,10 +857,30 @@ Leave empty to automatically apply the maximum value.</string>
837857
</property>
838858
</spacer>
839859
</item>
860+
<item>
861+
<widget class="QPushButton" name="mAddAttributeExpression">
862+
<property name="enabled">
863+
<bool>true</bool>
864+
</property>
865+
<property name="toolTip">
866+
<string>Add expression</string>
867+
</property>
868+
<property name="icon">
869+
<iconset resource="../../images/images.qrc">
870+
<normaloff>:/images/themes/default/mIconExpressionEditorOpen.svg</normaloff>:/images/themes/default/mIconExpressionEditorOpen.svg</iconset>
871+
</property>
872+
<property name="iconSize">
873+
<size>
874+
<width>24</width>
875+
<height>16</height>
876+
</size>
877+
</property>
878+
</widget>
879+
</item>
840880
<item>
841881
<widget class="QPushButton" name="mAddCategoryPushButton">
842882
<property name="sizePolicy">
843-
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
883+
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
844884
<horstretch>0</horstretch>
845885
<verstretch>0</verstretch>
846886
</sizepolicy>
@@ -857,7 +897,7 @@ Leave empty to automatically apply the maximum value.</string>
857897
<item>
858898
<widget class="QPushButton" name="mRemoveCategoryPushButton">
859899
<property name="sizePolicy">
860-
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
900+
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
861901
<horstretch>0</horstretch>
862902
<verstretch>0</verstretch>
863903
</sizepolicy>

‎tests/src/core/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ ADD_QGIS_TEST(clippertest testqgsclipper.cpp)
8080
ADD_QGIS_TEST(distanceareatest testqgsdistancearea.cpp)
8181
ADD_QGIS_TEST(applicationtest testqgsapplication.cpp)
8282
ADD_QGIS_TEST(diagramtest testqgsdiagram.cpp)
83+
ADD_QGIS_TEST(diagramexpressiontest testqgsdiagramexpression.cpp)
8384
ADD_QGIS_TEST(expressiontest testqgsexpression.cpp)
8485
ADD_QGIS_TEST(filewritertest testqgsvectorfilewriter.cpp)
8586
ADD_QGIS_TEST(regression992 regression992.cpp)
@@ -115,4 +116,3 @@ ADD_QGIS_TEST(composerscalebartest testqgscomposerscalebar.cpp )
115116
ADD_QGIS_TEST(ogcutilstest testqgsogcutils.cpp)
116117
ADD_QGIS_TEST(vectorlayercachetest testqgsvectorlayercache.cpp )
117118
ADD_QGIS_TEST(gradienttest testqgsgradients.cpp )
118-

‎tests/src/core/testqgsdiagram.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ class TestQgsDiagram: public QObject
135135
col1.setAlphaF( 0.5 );
136136
col2.setAlphaF( 0.5 );
137137
ds.categoryColors = QList<QColor>() << col1 << col2;
138-
ds.categoryIndices = QList<int>() << 3 << 4; // Pilots / Cabin Crew
138+
ds.categoryAttributes = QList<QString>() << "\"Pilots\"" << "\"Cabin Crew\"";
139139
ds.maxScaleDenominator = -1;
140140
ds.minScaleDenominator = -1;
141141
ds.minimumSize = 0;
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
/***************************************************************************
2+
testqgsdiagram.cpp
3+
--------------------------------------
4+
Date : Sep 7 2012
5+
Copyright : (C) 2012 by Matthias Kuhn
6+
Email : matthias dot kuhn at gmx dot ch
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
#include <QtTest>
16+
#include <QObject>
17+
#include <QString>
18+
#include <QStringList>
19+
#include <QObject>
20+
#include <QApplication>
21+
#include <QFileInfo>
22+
#include <QDir>
23+
#include <QDesktopServices>
24+
#include <QPainter>
25+
26+
#include <iostream>
27+
//qgis includes...
28+
// #include <qgisapp.h>
29+
#include <diagram/qgspiediagram.h>
30+
#include <qgsdiagramrendererv2.h>
31+
#include <qgscomposition.h>
32+
#include <qgscompositionchecker.h>
33+
#include <qgscomposermap.h>
34+
#include <qgsmaprenderer.h>
35+
#include <qgsmaplayer.h>
36+
#include <qgsvectordataprovider.h>
37+
#include <qgsvectorlayer.h>
38+
#include <qgsapplication.h>
39+
#include <qgsproviderregistry.h>
40+
#include <qgsmaplayerregistry.h>
41+
#include <qgsrendererv2.h>
42+
//qgis test includes
43+
#include "qgsrenderchecker.h"
44+
#include "qgspallabeling.h"
45+
46+
/** \ingroup UnitTests
47+
* This is a unit test for the vector layer class.
48+
*/
49+
class TestQgsDiagramExpression: public QObject
50+
{
51+
Q_OBJECT;
52+
private:
53+
bool mTestHasError;
54+
QgsMapRenderer * mMapRenderer;
55+
QgsVectorLayer * mPointsLayer;
56+
QgsComposition * mComposition;
57+
QString mTestDataDir;
58+
QString mReport;
59+
QgsPieDiagram * mPieDiagram;
60+
QgsComposerMap * mComposerMap;
61+
62+
private slots:
63+
64+
65+
// will be called before the first testfunction is executed.
66+
void initTestCase()
67+
{
68+
mTestHasError = false;
69+
QgsApplication::init();
70+
QgsApplication::initQgis();
71+
QgsApplication::showSettings();
72+
73+
//create some objects that will be used in all tests...
74+
75+
//
76+
//create a non spatial layer that will be used in all tests...
77+
//
78+
QString myDataDir( TEST_DATA_DIR ); //defined in CmakeLists.txt
79+
mTestDataDir = myDataDir + QDir::separator();
80+
81+
//
82+
//create a point layer that will be used in all tests...
83+
//
84+
QString myPointsFileName = mTestDataDir + "points.shp";
85+
QFileInfo myPointFileInfo( myPointsFileName );
86+
mPointsLayer = new QgsVectorLayer( myPointFileInfo.filePath(),
87+
myPointFileInfo.completeBaseName(), "ogr" );
88+
89+
// Register the layer with the registry
90+
QgsMapLayerRegistry::instance()->addMapLayers(
91+
QList<QgsMapLayer *>() << mPointsLayer );
92+
93+
// Create diagrams
94+
mPieDiagram = new QgsPieDiagram();
95+
96+
// Create map composition to draw on
97+
mMapRenderer = new QgsMapRenderer();
98+
mMapRenderer->setLayerSet( QStringList() << mPointsLayer->id() );
99+
mMapRenderer->setLabelingEngine( new QgsPalLabeling() );
100+
mComposition = new QgsComposition( mMapRenderer );
101+
mComposition->setPaperSize( 297, 210 ); // A4 landscape
102+
mComposerMap = new QgsComposerMap( mComposition, 20, 20, 200, 100 );
103+
mComposerMap->setFrameEnabled( true );
104+
mComposition->addComposerMap( mComposerMap );
105+
106+
mReport += "<h1>Diagram Tests</h1>\n";
107+
}
108+
109+
// will be called after the last testfunction was executed.
110+
void cleanupTestCase()
111+
{
112+
QString myReportFile = QDir::tempPath() + QDir::separator() + "qgistest.html";
113+
QFile myFile( myReportFile );
114+
if ( myFile.open( QIODevice::WriteOnly | QIODevice::Append ) )
115+
{
116+
QTextStream myQTextStream( &myFile );
117+
myQTextStream << mReport;
118+
myFile.close();
119+
}
120+
121+
delete mComposerMap;
122+
delete mComposition;
123+
delete mMapRenderer;
124+
delete mPointsLayer;
125+
}
126+
127+
void init() {};// will be called before each testfunction is executed.
128+
void cleanup() {};// will be called after every testfunction.
129+
130+
// will be called after the last testfunction was executed.
131+
void testPieDiagramExpression()
132+
{
133+
QgsDiagramSettings ds;
134+
QColor col1 = Qt::red;
135+
QColor col2 = Qt::yellow;
136+
col1.setAlphaF( 0.5 );
137+
col2.setAlphaF( 0.5 );
138+
ds.categoryColors = QList<QColor>() << col1 << col2;
139+
ds.categoryAttributes = QList<QString>() << "ln(Pilots + 1)" << "ln(\"Cabin Crew\" + 1)";
140+
ds.maxScaleDenominator = -1;
141+
ds.minScaleDenominator = -1;
142+
ds.minimumSize = 0;
143+
ds.penColor = Qt::green;
144+
ds.penWidth = .5;
145+
ds.scaleByArea = true;
146+
ds.sizeType = QgsDiagramSettings::MM;
147+
ds.size = QSizeF( 15, 15 );
148+
ds.angleOffset = 0;
149+
150+
151+
QgsLinearlyInterpolatedDiagramRenderer *dr = new QgsLinearlyInterpolatedDiagramRenderer();
152+
dr->setLowerValue( 0.0 );
153+
dr->setLowerSize( QSizeF( 0.0, 0.0 ) );
154+
dr->setUpperValue( 10 );
155+
dr->setUpperSize( QSizeF( 100, 100 ) );
156+
dr->setClassificationAttributeIsExpression( true );
157+
dr->setClassificationAttributeExpression( "ln(Staff + 1)" );
158+
dr->setDiagram( mPieDiagram );
159+
dr->setDiagramSettings( ds );
160+
mPointsLayer->setDiagramRenderer( dr );
161+
162+
QgsDiagramLayerSettings dls = QgsDiagramLayerSettings();
163+
dls.placement = QgsDiagramLayerSettings::OverPoint;
164+
dls.renderer = dr;
165+
166+
dynamic_cast<QgsPalLabeling*>( mMapRenderer->labelingEngine() )->setShowingAllLabels( true );
167+
168+
mPointsLayer->setDiagramLayerSettings( dls );
169+
170+
mComposerMap->setNewExtent( QgsRectangle( -122, -79, -70, 47 ) );
171+
QgsCompositionChecker checker( "piediagram_expression", mComposition );
172+
173+
QVERIFY( checker.testComposition( mReport ) );
174+
175+
mPointsLayer->setDiagramRenderer( 0 );
176+
}
177+
};
178+
179+
QTEST_MAIN( TestQgsDiagramExpression )
180+
#include "moc_testqgsdiagramexpression.cxx"
Loading

0 commit comments

Comments
 (0)
Please sign in to comment.