QGIS API Documentation  3.14.0-Pi (9f7028fd23)
qgslayoutitemmarker.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgslayoutitemmarker.cpp
3  ---------------------
4  begin : April 2020
5  copyright : (C) 2020 by Nyall Dawson
6  email : nyall dot dawson at gmail dot com
7  ***************************************************************************/
8 /***************************************************************************
9  * *
10  * This program is free software; you can redistribute it and/or modify *
11  * it under the terms of the GNU General Public License as published by *
12  * the Free Software Foundation; either version 2 of the License, or *
13  * (at your option) any later version. *
14  * *
15  ***************************************************************************/
16 
17 #include "qgslayoutitemmarker.h"
18 #include "qgslayout.h"
19 #include "qgslayoututils.h"
20 #include "qgssymbollayerutils.h"
21 #include "qgslayoutmodel.h"
22 #include "qgsstyleentityvisitor.h"
23 #include "qgslayoutitemmap.h"
24 
25 #include <QPainter>
26 
28  : QgsLayoutItem( layout )
29  , mNorthArrowHandler( new QgsLayoutNorthArrowHandler( this ) )
30 {
31  setBackgroundEnabled( false );
32  setFrameEnabled( false );
34  QgsStringMap properties;
35  properties.insert( QStringLiteral( "size" ), QStringLiteral( "4" ) );
36  mShapeStyleSymbol.reset( QgsMarkerSymbol::createSimple( properties ) );
37  refreshSymbol();
38 
39  connect( this, &QgsLayoutItemMarker::sizePositionChanged, this, [ = ]
40  {
41  updateBoundingRect();
42  update();
43  } );
44 
45  connect( mNorthArrowHandler, &QgsLayoutNorthArrowHandler::arrowRotationChanged, this, &QgsLayoutItemMarker::northArrowRotationChanged );
46 }
47 
49 
51 {
52  return new QgsLayoutItemMarker( layout );
53 }
54 
56 {
58 }
59 
61 {
62  return QgsApplication::getThemeIcon( QStringLiteral( "/mLayoutItemMarker.svg" ) );
63 }
64 
65 void QgsLayoutItemMarker::refreshSymbol()
66 {
67  if ( layout() )
68  {
69  QgsRenderContext rc = QgsLayoutUtils::createRenderContextForLayout( layout(), nullptr, layout()->renderContext().dpi() );
70 
71  std::unique_ptr< QgsMarkerSymbol > sym( mShapeStyleSymbol->clone() );
72  sym->setAngle( sym->angle() + mNorthArrowRotation );
73  sym->startRender( rc );
74  QRectF bounds = sym->bounds( QPointF( 0, 0 ), rc );
75  sym->stopRender( rc );
76  mPoint = QPointF( -bounds.left() * 25.4 / layout()->renderContext().dpi(),
77  -bounds.top() * 25.4 / layout()->renderContext().dpi() );
78  bounds.translate( mPoint );
79 
80  QgsLayoutSize newSizeMm = QgsLayoutSize( bounds.size() * 25.4 / layout()->renderContext().dpi(), QgsUnitTypes::LayoutMillimeters );
81  mFixedSize = mLayout->renderContext().measurementConverter().convert( newSizeMm, sizeWithUnits().units() );
82 
83  attemptResize( mFixedSize );
84  }
85 
86  updateBoundingRect();
87 
88  update();
89  emit frameChanged();
90 }
91 
92 void QgsLayoutItemMarker::updateBoundingRect()
93 {
94  QRectF rectangle = rect();
95 
96  // add a bit, to account for antialiasing on stroke and miter effects on stroke
97  rectangle.adjust( -5, -5, 5, 5 );
98  if ( rectangle != mCurrentRectangle )
99  {
100  prepareGeometryChange();
101  mCurrentRectangle = rectangle;
102  }
103 }
104 
105 void QgsLayoutItemMarker::northArrowRotationChanged( double rotation )
106 {
107  mNorthArrowRotation = rotation;
108  refreshSymbol();
109 }
110 
112 {
113  if ( !symbol )
114  return;
115 
116  mShapeStyleSymbol.reset( symbol );
117  refreshSymbol();
118 }
119 
121 {
122  return mShapeStyleSymbol.get();
123 }
124 
126 {
127  mNorthArrowHandler->setLinkedMap( map );
128 }
129 
131 {
132  return mNorthArrowHandler->linkedMap();
133 }
134 
136 {
137  return mNorthArrowHandler->northMode();
138 
139 }
140 
142 {
143  mNorthArrowHandler->setNorthMode( mode );
144 
145 }
146 
148 {
149  return mNorthArrowHandler->northOffset();
150 }
151 
153 {
154  mNorthArrowHandler->setNorthOffset( offset );
155 }
156 
158 {
159  return mCurrentRectangle;
160 }
161 
163 {
164  return mFixedSize;
165 }
166 
168 {
169  if ( mShapeStyleSymbol )
170  {
171  QgsStyleSymbolEntity entity( mShapeStyleSymbol.get() );
172  if ( !visitor->visit( QgsStyleEntityVisitorInterface::StyleLeaf( &entity, uuid(), displayName() ) ) )
173  return false;
174  }
175 
176  return true;
177 }
178 
180 {
181  QPainter *painter = context.renderContext().painter();
182  painter->setPen( Qt::NoPen );
183  painter->setBrush( Qt::NoBrush );
184 
186 
187  QPointF shapePoint = mPoint * scale;
188 
189  std::unique_ptr< QgsMarkerSymbol > sym( mShapeStyleSymbol->clone() );
190  sym->setAngle( sym->angle() + mNorthArrowRotation );
191  sym->startRender( context.renderContext() );
192  sym->renderPoint( shapePoint, nullptr, context.renderContext() );
193  sym->stopRender( context.renderContext() );
194 }
195 
196 bool QgsLayoutItemMarker::writePropertiesToElement( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const
197 {
198  QDomElement shapeStyleElem = QgsSymbolLayerUtils::saveSymbol( QString(), mShapeStyleSymbol.get(), document, context );
199  element.appendChild( shapeStyleElem );
200 
201  //rotation
202  element.setAttribute( QStringLiteral( "arrowRotation" ), QString::number( mNorthArrowRotation ) );
203  if ( !mNorthArrowHandler->linkedMap() )
204  {
205  element.setAttribute( QStringLiteral( "mapUuid" ), QString() );
206  }
207  else
208  {
209  element.setAttribute( QStringLiteral( "mapUuid" ), mNorthArrowHandler->linkedMap()->uuid() );
210  }
211  element.setAttribute( QStringLiteral( "northMode" ), mNorthArrowHandler->northMode() );
212  element.setAttribute( QStringLiteral( "northOffset" ), mNorthArrowHandler->northOffset() );
213 
214  return true;
215 }
216 
217 bool QgsLayoutItemMarker::readPropertiesFromElement( const QDomElement &element, const QDomDocument &, const QgsReadWriteContext &context )
218 {
219  QDomElement shapeStyleSymbolElem = element.firstChildElement( QStringLiteral( "symbol" ) );
220  if ( !shapeStyleSymbolElem.isNull() )
221  {
222  mShapeStyleSymbol.reset( QgsSymbolLayerUtils::loadSymbol<QgsMarkerSymbol>( shapeStyleSymbolElem, context ) );
223  }
224 
225  //picture rotation
226  if ( !qgsDoubleNear( element.attribute( QStringLiteral( "arrowRotation" ), QStringLiteral( "0" ) ).toDouble(), 0.0 ) )
227  {
228  mNorthArrowRotation = element.attribute( QStringLiteral( "arrowRotation" ), QStringLiteral( "0" ) ).toDouble();
229  }
230 
231  //rotation map
232  mNorthArrowHandler->setNorthMode( static_cast< QgsLayoutNorthArrowHandler::NorthMode >( element.attribute( QStringLiteral( "northMode" ), QStringLiteral( "0" ) ).toInt() ) );
233  mNorthArrowHandler->setNorthOffset( element.attribute( QStringLiteral( "northOffset" ), QStringLiteral( "0" ) ).toDouble() );
234 
235  mNorthArrowHandler->setLinkedMap( nullptr );
236  mRotationMapUuid = element.attribute( QStringLiteral( "mapUuid" ) );
237 
238  refreshSymbol();
239 
240  return true;
241 }
242 
244 {
245  if ( !mLayout || mRotationMapUuid.isEmpty() )
246  {
247  mNorthArrowHandler->setLinkedMap( nullptr );
248  }
249  else
250  {
251  mNorthArrowHandler->setLinkedMap( qobject_cast< QgsLayoutItemMap * >( mLayout->itemByUuid( mRotationMapUuid, true ) ) );
252  }
253  emit changed();
254 }
QgsLayoutObject::layout
const QgsLayout * layout() const
Returns the layout the object is attached to.
Definition: qgslayoutobject.cpp:118
QgsRenderContext::convertToPainterUnits
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale()) const
Converts a size from the specified units to painter units (pixels).
Definition: qgsrendercontext.cpp:287
QgsLayoutItemMarker
A layout item for showing marker symbols.
Definition: qgslayoutitemmarker.h:33
QgsApplication::getThemeIcon
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
Definition: qgsapplication.cpp:605
QgsLayoutItem::sizePositionChanged
void sizePositionChanged()
Emitted when the item's size or position changes.
QgsLayoutItem::setFrameEnabled
virtual void setFrameEnabled(bool drawFrame)
Sets whether this item has a frame drawn around it or not.
Definition: qgslayoutitem.cpp:834
QgsReadWriteContext
Definition: qgsreadwritecontext.h:34
QgsLayoutItemMarker::readPropertiesFromElement
bool readPropertiesFromElement(const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context) override
Sets item state from a DOM element.
Definition: qgslayoutitemmarker.cpp:217
QgsLayoutItem::Middle
@ Middle
Center of item.
Definition: qgslayoutitem.h:207
QgsStyleSymbolEntity
Definition: qgsstyle.h:1134
QgsLayoutNorthArrowHandler::linkedMap
QgsLayoutItemMap * linkedMap() const
Returns the linked rotation map, if set.
Definition: qgslayoutnortharrowhandler.cpp:107
QgsMarkerSymbol::createSimple
static QgsMarkerSymbol * createSimple(const QgsStringMap &properties)
Create a marker symbol with one symbol layer: SimpleMarker with specified properties.
Definition: qgssymbol.cpp:1418
qgssymbollayerutils.h
QgsLayoutItemMarker::~QgsLayoutItemMarker
~QgsLayoutItemMarker() override
QgsLayoutItemRenderContext
Definition: qgslayoutitem.h:44
QgsRenderContext
Definition: qgsrendercontext.h:57
QgsStyleEntityVisitorInterface
Definition: qgsstyleentityvisitor.h:33
QgsLayoutItemMarker::setNorthOffset
void setNorthOffset(double offset)
Sets the offset added to the marker's rotation from a map's North.
Definition: qgslayoutitemmarker.cpp:152
QgsUnitTypes::RenderMillimeters
@ RenderMillimeters
Millimeters.
Definition: qgsunittypes.h:168
QgsLayoutItemMarker::northMode
QgsLayoutNorthArrowHandler::NorthMode northMode() const
Returns the mode used to align the marker to a map's North.
Definition: qgslayoutitemmarker.cpp:135
QgsLayoutObject::changed
void changed()
Emitted when the object's properties change.
QgsLayoutItem::sizeWithUnits
QgsLayoutSize sizeWithUnits() const
Returns the item's current size, including units.
Definition: qgslayoutitem.h:668
QgsStyleEntityVisitorInterface::StyleLeaf
Contains information relating to the style entity currently being visited.
Definition: qgsstyleentityvisitor.h:60
QgsLayoutItemMarker::linkedMap
QgsLayoutItemMap * linkedMap() const
Returns the linked rotation map, if set.
Definition: qgslayoutitemmarker.cpp:130
QgsLayoutItemMarker::northOffset
double northOffset() const
Returns the offset added to the marker's rotation from a map's North.
Definition: qgslayoutitemmarker.cpp:147
QgsLayoutItemMarker::writePropertiesToElement
bool writePropertiesToElement(QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context) const override
Stores item state within an XML DOM element.
Definition: qgslayoutitemmarker.cpp:196
QgsLayoutItemMarker::accept
bool accept(QgsStyleEntityVisitorInterface *visitor) const override
Accepts the specified style entity visitor, causing it to visit all style entities associated with th...
Definition: qgslayoutitemmarker.cpp:167
qgslayoututils.h
QgsLayoutNorthArrowHandler::northMode
NorthMode northMode() const
Returns the mode used to calculate the arrow rotation.
Definition: qgslayoutnortharrowhandler.h:74
QgsLayoutUtils::createRenderContextForLayout
static QgsRenderContext createRenderContextForLayout(QgsLayout *layout, QPainter *painter, double dpi=-1)
Creates a render context suitable for the specified layout and painter destination.
Definition: qgslayoututils.cpp:138
QgsLayoutItemMarker::create
static QgsLayoutItemMarker * create(QgsLayout *layout)
Returns a new marker item for the specified layout.
Definition: qgslayoutitemmarker.cpp:50
QgsLayoutItemMarker::boundingRect
QRectF boundingRect() const override
Definition: qgslayoutitemmarker.cpp:157
QgsLayoutItemMarker::setLinkedMap
void setLinkedMap(QgsLayoutItemMap *map)
Sets the map object for rotation.
Definition: qgslayoutitemmarker.cpp:125
QgsMarkerSymbol
Definition: qgssymbol.h:917
qgsDoubleNear
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:315
QgsLayoutItem::frameChanged
void frameChanged()
Emitted if the item's frame style changes.
QgsLayoutNorthArrowHandler::setNorthOffset
void setNorthOffset(double offset)
Sets the offset added to the arrows's rotation from a map's North.
Definition: qgslayoutnortharrowhandler.cpp:118
QgsLayoutItem::setBackgroundEnabled
void setBackgroundEnabled(bool drawBackground)
Sets whether this item has a background drawn under it or not.
Definition: qgslayoutitem.cpp:887
QgsLayoutItemMarker::symbol
QgsMarkerSymbol * symbol()
Returns the marker symbol used to draw the shape.
Definition: qgslayoutitemmarker.cpp:120
QgsLayoutItemMarker::fixedSize
QgsLayoutSize fixedSize() const override
Returns the fixed size of the item, if applicable, or an empty size if item can be freely resized.
Definition: qgslayoutitemmarker.cpp:162
QgsLayoutNorthArrowHandler::setLinkedMap
void setLinkedMap(QgsLayoutItemMap *map)
Sets the linked map item.
Definition: qgslayoutnortharrowhandler.cpp:81
QgsLayoutNorthArrowHandler::arrowRotationChanged
void arrowRotationChanged(double newRotation)
Emitted on arrow rotation change.
QgsLayoutItem
Base class for graphical items within a QgsLayout.
Definition: qgslayoutitem.h:112
QgsLayoutNorthArrowHandler::setNorthMode
void setNorthMode(NorthMode mode)
Sets the mode used to calculate the arrow rotation.
Definition: qgslayoutnortharrowhandler.cpp:112
qgslayoutitemmarker.h
qgslayout.h
QgsLayoutNorthArrowHandler
Definition: qgslayoutnortharrowhandler.h:32
QgsLayoutNorthArrowHandler::NorthMode
NorthMode
Method for syncing rotation to a map's North direction.
Definition: qgslayoutnortharrowhandler.h:38
QgsLayoutItemMap
Layout graphical items for displaying a map.
Definition: qgslayoutitemmap.h:39
QgsLayoutItemMarker::type
int type() const override
Definition: qgslayoutitemmarker.cpp:55
QgsLayoutItemMarker::setNorthMode
void setNorthMode(QgsLayoutNorthArrowHandler::NorthMode mode)
Sets the mode used to align the marker to a map's North.
Definition: qgslayoutitemmarker.cpp:141
QgsLayoutItem::setReferencePoint
void setReferencePoint(ReferencePoint point)
Sets the reference point for positioning of the layout item.
Definition: qgslayoutitem.cpp:418
QgsLayoutItemRenderContext::renderContext
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
Definition: qgslayoutitem.h:72
QgsLayoutItem::uuid
virtual QString uuid() const
Returns the item identification string.
Definition: qgslayoutitem.h:340
QgsStringMap
QMap< QString, QString > QgsStringMap
Definition: qgis.h:714
QgsLayoutObject::mLayout
QPointer< QgsLayout > mLayout
Definition: qgslayoutobject.h:335
QgsLayoutItemMarker::QgsLayoutItemMarker
QgsLayoutItemMarker(QgsLayout *layout)
Constructor for QgsLayoutItemMarker, with the specified parent layout.
Definition: qgslayoutitemmarker.cpp:27
QgsLayout
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
Definition: qgslayout.h:49
QgsLayoutItem::displayName
virtual QString displayName() const
Gets item display name.
Definition: qgslayoutitem.cpp:107
QgsLayoutItemRegistry::LayoutMarker
@ LayoutMarker
Marker item.
Definition: qgslayoutitemregistry.h:339
QgsLayoutItemMarker::draw
void draw(QgsLayoutItemRenderContext &context) override
Draws the item's contents using the specified item render context.
Definition: qgslayoutitemmarker.cpp:179
QgsLayoutItemMarker::setSymbol
void setSymbol(QgsMarkerSymbol *symbol)
Sets the marker symbol used to draw the shape.
Definition: qgslayoutitemmarker.cpp:111
QgsLayoutItem::attemptResize
virtual void attemptResize(const QgsLayoutSize &size, bool includesFrame=false)
Attempts to resize the item to a specified target size.
Definition: qgslayoutitem.cpp:432
QgsStyleEntityVisitorInterface::visit
virtual bool visit(const QgsStyleEntityVisitorInterface::StyleLeaf &entity)
Called when the visitor will visit a style entity.
Definition: qgsstyleentityvisitor.h:153
QgsLayoutNorthArrowHandler::northOffset
double northOffset() const
Returns the offset added to the arrows's rotation from a map's North.
Definition: qgslayoutnortharrowhandler.h:88
QgsLayoutSize
This class provides a method of storing sizes, consisting of a width and height, for use in QGIS layo...
Definition: qgslayoutsize.h:40
QgsUnitTypes::LayoutMillimeters
@ LayoutMillimeters
Millimeters.
Definition: qgsunittypes.h:182
QgsLayoutItemMarker::finalizeRestoreFromXml
void finalizeRestoreFromXml() override
Called after all pending items have been restored from XML.
Definition: qgslayoutitemmarker.cpp:243
QgsRenderContext::painter
QPainter * painter()
Returns the destination QPainter for the render operation.
Definition: qgsrendercontext.h:174
QgsLayoutItemMarker::icon
QIcon icon() const override
Returns the item's icon.
Definition: qgslayoutitemmarker.cpp:60
qgslayoutmodel.h
QgsSymbolLayerUtils::saveSymbol
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
Definition: qgssymbollayerutils.cpp:1180
qgsstyleentityvisitor.h
qgslayoutitemmap.h