16
16
***************************************************************************/
17
17
18
18
#include " qgscomposershape.h"
19
+ #include " qgscomposition.h"
20
+ #include " qgssymbolv2.h"
21
+ #include " qgssymbollayerv2utils.h"
19
22
#include < QPainter>
20
23
21
- QgsComposerShape::QgsComposerShape ( QgsComposition* composition ): QgsComposerItem( composition ), mShape( Ellipse ), mCornerRadius( 0 )
24
+ QgsComposerShape::QgsComposerShape ( QgsComposition* composition ): QgsComposerItem( composition ),
25
+ mShape( Ellipse ),
26
+ mCornerRadius( 0 ),
27
+ mUseSymbolV2( false ), // default to not using SymbolV2 for shapes, to preserve 2.0 api
28
+ mShapeStyleSymbol( 0 )
22
29
{
23
30
setFrameEnabled ( true );
31
+ createDefaultShapeStyleSymbol ();
24
32
}
25
33
26
- QgsComposerShape::QgsComposerShape ( qreal x, qreal y, qreal width, qreal height, QgsComposition* composition ): QgsComposerItem( x, y, width, height, composition ),
34
+ QgsComposerShape::QgsComposerShape ( qreal x, qreal y, qreal width, qreal height, QgsComposition* composition ):
35
+ QgsComposerItem( x, y, width, height, composition ),
27
36
mShape( Ellipse ),
28
- mCornerRadius( 0 )
37
+ mCornerRadius( 0 ),
38
+ mUseSymbolV2( false ), // default to not using SymbolV2 for shapes, to preserve 2.0 api
39
+ mShapeStyleSymbol( 0 )
29
40
{
30
41
setSceneRect ( QRectF ( x, y, width, height ) );
31
42
setFrameEnabled ( true );
43
+ createDefaultShapeStyleSymbol ();
32
44
}
33
45
34
46
QgsComposerShape::~QgsComposerShape ()
35
47
{
48
+ delete mShapeStyleSymbol ;
49
+ }
50
+
51
+ void QgsComposerShape::setUseSymbolV2 ( bool useSymbolV2 )
52
+ {
53
+ mUseSymbolV2 = useSymbolV2;
54
+ setFrameEnabled ( !useSymbolV2 );
55
+ }
36
56
57
+ void QgsComposerShape::setShapeStyleSymbol ( QgsFillSymbolV2* symbol )
58
+ {
59
+ delete mShapeStyleSymbol ;
60
+ mShapeStyleSymbol = symbol;
61
+ update ();
62
+ }
63
+
64
+ void QgsComposerShape::createDefaultShapeStyleSymbol ()
65
+ {
66
+ delete mShapeStyleSymbol ;
67
+ QgsStringMap properties;
68
+ properties.insert ( " color" , " white" );
69
+ properties.insert ( " style" , " solid" );
70
+ properties.insert ( " style_border" , " solid" );
71
+ properties.insert ( " color_border" , " black" );
72
+ properties.insert ( " width_border" , " 0.3" );
73
+ mShapeStyleSymbol = QgsFillSymbolV2::createSimple ( properties );
37
74
}
38
75
39
76
void QgsComposerShape::paint ( QPainter* painter, const QStyleOptionGraphicsItem* itemStyle, QWidget* pWidget )
@@ -56,7 +93,13 @@ void QgsComposerShape::paint( QPainter* painter, const QStyleOptionGraphicsItem*
56
93
57
94
void QgsComposerShape::drawShape ( QPainter* p )
58
95
{
96
+ if ( mUseSymbolV2 )
97
+ {
98
+ drawShapeUsingSymbol ( p );
99
+ return ;
100
+ }
59
101
102
+ // draw using QPainter brush and pen to keep 2.0 api compatibility
60
103
p->save ();
61
104
p->setRenderHint ( QPainter::Antialiasing );
62
105
@@ -85,13 +128,101 @@ void QgsComposerShape::drawShape( QPainter* p )
85
128
break ;
86
129
}
87
130
p->restore ();
131
+ }
132
+
133
+ void QgsComposerShape::drawShapeUsingSymbol ( QPainter* p )
134
+ {
135
+ p->save ();
136
+ p->setRenderHint ( QPainter::Antialiasing );
137
+
138
+ QgsRenderContext context;
139
+ context.setPainter ( p );
140
+ context.setScaleFactor ( 1.0 );
141
+ if ( mComposition ->plotStyle () == QgsComposition::Preview )
142
+ {
143
+ context.setRasterScaleFactor ( horizontalViewScaleFactor () );
144
+ }
145
+ else
146
+ {
147
+ context.setRasterScaleFactor ( mComposition ->printResolution () / 25.4 );
148
+ }
149
+
150
+ // generate polygon to draw
151
+ QList<QPolygonF> rings; // empty list
152
+ QPolygonF shapePolygon;
88
153
154
+ // shapes with curves must be enlarged before conversion to QPolygonF, or
155
+ // the curves are approximated too much and appear jaggy
156
+ QTransform t = QTransform::fromScale ( 100 , 100 );
157
+ // inverse transform used to scale created polygons back to expected size
158
+ QTransform ti = t.inverted ();
159
+
160
+ switch ( mShape )
161
+ {
162
+ case Ellipse:
163
+ {
164
+ // create an ellipse
165
+ QPainterPath ellipsePath;
166
+ ellipsePath.addEllipse ( QRectF ( 0 , 0 , rect ().width (), rect ().height () ) );
167
+ QPolygonF ellipsePoly = ellipsePath.toFillPolygon ( t );
168
+ shapePolygon = ti.map ( ellipsePoly );
169
+ break ;
170
+ }
171
+ case Rectangle:
172
+ {
173
+ // if corner radius set, then draw a rounded rectangle
174
+ if ( mCornerRadius > 0 )
175
+ {
176
+ QPainterPath roundedRectPath;
177
+ roundedRectPath.addRoundedRect ( QRectF ( 0 , 0 , rect ().width (), rect ().height () ), mCornerRadius , mCornerRadius );
178
+ QPolygonF roundedPoly = roundedRectPath.toFillPolygon ( t );
179
+ shapePolygon = ti.map ( roundedPoly );
180
+ }
181
+ else
182
+ {
183
+ shapePolygon = QPolygonF ( QRectF ( 0 , 0 , rect ().width (), rect ().height () ) );
184
+ }
185
+ break ;
186
+ }
187
+ case Triangle:
188
+ {
189
+ shapePolygon << QPointF ( 0 , rect ().height () );
190
+ shapePolygon << QPointF ( rect ().width () , rect ().height () );
191
+ shapePolygon << QPointF ( rect ().width () / 2.0 , 0 );
192
+ shapePolygon << QPointF ( 0 , rect ().height () );
193
+ break ;
194
+ }
195
+ }
196
+
197
+ mShapeStyleSymbol ->startRender ( context );
198
+
199
+ double maxBleed = QgsSymbolLayerV2Utils::estimateMaxSymbolBleed ( mShapeStyleSymbol );
200
+
201
+ // even though we aren't going to use it to draw the shape, set the pen width as 2 * symbol bleed
202
+ // so that the item is fully rendered within it's scene rect
203
+ // (QGraphicsRectItem considers the pen width when calculating an item's scene rect)
204
+ setPen ( QPen ( QBrush ( Qt::NoBrush ), maxBleed * 2.0 ) );
205
+
206
+ // need to render using atlas feature properties?
207
+ if ( mComposition ->atlasComposition ().enabled () && mComposition ->atlasMode () != QgsComposition::AtlasOff )
208
+ {
209
+ // using an atlas, so render using current atlas feature
210
+ // since there may be data defined symbols using atlas feature properties
211
+ mShapeStyleSymbol ->renderPolygon ( shapePolygon, &rings, mComposition ->atlasComposition ().currentFeature (), context );
212
+ }
213
+ else
214
+ {
215
+ mShapeStyleSymbol ->renderPolygon ( shapePolygon, &rings, 0 , context );
216
+ }
217
+
218
+ mShapeStyleSymbol ->stopRender ( context );
219
+ p->restore ();
89
220
}
90
221
91
222
92
223
void QgsComposerShape::drawFrame ( QPainter* p )
93
224
{
94
- if ( mFrame && p )
225
+ if ( mFrame && p && ! mUseSymbolV2 )
95
226
{
96
227
p->setPen ( pen () );
97
228
p->setBrush ( Qt::NoBrush );
@@ -102,7 +233,7 @@ void QgsComposerShape::drawFrame( QPainter* p )
102
233
103
234
void QgsComposerShape::drawBackground ( QPainter* p )
104
235
{
105
- if ( mBackground && p )
236
+ if ( p && ( mBackground || mUseSymbolV2 ) )
106
237
{
107
238
p->setBrush ( brush () );// this causes a problem in atlas generation
108
239
p->setPen ( Qt::NoPen );
@@ -117,6 +248,10 @@ bool QgsComposerShape::writeXML( QDomElement& elem, QDomDocument & doc ) const
117
248
QDomElement composerShapeElem = doc.createElement ( " ComposerShape" );
118
249
composerShapeElem.setAttribute ( " shapeType" , mShape );
119
250
composerShapeElem.setAttribute ( " cornerRadius" , mCornerRadius );
251
+
252
+ QDomElement shapeStyleElem = QgsSymbolLayerV2Utils::saveSymbol ( QString (), mShapeStyleSymbol , doc );
253
+ composerShapeElem.appendChild ( shapeStyleElem );
254
+
120
255
elem.appendChild ( composerShapeElem );
121
256
return _writeXML ( composerShapeElem, doc );
122
257
}
@@ -141,6 +276,39 @@ bool QgsComposerShape::readXML( const QDomElement& itemElem, const QDomDocument&
141
276
142
277
_readXML ( composerItemElem, doc );
143
278
}
279
+
280
+ QDomElement shapeStyleSymbolElem = itemElem.firstChildElement ( " symbol" );
281
+ if ( !shapeStyleSymbolElem.isNull () )
282
+ {
283
+ delete mShapeStyleSymbol ;
284
+ mShapeStyleSymbol = dynamic_cast <QgsFillSymbolV2*>( QgsSymbolLayerV2Utils::loadSymbol ( shapeStyleSymbolElem ) );
285
+ }
286
+ else
287
+ {
288
+ // upgrade project file from 2.0 to use symbolV2 styling
289
+ delete mShapeStyleSymbol ;
290
+ QgsStringMap properties;
291
+ properties.insert ( " color" , QgsSymbolLayerV2Utils::encodeColor ( brush ().color () ) );
292
+ if ( hasBackground () )
293
+ {
294
+ properties.insert ( " style" , " solid" );
295
+ }
296
+ else
297
+ {
298
+ properties.insert ( " style" , " no" );
299
+ }
300
+ if ( hasFrame () )
301
+ {
302
+ properties.insert ( " style_border" , " solid" );
303
+ }
304
+ else
305
+ {
306
+ properties.insert ( " style_border" , " no" );
307
+ }
308
+ properties.insert ( " color_border" , QgsSymbolLayerV2Utils::encodeColor ( pen ().color () ) );
309
+ properties.insert ( " width_border" , QString::number ( pen ().widthF () ) );
310
+ mShapeStyleSymbol = QgsFillSymbolV2::createSimple ( properties );
311
+ }
144
312
emit itemChanged ();
145
313
return true ;
146
314
}
0 commit comments