26 #include <QSvgRenderer> 32 createDefaultPolylineStyleSymbol();
38 createDefaultPolylineStyleSymbol();
63 if ( indexPoint == (
mPolygon.size() - 1 ) )
65 if ( distEnd < radius )
67 else if ( distStart < radius )
71 mPolygon.insert( indexPoint + 1, newPoint );
78 if ( index < 0 || index >=
mPolygon.size() )
87 int newSelectNode = index;
96 void QgsLayoutItemPolyline::createDefaultPolylineStyleSymbol()
99 properties.insert( QStringLiteral(
"color" ), QStringLiteral(
"0,0,0,255" ) );
100 properties.insert( QStringLiteral(
"width" ), QStringLiteral(
"0.3" ) );
101 properties.insert( QStringLiteral(
"capstyle" ), QStringLiteral(
"square" ) );
107 void QgsLayoutItemPolyline::refreshSymbol()
120 void QgsLayoutItemPolyline::drawStartMarker( QPainter *painter )
125 switch ( mStartMarker )
127 case MarkerMode::NoMarker:
130 case MarkerMode::ArrowHead:
134 double angle = startLine.angle();
139 case MarkerMode::SvgMarker:
143 double angle = startLine.angle();
144 drawSvgMarker( painter,
mPolygon.at( 0 ),
angle, mStartMarkerFile, mStartArrowHeadHeight );
151 void QgsLayoutItemPolyline::drawEndMarker( QPainter *painter )
156 switch ( mEndMarker )
158 case MarkerMode::NoMarker:
161 case MarkerMode::ArrowHead:
165 double angle = endLine.angle();
166 drawArrow( painter, endLine.p2(),
angle );
169 case MarkerMode::SvgMarker:
173 double angle = endLine.angle();
174 drawSvgMarker( painter, endLine.p2(),
angle, mEndMarkerFile, mEndArrowHeadHeight );
180 void QgsLayoutItemPolyline::drawArrow( QPainter *painter, QPointF center,
double angle )
185 p.setColor( mArrowHeadStrokeColor );
186 p.setWidthF( mArrowHeadStrokeWidth );
187 painter->setPen( p );
189 b.setColor( mArrowHeadFillColor );
190 painter->setBrush( b );
191 drawArrowHead( painter, center.x(), center.y(),
angle, mArrowHeadWidth );
194 void QgsLayoutItemPolyline::updateMarkerSvgSizes()
200 void QgsLayoutItemPolyline::drawArrowHead( QPainter *p,
const double x,
const double y,
const double angle,
const double arrowHeadWidth )
205 double angleRad =
angle / 180.0 * M_PI;
206 QPointF middlePoint( x, y );
208 QPointF p1 = QPointF( -arrowHeadWidth / 2.0, arrowHeadWidth );
209 QPointF p2 = QPointF( arrowHeadWidth / 2.0, arrowHeadWidth );
211 QPointF p1Rotated, p2Rotated;
212 p1Rotated.setX( p1.x() * std::cos( angleRad ) + p1.y() * -std::sin( angleRad ) );
213 p1Rotated.setY( p1.x() * std::sin( angleRad ) + p1.y() * std::cos( angleRad ) );
214 p2Rotated.setX( p2.x() * std::cos( angleRad ) + p2.y() * -std::sin( angleRad ) );
215 p2Rotated.setY( p2.x() * std::sin( angleRad ) + p2.y() * std::cos( angleRad ) );
217 QPolygonF arrowHeadPoly;
218 arrowHeadPoly << middlePoint;
219 arrowHeadPoly << QPointF( middlePoint.x() + p1Rotated.x(), middlePoint.y() + p1Rotated.y() );
220 arrowHeadPoly << QPointF( middlePoint.x() + p2Rotated.x(), middlePoint.y() + p2Rotated.y() );
221 QPen arrowPen = p->pen();
222 arrowPen.setJoinStyle( Qt::RoundJoin );
223 QBrush arrowBrush = p->brush();
224 arrowBrush.setStyle( Qt::SolidPattern );
225 p->setPen( arrowPen );
226 p->setBrush( arrowBrush );
227 arrowBrush.setStyle( Qt::SolidPattern );
228 p->drawPolygon( arrowHeadPoly );
231 void QgsLayoutItemPolyline::drawSvgMarker( QPainter *p, QPointF point,
double angle,
const QString &markerPath,
double height )
const 236 if ( mArrowHeadWidth <= 0 || height <= 0 )
242 if ( markerPath.isEmpty() )
246 const QByteArray &svgContent =
QgsApplication::svgCache()->
svgContent( markerPath, mArrowHeadWidth, mArrowHeadFillColor, mArrowHeadStrokeColor, mArrowHeadStrokeWidth,
248 r.load( svgContent );
251 p->translate( point.x(), point.y() );
253 p->translate( -mArrowHeadWidth / 2.0, -height / 2.0 );
254 r.render( p, QRectF( 0, 0, mArrowHeadWidth, height ) );
260 if ( !
id().isEmpty() )
263 return tr(
"<Polyline>" );
271 QTransform t = QTransform::fromScale( scale, scale );
273 mPolylineStyleSymbol->startRender( context.
renderContext() );
287 mPolylineStyleSymbol.reset( QgsSymbolLayerUtils::loadSymbol<QgsLineSymbol>( elmt, context ) );
292 mPolylineStyleSymbol.reset( static_cast<QgsLineSymbol *>( symbol->
clone() ) );
310 mArrowHeadWidth = width;
311 updateMarkerSvgSizes();
318 mStartMarkerFile = path;
319 if ( path.isEmpty() || !r.load( path ) )
321 mStartArrowHeadHeight = 0;
326 QRect viewBox = r.viewBox();
327 mStartArrowHeadHeight = mArrowHeadWidth / viewBox.width() * viewBox.height();
335 mEndMarkerFile = path;
336 if ( path.isEmpty() || !r.load( path ) )
338 mEndArrowHeadHeight = 0;
343 QRect viewBox = r.viewBox();
344 mEndArrowHeadHeight = mArrowHeadWidth / viewBox.width() * viewBox.height();
351 mArrowHeadStrokeColor = color;
357 mArrowHeadFillColor = color;
363 mArrowHeadStrokeWidth = width;
371 mPolylineStyleSymbol.get(),
374 elmt.appendChild( pe );
385 elmt.setAttribute( QStringLiteral(
"arrowHeadWidth" ), QString::number( mArrowHeadWidth ) );
388 elmt.setAttribute( QStringLiteral(
"outlineWidth" ), QString::number( mArrowHeadStrokeWidth ) );
389 elmt.setAttribute( QStringLiteral(
"markerMode" ), mEndMarker );
390 elmt.setAttribute( QStringLiteral(
"startMarkerMode" ), mStartMarker );
391 elmt.setAttribute( QStringLiteral(
"startMarkerFile" ), startMarkerPath );
392 elmt.setAttribute( QStringLiteral(
"endMarkerFile" ), endMarkerPath );
399 mArrowHeadWidth = elmt.attribute( QStringLiteral(
"arrowHeadWidth" ), QStringLiteral(
"2.0" ) ).toDouble();
402 mArrowHeadStrokeWidth = elmt.attribute( QStringLiteral(
"outlineWidth" ), QStringLiteral(
"1.0" ) ).toDouble();
404 QString startMarkerPath = elmt.attribute( QStringLiteral(
"startMarkerFile" ), QLatin1String(
"" ) );
405 QString endMarkerPath = elmt.attribute( QStringLiteral(
"endMarkerFile" ), QLatin1String(
"" ) );
422 br.adjust( -margin, -margin, margin, margin );
426 prepareGeometryChange();
431 double QgsLayoutItemPolyline::computeMarkerMargin()
const 437 margin = mArrowHeadStrokeWidth / 2.0 + mArrowHeadWidth * M_SQRT2;
442 double startMarkerMargin = std::sqrt( 0.25 * ( mStartArrowHeadHeight * mStartArrowHeadHeight + mArrowHeadWidth * mArrowHeadWidth ) );
443 margin = std::max( startMarkerMargin, margin );
448 double endMarkerMargin = std::sqrt( 0.25 * ( mEndArrowHeadHeight * mEndArrowHeadHeight + mArrowHeadWidth * mArrowHeadWidth ) );
449 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 euclidian 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.
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.
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.
QPolygonF mPolygon
Shape's nodes.
void updateBoundingRect() override
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.
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.
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.
QByteArray svgContent(const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth, double widthScaleFactor, double fixedAspectRatio=0)
Gets SVG content.
static QDomElement saveSymbol(const QString &symbolName, QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
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.
static QColor decodeColor(const QString &str)
QgsLineSymbol * clone() const override
Gets a deep copy of this symbol.