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