23 #include <QSvgRenderer> 34 , mMarkerMode( DefaultMarker )
35 , mArrowHeadOutlineWidth( 1.0 )
36 , mArrowHeadOutlineColor( Qt::black )
37 , mArrowHeadFillColor( Qt::black )
38 , mBoundsBehaviour( 24 )
46 , mStartPoint( startPoint )
47 , mStopPoint( stopPoint )
49 , mArrowHeadOutlineWidth( 1.0 )
50 , mArrowHeadOutlineColor( Qt::black )
51 , mArrowHeadFillColor( Qt::black )
52 , mBoundsBehaviour( 24 )
55 mStartXIdx = mStopPoint.x() < mStartPoint.x();
56 mStartYIdx = mStopPoint.y() < mStartPoint.y();
66 void QgsComposerArrow::init()
69 mPen.setColor( mArrowHeadOutlineColor );
71 mBrush.setColor( mArrowHeadFillColor );
72 createDefaultLineSymbol();
79 void QgsComposerArrow::createDefaultLineSymbol()
83 properties.insert(
"color",
"0,0,0,255" );
84 properties.insert(
"width",
"1" );
85 properties.insert(
"capstyle",
"square" );
91 Q_UNUSED( itemStyle );
93 if ( !painter || !painter->device() )
106 painter->setRenderHint( QPainter::Antialiasing,
true );
114 painter->setBrush( mBrush );
115 painter->setPen( mPen );
119 drawHardcodedMarker( painter, EndMarker );
123 drawSVGMarker( painter, StartMarker, mStartMarkerFile );
124 drawSVGMarker( painter, EndMarker, mEndMarkerFile );
142 if ( evaluatedRect.width() < 0 )
144 mStartXIdx = 1 - mStartXIdx;
146 if ( evaluatedRect.height() < 0 )
148 mStartYIdx = 1 - mStartYIdx;
151 double margin = computeMarkerMargin();
154 QRectF rect = rectangle.united( QRectF( evaluatedRect.x(), evaluatedRect.y(), 2. * margin, 2. * margin ) );
157 double x[2] = {rect.x(), rect.x() + rect.width()};
158 double y[2] = {rect.y(), rect.y() + rect.height()};
160 double xsign = x[mStartXIdx] < x[1 - mStartXIdx] ? 1.0 : -1.0;
161 double ysign = y[mStartYIdx] < y[1 - mStartYIdx] ? 1.0 : -1.0;
163 mStartPoint = QPointF( x[mStartXIdx] + xsign * margin, y[mStartYIdx] + ysign * margin );
164 mStopPoint = QPointF( x[1 - mStartXIdx] - xsign * margin, y[1 - mStartYIdx] - ysign * margin );
169 void QgsComposerArrow::drawLine( QPainter *painter )
176 QPaintDevice* thePaintDevice = painter->device();
179 double dotsPerMM = thePaintDevice->logicalDpiX() / 25.4;
180 painter->scale( 1 / dotsPerMM, 1 / dotsPerMM );
192 line << QPointF( mStartPoint.x() - pos().x(), mStartPoint.y() - pos().y() ) * dotsPerMM
193 << QPointF( mStopPoint.x() - pos().x(), mStopPoint.y() - pos().y() ) * dotsPerMM;
202 void QgsComposerArrow::drawHardcodedMarker( QPainter *p, MarkerType
type )
205 if ( mBoundsBehaviour == 22 )
212 QVector2D dir = QVector2D( mStopPoint - mStartPoint ).normalized();
213 QPointF stop = mStopPoint + ( dir * 0.5 * mArrowHeadWidth ).toPointF();
218 void QgsComposerArrow::drawSVGMarker( QPainter* p, MarkerType
type,
const QString &markerPath )
220 Q_UNUSED( markerPath );
223 double arrowHeadHeight;
224 if (
type == StartMarker )
226 arrowHeadHeight = mStartArrowHeadHeight;
230 arrowHeadHeight = mStopArrowHeadHeight;
232 if ( mArrowHeadWidth <= 0 || arrowHeadHeight <= 0 )
238 QPointF imageFixPoint;
239 imageFixPoint.setX( mArrowHeadWidth / 2.0 );
241 if (
type == StartMarker )
243 canvasPoint = QPointF( mStartPoint.x() - pos().x(), mStartPoint.y() - pos().y() );
244 imageFixPoint.setY( mStartArrowHeadHeight );
248 canvasPoint = QPointF( mStopPoint.x() - pos().x(), mStopPoint.y() - pos().y() );
249 imageFixPoint.setY( 0 );
254 if (
type == StartMarker )
256 if ( mStartMarkerFile.isEmpty() || !r.load( mStartMarkerFile ) )
263 if ( mEndMarkerFile.isEmpty() || !r.load( mEndMarkerFile ) )
270 p->setRenderHint( QPainter::Antialiasing );
271 if ( mBoundsBehaviour == 22 )
276 if (
type == StartMarker )
278 fixPoint.setX( 0 ); fixPoint.setY( arrowHeadHeight / 2.0 );
282 fixPoint.setX( 0 ); fixPoint.setY( -arrowHeadHeight / 2.0 );
284 QPointF rotatedFixPoint;
285 double angleRad = ang / 180 *
M_PI;
286 rotatedFixPoint.setX( fixPoint.x() * cos( angleRad ) + fixPoint.y() * -sin( angleRad ) );
287 rotatedFixPoint.setY( fixPoint.x() * sin( angleRad ) + fixPoint.y() * cos( angleRad ) );
288 p->translate( canvasPoint.x() - rotatedFixPoint.x(), canvasPoint.y() - rotatedFixPoint.y() );
292 p->translate( canvasPoint.x(), canvasPoint.y() );
296 p->translate( -mArrowHeadWidth / 2.0, -arrowHeadHeight / 2.0 );
297 r.render( p, QRectF( 0, 0, mArrowHeadWidth, arrowHeadHeight ) );
306 mStartMarkerFile = svgPath;
307 if ( svgPath.isEmpty() || !r.load( svgPath ) )
309 mStartArrowHeadHeight = 0;
314 QRect viewBox = r.viewBox();
315 mStartArrowHeadHeight = mArrowHeadWidth / viewBox.width() * viewBox.height();
317 adaptItemSceneRect();
323 mEndMarkerFile = svgPath;
324 if ( svgPath.isEmpty() || !r.load( svgPath ) )
326 mStopArrowHeadHeight = 0;
331 QRect viewBox = r.viewBox();
332 mStopArrowHeadHeight = mArrowHeadWidth / viewBox.width() * viewBox.height();
334 adaptItemSceneRect();
341 return mLineSymbol->
color();
353 mArrowHeadOutlineColor = c;
354 mArrowHeadFillColor = c;
356 mBrush.setColor( c );
361 mArrowHeadOutlineColor = color;
362 mPen.setColor( color );
367 mArrowHeadFillColor = color;
368 mBrush.setColor( color );
377 mArrowHeadOutlineWidth = width;
378 mPen.setWidthF( mArrowHeadOutlineWidth );
380 adaptItemSceneRect();
387 return mLineSymbol->
width();
395 mArrowHeadOutlineWidth = width;
396 mPen.setWidthF( mArrowHeadOutlineWidth );
398 adaptItemSceneRect();
404 mLineSymbol = symbol;
409 mArrowHeadWidth = width;
412 adaptItemSceneRect();
415 double QgsComposerArrow::computeMarkerMargin()
const 419 if ( mBoundsBehaviour == 22 )
424 margin = mPen.widthF() / 2.0 + mArrowHeadWidth / 2.0;
428 margin = mPen.widthF() / 2.0;
432 double maxArrowHeight = qMax( mStartArrowHeadHeight, mStopArrowHeadHeight );
433 margin = mPen.widthF() / 2 + qMax( mArrowHeadWidth / 2.0, maxArrowHeight / 2.0 );
440 margin = mPen.widthF() / std::sqrt( 2.0 ) + mArrowHeadWidth / 2.0;
444 margin = mPen.widthF() / std::sqrt( 2.0 );
448 double startMarkerMargin = std::sqrt( 0.25 * ( mStartArrowHeadHeight * mStartArrowHeadHeight + mArrowHeadWidth * mArrowHeadWidth ) );
449 double stopMarkerMargin = std::sqrt( 0.25 * ( mStopArrowHeadHeight * mStopArrowHeadHeight + mArrowHeadWidth * mArrowHeadWidth ) );
450 double markerMargin = qMax( startMarkerMargin, stopMarkerMargin );
451 margin = qMax( mPen.widthF() / std::sqrt( 2.0 ), markerMargin );
457 void QgsComposerArrow::adaptItemSceneRect()
460 QRectF rect = QRectF( qMin( mStartPoint.x(), mStopPoint.x() ), qMin( mStartPoint.y(), mStopPoint.y() ),
461 qAbs( mStopPoint.x() - mStartPoint.x() ), qAbs( mStopPoint.y() - mStartPoint.y() ) );
462 double enlarge = computeMarkerMargin();
463 rect.adjust( -enlarge, -enlarge, enlarge, enlarge );
470 adaptItemSceneRect();
475 QDomElement composerArrowElem = doc.createElement(
"ComposerArrow" );
476 composerArrowElem.setAttribute(
"arrowHeadWidth", QString::number( mArrowHeadWidth ) );
479 composerArrowElem.setAttribute(
"outlineWidth", QString::number( mArrowHeadOutlineWidth ) );
480 composerArrowElem.setAttribute(
"markerMode", mMarkerMode );
481 composerArrowElem.setAttribute(
"startMarkerFile", mStartMarkerFile );
482 composerArrowElem.setAttribute(
"endMarkerFile", mEndMarkerFile );
483 composerArrowElem.setAttribute(
"boundsBehaviourVersion", QString::number( mBoundsBehaviour ) );
485 QDomElement styleElem = doc.createElement(
"lineStyle" );
487 styleElem.appendChild( lineStyleElem );
488 composerArrowElem.appendChild( styleElem );
491 QDomElement startPointElem = doc.createElement(
"StartPoint" );
492 startPointElem.setAttribute(
"x", QString::number( mStartPoint.x() ) );
493 startPointElem.setAttribute(
"y", QString::number( mStartPoint.y() ) );
494 composerArrowElem.appendChild( startPointElem );
497 QDomElement stopPointElem = doc.createElement(
"StopPoint" );
498 stopPointElem.setAttribute(
"x", QString::number( mStopPoint.x() ) );
499 stopPointElem.setAttribute(
"y", QString::number( mStopPoint.y() ) );
500 composerArrowElem.appendChild( stopPointElem );
502 elem.appendChild( composerArrowElem );
503 return _writeXML( composerArrowElem, doc );
508 mArrowHeadWidth = itemElem.attribute(
"arrowHeadWidth",
"2.0" ).toDouble();
511 mArrowHeadOutlineWidth = itemElem.attribute(
"outlineWidth",
"1.0" ).toDouble();
513 setEndMarker( itemElem.attribute(
"endMarkerFile",
"" ) );
516 mBoundsBehaviour = itemElem.attribute(
"boundsBehaviourVersion",
"22" ).toInt();
519 QDomElement styleElem = itemElem.firstChildElement(
"lineStyle" );
520 if ( !styleElem.isNull() )
522 QDomElement lineStyleElem = styleElem.firstChildElement(
"symbol" );
523 if ( !lineStyleElem.isNull() )
526 mLineSymbol = QgsSymbolLayerV2Utils::loadSymbol<QgsLineSymbolV2>( lineStyleElem );
535 properties.insert(
"width", itemElem.attribute(
"outlineWidth",
"1.0" ) );
537 if ( mBoundsBehaviour == 22 )
540 properties.insert(
"capstyle",
"flat" );
544 properties.insert(
"capstyle",
"square" );
551 QDomNodeList arrowColorList = itemElem.elementsByTagName(
"ArrowColor" );
552 if ( arrowColorList.size() > 0 )
554 QDomElement arrowColorElem = arrowColorList.at( 0 ).toElement();
555 red = arrowColorElem.attribute(
"red",
"0" ).toInt();
556 green = arrowColorElem.attribute(
"green",
"0" ).toInt();
557 blue = arrowColorElem.attribute(
"blue",
"0" ).toInt();
558 alpha = arrowColorElem.attribute(
"alpha",
"255" ).toInt();
559 mArrowHeadFillColor = QColor( red, green, blue, alpha );
560 mArrowHeadOutlineColor = QColor( red, green, blue, alpha );
562 properties.insert(
"color", QString(
"%1,%2,%3,%4" ).arg( red ).arg( green ).arg( blue ).arg( alpha ) );
566 mPen.setColor( mArrowHeadOutlineColor );
567 mPen.setWidthF( mArrowHeadOutlineWidth );
568 mBrush.setColor( mArrowHeadFillColor );
572 QDomNodeList composerItemList = itemElem.elementsByTagName(
"ComposerItem" );
573 if ( composerItemList.size() > 0 )
575 QDomElement composerItemElem = composerItemList.at( 0 ).toElement();
580 QDomNodeList startPointList = itemElem.elementsByTagName(
"StartPoint" );
581 if ( startPointList.size() > 0 )
583 QDomElement startPointElem = startPointList.at( 0 ).toElement();
584 mStartPoint.setX( startPointElem.attribute(
"x",
"0.0" ).toDouble() );
585 mStartPoint.setY( startPointElem.attribute(
"y",
"0.0" ).toDouble() );
589 QDomNodeList stopPointList = itemElem.elementsByTagName(
"StopPoint" );
590 if ( stopPointList.size() > 0 )
592 QDomElement stopPointElem = stopPointList.at( 0 ).toElement();
593 mStopPoint.setX( stopPointElem.attribute(
"x",
"0.0" ).toDouble() );
594 mStopPoint.setY( stopPointElem.attribute(
"y",
"0.0" ).toDouble() );
597 mStartXIdx = mStopPoint.x() < mStartPoint.x();
598 mStartYIdx = mStopPoint.y() < mStartPoint.y();
600 adaptItemSceneRect();
QgsComposerArrow(QgsComposition *c)
Constructor.
void setForceVectorOutput(bool force)
Q_DECL_DEPRECATED void setOutlineWidth(double width)
Sets the pen width for drawing the line and arrow head.
virtual int type() const override
Return composer item type.
void setOutputDpi(int dpi)
Set DPI used for conversion between real world units (e.g. mm) and pixels.
void itemChanged()
Emitted when the item changes.
const QgsMapSettings & mapSettings() const
Return setting of QGIS map canvas.
A item that forms part of a map composition.
void setStartMarker(const QString &svgPath)
Sets the marker to draw at the start of the line.
static QColor decodeColor(QString str)
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
void setWidth(double width)
void setArrowHeadOutlineWidth(const double width)
Sets the pen width for the outline of the arrow head.
Q_DECL_DEPRECATED double outlineWidth() const
Returns the pen width for drawing the line and arrow head.
static QString encodeColor(QColor color)
The QgsMapSettings class contains configuration for rendering of the map.
bool _readXML(const QDomElement &itemElem, const QDomDocument &doc)
Reads parameter that are not subclass specific in document.
void setSceneRect(const QRectF &rectangle) override
Modifies position of start and endpoint and calls QgsComposerItem::setSceneRect.
static QDomElement saveSymbol(QString symbolName, QgsSymbolV2 *symbol, QDomDocument &doc)
void setColor(const QColor &color)
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.
Q_DECL_DEPRECATED QColor arrowColor() const
Returns the color for the line and arrow head.
void startRender(QgsRenderContext &context, const QgsFields *fields=0)
virtual void drawSelectionBoxes(QPainter *p)
Draws additional graphics on selected items.
static QgsLineSymbolV2 * createSimple(const QgsStringMap &properties)
Create a line symbol with one symbol layer: SimpleLine with specified properties. ...
void renderPolyline(const QPolygonF &points, const QgsFeature *f, QgsRenderContext &context, int layer=-1, bool selected=false)
void setPainter(QPainter *p)
void setArrowHeadOutlineColor(const QColor &color)
Sets the color used to draw the outline around the arrow head.
void setLineSymbol(QgsLineSymbolV2 *symbol)
Sets the line symbol used for drawing the line portion of the arrow.
void setMarkerMode(MarkerMode mode)
Sets the marker mode, which controls how the arrow endpoints are drawn.
Q_DECL_DEPRECATED void setArrowColor(const QColor &c)
Sets the color for the line and arrow head.
bool shouldDrawItem() const
Returns whether the item should be drawn in the current context.
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.
QgsComposition * mComposition
QRectF evalItemRect(const QRectF &newRect, const bool resizeOnly=false)
Evaluates an item's bounding rect to consider data defined position and size of item and reference po...
Contains information about the context of a rendering operation.
void stopRender(QgsRenderContext &context)
bool _writeXML(QDomElement &itemElem, QDomDocument &doc) const
Writes parameter that are not subclass specific in document.
static QgsRenderContext fromMapSettings(const QgsMapSettings &mapSettings)
create initialized QgsRenderContext instance from given QgsMapSettings
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...
bool readXML(const QDomElement &itemElem, const QDomDocument &doc) override
Sets state from DOM document.
static double angle(const QPointF &p1, const QPointF &p2)
Calculates the angle of the line from p1 to p2 (counter clockwise, starting from a line from north to...
bool writeXML(QDomElement &elem, QDomDocument &doc) const override
Stores state in DOM element.
void paint(QPainter *painter, const QStyleOptionGraphicsItem *itemStyle, QWidget *pWidget) override
Reimplementation of QCanvasItem::paint - draw on canvas.
void setEndMarker(const QString &svgPath)
Sets the marker to draw at the end of the line.