QGIS API Documentation 3.99.0-Master (2fe06baccd8)
Loading...
Searching...
No Matches
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
19#include "qgslayout.h"
20#include "qgslayoutitemmap.h"
22#include "qgslayoututils.h"
23#include "qgsmarkersymbol.h"
25#include "qgssymbollayerutils.h"
26
27#include <QPainter>
28
29#include "moc_qgslayoutitemmarker.cpp"
30
33 , mNorthArrowHandler( new QgsLayoutNorthArrowHandler( this ) )
34{
35 setBackgroundEnabled( false );
36 setFrameEnabled( false );
38 QVariantMap properties;
39 properties.insert( QStringLiteral( "size" ), QStringLiteral( "4" ) );
40 mShapeStyleSymbol = QgsMarkerSymbol::createSimple( properties );
41 refreshSymbol();
42
43 connect( this, &QgsLayoutItemMarker::sizePositionChanged, this, [this]
44 {
45 updateBoundingRect();
46 update();
47 } );
48
49 connect( mNorthArrowHandler, &QgsLayoutNorthArrowHandler::arrowRotationChanged, this, &QgsLayoutItemMarker::northArrowRotationChanged );
50}
51
53
58
63
65{
66 return QgsApplication::getThemeIcon( QStringLiteral( "/mLayoutItemMarker.svg" ) );
67}
68
69void QgsLayoutItemMarker::refreshSymbol()
70{
71 if ( auto *lLayout = layout() )
72 {
73 QgsRenderContext rc = QgsLayoutUtils::createRenderContextForLayout( lLayout, nullptr, lLayout->renderContext().dpi() );
74
75 std::unique_ptr< QgsMarkerSymbol > sym( mShapeStyleSymbol->clone() );
76 sym->setAngle( sym->angle() + mNorthArrowRotation );
77 sym->startRender( rc );
78 QRectF bounds = sym->bounds( QPointF( 0, 0 ), rc );
79 sym->stopRender( rc );
80 mPoint = QPointF( -bounds.left() * 25.4 / lLayout->renderContext().dpi(),
81 -bounds.top() * 25.4 / lLayout->renderContext().dpi() );
82 bounds.translate( mPoint );
83
84 const QgsLayoutSize newSizeMm = QgsLayoutSize( bounds.size() * 25.4 / lLayout->renderContext().dpi(), Qgis::LayoutUnit::Millimeters );
85 mFixedSize = mLayout->renderContext().measurementConverter().convert( newSizeMm, sizeWithUnits().units() );
86
87 attemptResize( mFixedSize );
88 }
89
90 updateBoundingRect();
91
92 update();
93 emit frameChanged();
94}
95
96void QgsLayoutItemMarker::updateBoundingRect()
97{
98 QRectF rectangle = rect();
99
100 // add a bit, to account for antialiasing on stroke and miter effects on stroke
101 rectangle.adjust( -5, -5, 5, 5 );
102 if ( rectangle != mCurrentRectangle )
103 {
104 prepareGeometryChange();
105 mCurrentRectangle = rectangle;
106 }
107}
108
109void QgsLayoutItemMarker::northArrowRotationChanged( double rotation )
110{
111 mNorthArrowRotation = rotation;
112 refreshSymbol();
113}
114
116{
117 if ( !symbol )
118 return;
119
120 mShapeStyleSymbol.reset( symbol );
121 refreshSymbol();
122}
123
125{
126 return mShapeStyleSymbol.get();
127}
128
130{
131 mNorthArrowHandler->setLinkedMap( map );
132}
133
135{
136 return mNorthArrowHandler->linkedMap();
137}
138
140{
141 return mNorthArrowHandler->northMode();
142
143}
144
146{
147 mNorthArrowHandler->setNorthMode( mode );
148
149}
150
152{
153 return mNorthArrowHandler->northOffset();
154}
155
157{
158 mNorthArrowHandler->setNorthOffset( offset );
159}
160
162{
163 return mCurrentRectangle;
164}
165
167{
168 return mFixedSize;
169}
170
172{
173 if ( mShapeStyleSymbol )
174 {
175 QgsStyleSymbolEntity entity( mShapeStyleSymbol.get() );
176 if ( !visitor->visit( QgsStyleEntityVisitorInterface::StyleLeaf( &entity, uuid(), displayName() ) ) )
177 return false;
178 }
179
180 return true;
181}
182
184{
185 QPainter *painter = context.renderContext().painter();
186 painter->setPen( Qt::NoPen );
187 painter->setBrush( Qt::NoBrush );
188
189 const double scale = context.renderContext().convertToPainterUnits( 1, Qgis::RenderUnit::Millimeters );
190
191 const QPointF shapePoint = mPoint * scale;
192
193 std::unique_ptr< QgsMarkerSymbol > sym( mShapeStyleSymbol->clone() );
194 sym->setAngle( sym->angle() + mNorthArrowRotation );
195 sym->startRender( context.renderContext() );
196 sym->renderPoint( shapePoint, nullptr, context.renderContext() );
197 sym->stopRender( context.renderContext() );
198}
199
200bool QgsLayoutItemMarker::writePropertiesToElement( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const
201{
202 const QDomElement shapeStyleElem = QgsSymbolLayerUtils::saveSymbol( QString(), mShapeStyleSymbol.get(), document, context );
203 element.appendChild( shapeStyleElem );
204
205 //rotation
206 element.setAttribute( QStringLiteral( "arrowRotation" ), QString::number( mNorthArrowRotation ) );
207 if ( !mNorthArrowHandler->linkedMap() )
208 {
209 element.setAttribute( QStringLiteral( "mapUuid" ), QString() );
210 }
211 else
212 {
213 element.setAttribute( QStringLiteral( "mapUuid" ), mNorthArrowHandler->linkedMap()->uuid() );
214 }
215 element.setAttribute( QStringLiteral( "northMode" ), mNorthArrowHandler->northMode() );
216 element.setAttribute( QStringLiteral( "northOffset" ), mNorthArrowHandler->northOffset() );
217
218 return true;
219}
220
221bool QgsLayoutItemMarker::readPropertiesFromElement( const QDomElement &element, const QDomDocument &, const QgsReadWriteContext &context )
222{
223 const QDomElement shapeStyleSymbolElem = element.firstChildElement( QStringLiteral( "symbol" ) );
224 if ( !shapeStyleSymbolElem.isNull() )
225 {
226 mShapeStyleSymbol = QgsSymbolLayerUtils::loadSymbol<QgsMarkerSymbol>( shapeStyleSymbolElem, context );
227 }
228
229 //picture rotation
230 if ( !qgsDoubleNear( element.attribute( QStringLiteral( "arrowRotation" ), QStringLiteral( "0" ) ).toDouble(), 0.0 ) )
231 {
232 mNorthArrowRotation = element.attribute( QStringLiteral( "arrowRotation" ), QStringLiteral( "0" ) ).toDouble();
233 }
234
235 //rotation map
236 mNorthArrowHandler->setNorthMode( static_cast< QgsLayoutNorthArrowHandler::NorthMode >( element.attribute( QStringLiteral( "northMode" ), QStringLiteral( "0" ) ).toInt() ) );
237 mNorthArrowHandler->setNorthOffset( element.attribute( QStringLiteral( "northOffset" ), QStringLiteral( "0" ) ).toDouble() );
238
239 mNorthArrowHandler->setLinkedMap( nullptr );
240 mRotationMapUuid = element.attribute( QStringLiteral( "mapUuid" ) );
241
242 refreshSymbol();
243
244 return true;
245}
246
248{
249 if ( !mLayout || mRotationMapUuid.isEmpty() )
250 {
251 mNorthArrowHandler->setLinkedMap( nullptr );
252 }
253 else
254 {
255 mNorthArrowHandler->setLinkedMap( qobject_cast< QgsLayoutItemMap * >( mLayout->itemByUuid( mRotationMapUuid, true ) ) );
256 }
257 emit changed();
258}
@ Millimeters
Millimeters.
Definition qgis.h:5204
@ Millimeters
Millimeters.
Definition qgis.h:5184
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
~QgsLayoutItemMarker() override
double northOffset() const
Returns the offset added to the marker's rotation from a map's North.
void draw(QgsLayoutItemRenderContext &context) override
Draws the item's contents using the specified item render context.
bool readPropertiesFromElement(const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context) override
Sets item state from a DOM element.
bool writePropertiesToElement(QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context) const override
Stores item state within an XML DOM element.
QIcon icon() const override
Returns the item's icon.
void setLinkedMap(QgsLayoutItemMap *map)
Sets the map object for rotation.
QgsLayoutNorthArrowHandler::NorthMode northMode() const
Returns the mode used to align the marker to a map's North.
QgsLayoutItemMarker(QgsLayout *layout)
Constructor for QgsLayoutItemMarker, with the specified parent layout.
QgsLayoutSize fixedSize() const override
Returns the fixed size of the item, if applicable, or an empty size if item can be freely resized.
void setNorthOffset(double offset)
Sets the offset added to the marker's rotation from a map's North.
int type() const override
void setNorthMode(QgsLayoutNorthArrowHandler::NorthMode mode)
Sets the mode used to align the marker to a map's North.
static QgsLayoutItemMarker * create(QgsLayout *layout)
Returns a new marker item for the specified layout.
QgsLayoutItemMap * linkedMap() const
Returns the linked rotation map, if set.
void setSymbol(QgsMarkerSymbol *symbol)
Sets the marker symbol used to draw the shape.
void finalizeRestoreFromXml() override
Called after all pending items have been restored from XML.
QRectF boundingRect() const override
QgsMarkerSymbol * symbol()
Returns the marker symbol used to draw the shape.
bool accept(QgsStyleEntityVisitorInterface *visitor) const override
Accepts the specified style entity visitor, causing it to visit all style entities associated with th...
Contains settings and helpers relating to a render of a QgsLayoutItem.
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
friend class QgsLayout
QgsLayoutSize sizeWithUnits() const
Returns the item's current size, including units.
QgsLayoutItem(QgsLayout *layout, bool manageZValue=true)
Constructor for QgsLayoutItem, with the specified parent layout.
@ Middle
Center of item.
friend class QgsLayoutItemMap
virtual void setFrameEnabled(bool drawFrame)
Sets whether this item has a frame drawn around it or not.
virtual QString displayName() const
Gets item display name.
virtual void attemptResize(const QgsLayoutSize &size, bool includesFrame=false)
Attempts to resize the item to a specified target size.
void sizePositionChanged()
Emitted when the item's size or position changes.
virtual QString uuid() const
Returns the item identification string.
void frameChanged()
Emitted if the item's frame style changes.
void setReferencePoint(ReferencePoint point)
Sets the reference point for positioning of the layout item.
void setBackgroundEnabled(bool drawBackground)
Sets whether this item has a background drawn under it or not.
An object which handles north-arrow type behavior for layout items.
void arrowRotationChanged(double newRotation)
Emitted on arrow rotation change.
NorthMode
Method for syncing rotation to a map's North direction.
const QgsLayout * layout() const
Returns the layout the object is attached to.
void changed()
Emitted when the object's properties change.
QPointer< QgsLayout > mLayout
Provides a method of storing sizes, consisting of a width and height, for use in QGIS layouts.
static QgsRenderContext createRenderContextForLayout(QgsLayout *layout, QPainter *painter, double dpi=-1)
Creates a render context suitable for the specified layout and painter destination.
A marker symbol type, for rendering Point and MultiPoint geometries.
static std::unique_ptr< QgsMarkerSymbol > createSimple(const QVariantMap &properties)
Create a marker symbol with one symbol layer: SimpleMarker with specified properties.
A container for the context for various read/write operations on objects.
Contains information about the context of a rendering operation.
double convertToPainterUnits(double size, Qgis::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
QPainter * painter()
Returns the destination QPainter for the render operation.
An interface for classes which can visit style entity (e.g.
virtual bool visit(const QgsStyleEntityVisitorInterface::StyleLeaf &entity)
Called when the visitor will visit a style entity.
A symbol entity for QgsStyle databases.
Definition qgsstyle.h:1397
static std::unique_ptr< QgsSymbol > loadSymbol(const QDomElement &element, const QgsReadWriteContext &context)
Attempts to load a symbol from a DOM element.
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
Definition qgis.h:6607
Contains information relating to the style entity currently being visited.