Skip to content

Commit 1e46196

Browse files
vmoranyalldawson
authored andcommitted
[FEATURE] add expressions at the symbollist level
Size and Rotation can be defined by an expression for all symbols composing a marker. Width can be defined by an expression for all symbols composing a line. For markers, a legend is generated for varying sizes. This allows multivariate analysis legend in the case of classified/graduated colors. The offset is now set along with size to maintain the relative position of symbols composing a marker. An asistant, with preview, is accessible through the data defined button to help the user define the size expression. Three methods are available: Frannery, Area and Radius. Added a widget for use in categorized/classified symbology gui to set the expression if needed. The assistant is also available from it.
1 parent c38ff51 commit 1e46196

25 files changed

+1474
-74
lines changed

python/gui/gui.sip

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@
172172
%Include symbology-ng/characterwidget.sip
173173
%Include symbology-ng/qgsdashspacedialog.sip
174174
%Include symbology-ng/qgsdatadefinedsymboldialog.sip
175+
%Include symbology-ng/qgssizescalewidget.sip
175176
%Include symbology-ng/qgsstylev2exportimportdialog.sip
176177
%Include symbology-ng/qgssvgselectorwidget.sip
177178
%Include symbology-ng/qgsgraduatedhistogramwidget.sip

python/gui/qgsdatadefinedbutton.sip

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class QgsDataDefinedAssistant: QDialog
1111
#include <qgsdatadefinedbutton.h>
1212
%End
1313
public:
14-
virtual QgsDataDefined* dataDefined() const = 0 /Factory/;
14+
virtual QgsDataDefined dataDefined() const = 0;
1515
};
1616

