QGIS API Documentation  2.99.0-Master (b8fd1fd)
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  , mArrowHeadStrokeWidth( 1.0 )
38  , mArrowHeadStrokeColor( 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  , mArrowHeadStrokeWidth( 1.0 )
52  , mArrowHeadStrokeColor( 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( mArrowHeadStrokeColor );
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 *paintDevice = painter->device();
179  painter->save();
180  //setup painter scaling to dots so that raster symbology is drawn to scale
181  double dotsPerMM = paintDevice->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 angle = 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, mArrowHeadStrokeColor, mArrowHeadStrokeWidth,
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 = angle / 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( angle );
291  p->translate( -mArrowHeadWidth / 2.0, -arrowHeadHeight / 2.0 );
292  r.render( p, QRectF( 0, 0, mArrowHeadWidth, arrowHeadHeight ) );
293  p->restore();
294 }
295 
296 void QgsComposerArrow::setStartMarker( const QString &svgPath )
297 {
298  QSvgRenderer r;
299  mStartMarkerFile = svgPath;
300  if ( svgPath.isEmpty() || !r.load( svgPath ) )
301  {
302  mStartArrowHeadHeight = 0;
303  }
304  else
305  {
306  //calculate mArrowHeadHeight from svg file and mArrowHeadWidth
307  QRect viewBox = r.viewBox();
308  mStartArrowHeadHeight = mArrowHeadWidth / viewBox.width() * viewBox.height();
309  }
310  adaptItemSceneRect();
311 }
312 
313 void QgsComposerArrow::setEndMarker( const QString &svgPath )
314 {
315  QSvgRenderer r;
316  mEndMarkerFile = svgPath;
317  if ( svgPath.isEmpty() || !r.load( svgPath ) )
318  {
319  mStopArrowHeadHeight = 0;
320  }
321  else
322  {
323  //calculate mArrowHeadHeight from svg file and mArrowHeadWidth
324  QRect viewBox = r.viewBox();
325  mStopArrowHeadHeight = mArrowHeadWidth / viewBox.width() * viewBox.height();
326  }
327  adaptItemSceneRect();
328 }
329 
330 void QgsComposerArrow::setArrowHeadStrokeColor( const QColor &color )
331 {
332  mArrowHeadStrokeColor = color;
333  mPen.setColor( color );
334 }
335 
336 void QgsComposerArrow::setArrowHeadFillColor( const QColor &color )
337 {
338  mArrowHeadFillColor = color;
339  mBrush.setColor( color );
340 }
341 
343 {
344  mArrowHeadStrokeWidth = width;
345  mPen.setWidthF( mArrowHeadStrokeWidth );
346 
347  adaptItemSceneRect();
348 }
349 
351 {
352  delete mLineSymbol;
353  mLineSymbol = symbol;
354 }
355 
357 {
358  mArrowHeadWidth = width;
359  setStartMarker( mStartMarkerFile );
360  setEndMarker( mEndMarkerFile );
361  adaptItemSceneRect();
362 }
363 
364 double QgsComposerArrow::computeMarkerMargin() const
365 {
366  double margin = 0;
367 
368  if ( mBoundsBehavior == 22 )
369  {
370  //if arrow was created in versions prior to 2.4, use the old rendering style
371  if ( mMarkerMode == DefaultMarker )
372  {
373  margin = mPen.widthF() / 2.0 + mArrowHeadWidth / 2.0;
374  }
375  else if ( mMarkerMode == NoMarker )
376  {
377  margin = mPen.widthF() / 2.0;
378  }
379  else if ( mMarkerMode == SVGMarker )
380  {
381  double maxArrowHeight = qMax( mStartArrowHeadHeight, mStopArrowHeadHeight );
382  margin = mPen.widthF() / 2 + qMax( mArrowHeadWidth / 2.0, maxArrowHeight / 2.0 );
383  }
384  }
385  else
386  {
387  if ( mMarkerMode == DefaultMarker )
388  {
389  margin = mPen.widthF() / std::sqrt( 2.0 ) + mArrowHeadWidth / 2.0;
390  }
391  else if ( mMarkerMode == NoMarker )
392  {
393  margin = mPen.widthF() / std::sqrt( 2.0 );
394  }
395  else if ( mMarkerMode == SVGMarker )
396  {
397  double startMarkerMargin = std::sqrt( 0.25 * ( mStartArrowHeadHeight * mStartArrowHeadHeight + mArrowHeadWidth * mArrowHeadWidth ) );
398  double stopMarkerMargin = std::sqrt( 0.25 * ( mStopArrowHeadHeight * mStopArrowHeadHeight + mArrowHeadWidth * mArrowHeadWidth ) );
399  double markerMargin = qMax( startMarkerMargin, stopMarkerMargin );
400  margin = qMax( mPen.widthF() / std::sqrt( 2.0 ), markerMargin );
401  }
402  }
403  return margin;
404 }
405 
406 void QgsComposerArrow::adaptItemSceneRect()
407 {
408  //rectangle containing start and end point
409  QRectF rect = QRectF( qMin( mStartPoint.x(), mStopPoint.x() ), qMin( mStartPoint.y(), mStopPoint.y() ),
410  qAbs( mStopPoint.x() - mStartPoint.x() ), qAbs( mStopPoint.y() - mStartPoint.y() ) );
411  double enlarge = computeMarkerMargin();
412  rect.adjust( -enlarge, -enlarge, enlarge, enlarge );
414 }
415 
417 {
418  mMarkerMode = mode;
419  adaptItemSceneRect();
420 }
421 
422 bool QgsComposerArrow::writeXml( QDomElement &elem, QDomDocument &doc ) const
423 {
424  QDomElement composerArrowElem = doc.createElement( QStringLiteral( "ComposerArrow" ) );
425  composerArrowElem.setAttribute( QStringLiteral( "arrowHeadWidth" ), QString::number( mArrowHeadWidth ) );
426  composerArrowElem.setAttribute( QStringLiteral( "arrowHeadFillColor" ), QgsSymbolLayerUtils::encodeColor( mArrowHeadFillColor ) );
427  composerArrowElem.setAttribute( QStringLiteral( "arrowHeadOutlineColor" ), QgsSymbolLayerUtils::encodeColor( mArrowHeadStrokeColor ) );
428  composerArrowElem.setAttribute( QStringLiteral( "outlineWidth" ), QString::number( mArrowHeadStrokeWidth ) );
429  composerArrowElem.setAttribute( QStringLiteral( "markerMode" ), mMarkerMode );
430  composerArrowElem.setAttribute( QStringLiteral( "startMarkerFile" ), mStartMarkerFile );
431  composerArrowElem.setAttribute( QStringLiteral( "endMarkerFile" ), mEndMarkerFile );
432  composerArrowElem.setAttribute( QStringLiteral( "boundsBehaviorVersion" ), QString::number( mBoundsBehavior ) );
433 
434  QDomElement styleElem = doc.createElement( QStringLiteral( "lineStyle" ) );
435  QDomElement lineStyleElem = QgsSymbolLayerUtils::saveSymbol( QString(), mLineSymbol, doc );
436  styleElem.appendChild( lineStyleElem );
437  composerArrowElem.appendChild( styleElem );
438 
439  //start point
440  QDomElement startPointElem = doc.createElement( QStringLiteral( "StartPoint" ) );
441  startPointElem.setAttribute( QStringLiteral( "x" ), QString::number( mStartPoint.x() ) );
442  startPointElem.setAttribute( QStringLiteral( "y" ), QString::number( mStartPoint.y() ) );
443  composerArrowElem.appendChild( startPointElem );
444 
445  //stop point
446  QDomElement stopPointElem = doc.createElement( QStringLiteral( "StopPoint" ) );
447  stopPointElem.setAttribute( QStringLiteral( "x" ), QString::number( mStopPoint.x() ) );
448  stopPointElem.setAttribute( QStringLiteral( "y" ), QString::number( mStopPoint.y() ) );
449  composerArrowElem.appendChild( stopPointElem );
450 
451  elem.appendChild( composerArrowElem );
452  return _writeXml( composerArrowElem, doc );
453 }
454 
455 bool QgsComposerArrow::readXml( const QDomElement &itemElem, const QDomDocument &doc )
456 {
457  mArrowHeadWidth = itemElem.attribute( QStringLiteral( "arrowHeadWidth" ), QStringLiteral( "2.0" ) ).toDouble();
458  mArrowHeadFillColor = QgsSymbolLayerUtils::decodeColor( itemElem.attribute( QStringLiteral( "arrowHeadFillColor" ), QStringLiteral( "0,0,0,255" ) ) );
459  mArrowHeadStrokeColor = QgsSymbolLayerUtils::decodeColor( itemElem.attribute( QStringLiteral( "arrowHeadOutlineColor" ), QStringLiteral( "0,0,0,255" ) ) );
460  mArrowHeadStrokeWidth = itemElem.attribute( QStringLiteral( "outlineWidth" ), QStringLiteral( "1.0" ) ).toDouble();
461  setStartMarker( itemElem.attribute( QStringLiteral( "startMarkerFile" ), QLatin1String( "" ) ) );
462  setEndMarker( itemElem.attribute( QStringLiteral( "endMarkerFile" ), QLatin1String( "" ) ) );
463  mMarkerMode = QgsComposerArrow::MarkerMode( itemElem.attribute( QStringLiteral( "markerMode" ), QStringLiteral( "0" ) ).toInt() );
464  //if bounds behavior version is not set, default to 2.2 behavior
465  mBoundsBehavior = itemElem.attribute( QStringLiteral( "boundsBehaviorVersion" ), QStringLiteral( "22" ) ).toInt();
466 
467  //arrow style
468  QDomElement styleElem = itemElem.firstChildElement( QStringLiteral( "lineStyle" ) );
469  if ( !styleElem.isNull() )
470  {
471  QDomElement lineStyleElem = styleElem.firstChildElement( QStringLiteral( "symbol" ) );
472  if ( !lineStyleElem.isNull() )
473  {
474  delete mLineSymbol;
475  mLineSymbol = QgsSymbolLayerUtils::loadSymbol<QgsLineSymbol>( lineStyleElem );
476  }
477  }
478  else
479  {
480  //old project file, read arrow width and color
481  delete mLineSymbol;
482 
483  QgsStringMap properties;
484  properties.insert( QStringLiteral( "width" ), itemElem.attribute( QStringLiteral( "outlineWidth" ), QStringLiteral( "1.0" ) ) );
485 
486  if ( mBoundsBehavior == 22 )
487  {
488  //if arrow was created in versions prior to 2.4, use the old rendering style
489  properties.insert( QStringLiteral( "capstyle" ), QStringLiteral( "flat" ) );
490  }
491  else
492  {
493  properties.insert( QStringLiteral( "capstyle" ), QStringLiteral( "square" ) );
494  }
495  int red = 0;
496  int blue = 0;
497  int green = 0;
498  int alpha = 255;
499 
500  QDomNodeList arrowColorList = itemElem.elementsByTagName( QStringLiteral( "ArrowColor" ) );
501  if ( !arrowColorList.isEmpty() )
502  {
503  QDomElement arrowColorElem = arrowColorList.at( 0 ).toElement();
504  red = arrowColorElem.attribute( QStringLiteral( "red" ), QStringLiteral( "0" ) ).toInt();
505  green = arrowColorElem.attribute( QStringLiteral( "green" ), QStringLiteral( "0" ) ).toInt();
506  blue = arrowColorElem.attribute( QStringLiteral( "blue" ), QStringLiteral( "0" ) ).toInt();
507  alpha = arrowColorElem.attribute( QStringLiteral( "alpha" ), QStringLiteral( "255" ) ).toInt();
508  mArrowHeadFillColor = QColor( red, green, blue, alpha );
509  mArrowHeadStrokeColor = QColor( red, green, blue, alpha );
510  }
511  properties.insert( QStringLiteral( "color" ), QStringLiteral( "%1,%2,%3,%4" ).arg( red ).arg( green ).arg( blue ).arg( alpha ) );
512  mLineSymbol = QgsLineSymbol::createSimple( properties );
513  }
514 
515  mPen.setColor( mArrowHeadStrokeColor );
516  mPen.setWidthF( mArrowHeadStrokeWidth );
517  mBrush.setColor( mArrowHeadFillColor );
518 
519  //restore general composer item properties
520  //needs to be before start point / stop point because setSceneRect()
521  QDomNodeList composerItemList = itemElem.elementsByTagName( QStringLiteral( "ComposerItem" ) );
522  if ( !composerItemList.isEmpty() )
523  {
524  QDomElement composerItemElem = composerItemList.at( 0 ).toElement();
525  _readXml( composerItemElem, doc );
526  }
527 
528  //start point
529  QDomNodeList startPointList = itemElem.elementsByTagName( QStringLiteral( "StartPoint" ) );
530  if ( !startPointList.isEmpty() )
531  {
532  QDomElement startPointElem = startPointList.at( 0 ).toElement();
533  mStartPoint.setX( startPointElem.attribute( QStringLiteral( "x" ), QStringLiteral( "0.0" ) ).toDouble() );
534  mStartPoint.setY( startPointElem.attribute( QStringLiteral( "y" ), QStringLiteral( "0.0" ) ).toDouble() );
535  }
536 
537  //stop point
538  QDomNodeList stopPointList = itemElem.elementsByTagName( QStringLiteral( "StopPoint" ) );
539  if ( !stopPointList.isEmpty() )
540  {
541  QDomElement stopPointElem = stopPointList.at( 0 ).toElement();
542  mStopPoint.setX( stopPointElem.attribute( QStringLiteral( "x" ), QStringLiteral( "0.0" ) ).toDouble() );
543  mStopPoint.setY( stopPointElem.attribute( QStringLiteral( "y" ), QStringLiteral( "0.0" ) ).toDouble() );
544  }
545 
546  mStartXIdx = mStopPoint.x() < mStartPoint.x();
547  mStartYIdx = mStopPoint.y() < mStartPoint.y();
548 
549  adaptItemSceneRect();
550  emit itemChanged();
551  return true;
552 }
553 
554 
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:1041
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:1627
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:341
void startRender(QgsRenderContext &context, const QgsFields &fields=QgsFields())
Begins the rendering process for the symbol.
Definition: qgssymbol.cpp:378
QByteArray svgContent(const QString &file, double size, const QColor &fill, const QColor &stroke, double strokeWidth, double widthScaleFactor)
Get SVG content.
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 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 setArrowHeadStrokeColor(const QColor &color)
Sets the color used to draw the stroke around the arrow head.
void setArrowHeadStrokeWidth(const double width)
Sets the pen width for the stroke of the arrow head.
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...
static QgsRenderContext createRenderContextForComposition(QgsComposition *composition, QPainter *painter)
Creates a render context suitable for the specified composition and painter destination.
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:399
double ANALYSIS_EXPORT angle(Point3D *p1, Point3D *p2, Point3D *p3, Point3D *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
Definition: MathUtils.cc:857
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)