33#include "moc_qgsannotationmanager.cpp"
35using namespace Qt::StringLiterals;
54 if ( mAnnotations.contains( annotation ) )
57 mAnnotations << annotation;
59 mProject->setDirty(
true );
68 if ( !mAnnotations.contains( annotation ) )
72 mAnnotations.removeAll( annotation );
75 mProject->setDirty(
true );
81 for (
auto *a : std::as_const( mAnnotations ) )
94 QList<QgsAnnotation *> results;
95 for (
const auto *a : std::as_const( mAnnotations ) )
97 results << a->clone();
109 return readXmlPrivate( element, context, layer, transformContext );
118 auto createAnnotationFromElement = [
this, &context, layer, &transformContext](
const QDomElement & element )
120 std::unique_ptr< QgsAnnotation > annotation( createAnnotationFromXml( element, context ) );
126 std::unique_ptr< QgsAnnotationItem > annotationItem = convertToAnnotationItem( annotation.get(), layer, transformContext );
127 if ( annotationItem )
129 layer->
addItem( annotationItem.release() );
143 QDomElement annotationsElem = element.firstChildElement( u
"Annotations"_s );
145 QDomElement annotationElement = annotationsElem.firstChildElement( u
"Annotation"_s );
146 while ( ! annotationElement.isNull() )
148 createAnnotationFromElement( annotationElement );
149 annotationElement = annotationElement.nextSiblingElement( u
"Annotation"_s );
153 if ( annotationElement.isNull() )
155 QDomNodeList oldItemList = element.elementsByTagName( u
"TextAnnotationItem"_s );
156 for (
int i = 0; i < oldItemList.size(); ++i )
158 createAnnotationFromElement( oldItemList.at( i ).toElement() );
160 oldItemList = element.elementsByTagName( u
"FormAnnotationItem"_s );
161 for (
int i = 0; i < oldItemList.size(); ++i )
163 createAnnotationFromElement( oldItemList.at( i ).toElement() );
165 oldItemList = element.elementsByTagName( u
"HtmlAnnotationItem"_s );
166 for (
int i = 0; i < oldItemList.size(); ++i )
168 createAnnotationFromElement( oldItemList.at( i ).toElement() );
170 oldItemList = element.elementsByTagName( u
"SVGAnnotationItem"_s );
171 for (
int i = 0; i < oldItemList.size(); ++i )
173 createAnnotationFromElement( oldItemList.at( i ).toElement() );
182 auto setCommonProperties = [layer, &transformContext](
const QgsAnnotation * source, QgsAnnotationItem * destination ) ->
bool
184 destination->setEnabled( source->isVisible() );
185 if ( source->hasFixedMapPosition() )
187 QgsPointXY mapPosition = source->mapPosition();
188 QgsCoordinateTransform transform( source->mapPositionCrs(), layer->
crs(), transformContext );
191 mapPosition = transform.transform( mapPosition );
193 catch ( QgsCsException & )
195 QgsDebugError( u
"Error transforming annotation position"_s );
201 auto callout = std::make_unique< QgsBalloonCallout >();
202 if ( QgsFillSymbol *fill = source->fillSymbol() )
203 callout->setFillSymbol( fill->clone() );
205 if ( QgsMarkerSymbol *marker = source->markerSymbol() )
206 callout->setMarkerSymbol( marker->clone() );
207 callout->setMargins( source->contentsMargin() );
209 destination->setCallout( callout.release() );
212 if ( source->mapLayer() )
218 if (
const QgsSvgAnnotation *svg =
dynamic_cast< const QgsSvgAnnotation *
>( annotation ) )
220 QgsPointXY mapPosition = svg->mapPosition();
221 QgsCoordinateTransform transform( svg->mapPositionCrs(), layer->
crs(), transformContext );
224 transform.transform( mapPosition );
226 catch ( QgsCsException & )
228 QgsDebugError( u
"Error transforming annotation position"_s );
233 if ( !setCommonProperties( annotation, item.get() ) )
236 const QgsMargins margins = svg->contentsMargin();
237 item->setFixedSize( QSizeF( svg->frameSizeMm().width() - margins.
left() - margins.
right(),
238 svg->frameSizeMm().height() - margins.
top() - margins.
bottom() ) );
241 if ( svg->hasFixedMapPosition() )
245 item->setOffsetFromCallout( QSizeF( svg->frameOffsetFromReferencePointMm().x() + margins.
left(),
246 svg->frameOffsetFromReferencePointMm().y() + margins.
top() ) );
252 item->setBounds( QgsRectangle( svg->relativePosition().x(), svg->relativePosition().y(),
253 svg->relativePosition().x(), svg->relativePosition().y() ) );
254 if ( QgsFillSymbol *fill = svg->fillSymbol() )
256 item->setBackgroundEnabled(
true );
257 item->setBackgroundSymbol( fill->clone() );
263 else if (
const QgsTextAnnotation *text =
dynamic_cast< const QgsTextAnnotation *
>( annotation ) )
265 QgsPointXY mapPosition = text->mapPosition();
266 QgsCoordinateTransform transform( text->mapPositionCrs(), layer->
crs(), transformContext );
269 transform.transform( mapPosition );
271 catch ( QgsCsException & )
273 QgsDebugError( u
"Error transforming annotation position"_s );
277 if ( !setCommonProperties( annotation, item.get() ) )
280 QgsTextFormat format = item->format();
282 item->setFormat( format );
284 const QgsMargins margins = text->contentsMargin();
285 item->setFixedSize( QSizeF( text->frameSizeMm().width() - margins.
left() - margins.
right(),
286 text->frameSizeMm().height() - margins.
top() - margins.
bottom() ) );
289 if ( text->hasFixedMapPosition() )
293 item->setOffsetFromCallout( QSizeF( text->frameOffsetFromReferencePointMm().x() + margins.
left(),
294 text->frameOffsetFromReferencePointMm().y() + margins.
top() ) );
296 item->setBackgroundEnabled(
false );
297 item->setFrameEnabled(
false );
302 item->setBounds( QgsRectangle( text->relativePosition().x(), text->relativePosition().y(),
303 text->relativePosition().x(), text->relativePosition().y() ) );
304 if ( QgsFillSymbol *fill = text->fillSymbol() )
306 item->setBackgroundEnabled(
true );
307 item->setBackgroundSymbol( fill->clone() );
319 QDomElement annotationsElem = doc.createElement( u
"Annotations"_s );
320 QListIterator<QgsAnnotation *> i( mAnnotations );
323 while ( i.hasPrevious() )
332 annotation->
writeXml( annotationsElem, doc, context );
334 return annotationsElem;
339 if ( mAnnotations.empty() )
348 if ( !a->accept( visitor ) )
360 QString type = element.tagName();
365 annotation->
readXml( element, context );
@ Millimeters
Millimeters.
@ FixedSize
Item is rendered at a fixed size, regardless of map scale. Item's location is georeferenced to a spat...
@ RelativeToMapFrame
Items size and placement is relative to the map's frame, and the item will always be rendered in the ...
Represents a map layer containing a set of georeferenced annotations, e.g.
void setLinkedVisibilityLayer(QgsMapLayer *layer)
Sets a linked layer, where the items in this annotation layer will only be visible when the linked la...
QString addItem(QgsAnnotationItem *item)
Adds an item to the layer.
QList< QgsAnnotation * > annotations() const
Returns a list of all annotations contained in the manager.
QList< QgsAnnotation * > cloneAnnotations() const
Returns a list containing clones of all annotations contained in the manager.
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context) const
Returns a DOM element representing the state of the manager.
void annotationRemoved()
Emitted when an annotation was removed from the manager.
QgsAnnotationManager(QgsProject *project=nullptr)
Constructor for QgsAnnotationManager.
void annotationAboutToBeRemoved(QgsAnnotation *annotation)
Emitted when an annotation is about to be removed from the manager.
bool readXml(const QDomElement &element, const QgsReadWriteContext &context)
Reads the manager's state from a DOM element, restoring all annotations present in the XML document.
bool readXmlAndUpgradeToAnnotationLayerItems(const QDomElement &element, const QgsReadWriteContext &context, QgsAnnotationLayer *layer, const QgsCoordinateTransformContext &transformContext)
Reads the manager's state from a DOM element, restoring annotations present in the XML document.
~QgsAnnotationManager() override
bool removeAnnotation(QgsAnnotation *annotation)
Removes an annotation from the manager.
bool accept(QgsStyleEntityVisitorInterface *visitor) const
Accepts the specified style entity visitor, causing it to visit all style entities associated within ...
void clear()
Removes and deletes all annotations from the manager.
bool addAnnotation(QgsAnnotation *annotation)
Adds an annotation to the manager.
void annotationAdded(QgsAnnotation *annotation)
Emitted when a annotation has been added to the manager.
Abstract base class for annotation items which are drawn over a map.
QgsCoordinateReferenceSystem mapPositionCrs() const
Returns the CRS of the map position, or an invalid CRS if the annotation does not have a fixed map po...
void setMapPositionCrs(const QgsCoordinateReferenceSystem &crs)
Sets the CRS of the map position.
virtual void readXml(const QDomElement &itemElem, const QgsReadWriteContext &context)=0
Restores the annotation's state from a DOM element.
virtual void writeXml(QDomElement &elem, QDomDocument &doc, const QgsReadWriteContext &context) const =0
Writes the annotation state to a DOM element.
static QgsAnnotationRegistry * annotationRegistry()
Returns the application's annotation registry, used for managing annotation types.
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
Contains information about the context in which a coordinate transform is executed.
static QgsGeometry fromPointXY(const QgsPointXY &point)
Creates a new geometry from a QgsPointXY object.
QgsCoordinateReferenceSystem crs
double top() const
Returns the top margin.
double right() const
Returns the right margin.
double bottom() const
Returns the bottom margin.
double left() const
Returns the left margin.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
QgsCoordinateReferenceSystem crs
A container for the context for various read/write operations on objects.
static QgsRectangle fromCenterAndSize(const QgsPointXY ¢er, double width, double height)
Creates a new rectangle, given the specified center point and width and height.
An interface for classes which can visit style entity (e.g.
@ Annotations
Annotations collection.
virtual bool visitExit(const QgsStyleEntityVisitorInterface::Node &node)
Called when the visitor stops visiting a node.
virtual bool visitEnter(const QgsStyleEntityVisitorInterface::Node &node)
Called when the visitor starts visiting a node.
void setAllowHtmlFormatting(bool allow)
Sets whether text should be treated as a HTML document and HTML tags should be used for formatting th...
#define QgsDebugError(str)
Contains information relating to a node (i.e.