27 #include <QSvgRenderer>    29 #include <QGraphicsPathItem>    35   createDefaultPolylineStyleSymbol();
    41   createDefaultPolylineStyleSymbol();
    66   if ( indexPoint == ( 
mPolygon.size() - 1 ) )
    68     if ( distEnd < radius )
    70     else if ( distStart < radius )
    74     mPolygon.insert( indexPoint + 1, newPoint );
    81   if ( index < 0 || index >= 
mPolygon.size() )
    90     int newSelectNode = index;
    99 void QgsLayoutItemPolyline::createDefaultPolylineStyleSymbol()
   102   properties.insert( QStringLiteral( 
"color" ), QStringLiteral( 
"0,0,0,255" ) );
   103   properties.insert( QStringLiteral( 
"width" ), QStringLiteral( 
"0.3" ) );
   104   properties.insert( QStringLiteral( 
"capstyle" ), QStringLiteral( 
"square" ) );
   110 void QgsLayoutItemPolyline::refreshSymbol()
   123 void QgsLayoutItemPolyline::drawStartMarker( QPainter *painter )
   128   switch ( mStartMarker )
   130     case MarkerMode::NoMarker:
   133     case MarkerMode::ArrowHead:
   137       double angle = startLine.angle();
   142     case MarkerMode::SvgMarker:
   146       double angle = startLine.angle();
   147       drawSvgMarker( painter, 
mPolygon.at( 0 ), 
angle, mStartMarkerFile, mStartArrowHeadHeight );
   154 void QgsLayoutItemPolyline::drawEndMarker( QPainter *painter )
   159   switch ( mEndMarker )
   161     case MarkerMode::NoMarker:
   164     case MarkerMode::ArrowHead:
   168       double angle = endLine.angle();
   171       QVector2D dir = QVector2D( endLine.dx(), endLine.dy() ).normalized();
   172       QPointF endPoint = endLine.p2();
   173       endPoint += ( dir * 0.5 * mArrowHeadWidth ).toPointF();
   175       drawArrow( painter, endPoint, angle );
   178     case MarkerMode::SvgMarker:
   182       double angle = endLine.angle();
   183       drawSvgMarker( painter, endLine.p2(), 
angle, mEndMarkerFile, mEndArrowHeadHeight );
   189 void QgsLayoutItemPolyline::drawArrow( QPainter *painter, QPointF center, 
double angle )
   194   p.setColor( mArrowHeadStrokeColor );
   195   p.setWidthF( mArrowHeadStrokeWidth );
   196   painter->setPen( p );
   198   b.setColor( mArrowHeadFillColor );
   199   painter->setBrush( b );
   201   drawArrowHead( painter, center.x(), center.y(), 
angle, mArrowHeadWidth );
   204 void QgsLayoutItemPolyline::updateMarkerSvgSizes()
   210 void QgsLayoutItemPolyline::drawArrowHead( QPainter *p, 
const double x, 
const double y, 
const double angle, 
const double arrowHeadWidth )
   215   double angleRad = 
