Branch data Line data Source code
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" 18 : : #include "qgsannotationlayerrenderer.h" 19 : : #include "qgsannotationitem.h" 20 : : #include "qgsannotationitemregistry.h" 21 : : #include "qgsapplication.h" 22 : : #include "qgslogger.h" 23 : : #include "qgspainting.h" 24 : : #include "qgsmaplayerfactory.h" 25 : : #include <QUuid> 26 : : 27 : 10 : QgsAnnotationLayer::QgsAnnotationLayer( const QString &name, const LayerOptions &options ) 28 : 5 : : QgsMapLayer( QgsMapLayerType::AnnotationLayer, name ) 29 : 5 : , mTransformContext( options.transformContext ) 30 : 5 : { 31 : 5 : mShouldValidateCrs = false; 32 : 5 : mValid = true; 33 : 5 : } 34 : : 35 : 6 : QgsAnnotationLayer::~QgsAnnotationLayer() 36 : 6 : { 37 : 3 : emit willBeDeleted(); 38 : 3 : qDeleteAll( mItems ); 39 : 6 : } 40 : : 41 : 8 : void QgsAnnotationLayer::reset() 42 : : { 43 : 8 : setOpacity( 1.0 ); 44 : 8 : setCrs( QgsCoordinateReferenceSystem() ); 45 : 8 : setTransformContext( QgsCoordinateTransformContext() ); 46 : 8 : clear(); 47 : 8 : } 48 : : 49 : 0 : QString QgsAnnotationLayer::addItem( QgsAnnotationItem *item ) 50 : : { 51 : 0 : const QString uuid = QUuid::createUuid().toString(); 52 : 0 : mItems.insert( uuid, item ); 53 : : 54 : 0 : triggerRepaint(); 55 : : 56 : 0 : return uuid; 57 : 0 : } 58 : : 59 : 0 : bool QgsAnnotationLayer::removeItem( const QString &id ) 60 : : { 61 : 0 : if ( !mItems.contains( id ) ) 62 : 0 : return false; 63 : : 64 : 0 : delete mItems.take( id ); 65 : : 66 : 0 : triggerRepaint(); 67 : : 68 : 0 : return true; 69 : 0 : } 70 : : 71 : 8 : void QgsAnnotationLayer::clear() 72 : : { 73 : 8 : qDeleteAll( mItems ); 74 : 8 : mItems.clear(); 75 : : 76 : 8 : triggerRepaint(); 77 : 8 : } 78 : : 79 : 0 : bool QgsAnnotationLayer::isEmpty() const 80 : : { 81 : 0 : return mItems.empty(); 82 : : } 83 : : 84 : 0 : QgsAnnotationLayer *QgsAnnotationLayer::clone() const 85 : : { 86 : 0 : QgsAnnotationLayer::LayerOptions options( mTransformContext ); 87 : 0 : std::unique_ptr< QgsAnnotationLayer > layer = std::make_unique< QgsAnnotationLayer >( name(), options ); 88 : 0 : QgsMapLayer::clone( layer.get() ); 89 : : 90 : 0 : for ( auto it = mItems.constBegin(); it != mItems.constEnd(); ++it ) 91 : : { 92 : 0 : layer->mItems.insert( it.key(), ( *it )->clone() ); 93 : 0 : } 94 : : 95 : 0 : return layer.release(); 96 : 0 : } 97 : : 98 : 0 : QgsMapLayerRenderer *QgsAnnotationLayer::createMapRenderer( QgsRenderContext &rendererContext ) 99 : : { 100 : 0 : return new QgsAnnotationLayerRenderer( this, rendererContext ); 101 : 0 : } 102 : : 103 : 0 : QgsRectangle QgsAnnotationLayer::extent() const 104 : : { 105 : 0 : QgsRectangle rect; 106 : 0 : for ( auto it = mItems.constBegin(); it != mItems.constEnd(); ++it ) 107 : : { 108 : 0 : if ( rect.isNull() ) 109 : : { 110 : 0 : rect = it.value()->boundingBox(); 111 : 0 : } 112 : : else 113 : : { 114 : 0 : rect.combineExtentWith( it.value()->boundingBox() ); 115 : : } 116 : 0 : } 117 : 0 : return rect; 118 : : } 119 : : 120 : 8 : void QgsAnnotationLayer::setTransformContext( const QgsCoordinateTransformContext &context ) 121 : : { 122 : 8 : mTransformContext = context; 123 : 8 : invalidateWgs84Extent(); 124 : 8 : } 125 : : 126 : 0 : bool QgsAnnotationLayer::readXml( const QDomNode &layerNode, QgsReadWriteContext &context ) 127 : : { 128 : 0 : if ( mReadFlags & QgsMapLayer::FlagDontResolveLayers ) 129 : : { 130 : 0 : return false; 131 : : } 132 : : 133 : 0 : qDeleteAll( mItems ); 134 : 0 : mItems.clear(); 135 : : 136 : 0 : QDomNodeList itemsElements = layerNode.toElement().elementsByTagName( QStringLiteral( "items" ) ); 137 : 0 : if ( itemsElements.size() == 0 ) 138 : 0 : return false; 139 : : 140 : 0 : QDomNodeList items = itemsElements.at( 0 ).childNodes(); 141 : 0 : for ( int i = 0; i < items.size(); ++i ) 142 : : { 143 : 0 : QDomElement itemElement = items.at( i ).toElement(); 144 : 0 : const QString id = itemElement.attribute( QStringLiteral( "id" ) ); 145 : 0 : const QString type = itemElement.attribute( QStringLiteral( "type" ) ); 146 : 0 : std::unique_ptr< QgsAnnotationItem > item( QgsApplication::annotationItemRegistry()->createItem( type ) ); 147 : 0 : if ( item ) 148 : : { 149 : 0 : item->readXml( itemElement, context ); 150 : 0 : mItems.insert( id, item.release() ); 151 : 0 : } 152 : 0 : } 153 : : 154 : 0 : QString errorMsg; 155 : 0 : readSymbology( layerNode, errorMsg, context ); 156 : : 157 : 0 : triggerRepaint(); 158 : : 159 : 0 : return mValid; 160 : 0 : } 161 : : 162 : 0 : 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 : 0 : QDomElement mapLayerNode = layer_node.toElement(); 166 : : 167 : 0 : if ( mapLayerNode.isNull() ) 168 : : { 169 : 0 : QgsDebugMsgLevel( QStringLiteral( "can't find maplayer node" ), 2 ); 170 : 0 : return false; 171 : : } 172 : : 173 : 0 : mapLayerNode.setAttribute( QStringLiteral( "type" ), QgsMapLayerFactory::typeToString( QgsMapLayerType::AnnotationLayer ) ); 174 : : 175 : 0 : QDomElement itemsElement = doc.createElement( "items" ); 176 : 0 : for ( auto it = mItems.constBegin(); it != mItems.constEnd(); ++it ) 177 : : { 178 : 0 : QDomElement itemElement = doc.createElement( "item" ); 179 : 0 : itemElement.setAttribute( QStringLiteral( "type" ), ( *it )->type() ); 180 : 0 : itemElement.setAttribute( QStringLiteral( "id" ), it.key() ); 181 : 0 : ( *it )->writeXml( itemElement, doc, context ); 182 : 0 : itemsElement.appendChild( itemElement ); 183 : 0 : } 184 : 0 : mapLayerNode.appendChild( itemsElement ); 185 : : 186 : : // renderer specific settings 187 : 0 : QString errorMsg; 188 : 0 : return writeSymbology( layer_node, doc, errorMsg, context ); 189 : 0 : } 190 : : 191 : 0 : bool QgsAnnotationLayer::writeSymbology( QDomNode &node, QDomDocument &doc, QString &, const QgsReadWriteContext &, QgsMapLayer::StyleCategories categories ) const 192 : : { 193 : : // add the layer opacity 194 : 0 : if ( categories.testFlag( Rendering ) ) 195 : : { 196 : 0 : QDomElement layerOpacityElem = doc.createElement( QStringLiteral( "layerOpacity" ) ); 197 : 0 : QDomText layerOpacityText = doc.createTextNode( QString::number( opacity() ) ); 198 : 0 : layerOpacityElem.appendChild( layerOpacityText ); 199 : 0 : node.appendChild( layerOpacityElem ); 200 : 0 : } 201 : : 202 : 0 : if ( categories.testFlag( Symbology ) ) 203 : : { 204 : : // add the blend mode field 205 : 0 : QDomElement blendModeElem = doc.createElement( QStringLiteral( "blendMode" ) ); 206 : 0 : QDomText blendModeText = doc.createTextNode( QString::number( QgsPainting::getBlendModeEnum( blendMode() ) ) ); 207 : 0 : blendModeElem.appendChild( blendModeText ); 208 : 0 : node.appendChild( blendModeElem ); 209 : 0 : } 210 : : 211 : 0 : return true; 212 : 0 : } 213 : : 214 : 0 : bool QgsAnnotationLayer::readSymbology( const QDomNode &node, QString &, QgsReadWriteContext &, QgsMapLayer::StyleCategories categories ) 215 : : { 216 : 0 : if ( categories.testFlag( Rendering ) ) 217 : : { 218 : 0 : QDomNode layerOpacityNode = node.namedItem( QStringLiteral( "layerOpacity" ) ); 219 : 0 : if ( !layerOpacityNode.isNull() ) 220 : : { 221 : 0 : QDomElement e = layerOpacityNode.toElement(); 222 : 0 : setOpacity( e.text().toDouble() ); 223 : 0 : } 224 : 0 : } 225 : : 226 : 0 : if ( categories.testFlag( Symbology ) ) 227 : : { 228 : : // get and set the blend mode if it exists 229 : 0 : QDomNode blendModeNode = node.namedItem( QStringLiteral( "blendMode" ) ); 230 : 0 : if ( !blendModeNode.isNull() ) 231 : : { 232 : 0 : QDomElement e = blendModeNode.toElement(); 233 : 0 : setBlendMode( QgsPainting::getCompositionMode( static_cast< QgsPainting::BlendMode >( e.text().toInt() ) ) ); 234 : 0 : } 235 : 0 : } 236 : : 237 : 0 : return true; 238 : 0 : }