QGIS API Documentation  3.18.1-Zürich (202f1bf7e5)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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 = qgis::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;
123 }
124 
125 bool QgsAnnotationLayer::readXml( const QDomNode &layerNode, QgsReadWriteContext &context )
126 {
128  {
129  return false;
130  }
131 
132  qDeleteAll( mItems );
133  mItems.clear();
134 
135  QDomNodeList itemsElements = layerNode.toElement().elementsByTagName( QStringLiteral( "items" ) );
136  if ( itemsElements.size() == 0 )
137  return false;
138 
139  QDomNodeList items = itemsElements.at( 0 ).childNodes();
140  for ( int i = 0; i < items.size(); ++i )
141  {
142  QDomElement itemElement = items.at( i ).toElement();
143  const QString id = itemElement.attribute( QStringLiteral( "id" ) );
144  const QString type = itemElement.attribute( QStringLiteral( "type" ) );
145  std::unique_ptr< QgsAnnotationItem > item( QgsApplication::annotationItemRegistry()->createItem( type ) );
146  if ( item )
147  {
148  item->readXml( itemElement, context );
149  mItems.insert( id, item.release() );
150  }
151  }
152 
153  QString errorMsg;
154  readSymbology( layerNode, errorMsg, context );
155 
156  triggerRepaint();
157 
158  return mValid;
159 }
160 
161 bool QgsAnnotationLayer::writeXml( QDomNode &layer_node, QDomDocument &doc, const QgsReadWriteContext &context ) const
162 {
163  // first get the layer element so that we can append the type attribute
164  QDomElement mapLayerNode = layer_node.toElement();
165 
166  if ( mapLayerNode.isNull() )
167  {
168  QgsDebugMsgLevel( QStringLiteral( "can't find maplayer node" ), 2 );
169  return false;
170  }
171 
172  mapLayerNode.setAttribute( QStringLiteral( "type" ), QgsMapLayerFactory::typeToString( QgsMapLayerType::AnnotationLayer ) );
173 
174  QDomElement itemsElement = doc.createElement( "items" );
175  for ( auto it = mItems.constBegin(); it != mItems.constEnd(); ++it )
176  {
177  QDomElement itemElement = doc.createElement( "item" );
178  itemElement.setAttribute( QStringLiteral( "type" ), ( *it )->type() );
179  itemElement.setAttribute( QStringLiteral( "id" ), it.key() );
180  ( *it )->writeXml( itemElement, doc, context );
181  itemsElement.appendChild( itemElement );
182  }
183  mapLayerNode.appendChild( itemsElement );
184 
185  // renderer specific settings
186  QString errorMsg;
187  return writeSymbology( layer_node, doc, errorMsg, context );
188 }
189 
190 bool QgsAnnotationLayer::writeSymbology( QDomNode &node, QDomDocument &doc, QString &, const QgsReadWriteContext &, QgsMapLayer::StyleCategories categories ) const
191 {
192  // add the layer opacity
193  if ( categories.testFlag( Rendering ) )
194  {
195  QDomElement layerOpacityElem = doc.createElement( QStringLiteral( "layerOpacity" ) );
196  QDomText layerOpacityText = doc.createTextNode( QString::number( opacity() ) );
197  layerOpacityElem.appendChild( layerOpacityText );
198  node.appendChild( layerOpacityElem );
199  }
200 
201  if ( categories.testFlag( Symbology ) )
202  {
203  // add the blend mode field
204  QDomElement blendModeElem = doc.createElement( QStringLiteral( "blendMode" ) );
205  QDomText blendModeText = doc.createTextNode( QString::number( QgsPainting::getBlendModeEnum( blendMode() ) ) );
206  blendModeElem.appendChild( blendModeText );
207  node.appendChild( blendModeElem );
208  }
209 
210  return true;
211 }
212 
213 bool QgsAnnotationLayer::readSymbology( const QDomNode &node, QString &, QgsReadWriteContext &, QgsMapLayer::StyleCategories categories )
214 {
215  if ( categories.testFlag( Rendering ) )
216  {
217  QDomNode layerOpacityNode = node.namedItem( QStringLiteral( "layerOpacity" ) );
218  if ( !layerOpacityNode.isNull() )
219  {
220  QDomElement e = layerOpacityNode.toElement();
221  setOpacity( e.text().toDouble() );
222  }
223  }
224 
225  if ( categories.testFlag( Symbology ) )
226  {
227  // get and set the blend mode if it exists
228  QDomNode blendModeNode = node.namedItem( QStringLiteral( "blendMode" ) );
229  if ( !blendModeNode.isNull() )
230  {
231  QDomElement e = blendModeNode.toElement();
232  setBlendMode( QgsPainting::getCompositionMode( static_cast< QgsPainting::BlendMode >( e.text().toInt() ) ) );
233  }
234  }
235 
236  return true;
237 }
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:85
QString name
Definition: qgsmaplayer.h:88
void setBlendMode(QPainter::CompositionMode blendMode)
Set the blending mode used for rendering a layer.
QgsMapLayerType type
Definition: qgsmaplayer.h:92
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:584
QgsMapLayer::ReadFlags mReadFlags
Read flags. It's up to the subclass to respect these when restoring state from XML.
Definition: qgsmaplayer.h:1663
double opacity
Definition: qgsmaplayer.h:94
bool mValid
Indicates if the layer is valid and can be drawn.
Definition: qgsmaplayer.h:1609
@ Symbology
Symbology.
Definition: qgsmaplayer.h:170
@ Rendering
Rendering: scale visibility, simplify method, opacity.
Definition: qgsmaplayer.h:179
bool mShouldValidateCrs
true if the layer's CRS should be validated and invalid CRSes are not permitted.
Definition: qgsmaplayer.h:1670
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:447
void combineExtentWith(const QgsRectangle &rect)
Expands the rectangle so that it covers both the original rectangle and the given rectangle.
Definition: qgsrectangle.h:359
Contains information about the context of a rendering operation.
QgsMapLayerType
Types of layers that can be added to a map.
Definition: qgsmaplayer.h:69
@ AnnotationLayer
Contains freeform, georeferenced annotations. Added in QGIS 3.16.
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
Setting options for loading annotation layers.