angle / 180.0 * M_PI;
   216   QPointF middlePoint( x, y );
   219   QPointF p1 = QPointF( -arrowHeadWidth / 2.0, arrowHeadWidth );
   220   QPointF p2 = QPointF( arrowHeadWidth / 2.0, arrowHeadWidth );
   222   QPointF p1Rotated, p2Rotated;
   223   p1Rotated.setX( p1.x() * std::cos( angleRad ) + p1.y() * -std::sin( angleRad ) );
   224   p1Rotated.setY( p1.x() * std::sin( angleRad ) + p1.y() * std::cos( angleRad ) );
   225   p2Rotated.setX( p2.x() * std::cos( angleRad ) + p2.y() * -std::sin( angleRad ) );
   226   p2Rotated.setY( p2.x() * std::sin( angleRad ) + p2.y() * std::cos( angleRad ) );
   228   QPolygonF arrowHeadPoly;
   229   arrowHeadPoly << middlePoint;
   230   arrowHeadPoly << QPointF( middlePoint.x() + p1Rotated.x(), middlePoint.y() + p1Rotated.y() );
   231   arrowHeadPoly << QPointF( middlePoint.x() + p2Rotated.x(), middlePoint.y() + p2Rotated.y() );
   232   QPen arrowPen = p->pen();
   233   arrowPen.setJoinStyle( Qt::RoundJoin );
   234   QBrush arrowBrush = p->brush();
   235   arrowBrush.setStyle( Qt::SolidPattern );
   236   p->setPen( arrowPen );
   237   p->setBrush( arrowBrush );
   238   arrowBrush.setStyle( Qt::SolidPattern );
   239   p->drawPolygon( arrowHeadPoly );
   242 void QgsLayoutItemPolyline::drawSvgMarker( QPainter *p, QPointF point, 
double angle, 
const QString &markerPath, 
double height )
 const   247   if ( mArrowHeadWidth <= 0 || height <= 0 )
   253   if ( markerPath.isEmpty() )
   257   const QByteArray &svgContent = 