1717
/** \ingroup gui
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
class QgsSizeScaleWidget : QgsDataDefinedAssistant
2+
{
3+
%TypeHeaderCode
4+
#include <qgssizescalewidget.h>
5+
%End
6+
public:
7+
QgsSizeScaleWidget( const QgsVectorLayer * layer, const QgsMarkerSymbolV2 * symbol );
8+
9+
QgsDataDefined dataDefined() const;
10+
};
11+

python/gui/symbology-ng/qgssymbolslistwidget.sip

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ class QgsSymbolsListWidget : QWidget
44
#include <qgssymbolslistwidget.h>
55
%End
66
public:
7-
QgsSymbolsListWidget( QgsSymbolV2* symbol, QgsStyleV2* style, QMenu* menu, QWidget* parent /TransferThis/ = 0 );
7+
QgsSymbolsListWidget( QgsSymbolV2* symbol, QgsStyleV2* style, QMenu* menu, QWidget* parent /TransferThis/ = 0, const QgsVectorLayer * layer = 0 );
88

99
public slots:
1010
void setSymbolFromStyle( const QModelIndex & index );

src/core/symbology-ng/qgscategorizedsymbolrendererv2.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#include "qgspointdisplacementrenderer.h"
2323
#include "qgsinvertedpolygonrenderer.h"
2424
#include "qgspainteffect.h"
25+
#include "qgsscaleexpression.h"
26+
#include "qgsdatadefined.h"
2527

2628
#include "qgsfeature.h"
2729
#include "qgsvectorlayer.h"
@@ -695,6 +697,56 @@ QgsLegendSymbolList QgsCategorizedSymbolRendererV2::legendSymbolItems( double sc
695697
return lst;
696698
}
697699

700+
QgsLegendSymbolListV2 QgsCategorizedSymbolRendererV2::legendSymbolItemsV2() const
701+
{
702+
QgsLegendSymbolListV2 lst;
703+
if ( mSourceSymbol.data() && mSourceSymbol->type() == QgsSymbolV2::Marker )
704+
{
705+
// check that all symbols that have the same size expression
706+
QgsDataDefined ddSize;
707+
foreach ( QgsRendererCategoryV2 category, mCategories )
708+
{
709+
const QgsMarkerSymbolV2 * symbol = static_cast<const QgsMarkerSymbolV2 *>( category.symbol() );
710+
if ( !ddSize.hasDefaultValues() && symbol->dataDefinedSize() != ddSize )
711+
{
712+
// no common size expression
713+
return QgsFeatureRendererV2::legendSymbolItemsV2();
714+
}
715+
else
716+
{
717+
ddSize = symbol->dataDefinedSize();
718+
}
719+
}
720+
721+
if ( !ddSize.isActive() || !ddSize.useExpression() )
722+
{
723+
return QgsFeatureRendererV2::legendSymbolItemsV2();
724+
}
725+
726+
QgsScaleExpression exp( ddSize.expressionString() );
727+
if ( exp.type() != QgsScaleExpression::Unknown )
728+
{
729+
QgsLegendSymbolItemV2 title( NULL, exp.baseExpression(), "" );
730+
lst << title;
731+
foreach ( double v, QgsSymbolLayerV2Utils::prettyBreaks( exp.minValue(), exp.maxValue(), 4 ) )
732+
{
733+
QgsLegendSymbolItemV2 si( mSourceSymbol.data(), QString::number( v ), "" );
734+
QgsMarkerSymbolV2 * s = static_cast<QgsMarkerSymbolV2 *>( si.symbol() );
735+
s->setColor( QColor( 0, 0, 0 ) );
736+
s->setDataDefinedSize( QgsDataDefined() );
737+
s->setSize( exp.size( v ) );
738+
lst << si;
739+
}
740+
// now list the categorized symbols
741+
const QgsLegendSymbolListV2 list2 = QgsFeatureRendererV2::legendSymbolItemsV2() ;
742+
foreach ( QgsLegendSymbolItemV2 item, list2 )
743+
lst << item;
744+
return lst;
745+
}
746+
}
747+
748+
return QgsFeatureRendererV2::legendSymbolItemsV2();
749+
}
698750

699751
QgsSymbolV2* QgsCategorizedSymbolRendererV2::sourceSymbol()
700752
{

src/core/symbology-ng/qgscategorizedsymbolrendererv2.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,9 @@ class CORE_EXPORT QgsCategorizedSymbolRendererV2 : public QgsFeatureRendererV2
139139
//! @note not available in python bindings
140140
virtual QgsLegendSymbolList legendSymbolItems( double scaleDenominator = -1, QString rule = QString() ) override;
141141

142+
//! @note added in 2.10
143+
QgsLegendSymbolListV2 legendSymbolItemsV2() const override;
144+
142145
QgsSymbolV2* sourceSymbol();
143146
void setSourceSymbol( QgsSymbolV2* sym );
144147

src/core/symbology-ng/qgsgraduatedsymbolrendererv2.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
#include "qgspointdisplacementrenderer.h"
2222
#include "qgsinvertedpolygonrenderer.h"
2323
#include "qgspainteffect.h"
24+
#include "qgsscaleexpression.h"
25+
#include "qgsdatadefined.h"
2426

2527
#include "qgsfeature.h"
2628
#include "qgsvectorlayer.h"
@@ -1151,6 +1153,57 @@ QgsLegendSymbologyList QgsGraduatedSymbolRendererV2::legendSymbologyItems( QSize
11511153
return lst;
11521154
}
11531155

1156+
QgsLegendSymbolListV2 QgsGraduatedSymbolRendererV2::legendSymbolItemsV2() const
1157+
{
1158+
QgsLegendSymbolListV2 list;
1159+
if ( mSourceSymbol.data() && mSourceSymbol->type() == QgsSymbolV2::Marker )
1160+
{
1161+
// check that all symbols that have the same size expression
1162+
QgsDataDefined ddSize;
1163+
foreach ( QgsRendererRangeV2 range, mRanges )
1164+
{
1165+
const QgsMarkerSymbolV2 * symbol = static_cast<const QgsMarkerSymbolV2 *>( range.symbol() );
1166+
if ( !ddSize.hasDefaultValues() && symbol->dataDefinedSize() != ddSize )
1167+
{
1168+
// no common size expression
1169+
return QgsFeatureRendererV2::legendSymbolItemsV2();
1170+
}
1171+
else
1172+
{
1173+
ddSize = symbol->dataDefinedSize();
1174+
}
1175+
}
1176+
1177+
if ( !ddSize.isActive() || !ddSize.useExpression() )
1178+
{
1179+
return QgsFeatureRendererV2::legendSymbolItemsV2();
1180+
}
1181+
1182+
QgsScaleExpression exp( ddSize.expressionString() );
1183+
if ( exp.type() != QgsScaleExpression::Unknown )
1184+
{
1185+
QgsLegendSymbolItemV2 title( NULL, exp.baseExpression(), "" );
1186+
list << title;
1187+
foreach ( double v, QgsSymbolLayerV2Utils::prettyBreaks( exp.minValue(), exp.maxValue(), 4 ) )
1188+
{
1189+
QgsLegendSymbolItemV2 si( mSourceSymbol.data(), QString::number( v ), "" );
1190+
QgsMarkerSymbolV2 * s = static_cast<QgsMarkerSymbolV2 *>( si.symbol() );
1191+
s->setColor( QColor( 0, 0, 0 ) );
1192+
s->setDataDefinedSize( QgsDataDefined() );
1193+
s->setSize( exp.size( v ) );
1194+
list << si;
1195+
}
1196+
// now list the graduated symbols
1197+
const QgsLegendSymbolListV2 list2 = QgsFeatureRendererV2::legendSymbolItemsV2() ;
1198+
foreach ( QgsLegendSymbolItemV2 item, list2 )
1199+
list << item;
1200+
return list;
1201+
}
1202+
}
1203+
1204+
return QgsFeatureRendererV2::legendSymbolItemsV2();
1205+
}
1206+
11541207
QgsLegendSymbolList QgsGraduatedSymbolRendererV2::legendSymbolItems( double scaleDenominator, QString rule )
11551208
{
11561209
Q_UNUSED( scaleDenominator );

src/core/symbology-ng/qgsgraduatedsymbolrendererv2.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,10 @@ class CORE_EXPORT QgsGraduatedSymbolRendererV2 : public QgsFeatureRendererV2
239239
//! @note not available in python bindings
240240
virtual QgsLegendSymbolList legendSymbolItems( double scaleDenominator = -1, QString rule = QString() ) override;
241241

242+
//! @note added in 2.10
243+
QgsLegendSymbolListV2 legendSymbolItemsV2() const override;
244+
245+
242246
QgsSymbolV2* sourceSymbol();
243247
void setSourceSymbol( QgsSymbolV2* sym );
244248

src/core/symbology-ng/qgssinglesymbolrendererv2.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
#include "qgspointdisplacementrenderer.h"
2727
#include "qgsinvertedpolygonrenderer.h"
2828
#include "qgspainteffect.h"
29+
#include "qgsscaleexpression.h"
30+
#include "qgsdatadefined.h"
2931

3032
#include <QDomDocument>
3133
#include <QDomElement>
@@ -384,6 +386,30 @@ QgsLegendSymbolList QgsSingleSymbolRendererV2::legendSymbolItems( double scaleDe
384386
QgsLegendSymbolListV2 QgsSingleSymbolRendererV2::legendSymbolItemsV2() const
385387
{
386388
QgsLegendSymbolListV2 lst;
389+
if ( mSymbol->type() == QgsSymbolV2::Marker )
390+
{
391+
const QgsMarkerSymbolV2 * symbol = static_cast<const QgsMarkerSymbolV2 *>( mSymbol.data() );
392+
QgsDataDefined sizeDD = symbol->dataDefinedSize();
393+
if ( sizeDD.isActive() && sizeDD.useExpression() )
394+
{
395+
QgsScaleExpression scaleExp( sizeDD.expressionString() );
396+
if ( scaleExp.type() != QgsScaleExpression::Unknown )
397+
{
398+
QgsLegendSymbolItemV2 title( NULL, scaleExp.baseExpression(), 0 );
399+
lst << title;
400+
foreach ( double v, QgsSymbolLayerV2Utils::prettyBreaks( scaleExp.minValue(), scaleExp.maxValue(), 4 ) )
401+
{
402+
QgsLegendSymbolItemV2 si( mSymbol.data(), QString::number( v ), 0 );
403+
QgsMarkerSymbolV2 * s = static_cast<QgsMarkerSymbolV2 *>( si.symbol() );
404+
s->setDataDefinedSize( 0 );
405+
s->setSize( scaleExp.size( v ) );
406+
lst << si;
407+
}
408+
return lst;
409+
}
410+
}
411+
}
412+
387413
lst << QgsLegendSymbolItemV2( mSymbol.data(), QString(), 0 );
388414
return lst;
389415
}

src/core/symbology-ng/qgssymbollayerv2.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
#endif
2222

2323
#define DEG2RAD(x) ((x)*M_PI/180)
24-
#define DEFAULT_SCALE_METHOD QgsSymbolV2::ScaleArea
24+
#define DEFAULT_SCALE_METHOD QgsSymbolV2::ScaleDiameter
2525

2626
#include <QColor>
2727
#include <QMap>
@@ -330,7 +330,7 @@ class CORE_EXPORT QgsMarkerSymbolLayerV2 : public QgsSymbolLayerV2
330330
QgsSymbolV2::ScaleMethod scaleMethod() const { return mScaleMethod; }
331331

332332
void setOffset( QPointF offset ) { mOffset = offset; }
333-
QPointF offset() { return mOffset; }
333+
QPointF offset() const { return mOffset; }
334334

335335
virtual void toSld( QDomDocument &doc, QDomElement &element, QgsStringMap props ) const override;
336336

0 commit comments

Comments
 (0)