QGIS API Documentation  3.20.0-Odense (decaadbb31)
qgsannotationlayer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsannotationlayer.cpp
3  ------------------
4  copyright : (C) 2019 by Sandro Mani
5  email : smani at sourcepole dot ch
6  ***************************************************************************/
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 "qgsannotationlayer.h"
19 #include "qgsannotationitem.h"
21 #include "qgsapplication.h"
22 #include "qgslogger.h"
23 #include "qgspainting.h"
24 #include "qgsmaplayerfactory.h"
25 #include <QUuid>
26 
27 QgsAnnotationLayer::QgsAnnotationLayer( const QString &name, const LayerOptions &options )
29  , mTransformContext( options.transformContext )
30 {
31  mShouldValidateCrs = false;
32  mValid = true;
33 }
34 
36 {
37  emit willBeDeleted();
38  qDeleteAll( mItems );
39 }
40 
42 {
43  setOpacity( 1.0 );
46  clear();
47 }
48 
50 {
51  const QString uuid = QUuid::createUuid().toString();
52  mItems.insert( uuid, item );
53 
55 
56  return uuid;
57 }
58 
59 bool QgsAnnotationLayer::removeItem( const QString &id )
60 {
61  if ( !mItems.contains( id ) )
62  return false;
63 
64  delete mItems.take( id );
65 
67 
68  return true;
69 }
70 
72 {
73  qDeleteAll( mItems );
74  mItems.clear();
75 
77 }
78 
80 {
81  return mItems.empty();
82 }
83 
85 {
86  QgsAnnotationLayer::LayerOptions options( mTransformContext );
87  std::unique_ptr< QgsAnnotationLayer > layer = std::make_unique< QgsAnnotationLayer >( name(), options );
88  QgsMapLayer::clone( layer.get() );
89 
90  for ( auto it = mItems.constBegin(); it != mItems.constEnd(); ++it )
91  {
92  layer->mItems.insert( it.key(), ( *it )->clone() );
93  }
94 
95  return layer.release();
96 }
97 
99 {
100  return new QgsAnnotationLayerRenderer( this, rendererContext );
101 }
102 
104 {
105  QgsRectangle rect;
106  for ( auto it = mItems.constBegin(); it != mItems.constEnd(); ++it )
107  {
108  if ( rect.isNull() )
109  {
110  rect = it.value()->boundingBox();
111  }
112  else
113  {
114  rect.combineExtentWith( it.value()->boundingBox() );
115  }
116  }
117  return rect;
118 }
119 
121 {
122  mTransformContext = context;
124 }
125 
126 bool QgsAnnotationLayer::readXml( const QDomNode &layerNode, QgsReadWriteContext &context )
127 {
129  {
130  return false;
131  }
132 
133  qDeleteAll( mItems );
134  mItems.clear();
135 
136  QDomNodeList itemsElements = layerNode.toElement().elementsByTagName( QStringLiteral( "items" ) );
137  if ( itemsElements.size() == 0 )
138  return false;
139 
140  QDomNodeList items = itemsElements.at( 0 ).childNodes();
141  for ( int i = 0; i < items.size(); ++i )
142  {
143  QDomElement itemElement = items.at( i ).toElement();
144  const QString id = itemElement.attribute( QStringLiteral( "id" ) );
145  const QString type = itemElement.attribute( QStringLiteral( "type" ) );
146  std::unique_ptr< QgsAnnotationItem > item( QgsApplication::annotationItemRegistry()->createItem( type ) );
147  if ( item )
148  {
149  item->readXml( itemElement, context );
150  mItems.insert( id, item.release() );
151  }
152  }
153 
154  QString errorMsg;
155  readSymbology( layerNode, errorMsg, context );
156 
157  triggerRepaint();
158 
159  return mValid;
160 }
161 
162 bool QgsAnnotationLayer::writeXml( QDomNode &layer_node, QDomDocument &doc, const QgsReadWriteContext &context ) const
163 {
164  // first get the layer element so that we can append the type attribute
165  QDomElement mapLayerNode = layer_node.toElement();
166 
167  if ( mapLayerNode.isNull() )
168  {
169  QgsDebugMsgLevel( QStringLiteral( "can't find maplayer node" ), 2 );
170  return false;
171  }
172 
173  mapLayerNode.setAttribute( QStringLiteral( "type" ), QgsMapLayerFactory::typeToString( QgsMapLayerType::AnnotationLayer ) );
174 
175  QDomElement itemsElement = doc.createElement( "items" );
176  for ( auto it = mItems.constBegin(); it != mItems.constEnd(); ++it )
177  {
178  QDomElement itemElement = doc.createElement( "item" );
179  itemElement.setAttribute( QStringLiteral( "type" ), ( *it )->type() );
180  itemElement.setAttribute( QStringLiteral( "id" ), it.key() );
181  ( *it )->writeXml( itemElement, doc, context );
182  itemsElement.appendChild( itemElement );
183  }
184  mapLayerNode.appendChild( itemsElement );
185 
186  // renderer specific settings
187  QString errorMsg;
188  return writeSymbology( layer_node, doc, errorMsg, context );
189 }
190 
191 bool QgsAnnotationLayer::writeSymbology( QDomNode &node, QDomDocument &doc, QString &, const QgsReadWriteContext &, QgsMapLayer::StyleCategories categories ) const
192 {
193  // add the layer opacity
194  if ( categories.testFlag( Rendering ) )
195  {
196  QDomElement layerOpacityElem = doc.createElement( QStringLiteral( "layerOpacity" ) );
197  QDomText layerOpacityText = doc.createTextNode( QString::number( opacity() ) );
198  layerOpacityElem.appendChild( layerOpacityText );
199  node.appendChild( layerOpacityElem );
200  }
201 
202  if ( categories.testFlag( Symbology ) )
203  {
204  // add the blend mode field
205  QDomElement blendModeElem = doc.createElement( QStringLiteral( "blendMode" ) );
206  QDomText blendModeText = doc.createTextNode( QString::number( QgsPainting::getBlendModeEnum( blendMode() ) ) );
207  blendModeElem.appendChild( blendModeText );
208  node.appendChild( blendModeElem );
209  }
210 
211  return true;
212 }
213 
214 bool QgsAnnotationLayer::readSymbology( const QDomNode &node, QString &, QgsReadWriteContext &, QgsMapLayer::StyleCategories categories )
215 {
216  if ( categories.testFlag( Rendering ) )
217  {
218  QDomNode layerOpacityNode = node.namedItem( QStringLiteral( "layerOpacity" ) );
219  if ( !layerOpacityNode.isNull() )
220  {
221  QDomElement e = layerOpacityNode.toElement();
222  setOpacity( e.text().toDouble() );
223  }
224  }
225 
226  if ( categories.testFlag( Symbology ) )
227  {
228  // get and set the blend mode if it exists
229  QDomNode blendModeNode = node.namedItem( QStringLiteral( "blendMode" ) );
230  if ( !blendModeNode.isNull() )
231  {
232  QDomElement e = blendModeNode.toElement();
233  setBlendMode( QgsPainting::getCompositionMode( static_cast< QgsPainting::BlendMode >( e.text().toInt() ) ) );
234  }
235  }
236 
237  return true;
238 }
Abstract base class for annotation items which are drawn with QgsAnnotationLayers.
Implementation of threaded rendering for annotation layers.
Represents a map layer containing a set of georeferenced annotations, e.g.
QgsRectangle extent() const override
Returns the extent of the layer.
bool writeSymbology(QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &, StyleCategories categories=AllStyleCategories) const override
Write the style for the layer into the docment provided.
bool readSymbology(const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories) override
Read the symbology for the current layer from the DOM node supplied.
void clear()
Removes all items from the layer.
QgsMapLayerRenderer * createMapRenderer(QgsRenderContext &rendererContext) override
Returns new instance of QgsMapLayerRenderer that will be used for rendering of given context.
QMap< QString, QgsAnnotationItem * > items() const
Returns a map of items contained in the layer, by unique item ID.
bool removeItem(const QString &id)
Removes (and deletes) the item with matching id.
void setTransformContext(const QgsCoordinateTransformContext &context) override
Sets the coordinate transform context to transformContext.
QgsAnnotationLayer * clone() const override
Returns a new instance equivalent to this one except for the id which is still unique.
void reset()
Resets the annotation layer to a default state, and clears all items from it.
QString addItem(QgsAnnotationItem *item)
Adds an item to the layer.
bool isEmpty() const
Returns true if the annotation layer is empty and contains no annotations.
bool writeXml(QDomNode &layer_node, QDomDocument &doc, const QgsReadWriteContext &context) const override
Called by writeLayerXML(), used by children to write state specific to them to project files.
bool readXml(const QDomNode &layerNode, QgsReadWriteContext &context) override
Called by readLayerXML(), used by children to read state specific to them from project files.
QgsAnnotationLayer(const QString &name, const QgsAnnotationLayer::LayerOptions &options)
Constructor for a new QgsAnnotationLayer with the specified layer name.
static QgsAnnotationItemRegistry * annotationItemRegistry()
Returns the application's annotation item registry, used for annotation item types.
This class represents a coordinate reference system (CRS).
Contains information about the context in which a coordinate transform is executed.
static QString typeToString(QgsMapLayerType type)
Converts a map layer type to a string value.
Base class for utility classes that encapsulate information necessary for rendering of map layers.
Base class for all map layer types.
Definition: qgsmaplayer.h:70
QString name
Definition: qgsmaplayer.h:73
void setBlendMode(QPainter::CompositionMode blendMode)
Set the blending mode used for rendering a layer.
QgsMapLayerType type
Definition: qgsmaplayer.h:77
void triggerRepaint(bool deferredUpdate=false)
Will advise the map canvas (and any other interested party) that this layer requires to be repainted.
QPainter::CompositionMode blendMode() const
Returns the current blending mode for a layer.
virtual void setOpacity(double opacity)
Sets the opacity for the layer, where opacity is a value between 0 (totally transparent) and 1....
virtual QgsMapLayer * clone() const =0
Returns a new instance equivalent to this one except for the id which is still unique.
void willBeDeleted()
Emitted in the destructor when the layer is about to be deleted, but it is still in a perfectly valid...
@ FlagDontResolveLayers
Don't resolve layer paths or create data providers for layers.
Definition: qgsmaplayer.h:580
QgsMapLayer::ReadFlags mReadFlags
Read flags. It's up to the subclass to respect these when restoring state from XML.
Definition: qgsmaplayer.h:1716
double opacity
Definition: qgsmaplayer.h:79
bool mValid
Indicates if the layer is valid and can be drawn.
Definition: qgsmaplayer.h:1662
@ Symbology
Symbology.
Definition: qgsmaplayer.h:155
@ Rendering
Rendering: scale visibility, simplify method, opacity.
Definition: qgsmaplayer.h:164
void invalidateWgs84Extent()
Invalidates the WGS84 extent.
bool mShouldValidateCrs
true if the layer's CRS should be validated and invalid CRSes are not permitted.
Definition: qgsmaplayer.h:1723
void setCrs(const QgsCoordinateReferenceSystem &srs, bool emitSignal=true)
Sets layer's spatial reference system.
static QgsPainting::BlendMode getBlendModeEnum(QPainter::CompositionMode blendMode)
Returns a BlendMode corresponding to a QPainter::CompositionMode.
Definition: qgspainting.cpp:80
static QPainter::CompositionMode getCompositionMode(QgsPainting::BlendMode blendMode)
Returns a QPainter::CompositionMode corresponding to a BlendMode.
Definition: qgspainting.cpp:20
BlendMode
Blending modes enum defining the available composition modes that can be used when rendering a layer.
Definition: qgspainting.h:37
The class is used as a container of context for various read/write operations on other objects.
A rectangle specified with double values.
Definition: qgsrectangle.h:42
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()).
Definition: qgsrectangle.h:479
void combineExtentWith(const QgsRectangle &rect)
Expands the rectangle so that it covers both the original rectangle and the given rectangle.
Definition: qgsrectangle.h:391
Contains information about the context of a rendering operation.
QgsMapLayerType
Types of layers that can be added to a map.
Definition: qgis.h:46
@ AnnotationLayer
Contains freeform, georeferenced annotations. Added in QGIS 3.16.
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
Setting options for loading annotation layers.