13
13
* *
14
14
***************************************************************************/
15
15
#include " qgsellipsesymbollayerv2.h"
16
+ #include " qgsexpression.h"
16
17
#include " qgsfeature.h"
17
18
#include " qgsrendercontext.h"
18
19
#include " qgsvectorlayer.h"
24
25
#include < QDomElement>
25
26
26
27
QgsEllipseSymbolLayerV2::QgsEllipseSymbolLayerV2 (): mSymbolName( " circle" ), mSymbolWidth( 4 ), mSymbolWidthUnit( QgsSymbolV2::MM ), mSymbolHeight( 3 ),
27
- mSymbolHeightUnit( QgsSymbolV2::MM ), mFillColor( Qt::black ), mOutlineColor( Qt::white ), mOutlineWidth( 0 ), mOutlineWidthUnit( QgsSymbolV2::MM )
28
+ mSymbolHeightUnit( QgsSymbolV2::MM ), mFillColor( Qt::white ), mOutlineColor( Qt::black ), mOutlineWidth( 0 ), mOutlineWidthUnit( QgsSymbolV2::MM ),
29
+ mWidthExpression( 0 ), mHeightExpression( 0 ), mRotationExpression( 0 ), mOutlineWidthExpression( 0 ), mFillColorExpression( 0 ),
30
+ mOutlineColorExpression( 0 ), mSymbolNameExpression( 0 )
28
31
{
29
32
mPen .setColor ( mOutlineColor );
30
33
mPen .setWidth ( 1.0 );
@@ -91,63 +94,95 @@ QgsSymbolLayerV2* QgsEllipseSymbolLayerV2::create( const QgsStringMap& propertie
91
94
}
92
95
93
96
// data defined properties
94
- if ( properties.contains ( " height_field " ) )
97
+ if ( properties.contains ( " width_expression " ) )
95
98
{
96
- layer->setHeightField ( properties[" height_field " ] );
99
+ layer->setDataDefinedProperty ( " width " , properties[" width_expression " ] );
97
100
}
98
- if ( properties.contains ( " width_field " ) )
101
+ if ( properties.contains ( " height_expression " ) )
99
102
{
100
- layer->setWidthField ( properties[" width_field " ] );
103
+ layer->setDataDefinedProperty ( " height " , properties[" height_expression " ] );
101
104
}
102
- if ( properties.contains ( " rotation_field " ) )
105
+ if ( properties.contains ( " rotation_expression " ) )
103
106
{
104
- layer->setRotationField ( properties[" rotation_field " ] );
107
+ layer->setDataDefinedProperty ( " rotation " , properties[" rotation_expression " ] );
105
108
}
106
- if ( properties.contains ( " outline_width_field " ) )
109
+ if ( properties.contains ( " outline_width_expression " ) )
107
110
{
108
- layer->setOutlineWidthField ( properties[" outline_width_field " ] );
111
+ layer->setDataDefinedProperty ( " outline_width " , properties[ " outline_width_expression " ] );
109
112
}
110
- if ( properties.contains ( " fill_color_field " ) )
113
+ if ( properties.contains ( " fill_color_expression " ) )
111
114
{
112
- layer->setFillColorField ( properties[" fill_color_field " ] );
115
+ layer->setDataDefinedProperty ( " fill_color " , properties[" fill_color_expression " ] );
113
116
}
114
- if ( properties.contains ( " outline_color_field " ) )
117
+ if ( properties.contains ( " outline_color_expression " ) )
115
118
{
116
- layer->setOutlineColorField ( properties[" outline_color_field " ] );
119
+ layer->setDataDefinedProperty ( " outline_color " , properties[" outline_color_expression " ] );
117
120
}
118
- if ( properties.contains ( " symbol_name_field " ) )
121
+ if ( properties.contains ( " symbol_name_expression " ) )
119
122
{
120
- layer->setSymbolNameField ( properties[" symbol_name_field" ] );
123
+ layer->setDataDefinedProperty ( " symbol_name" , properties[" symbol_name_expression" ] );
124
+ }
125
+
126
+ // compatibility with old project file format
127
+ if ( !properties[" width_field" ].isEmpty () )
128
+ {
129
+ layer->setDataDefinedProperty ( " width" , properties[" width_field" ] );
130
+ }
131
+ if ( !properties[" height_field" ].isEmpty () )
132
+ {
133
+ layer->setDataDefinedProperty ( " height" , properties[" height_field" ] );
134
+ }
135
+ if ( !properties[" rotation_field" ].isEmpty () )
136
+ {
137
+ layer->setDataDefinedProperty ( " rotation" , properties[" rotation_field" ] );
138
+ }
139
+ if ( !properties[" outline_width_field" ].isEmpty () )
140
+ {
141
+ layer->setDataDefinedProperty ( " outline_width" , properties[ " outline_width_field" ] );
142
+ }
143
+ if ( !properties[" fill_color_field" ].isEmpty () )
144
+ {
145
+ layer->setDataDefinedProperty ( " fill_color" , properties[" fill_color_field" ] );
146
+ }
147
+ if ( !properties[" outline_color_field" ].isEmpty () )
148
+ {
149
+ layer->setDataDefinedProperty ( " outline_color" , properties[" outline_color_field" ] );
150
+ }
151
+ if ( !properties[" symbol_name_field" ].isEmpty () )
152
+ {
153
+ layer->setDataDefinedProperty ( " symbol_name" , properties[" symbol_name_field" ] );
121
154
}
122
155
123
156
return layer;
124
157
}
125
158
126
159
void QgsEllipseSymbolLayerV2::renderPoint ( const QPointF& point, QgsSymbolV2RenderContext& context )
127
160
{
128
- const QgsFeature* f = context.feature ();
129
161
130
- if ( f )
162
+ if ( mOutlineWidthExpression )
131
163
{
132
- if ( mOutlineWidthIndex != -1 )
133
- {
134
- double width = f->attribute ( mOutlineWidthIndex ).toDouble () * QgsSymbolLayerV2Utils::lineWidthScaleFactor ( context.renderContext (), mOutlineWidthUnit );
135
- mPen .setWidthF ( width );
136
- }
137
- if ( mFillColorIndex != -1 )
138
- {
139
- mBrush .setColor ( QColor ( f->attribute ( mFillColorIndex ).toString () ) );
140
- }
141
- if ( mOutlineColorIndex != -1 )
142
- {
143
- mPen .setColor ( QColor ( f->attribute ( mOutlineColorIndex ).toString () ) );
144
- }
145
-
146
- if ( mWidthIndex != -1 || mHeightIndex != -1 || mSymbolNameIndex != -1 )
164
+ double width = mOutlineWidthExpression ->evaluate ( const_cast <QgsFeature*>( context.feature () ) ).toDouble ();
165
+ width *= QgsSymbolLayerV2Utils::lineWidthScaleFactor ( context.renderContext (), mOutlineWidthUnit );
166
+ mPen .setWidthF ( width );
167
+ }
168
+ if ( mFillColorExpression )
169
+ {
170
+ QString colorString = mFillColorExpression ->evaluate ( const_cast <QgsFeature*>( context.feature () ) ).toString ();
171
+ mBrush .setColor ( QColor ( colorString ) );
172
+ }
173
+ if ( mOutlineColorExpression )
174
+ {
175
+ QString colorString = mOutlineColorExpression ->evaluate ( const_cast <QgsFeature*>( context.feature () ) ).toString ();
176
+ mPen .setColor ( QColor ( colorString ) );
177
+ }
178
+ if ( mWidthExpression || mHeightExpression || mSymbolNameExpression )
179
+ {
180
+ QString symbolName = mSymbolName ;
181
+ if ( mSymbolNameExpression )
147
182
{
148
- QString symbolName = ( mSymbolNameIndex == -1 ) ? mSymbolName : f->attribute ( mSymbolNameIndex ).toString ();
149
- preparePath ( symbolName, context, f );
183
+ symbolName = mSymbolNameExpression ->evaluate ( const_cast <QgsFeature*>( context.feature () ) ).toString ();
150
184
}
185
+ preparePath ( symbolName, context, context.feature () );
151
186
}
152
187
153
188
QPainter* p = context.renderContext ().painter ();
@@ -158,9 +193,9 @@ void QgsEllipseSymbolLayerV2::renderPoint( const QPointF& point, QgsSymbolV2Rend
158
193
159
194
// priority for rotation: 1. data defined symbol level, 2. symbol layer rotation (mAngle)
160
195
double rotation = 0.0 ;
161
- if ( f && mRotationIndex != - 1 )
196
+ if ( mRotationExpression )
162
197
{
163
- rotation = f-> attribute ( mRotationIndex ).toDouble ();
198
+ rotation = mRotationExpression -> evaluate ( const_cast <QgsFeature*>( context. feature () ) ).toDouble ();
164
199
}
165
200
else if ( !doubleNear ( mAngle , 0.0 ) )
166
201
{
@@ -193,19 +228,7 @@ void QgsEllipseSymbolLayerV2::startRender( QgsSymbolV2RenderContext& context )
193
228
mPen .setColor ( mOutlineColor );
194
229
mPen .setWidthF ( mOutlineWidth * QgsSymbolLayerV2Utils::lineWidthScaleFactor ( context.renderContext (), mOutlineWidthUnit ) );
195
230
mBrush .setColor ( mFillColor );
196
-
197
- // resolve data defined attribute indices
198
- const QgsVectorLayer* vlayer = context.layer ();
199
- if ( vlayer )
200
- {
201
- mWidthIndex = vlayer->fieldNameIndex ( mWidthField );
202
- mHeightIndex = vlayer->fieldNameIndex ( mHeightField );
203
- mRotationIndex = vlayer->fieldNameIndex ( mRotationField );
204
- mOutlineWidthIndex = vlayer->fieldNameIndex ( mOutlineWidthField );
205
- mFillColorIndex = vlayer->fieldNameIndex ( mFillColorField );
206
- mOutlineColorIndex = vlayer->fieldNameIndex ( mOutlineColorField );
207
- mSymbolNameIndex = vlayer->fieldNameIndex ( mSymbolNameField );
208
- }
231
+ prepareExpressions ( context.layer () );
209
232
}
210
233
211
234
void QgsEllipseSymbolLayerV2::stopRender ( QgsSymbolV2RenderContext & )
@@ -346,13 +369,67 @@ QgsStringMap QgsEllipseSymbolLayerV2::properties() const
346
369
map[" outline_color" ] = QgsSymbolLayerV2Utils::encodeColor ( mOutlineColor );
347
370
map[" outline_color_field" ] = mOutlineColorField ;
348
371
map[" symbol_name_field" ] = mSymbolNameField ;
372
+
373
+ // data defined properties
374
+ if ( mWidthExpression )
375
+ {
376
+ map[" width_expression" ] = mWidthExpression ->dump ();
377
+ }
378
+ if ( mHeightExpression )
379
+ {
380
+ map[" height_expression" ] = mHeightExpression ->dump ();
381
+ }
382
+ if ( mRotationExpression )
383
+ {
384
+ map[" rotation_expression" ] = mRotationExpression ->dump ();
385
+ }
386
+ if ( mOutlineWidthExpression )
387
+ {
388
+ map[" outline_width_expression" ] = mOutlineWidthExpression ->dump ();
389
+ }
390
+ if ( mFillColorExpression )
391
+ {
392
+ map[" fill_color_expression" ] = mFillColorExpression ->dump ();
393
+ }
394
+ if ( mOutlineColorExpression )
395
+ {
396
+ map[" outline_color_expression" ] = mOutlineColorExpression ->dump ();
397
+ }
398
+ if ( mSymbolNameExpression )
399
+ {
400
+ map[" symbol_name_expression" ] = mSymbolNameExpression ->dump ();
401
+ }
349
402
return map;
350
403
}
351
404
352
405
bool QgsEllipseSymbolLayerV2::hasDataDefinedProperty () const
353
406
{
354
- return ( mWidthIndex != -1 || mHeightIndex != -1 || mOutlineWidthIndex != -1
355
- || mFillColorIndex != -1 || mOutlineColorIndex != -1 );
407
+ return ( mWidthExpression || mHeightExpression || mRotationExpression || mOutlineWidthExpression ||
408
+ mFillColorExpression || mOutlineColorExpression || mSymbolNameExpression );
409
+ }
410
+
411
+ void QgsEllipseSymbolLayerV2::prepareExpressions ( const QgsVectorLayer* vl )
412
+ {
413
+ if ( !vl )
414
+ {
415
+ return ;
416
+ }
417
+
418
+ const QgsFields& fields = vl->pendingFields ();
419
+ if ( mWidthExpression )
420
+ mWidthExpression ->prepare ( fields );
421
+ if ( mHeightExpression )
422
+ mHeightExpression ->prepare ( fields );
423
+ if ( mRotationExpression )
424
+ mRotationExpression ->prepare ( fields );
425
+ if ( mOutlineWidthExpression )
426
+ mOutlineWidthExpression ->prepare ( fields );
427
+ if ( mFillColorExpression )
428
+ mFillColorExpression ->prepare ( fields );
429
+ if ( mOutlineColorExpression )
430
+ mOutlineColorExpression ->prepare ( fields );
431
+ if ( mSymbolNameExpression )
432
+ mSymbolNameExpression ->prepare ( fields );
356
433
}
357
434
358
435
void QgsEllipseSymbolLayerV2::preparePath ( const QString& symbolName, QgsSymbolV2RenderContext& context, const QgsFeature* f )
@@ -362,32 +439,34 @@ void QgsEllipseSymbolLayerV2::preparePath( const QString& symbolName, QgsSymbolV
362
439
363
440
double width = 0 ;
364
441
365
- if ( f && mWidthIndex != - 1 ) // 1. priority: data defined setting on symbol layer level
442
+ if ( mWidthExpression ) // 1. priority: data defined setting on symbol layer level
366
443
{
367
- width = f-> attribute ( mWidthIndex ). toDouble () * QgsSymbolLayerV2Utils::lineWidthScaleFactor ( ct, mSymbolWidthUnit );
444
+ width = mWidthExpression -> evaluate ( const_cast <QgsFeature*>( f ) ). toDouble ( );
368
445
}
369
446
else if ( context.renderHints () & QgsSymbolV2::DataDefinedSizeScale ) // 2. priority: is data defined size on symbol level
370
447
{
371
- width = mSize * QgsSymbolLayerV2Utils::lineWidthScaleFactor ( ct, mSymbolWidthUnit ) ;
448
+ width = mSize ;
372
449
}
373
450
else // 3. priority: global width setting
374
451
{
375
- width = mSymbolWidth * QgsSymbolLayerV2Utils::lineWidthScaleFactor ( ct, mSymbolWidthUnit ) ;
452
+ width = mSymbolWidth ;
376
453
}
454
+ width *= QgsSymbolLayerV2Utils::lineWidthScaleFactor ( ct, mSymbolWidthUnit );
377
455
378
456
double height = 0 ;
379
- if ( f && mHeightIndex != - 1 ) // 1. priority: data defined setting on symbol layer level
457
+ if ( mHeightExpression ) // 1. priority: data defined setting on symbol layer level
380
458
{
381
- height = f-> attribute ( mHeightIndex ). toDouble () * QgsSymbolLayerV2Utils::lineWidthScaleFactor ( ct, mSymbolHeightUnit );
459
+ height = mHeightExpression -> evaluate ( const_cast <QgsFeature*>( f ) ). toDouble ( );
382
460
}
383
461
else if ( context.renderHints () & QgsSymbolV2::DataDefinedSizeScale ) // 2. priority: is data defined size on symbol level
384
462
{
385
- height = mSize * QgsSymbolLayerV2Utils::lineWidthScaleFactor ( ct, mSymbolHeightUnit ) ;
463
+ height = mSize ;
386
464
}
387
465
else // 3. priority: global height setting
388
466
{
389
- height = mSymbolHeight * QgsSymbolLayerV2Utils::lineWidthScaleFactor ( ct, mSymbolHeightUnit ) ;
467
+ height = mSymbolHeight ;
390
468
}
469
+ height *= QgsSymbolLayerV2Utils::lineWidthScaleFactor ( ct, mSymbolHeightUnit );
391
470
392
471
if ( symbolName == " circle" )
393
472
{
@@ -415,51 +494,160 @@ void QgsEllipseSymbolLayerV2::preparePath( const QString& symbolName, QgsSymbolV
415
494
416
495
QSet<QString> QgsEllipseSymbolLayerV2::usedAttributes () const
417
496
{
418
- QSet<QString> dataDefinedAttributes;
419
- if ( !mWidthField .isEmpty () )
497
+ QSet<QString> attributes;
498
+
499
+ // add data defined attributes
500
+ QStringList columns;
501
+ if ( mWidthExpression )
502
+ columns.append ( mWidthExpression ->referencedColumns () );
503
+ if ( mHeightExpression )
504
+ columns.append ( mHeightExpression ->referencedColumns () );
505
+ if ( mRotationExpression )
506
+ columns.append ( mRotationExpression ->referencedColumns () );
507
+ if ( mOutlineWidthExpression )
508
+ columns.append ( mOutlineWidthExpression ->referencedColumns () );
509
+ if ( mFillColorExpression )
510
+ columns.append ( mFillColorExpression ->referencedColumns () );
511
+ if ( mOutlineColorExpression )
512
+ columns.append ( mOutlineColorExpression ->referencedColumns () );
513
+ if ( mSymbolNameExpression )
514
+ columns.append ( mSymbolNameExpression ->referencedColumns () );
515
+
516
+ QStringList::const_iterator it = columns.constBegin ();
517
+ for ( ; it != columns.constEnd (); ++it )
518
+ {
519
+ attributes.insert ( *it );
520
+ }
521
+ return attributes;
522
+ }
523
+
524
+ void QgsEllipseSymbolLayerV2::setOutputUnit ( QgsSymbolV2::OutputUnit unit )
525
+ {
526
+ mSymbolWidthUnit = unit;
527
+ mSymbolHeightUnit = unit;
528
+ mOutlineWidthUnit = unit;
529
+ }
530
+
531
+ QgsSymbolV2::OutputUnit QgsEllipseSymbolLayerV2::outputUnit () const
532
+ {
533
+ QgsSymbolV2::OutputUnit unit = mSymbolWidthUnit ;
534
+ if ( mSymbolHeightUnit != unit || mOutlineWidthUnit != unit )
420
535
{
421
- dataDefinedAttributes. insert ( mWidthField ) ;
536
+ return QgsSymbolV2::Mixed ;
422
537
}
423
- if ( !mHeightField .isEmpty () )
538
+ return unit;
539
+ }
540
+
541
+ const QgsExpression* QgsEllipseSymbolLayerV2::dataDefinedProperty ( const QString& property ) const
542
+ {
543
+ if ( property == " width" )
424
544
{
425
- dataDefinedAttributes. insert ( mHeightField ) ;
545
+ return mWidthExpression ;
426
546
}
427
- if ( ! mRotationField . isEmpty () )
547
+ else if ( property == " height " )
428
548
{
429
- dataDefinedAttributes. insert ( mRotationField ) ;
549
+ return mHeightExpression ;
430
550
}
431
- if ( ! mOutlineWidthField . isEmpty () )
551
+ else if ( property == " rotation " )
432
552
{
433
- dataDefinedAttributes. insert ( mOutlineWidthField ) ;
553
+ return mRotationExpression ;
434
554
}
435
- if ( ! mFillColorField . isEmpty () )
555
+ else if ( property == " outline_width " )
436
556
{
437
- dataDefinedAttributes. insert ( mFillColorField ) ;
557
+ return mOutlineWidthExpression ;
438
558
}
439
- if ( ! mOutlineColorField . isEmpty () )
559
+ else if ( property == " fill_color " )
440
560
{
441
- dataDefinedAttributes. insert ( mOutlineColorField ) ;
561
+ return mFillColorExpression ;
442
562
}
443
- if ( ! mSymbolNameField . isEmpty () )
563
+ else if ( property == " outline_color " )
444
564
{
445
- dataDefinedAttributes. insert ( mSymbolNameField ) ;
565
+ return mOutlineColorExpression ;
446
566
}
447
- return dataDefinedAttributes;
567
+ else if ( property == " symbol_name" )
568
+ {
569
+ return mSymbolNameExpression ;
570
+ }
571
+ return 0 ;
448
572
}
449
573
450
- void QgsEllipseSymbolLayerV2::setOutputUnit ( QgsSymbolV2::OutputUnit unit )
574
+ QString QgsEllipseSymbolLayerV2::dataDefinedPropertyString ( const QString& property ) const
451
575
{
452
- mSymbolWidthUnit = unit;
453
- mSymbolHeightUnit = unit;
454
- mOutlineWidthUnit = unit;
576
+ const QgsExpression* ex = dataDefinedProperty ( property );
577
+ return ( ex ? ex->dump () : QString () );
455
578
}
456
579
457
- QgsSymbolV2::OutputUnit QgsEllipseSymbolLayerV2::outputUnit () const
580
+ void QgsEllipseSymbolLayerV2::setDataDefinedProperty ( const QString& property, const QString& expressionString )
458
581
{
459
- QgsSymbolV2::OutputUnit unit = mSymbolWidthUnit ;
460
- if ( mSymbolHeightUnit != unit || mOutlineWidthUnit != unit )
582
+ if ( property == " width" )
461
583
{
462
- return QgsSymbolV2::Mixed ;
584
+ delete mWidthExpression ; mWidthExpression = new QgsExpression ( expressionString ) ;
463
585
}
464
- return unit;
586
+ else if ( property == " height" )
587
+ {
588
+ delete mHeightExpression ; mHeightExpression = new QgsExpression ( expressionString );
589
+ }
590
+ else if ( property == " rotation" )
591
+ {
592
+ delete mRotationExpression ; mRotationExpression = new QgsExpression ( expressionString );
593
+ }
594
+ else if ( property == " outline_width" )
595
+ {
596
+ delete mOutlineWidthExpression ; mOutlineWidthExpression = new QgsExpression ( expressionString );
597
+ }
598
+ else if ( property == " fill_color" )
599
+ {
600
+ delete mFillColorExpression ; mFillColorExpression = new QgsExpression ( expressionString );
601
+ }
602
+ else if ( property == " outline_color" )
603
+ {
604
+ delete mOutlineColorExpression ; mOutlineColorExpression = new QgsExpression ( expressionString );
605
+ }
606
+ else if ( property == " symbol_name" )
607
+ {
608
+ delete mSymbolNameExpression ; mSymbolNameExpression = new QgsExpression ( expressionString );
609
+ }
610
+ }
611
+
612
+ void QgsEllipseSymbolLayerV2::removeDataDefinedProperty ( const QString& property )
613
+ {
614
+ if ( property == " width" )
615
+ {
616
+ delete mWidthExpression ; mWidthExpression = 0 ;
617
+ }
618
+ else if ( property == " height" )
619
+ {
620
+ delete mHeightExpression ; mHeightExpression = 0 ;
621
+ }
622
+ else if ( property == " rotation" )
623
+ {
624
+ delete mRotationExpression ; mRotationExpression = 0 ;
625
+ }
626
+ else if ( property == " outline_width" )
627
+ {
628
+ delete mOutlineWidthExpression ; mOutlineWidthExpression = 0 ;
629
+ }
630
+ else if ( property == " fill_color" )
631
+ {
632
+ delete mFillColorExpression ; mFillColorExpression = 0 ;
633
+ }
634
+ else if ( property == " outline_color" )
635
+ {
636
+ delete mOutlineColorExpression ; mOutlineColorExpression = 0 ;
637
+ }
638
+ else if ( property == " symbol_name" )
639
+ {
640
+ delete mSymbolNameExpression ; mSymbolNameExpression = 0 ;
641
+ }
642
+ }
643
+
644
+ void QgsEllipseSymbolLayerV2::removeDataDefinedProperties ()
645
+ {
646
+ delete mWidthExpression ; mWidthExpression = 0 ;
647
+ delete mHeightExpression ; mHeightExpression = 0 ;
648
+ delete mRotationExpression ; mRotationExpression = 0 ;
649
+ delete mOutlineWidthExpression ; mOutlineWidthExpression = 0 ;
650
+ delete mFillColorExpression ; mFillColorExpression = 0 ;
651
+ delete mOutlineColorExpression ; mOutlineColorExpression = 0 ;
652
+ delete mSymbolNameExpression ; mSymbolNameExpression = 0 ;
465
653
}
0 commit comments