QGIS API Documentation  2.99.0-Master (5753576)
qgscomposerarrow.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgscomposerarrow.cpp
3  ----------------------
4  begin : November 2009
5  copyright : (C) 2009 by Marco Hugentobler
6  email : [email protected]
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "qgscomposerarrow.h"
19 #include "qgscomposition.h"
20 #include "qgscomposerutils.h"
21 #include "qgssymbollayerutils.h"
22 #include "qgssvgcache.h"
23 #include "qgsmapsettings.h"
24 #include <QPainter>
25 #include <QSvgRenderer>
26 #include <QVector2D>
27 
28 #include <cmath>
29 
31  : QgsComposerItem( c )
32  , mStartPoint( 0, 0 )
33  , mStopPoint( 0, 0 )
34  , mStartXIdx( 0 )
35  , mStartYIdx( 0 )
36  , mMarkerMode( DefaultMarker )
37  , mArrowHeadOutlineWidth( 1.0 )
38  , mArrowHeadOutlineColor( Qt::black )
39  , mArrowHeadFillColor( Qt::black )
40  , mBoundsBehavior( 24 )
41  , mLineSymbol( nullptr )
42 {
43  init();
44 }
45 
46 QgsComposerArrow::QgsComposerArrow( QPointF startPoint, QPointF stopPoint, QgsComposition* c )
47  : QgsComposerItem( c )
48  , mStartPoint( startPoint )
49  , mStopPoint( stopPoint )
50  , mMarkerMode( DefaultMarker )
51  , mArrowHeadOutlineWidth( 1.0 )
52  , mArrowHeadOutlineColor( Qt::black )
53  , mArrowHeadFillColor( Qt::black )
54  , mBoundsBehavior( 24 )
55  , mLineSymbol( nullptr )
56 {
57  mStartXIdx = mStopPoint.x() < mStartPoint.x();
58  mStartYIdx = mStopPoint.y() < mStartPoint.y();
59  init();
60  adaptItemSceneRect();
61 }
62 
64 {
65  delete mLineSymbol;
66 }
67 
68 void QgsComposerArrow::init()
69 {
70  setArrowHeadWidth( 4 );
71  mPen.setColor( mArrowHeadOutlineColor );
72  mPen.setWidthF( 1 );
73  mBrush.setColor( mArrowHeadFillColor );
74  createDefaultLineSymbol();
75 
76  //default to no background
77  setBackgroundEnabled( false );
78 }
79 
80 
81 void QgsComposerArrow::createDefaultLineSymbol()
82 {
83  delete mLineSymbol;
84  QgsStringMap properties;
85  properties.insert( QStringLiteral( "color" ), QStringLiteral( "0,0,0,255" ) );
86  properties.insert( QStringLiteral( "width" ), QStringLiteral( "1" ) );
87  properties.insert( QStringLiteral( "capstyle" ), QStringLiteral( "square" ) );
88  mLineSymbol = QgsLineSymbol::createSimple( properties );
89 }
90 
91 void QgsComposerArrow::paint( QPainter* painter, const QStyleOptionGraphicsItem *itemStyle, QWidget *pWidget )
92 {
93  Q_UNUSED( itemStyle );
94  Q_UNUSED( pWidget );
95  if ( !painter || !painter->device() )
96  {
97  return;
98  }
99  if ( !shouldDrawItem() )
100  {
101  return;
102  }
103 
104  drawBackground( painter );
105 
106  painter->save();
107  //antialiasing on
108  painter->setRenderHint( QPainter::Antialiasing, true );
109 
110  //draw line section
111  drawLine( painter );
112 
113  //draw arrowhead if required
114  if ( mMarkerMode != NoMarker )
115  {
116  painter->setBrush( mBrush );
117  painter->setPen( mPen );
118 
119  if ( mMarkerMode == DefaultMarker )
120  {
121  drawHardcodedMarker( painter, EndMarker );
122  }
123  else if ( mMarkerMode == SVGMarker )
124  {
125  drawSVGMarker( painter, StartMarker, mStartMarkerFile );
126  drawSVGMarker( painter, EndMarker, mEndMarkerFile );
127  }
128  }
129 
130  painter->restore();
131 
132  drawFrame( painter );
133  if ( isSelected() )
134  {
135  drawSelectionBoxes( painter );
136  }
137 }
138 
139 void QgsComposerArrow::setSceneRect( const QRectF& rectangle )
140 {
141  //update rect for data defined size and position
142  QRectF evaluatedRect = evalItemRect( rectangle );
143 
144  if ( evaluatedRect.width() < 0 )
145  {
146  mStartXIdx = 1 - mStartXIdx;
147  }
148  if ( evaluatedRect.height() < 0 )
149  {
150  mStartYIdx = 1 - mStartYIdx;
151  }
152 
153  double margin = computeMarkerMargin();
154 
155  // Ensure the rectangle is at least as large as needed to include the markers
156  QRectF rect = rectangle.united( QRectF( evaluatedRect.x(), evaluatedRect.y(), 2. * margin, 2. * margin ) );
157 
158  // Compute new start and stop positions
159  double x[2] = {rect.x(), rect.x() + rect.width()};
160  double y[2] = {rect.y(), rect.y() + rect.height()};
161 
162  double xsign = x[mStartXIdx] < x[1 - mStartXIdx] ? 1.0 : -1.0;
163  double ysign = y[mStartYIdx] < y[1 - mStartYIdx] ? 1.0 : -1.0;
164 
165  mStartPoint = QPointF( x[mStartXIdx] + xsign * margin, y[mStartYIdx] + ysign * margin );
166  mStopPoint = QPointF( x[1 - mStartXIdx] - xsign * margin, y[1 - mStartYIdx] - ysign * margin );
167 
169 }
170 
171 void QgsComposerArrow::drawLine( QPainter *painter )
172 {
173  if ( ! mLineSymbol || ! mComposition )
174  {
175  return;
176  }
177 
178  QPaintDevice* thePaintDevice = painter->device();
179  painter->save();
180  //setup painter scaling to dots so that raster symbology is drawn to scale
181  double dotsPerMM = thePaintDevice->logicalDpiX() / 25.4;
182  painter->scale( 1 / dotsPerMM, 1 / dotsPerMM ); //scale painter from mm to dots
183 
184  //setup render context
186  context.setForceVectorOutput( true );
187 
188  QgsExpressionContext expressionContext = createExpressionContext();
189  context.setExpressionContext( expressionContext );
190 
191  //line scaled to dots
192  QPolygonF line;
193  line << QPointF( mStartPoint.x() - pos().x(), mStartPoint.y() - pos().y() ) * dotsPerMM
194  << QPointF( mStopPoint.x() - pos().x(), mStopPoint.y() - pos().y() ) * dotsPerMM;
195 
196  mLineSymbol->startRender( context );
197  mLineSymbol->renderPolyline( line, nullptr, context );
198  mLineSymbol->stopRender( context );
199  painter->restore();
200 
201 }
202 
203 void QgsComposerArrow::drawHardcodedMarker( QPainter *p, MarkerType type )
204 {
205  Q_UNUSED( type );
206  if ( mBoundsBehavior == 22 )
207  {
208  //if arrow was created in versions prior to 2.4, use the old rendering style
209  QgsComposerUtils::drawArrowHead( p, mStopPoint.x() - pos().x(), mStopPoint.y() - pos().y(), QgsComposerUtils::angle( mStartPoint, mStopPoint ), mArrowHeadWidth );
210  }
211  else
212  {
213  QVector2D dir = QVector2D( mStopPoint - mStartPoint ).normalized();
214  QPointF stop = mStopPoint + ( dir * 0.5 * mArrowHeadWidth ).toPointF();
215  QgsComposerUtils::drawArrowHead( p, stop.x() - pos().x(), stop.y() - pos().y(), QgsComposerUtils::angle( mStartPoint, stop ), mArrowHeadWidth );
216  }
217 }
218 
219 void QgsComposerArrow::drawSVGMarker( QPainter* p, MarkerType type, const QString &markerPath )
220 {
221  Q_UNUSED( markerPath );
222  double theAngle = QgsComposerUtils::angle( mStartPoint, mStopPoint );
223 
224  double arrowHeadHeight;
225  if ( type == StartMarker )
226  {
227  arrowHeadHeight = mStartArrowHeadHeight;
228  }
229  else
230  {
231  arrowHeadHeight = mStopArrowHeadHeight;
232  }
233  if ( mArrowHeadWidth <= 0 || arrowHeadHeight <= 0 )
234  {
235  //bad image size
236  return;
237  }
238 
239  QPointF imageFixPoint;
240  imageFixPoint.setX( mArrowHeadWidth / 2.0 );
241  QPointF canvasPoint;
242  if ( type == StartMarker )
243  {
244  canvasPoint = QPointF( mStartPoint.x() - pos().x(), mStartPoint.y() - pos().y() );
245  imageFixPoint.setY( mStartArrowHeadHeight );
246  }
247  else //end marker
248  {
249  canvasPoint = QPointF( mStopPoint.x() - pos().x(), mStopPoint.y() - pos().y() );
250  imageFixPoint.setY( 0 );
251  }
252 
253  QString svgFileName = ( type == StartMarker ? mStartMarkerFile : mEndMarkerFile );
254  if ( svgFileName.isEmpty() )
255  return;
256 
257  QSvgRenderer r;
258  const QByteArray &svgContent = QgsApplication::svgCache()->svgContent( svgFileName, mArrowHeadWidth, mArrowHeadFillColor, mArrowHeadOutlineColor, mArrowHeadOutlineWidth,
259  1.0 );
260  r.load( svgContent );
261 
262  p->save();
263  p->setRenderHint( QPainter::Antialiasing );
264  if ( mBoundsBehavior == 22 )
265  {
266  //if arrow was created in versions prior to 2.4, use the old rendering style
267  //rotate image fix point for backtransform
268  QPointF fixPoint;
269  if ( type == StartMarker )
270  {
271  fixPoint.setX( 0 );
272  fixPoint.setY( arrowHeadHeight / 2.0 );
273  }
274  else
275  {
276  fixPoint.setX( 0 );
277  fixPoint.setY( -arrowHeadHeight / 2.0 );
278  }
279  QPointF rotatedFixPoint;
280  double angleRad = theAngle / 180 * M_PI;
281  rotatedFixPoint.setX( fixPoint.x() * cos( angleRad ) + fixPoint.y() * -sin( angleRad ) );
282  rotatedFixPoint.setY( fixPoint.x() * sin( angleRad ) + fixPoint.y() * cos( angleRad ) );
283  p->translate( canvasPoint.x() - rotatedFixPoint.x(), canvasPoint.y() - rotatedFixPoint.y() );
284  }
285  else
286  {
287  p->translate( canvasPoint.x(), canvasPoint.y() );
288  }
289 
290  p->rotate( theAngle );
291  p->translate( -mArrowHeadWidth / 2.0, -arrowHeadHeight / 2.0 );
292  r.render( p, QRectF( 0, 0, mArrowHeadWidth, arrowHeadHeight ) );
293  p->restore();
294 
295  return;
296 }
297 
298 void QgsComposerArrow::setStartMarker( const QString& svgPath )
299 {
300  QSvgRenderer r;
301  mStartMarkerFile = svgPath;
302  if ( svgPath.isEmpty() || !r.load( svgPath ) )
303  {
304  mStartArrowHeadHeight = 0;
305  }
306  else
307  {
308  //calculate mArrowHeadHeight from svg file and mArrowHeadWidth
309  QRect viewBox = r.viewBox();
310  mStartArrowHeadHeight = mArrowHeadWidth / viewBox.width() * viewBox.height();
311  }
312  adaptItemSceneRect();
313 }
314 
315 void QgsComposerArrow::setEndMarker( const QString& svgPath )
316 {
317  QSvgRenderer r;
318  mEndMarkerFile = svgPath;
319  if ( svgPath.isEmpty() || !r.load( svgPath ) )
320  {
321  mStopArrowHeadHeight = 0;
322  }
323  else
324  {
325  //calculate mArrowHeadHeight from svg file and mArrowHeadWidth
326  QRect viewBox = r.viewBox();
327  mStopArrowHeadHeight = mArrowHeadWidth / viewBox.width() * viewBox.height();
328  }
329  adaptItemSceneRect();
330 }
331 
333 {
334  mArrowHeadOutlineColor = color;
335  mPen.setColor( color );
336 }
337 
338 void QgsComposerArrow::setArrowHeadFillColor( const QColor &color )
339 {
340  mArrowHeadFillColor = color;
341  mBrush.setColor( color );
342 }
343 
345 {
346  mArrowHeadOutlineWidth = width;
347  mPen.setWidthF( mArrowHeadOutlineWidth );
348 
349  adaptItemSceneRect();
350 }
351 
353 {
354  delete mLineSymbol;
355  mLineSymbol = symbol;
356 }
357 
359 {
360  mArrowHeadWidth = width;
361  setStartMarker( mStartMarkerFile );
362  setEndMarker( mEndMarkerFile );
363  adaptItemSceneRect();
364 }
365 
366 double QgsComposerArrow::computeMarkerMargin() const
367 {
368  double margin = 0;
369 
370  if ( mBoundsBehavior == 22 )
371  {
372  //if arrow was created in versions prior to 2.4, use the old rendering style
373  if ( mMarkerMode == DefaultMarker )
374  {
375  margin = mPen.widthF() / 2.0 + mArrowHeadWidth / 2.0;
376  }
377  else if ( mMarkerMode == NoMarker )
378  {
379  margin = mPen.widthF() / 2.0;
380  }
381  else if ( mMarkerMode == SVGMarker )
382  {
383  double maxArrowHeight = qMax( mStartArrowHeadHeight, mStopArrowHeadHeight );
384  margin = mPen.widthF() / 2 + qMax( mArrowHeadWidth / 2.0, maxArrowHeight / 2.0 );
385  }
386  }
387  else
388  {
389  if ( mMarkerMode == DefaultMarker )
390  {
391  margin = mPen.widthF() / std::sqrt( 2.0 ) + mArrowHeadWidth / 2.0;
392  }
393  else if ( mMarkerMode == NoMarker )
394  {
395  margin = mPen.widthF() / std::sqrt( 2.0 );
396  }
397  else if ( mMarkerMode == SVGMarker )
398  {
399  double startMarkerMargin = std::sqrt( 0.25 * ( mStartArrowHeadHeight * mStartArrowHeadHeight + mArrowHeadWidth * mArrowHeadWidth ) );
400  double stopMarkerMargin = std::sqrt( 0.25 * ( mStopArrowHeadHeight * mStopArrowHeadHeight + mArrowHeadWidth * mArrowHeadWidth ) );
401  double markerMargin = qMax( startMarkerMargin, stopMarkerMargin );
402  margin = qMax( mPen.widthF() / std::sqrt( 2.0 ), markerMargin );
403  }
404  }
405  return margin;
406 }
407 
408 void QgsComposerArrow::adaptItemSceneRect()
409 {
410  //rectangle containing start and end point
411  QRectF rect = QRectF( qMin( mStartPoint.x(), mStopPoint.x() ), qMin( mStartPoint.y(), mStopPoint.y() ),
412  qAbs( mStopPoint.x() - mStartPoint.x() ), qAbs( mStopPoint.y() - mStartPoint.y() ) );
413  double enlarge = computeMarkerMargin();
414  rect.adjust( -enlarge, -enlarge, enlarge, enlarge );
416 }
417 
419 {
420  mMarkerMode = mode;
421  adaptItemSceneRect();
422 }
423 
424 bool QgsComposerArrow::writeXml( QDomElement& elem, QDomDocument & doc ) const
425 {
426  QDomElement composerArrowElem = doc.createElement( QStringLiteral( "ComposerArrow" ) );
427  composerArrowElem.setAttribute( QStringLiteral( "arrowHeadWidth" ), QString::number( mArrowHeadWidth ) );
428  composerArrowElem.setAttribute( QStringLiteral( "arrowHeadFillColor" ), QgsSymbolLayerUtils::encodeColor( mArrowHeadFillColor ) );
429  composerArrowElem.setAttribute( QStringLiteral( "arrowHeadOutlineColor" ), QgsSymbolLayerUtils::encodeColor( mArrowHeadOutlineColor ) );
430  composerArrowElem.setAttribute( QStringLiteral( "outlineWidth" ), QString::number( mArrowHeadOutlineWidth ) );
431  composerArrowElem.setAttribute( QStringLiteral( "markerMode" ), mMarkerMode );
432  composerArrowElem.setAttribute( QStringLiteral( "startMarkerFile" ), mStartMarkerFile );
433  composerArrowElem.setAttribute( QStringLiteral( "endMarkerFile" ), mEndMarkerFile );
434  composerArrowElem.setAttribute( QStringLiteral( "boundsBehaviorVersion" ), QString::number( mBoundsBehavior ) );
435 
436  QDomElement styleElem = doc.createElement( QStringLiteral( "lineStyle" ) );
437  QDomElement lineStyleElem = QgsSymbolLayerUtils::saveSymbol( QString(), mLineSymbol, doc );
438  styleElem.appendChild( lineStyleElem );
439  composerArrowElem.appendChild( styleElem );
440 
441  //start point
442  QDomElement startPointElem = doc.createElement( QStringLiteral( "StartPoint" ) );
443  startPointElem.setAttribute( QStringLiteral( "x" ), QString::number( mStartPoint.x() ) );
444  startPointElem.setAttribute( QStringLiteral( "y" ), QString::number( mStartPoint.y() ) );
445  composerArrowElem.appendChild( startPointElem );
446 
447  //stop point
448  QDomElement stopPointElem = doc.createElement( QStringLiteral( "StopPoint" ) );
449  stopPointElem.setAttribute( QStringLiteral( "x" ), QString::number( mStopPoint.x() ) );
450  stopPointElem.setAttribute( QStringLiteral( "y" ), QString::number( mStopPoint.y() ) );
451  composerArrowElem.appendChild( stopPointElem );
452 
453  elem.appendChild( composerArrowElem );
454  return _writeXml( composerArrowElem, doc );
455 }
456 
457 bool QgsComposerArrow::readXml( const QDomElement& itemElem, const QDomDocument& doc )
458 {
459  mArrowHeadWidth = itemElem.attribute( QStringLiteral( "arrowHeadWidth" ), QStringLiteral( "2.0" ) ).toDouble();
460  mArrowHeadFillColor = QgsSymbolLayerUtils::decodeColor( itemElem.attribute( QStringLiteral( "arrowHeadFillColor" ), QStringLiteral( "0,0,0,255" ) ) );
461  mArrowHeadOutlineColor = QgsSymbolLayerUtils::decodeColor( itemElem.attribute( QStringLiteral( "arrowHeadOutlineColor" ), QStringLiteral( "0,0,0,255" ) ) );
462  mArrowHeadOutlineWidth = itemElem.attribute( QStringLiteral( "outlineWidth" ), QStringLiteral( "1.0" ) ).toDouble();
463  setStartMarker( itemElem.attribute( QStringLiteral( "startMarkerFile" ), QLatin1String( "" ) ) );
464  setEndMarker( itemElem.attribute( QStringLiteral( "endMarkerFile" ), QLatin1String( "" ) ) );
465  mMarkerMode = QgsComposerArrow::MarkerMode( itemElem.attribute( QStringLiteral( "markerMode" ), QStringLiteral( "0" ) ).toInt() );
466  //if bounds behavior version is not set, default to 2.2 behavior
467  mBoundsBehavior = itemElem.attribute( QStringLiteral( "boundsBehaviorVersion" ), QStringLiteral( "22" ) ).toInt();
468 
469  //arrow style
470  QDomElement styleElem = itemElem.firstChildElement( QStringLiteral( "lineStyle" ) );
471  if ( !styleElem.isNull() )
472  {
473  QDomElement lineStyleElem = styleElem.firstChildElement( QStringLiteral( "symbol" ) );
474  if ( !lineStyleElem.isNull() )
475  {
476  delete mLineSymbol;
477  mLineSymbol = QgsSymbolLayerUtils::loadSymbol<QgsLineSymbol>( lineStyleElem );
478  }
479  }
480  else
481  {
482  //old project file, read arrow width and color
483  delete mLineSymbol;
484 
485  QgsStringMap properties;
486  properties.insert( QStringLiteral( "width" ), itemElem.attribute( QStringLiteral( "outlineWidth" ), QStringLiteral( "1.0" ) ) );
487 
488  if ( mBoundsBehavior == 22 )
489  {
490  //if arrow was created in versions prior to 2.4, use the old rendering style
491  properties.insert( QStringLiteral( "capstyle" ), QStringLiteral( "flat" ) );
492  }
493  else
494  {
495  properties.insert( QStringLiteral( "capstyle" ), QStringLiteral( "square" ) );
496  }
497  int red = 0;
498  int blue = 0;
499  int green = 0;
500  int alpha = 255;
501 
502  QDomNodeList arrowColorList = itemElem.elementsByTagName( QStringLiteral( "ArrowColor" ) );
503  if ( !arrowColorList.isEmpty() )
504  {
505  QDomElement arrowColorElem = arrowColorList.at( 0 ).toElement();
506  red = arrowColorElem.attribute( QStringLiteral( "red" ), QStringLiteral( "0" ) ).toInt();
507  green = arrowColorElem.attribute( QStringLiteral( "green" ), QStringLiteral( "0" ) ).toInt();
508  blue = arrowColorElem.attribute( QStringLiteral( "blue" ), QStringLiteral( "0" ) ).toInt();
509  alpha = arrowColorElem.attribute( QStringLiteral( "alpha" ), QStringLiteral( "255" ) ).toInt();
510  mArrowHeadFillColor = QColor( red, green, blue, alpha );
511  mArrowHeadOutlineColor = QColor( red, green, blue, alpha );
512  }
513  properties.insert( QStringLiteral( "color" ), QStringLiteral( "%1,%2,%3,%4" ).arg( red ).arg( green ).arg( blue ).arg( alpha ) );
514  mLineSymbol = QgsLineSymbol::createSimple( properties );
515  }
516 
517  mPen.setColor( mArrowHeadOutlineColor );
518  mPen.setWidthF( mArrowHeadOutlineWidth );
519  mBrush.setColor( mArrowHeadFillColor );
520 
521  //restore general composer item properties
522  //needs to be before start point / stop point because setSceneRect()
523  QDomNodeList composerItemList = itemElem.elementsByTagName( QStringLiteral( "ComposerItem" ) );
524  if ( !composerItemList.isEmpty() )
525  {
526  QDomElement composerItemElem = composerItemList.at( 0 ).toElement();
527  _readXml( composerItemElem, doc );
528  }
529 
530  //start point
531  QDomNodeList startPointList = itemElem.elementsByTagName( QStringLiteral( "StartPoint" ) );
532  if ( !startPointList.isEmpty() )
533  {
534  QDomElement startPointElem = startPointList.at( 0 ).toElement();
535  mStartPoint.setX( startPointElem.attribute( QStringLiteral( "x" ), QStringLiteral( "0.0" ) ).toDouble() );
536  mStartPoint.setY( startPointElem.attribute( QStringLiteral( "y" ), QStringLiteral( "0.0" ) ).toDouble() );
537  }
538 
539  //stop point
540  QDomNodeList stopPointList = itemElem.elementsByTagName( QStringLiteral( "StopPoint" ) );
541  if ( !stopPointList.isEmpty() )
542  {
543  QDomElement stopPointElem = stopPointList.at( 0 ).toElement();
544  mStopPoint.setX( stopPointElem.attribute( QStringLiteral( "x" ), QStringLiteral( "0.0" ) ).toDouble() );
545  mStopPoint.setY( stopPointElem.attribute( QStringLiteral( "y" ), QStringLiteral( "0.0" ) ).toDouble() );
546  }
547 
548  mStartXIdx = mStopPoint.x() < mStartPoint.x();
549  mStartYIdx = mStopPoint.y() < mStartPoint.y();
550 
551  adaptItemSceneRect();
552  emit itemChanged();
553  return true;
554 }
555 
556 
QgsComposerArrow(QgsComposition *c)
Constructor.
void setForceVectorOutput(bool force)
static QgsSvgCache * svgCache()
Returns the application&#39;s SVG cache, used for caching SVG images and handling parameter replacement w...
bool shouldDrawItem() const
Returns whether the item should be drawn in the current context.
virtual int type() const override
Return composer item type.
static QDomElement saveSymbol(const QString &symbolName, QgsSymbol *symbol, QDomDocument &doc)
static double angle(QPointF p1, QPointF p2)
Calculates the angle of the line from p1 to p2 (counter clockwise, starting from a line from north to...
static QgsLineSymbol * createSimple(const QgsStringMap &properties)
Create a line symbol with one symbol layer: SimpleLine with specified properties. ...
Definition: qgssymbol.cpp:1055
void itemChanged()
Emitted when the item changes.
bool writeXml(QDomElement &elem, QDomDocument &doc) const override
Stores state in DOM element.
void renderPolyline(const QPolygonF &points, const QgsFeature *f, QgsRenderContext &context, int layer=-1, bool selected=false)
Definition: qgssymbol.cpp:1645
A item that forms part of a map composition.
QRectF evalItemRect(const QRectF &newRect, const bool resizeOnly=false, const QgsExpressionContext *context=nullptr)
Evaluates an item&#39;s bounding rect to consider data defined position and size of item and reference po...
void setStartMarker(const QString &svgPath)
Sets the marker to draw at the start of the line.
virtual void drawFrame(QPainter *p)
Draw black frame around item.
void setArrowHeadWidth(double width)
Sets the width of the arrow head in mm.
QMap< QString, QString > QgsStringMap
Definition: qgis.h:325
QByteArray svgContent(const QString &file, double size, const QColor &fill, const QColor &outline, double outlineWidth, double widthScaleFactor)
Get SVG content.
void startRender(QgsRenderContext &context, const QgsFields &fields=QgsFields())
Begins the rendering process for the symbol.
Definition: qgssymbol.cpp:387
void setArrowHeadOutlineWidth(const double width)
Sets the pen width for the outline of the arrow head.
static QString encodeColor(const QColor &color)
void setSceneRect(const QRectF &rectangle) override
Modifies position of start and endpoint and calls QgsComposerItem::setSceneRect.
static void drawArrowHead(QPainter *p, const double x, const double y, const double angle, const double arrowHeadWidth)
Draws an arrow head on to a QPainter.
bool _writeXml(QDomElement &itemElem, QDomDocument &doc) const
Writes parameter that are not subclass specific in document. Usually called from writeXml methods of ...
bool readXml(const QDomElement &itemElem, const QDomDocument &doc) override
Sets state from DOM document.
virtual void drawSelectionBoxes(QPainter *p)
Draws additional graphics on selected items.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
#define M_PI
void setArrowHeadOutlineColor(const QColor &color)
Sets the color used to draw the outline around the arrow head.
static QgsRenderContext createRenderContext(QgsComposition *composition, QPainter *painter)
Creates a render context suitable for the specified composition and QPainter destination.
void setMarkerMode(MarkerMode mode)
Sets the marker mode, which controls how the arrow endpoints are drawn.
bool _readXml(const QDomElement &itemElem, const QDomDocument &doc)
Reads parameter that are not subclass specific in document. Usually called from readXml methods of su...
void setBackgroundEnabled(const bool drawBackground)
Set whether this item has a Background drawn around it or not.
void setArrowHeadFillColor(const QColor &color)
Sets the color used to fill the arrow head.
Graphics scene for map printing.
virtual QgsExpressionContext createExpressionContext() const override
Creates an expression context relating to the item&#39;s current state.
QgsComposition * mComposition
Contains information about the context of a rendering operation.
void setLineSymbol(QgsLineSymbol *symbol)
Sets the line symbol used for drawing the line portion of the arrow.
virtual void drawBackground(QPainter *p)
Draw background.
virtual void setSceneRect(const QRectF &rectangle)
Sets this items bound in scene coordinates such that 1 item size units corresponds to 1 scene size un...
void paint(QPainter *painter, const QStyleOptionGraphicsItem *itemStyle, QWidget *pWidget) override
Reimplementation of QCanvasItem::paint - draw on canvas.
void stopRender(QgsRenderContext &context)
Ends the rendering process.
Definition: qgssymbol.cpp:408
void setEndMarker(const QString &svgPath)
Sets the marker to draw at the end of the line.
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
static QColor decodeColor(const QString &str)