QgsApplication::svgCache()->
svgContent( markerPath, mArrowHeadWidth, mArrowHeadFillColor, mArrowHeadStrokeColor, mArrowHeadStrokeWidth,
   259   r.load( svgContent );
   262   p->translate( point.x(), point.y() );
   264   p->translate( -mArrowHeadWidth / 2.0, -height / 2.0 );
   265   r.render( p, QRectF( 0, 0, mArrowHeadWidth, height ) );
   271   if ( !
id().isEmpty() )
   274   return tr( 
"<Polyline>" );
   282   QTransform t = QTransform::fromScale( scale, scale );
   284   mPolylineStyleSymbol->startRender( context.
renderContext() );
   298   mPolylineStyleSymbol.reset( QgsSymbolLayerUtils::loadSymbol<QgsLineSymbol>( elmt, context ) );
   303   mPolylineStyleSymbol.reset( static_cast<QgsLineSymbol *>( symbol->
clone() ) );
   321   mArrowHeadWidth = width;
   322   updateMarkerSvgSizes();
   331   QPainterPathStroker ps;
   334   QPainterPath strokedOutline = ps.createStroke( path );
   336   return strokedOutline;
   342   mStartMarkerFile = path;
   343   if ( path.isEmpty() || !r.load( path ) )
   345     mStartArrowHeadHeight = 0;
   350     QRect viewBox = r.viewBox();
   351     mStartArrowHeadHeight = mArrowHeadWidth / viewBox.width() * viewBox.height();
   359   mEndMarkerFile = path;
   360   if ( path.isEmpty() || !r.load( path ) )
   362     mEndArrowHeadHeight = 0;
   367     QRect viewBox = r.viewBox();
   368     mEndArrowHeadHeight = mArrowHeadWidth / viewBox.width() * viewBox.height();
   375   mArrowHeadStrokeColor = color;
   381   mArrowHeadFillColor = color;
   387   mArrowHeadStrokeWidth = width;
   394   if ( mPolylineStyleSymbol )
   407                          mPolylineStyleSymbol.get(),
   410   elmt.appendChild( pe );
   421   elmt.setAttribute( QStringLiteral( 
"arrowHeadWidth" ), QString::number( mArrowHeadWidth ) );
   424   elmt.setAttribute( QStringLiteral( 
"outlineWidth" ), QString::number( mArrowHeadStrokeWidth ) );
   425   elmt.setAttribute( QStringLiteral( 
"markerMode" ), mEndMarker );
   426   elmt.setAttribute( QStringLiteral( 
"startMarkerMode" ), mStartMarker );
   427   elmt.setAttribute( QStringLiteral( 
"startMarkerFile" ), startMarkerPath );
   428   elmt.setAttribute( QStringLiteral( 
"endMarkerFile" ), endMarkerPath );
   435   mArrowHeadWidth = elmt.attribute( QStringLiteral( 
"arrowHeadWidth" ), QStringLiteral( 
"2.0" ) ).toDouble();
   438   mArrowHeadStrokeWidth = elmt.attribute( QStringLiteral( 
"outlineWidth" ), QStringLiteral( 
"1.0" ) ).toDouble();
   440   QString startMarkerPath = elmt.attribute( QStringLiteral( 
"startMarkerFile" ), QString() );
   441   QString endMarkerPath = elmt.attribute( QStringLiteral( 
"endMarkerFile" ), QString() );
   460     margin += 0.5 * mArrowHeadWidth;
   462   br.adjust( -margin, -margin, margin, margin );
   466   prepareGeometryChange();
   471 double QgsLayoutItemPolyline::computeMarkerMargin()
 const   477     margin = mArrowHeadStrokeWidth / 2.0 + mArrowHeadWidth * M_SQRT2;
   482     double startMarkerMargin = std::sqrt( 0.25 * ( mStartArrowHeadHeight * mStartArrowHeadHeight + mArrowHeadWidth * mArrowHeadWidth ) );
   483     margin = std::max( startMarkerMargin, margin );
   488     double endMarkerMargin = std::sqrt( 0.25 * ( mEndArrowHeadHeight * mEndArrowHeadHeight + mArrowHeadWidth * mArrowHeadWidth ) );
   489     margin = std::max( endMarkerMargin, margin );
 double arrowHeadWidth() const
Returns the width of line arrow heads in mm. 
 
double computeDistance(QPointF pt1, QPointF pt2) const
Compute an euclidean distance between 2 nodes. 
 
The class is used as a container of context for various read/write operations on other objects...
 
static QgsSvgCache * svgCache()
Returns the application's SVG cache, used for caching SVG images and handling parameter replacement w...
 
void setStartMarker(MarkerMode mode)
Sets the start marker mode, which controls what marker is drawn at the start of the line...
 
void updateSceneRect()
Update the current scene rectangle for this item. 
 
A symbol entity for QgsStyle databases. 
 
bool _removeNode(int nodeIndex) override
Method called in removeNode. 
 
bool readPropertiesFromElement(const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context) override
Sets item state from a DOM element. 
 
void setArrowHeadWidth(double width)
Sets the width of line arrow heads in mm. 
 
void _writeXmlStyle(QDomDocument &doc, QDomElement &elmt, const QgsReadWriteContext &context) const override
Method called in writeXml. 
 
QRectF mCurrentRectangle
Current bounding rectangle of shape. 
 
void setArrowHeadFillColor(const QColor &color)
Sets the color used to fill the arrow head. 
 
static QgsLineSymbol * createSimple(const QgsStringMap &properties)
Create a line symbol with one symbol layer: SimpleLine with specified properties. ...
 
void setStartSvgMarkerPath(const QString &path)
Sets the path to a SVG marker to draw at the start of the line. 
 
MarkerMode
Vertex marker mode. 
 
An abstract layout item that provides generic methods for node based shapes such as polygon or polyli...
 
QString displayName() const override
Gets item display name. 
 
double mMaxSymbolBleed
Max symbol bleed. 
 
QPainterPath shape() const override
 
void setEndSvgMarkerPath(const QString &path)
Sets the path to a SVG marker to draw at the end of the line. 
 
bool writePropertiesToElement(QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context) const override
Stores item state within an XML DOM element. 
 
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon. 
 
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML. 
 
QPolygonF mPolygon
Shape's nodes. 
 
An interface for classes which can visit style entity (e.g. 
 
void updateBoundingRect() override
 
QByteArray svgContent(const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth, double widthScaleFactor, double fixedAspectRatio=0, bool blocking=false)
Gets SVG content. 
 
QgsLayoutRenderContext & renderContext()
Returns a reference to the layout's render context, which stores information relating to the current ...
 
QMap< QString, QString > QgsStringMap
 
bool _addNode(int indexPoint, QPointF newPoint, double radius) override
Method called in addNode. 
 
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored) 
 
void setSymbol(QgsLineSymbol *symbol)
Sets the symbol used to draw the shape. 
 
A line symbol type, for rendering LineString and MultiLineString geometries. 
 
virtual bool visit(const QgsStyleEntityVisitorInterface::StyleLeaf &entity)
Called when the visitor will visit a style entity. 
 
static QString encodeColor(const QColor &color)
 
int type() const override
 
QgsLineSymbol * symbol()
Returns the line symbol used to draw the shape. 
 
void _readXmlStyle(const QDomElement &elmt, const QgsReadWriteContext &context) override
Method called in readXml. 
 
void setArrowHeadStrokeColor(const QColor &color)
Sets the color used to draw the stroke around the arrow head. 
 
void setEndMarker(MarkerMode mode)
Sets the end marker mode, which controls what marker is drawn at the end of the line. 
 
void frameChanged()
Emitted if the item's frame style changes. 
 
static QString svgSymbolPathToName(const QString &path, const QgsPathResolver &pathResolver)
Determines an SVG symbol's name from its path. 
 
void setArrowHeadStrokeWidth(double width)
Sets the pen width in millimeters for the stroke of the arrow head. 
 
Layout item for node based polyline shapes. 
 
QIcon icon() const override
Returns the item's icon. 
 
const QgsLayout * layout() const
Returns the layout the object is attached to. 
 
double dpi() const
Returns the dpi for outputting the layout. 
 
QgsRenderContext & renderContext()
Returns a reference to the context's render context. 
 
bool readPropertiesFromElement(const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context) override
Sets item state from a DOM element. 
 
static QgsRenderContext createRenderContextForLayout(QgsLayout *layout, QPainter *painter, double dpi=-1)
Creates a render context suitable for the specified layout and painter destination. 
 
static double estimateMaxSymbolBleed(QgsSymbol *symbol, const QgsRenderContext &context)
Returns the maximum estimated bleed for the symbol. 
 
QString id() const
Returns the item's ID name. 
 
Base class for layouts, which can contain items such as maps, labels, scalebars, etc. 
 
void _draw(QgsLayoutItemRenderContext &context, const QStyleOptionGraphicsItem *itemStyle=nullptr) override
Method called in paint. 
 
static QgsLayoutItemPolyline * create(QgsLayout *layout)
Returns a new polyline item for the specified layout. 
 
bool setSelectedNode(int index)
Selects a node by index. 
 
Contains settings and helpers relating to a render of a QgsLayoutItem. 
 
const QgsPathResolver & pathResolver() const
Returns path resolver for conversion between relative and absolute paths. 
 
bool accept(QgsStyleEntityVisitorInterface *visitor) const override
Accepts the specified style entity visitor, causing it to visit all style entities associated with th...
 
Contains information about the context of a rendering operation. 
 
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale()) const
Converts a size from the specified units to painter units (pixels). 
 
QPainter * painter()
Returns the destination QPainter for the render operation. 
 
virtual QString uuid() const
Returns the item identification string. 
 
QgsLayoutItemPolyline(QgsLayout *layout)
Constructor for QgsLayoutItemPolyline for the specified layout. 
 
static QString svgSymbolNameToPath(const QString &name, const QgsPathResolver &pathResolver)
Determines an SVG symbol's path from its name. 
 
double scaleFactor() const
Returns the scaling factor for the render to convert painter units to physical sizes. 
 
bool writePropertiesToElement(QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context) const override
Stores item state within an XML DOM element. 
 
Contains information relating to the style entity currently being visited. 
 
static QColor decodeColor(const QString &str)
 
QgsLineSymbol * clone() const override
Returns a deep copy of this symbol.