33#include "moc_qgsannotationmanager.cpp"
35using namespace Qt::StringLiterals;
52 if ( mAnnotations.contains( annotation ) )
55 mAnnotations << annotation;
57 mProject->setDirty(
true );
66 if ( !mAnnotations.contains( annotation ) )
70 mAnnotations.removeAll( annotation );
73 mProject->setDirty(
true );
79 for (
auto *a : std::as_const( mAnnotations ) )
92 QList<QgsAnnotation *> results;
93 for (
const auto *a : std::as_const( mAnnotations ) )
95 results << a->clone();
109 return readXmlPrivate( element, context, layer, transformContext );
118 auto createAnnotationFromElement = [
this, &context, layer, &transformContext](
const QDomElement &element ) {
119 std::unique_ptr< QgsAnnotation > annotation( createAnnotationFromXml( element, context ) );
125 std::unique_ptr< QgsAnnotationItem > annotationItem = convertToAnnotationItem( annotation.get(), layer, transformContext );
126 if ( annotationItem )
128 layer->
addItem( annotationItem.release() );
142 QDomElement annotationsElem = element.firstChildElement( u
"Annotations"_s );
144 QDomElement annotationElement = annotationsElem.firstChildElement( u
"Annotation"_s );
145 while ( !annotationElement.isNull() )
147 createAnnotationFromElement( annotationElement );
148 annotationElement = annotationElement.nextSiblingElement( u
"Annotation"_s );
152 if ( annotationElement.isNull() )
154 QDomNodeList oldItemList = element.elementsByTagName( u
"TextAnnotationItem"_s );
155 for (
int i = 0; i < oldItemList.size(); ++i )
157 createAnnotationFromElement( oldItemList.at( i ).toElement() );
159 oldItemList = element.elementsByTagName( u
"FormAnnotationItem"_s );
160 for (
int i = 0; i < oldItemList.size(); ++i )
162 createAnnotationFromElement( oldItemList.at( i ).toElement() );
164 oldItemList = element.elementsByTagName( u
"HtmlAnnotationItem"_s );
165 for (
int i = 0; i < oldItemList.size(); ++i )
167 createAnnotationFromElement( oldItemList.at( i ).toElement() );
169 oldItemList = element.elementsByTagName( u
"SVGAnnotationItem"_s );
170 for (
int i = 0; i < oldItemList.size(); ++i )
172 createAnnotationFromElement( oldItemList.at( i ).toElement() );
181 auto setCommonProperties = [layer, &transformContext](
const QgsAnnotation *source, QgsAnnotationItem *destination ) ->
bool {
182 destination->setEnabled( source->isVisible() );
183 if ( source->hasFixedMapPosition() )
185 QgsPointXY mapPosition = source->mapPosition();
186 QgsCoordinateTransform transform( source->mapPositionCrs(), layer->
crs(), transformContext );
189 mapPosition = transform.transform( mapPosition );
191 catch ( QgsCsException & )
193 QgsDebugError( u
"Error transforming annotation position"_s );
199 auto callout = std::make_unique< QgsBalloonCallout >();
200 if ( QgsFillSymbol *fill = source->fillSymbol() )
201 callout->setFillSymbol( fill->clone() );
203 if ( QgsMarkerSymbol *marker = source->markerSymbol() )
204 callout->setMarkerSymbol( marker->clone() );
205 callout->setMargins( source->contentsMargin() );
207 destination->setCallout( callout.release() );
210 if ( source->mapLayer() )
216 if (
const QgsSvgAnnotation *svg =
dynamic_cast< const QgsSvgAnnotation *
>( annotation ) )
218 QgsPointXY mapPosition = svg->mapPosition();
219 QgsCoordinateTransform transform( svg->mapPositionCrs(), layer->
crs(), transformContext );
222 transform.transform( mapPosition );
224 catch ( QgsCsException & )
226 QgsDebugError( u
"Error transforming annotation position"_s );
230 if ( !setCommonProperties( annotation, item.get() ) )
233 const QgsMargins margins = svg->contentsMargin();
234 item->setFixedSize( QSizeF( svg->frameSizeMm().width() - margins.
left() - margins.
right(), svg->frameSizeMm().height() - margins.
top() - margins.
bottom() ) );
237 if ( svg->hasFixedMapPosition() )
241 item->setOffsetFromCallout( QSizeF( svg->frameOffsetFromReferencePointMm().x() + margins.
left(), svg->frameOffsetFromReferencePointMm().y() + margins.
top() ) );
247 item->setBounds( QgsRectangle( svg->relativePosition().x(), svg->relativePosition().y(), svg->relativePosition().x(), svg->relativePosition().y() ) );
248 if ( QgsFillSymbol *fill = svg->fillSymbol() )
250 item->setBackgroundEnabled(
true );
251 item->setBackgroundSymbol( fill->clone() );
257 else if (
const QgsTextAnnotation *text =
dynamic_cast< const QgsTextAnnotation *
>( annotation ) )
259 QgsPointXY mapPosition = text->mapPosition();
260 QgsCoordinateTransform transform( text->mapPositionCrs(), layer->
crs(), transformContext );
263 transform.transform( mapPosition );
265 catch ( QgsCsException & )
267 QgsDebugError( u
"Error transforming annotation position"_s );
271 if ( !setCommonProperties( annotation, item.get() ) )
274 QgsTextFormat format = item->format();
276 item->setFormat( format );
278 const QgsMargins margins = text->contentsMargin();
279 item->setFixedSize( QSizeF( text->frameSizeMm().width() - margins.
left() - margins.
right(), text->frameSizeMm().height() - margins.
top() - margins.
bottom() ) );
282 if ( text->hasFixedMapPosition() )
286 item->setOffsetFromCallout( QSizeF( text->frameOffsetFromReferencePointMm().x() + margins.
left(), text->frameOffsetFromReferencePointMm().y() + margins.
top() ) );
288 item->setBackgroundEnabled(
false );
289 item->setFrameEnabled(
false );
294 item->setBounds( QgsRectangle( text->relativePosition().x(), text->relativePosition().y(), text->relativePosition().x(), text->relativePosition().y() ) );
295 if ( QgsFillSymbol *fill = text->fillSymbol() )
297 item->setBackgroundEnabled(
true );
298 item->setBackgroundSymbol( fill->clone() );
310 QDomElement annotationsElem = doc.createElement( u
"Annotations"_s );
311 QListIterator<QgsAnnotation *> i( mAnnotations );
314 while ( i.hasPrevious() )
323 annotation->
writeXml( annotationsElem, doc, context );
325 return annotationsElem;
330 if ( mAnnotations.empty() )
339 if ( !a->accept( visitor ) )
351 QString type = element.tagName();
356 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.