Branch data Line data Source code
1 : : /*************************************************************************** 2 : : qgsannotation.h 3 : : --------------- 4 : : begin : January 2017 5 : : copyright : (C) 2017 by Nyall Dawson 6 : : email : nyall dot dawson at gmail dot com 7 : : ***************************************************************************/ 8 : : 9 : : /*************************************************************************** 10 : : * * 11 : : * This program is free software; you can redistribute it and/or modify * 12 : : * it under the terms of the GNU General Public License as published by * 13 : : * the Free Software Foundation; either version 2 of the License, or * 14 : : * (at your option) any later version. * 15 : : * * 16 : : ***************************************************************************/ 17 : : 18 : : #ifndef QGSANNOTATION_H 19 : : #define QGSANNOTATION_H 20 : : 21 : : #include "qgis_core.h" 22 : : #include "qgis.h" 23 : : #include "qgspointxy.h" 24 : : #include "qgscoordinatereferencesystem.h" 25 : : #include "qgssymbol.h" 26 : : #include "qgsmargins.h" 27 : : #include "qgsmaplayer.h" 28 : : 29 : : #include <QPointer> 30 : : 31 : : class QgsRenderContext; 32 : : 33 : : /** 34 : : * \ingroup core 35 : : * \class QgsAnnotation 36 : : * 37 : : * \brief Abstract base class for annotation items which are drawn over a map. 38 : : * 39 : : * QgsAnnotation is an abstract base class for map annotation items. These annotations can be 40 : : * drawn within a map, and have either a fixed map position (retrieved using mapPosition()) 41 : : * or are placed relative to the map's frame (retrieved using relativePosition()). 42 : : * Annotations with a fixed map position also have a corresponding 43 : : * QgsCoordinateReferenceSystem, which can be determined by calling mapPositionCrs(). 44 : : * 45 : : * Derived classes should implement their custom painting routines within 46 : : * a renderAnnotation() override. 47 : : * 48 : : * \since QGIS 3.0 49 : : */ 50 : : 51 : 0 : class CORE_EXPORT QgsAnnotation : public QObject 52 : : { 53 : : 54 : : #ifdef SIP_RUN 55 : : SIP_CONVERT_TO_SUBCLASS_CODE 56 : : if ( dynamic_cast< QgsTextAnnotation * >( sipCpp ) ) 57 : : sipType = sipType_QgsTextAnnotation; 58 : : else if ( dynamic_cast< QgsSvgAnnotation * >( sipCpp ) ) 59 : : sipType = sipType_QgsSvgAnnotation; 60 : : else if ( dynamic_cast< QgsHtmlAnnotation * >( sipCpp ) ) 61 : : sipType = sipType_QgsHtmlAnnotation; 62 : : else 63 : : sipType = NULL; 64 : : SIP_END 65 : : #endif 66 : : 67 : : 68 : 0 : Q_OBJECT 69 : : Q_PROPERTY( bool visible READ isVisible WRITE setVisible ) 70 : : Q_PROPERTY( bool hasFixedMapPosition READ hasFixedMapPosition WRITE setHasFixedMapPosition ) 71 : : Q_PROPERTY( QgsPointXY mapPosition READ mapPosition WRITE setMapPosition ) 72 : : Q_PROPERTY( QSizeF frameSize READ frameSize WRITE setFrameSize ) 73 : : 74 : : public: 75 : : 76 : : /** 77 : : * Constructor for QgsAnnotation. 78 : : */ 79 : : QgsAnnotation( QObject *parent SIP_TRANSFERTHIS = nullptr ); 80 : : 81 : : /** 82 : : * Clones the annotation, returning a new copy of the annotation 83 : : * reflecting the annotation's current state. 84 : : */ 85 : : virtual QgsAnnotation *clone() const = 0 SIP_FACTORY; 86 : : 87 : : /** 88 : : * Returns TRUE if the annotation is visible and should be rendered. 89 : : * \see setVisible() 90 : : */ 91 : 0 : bool isVisible() const { return mVisible; } 92 : : 93 : : /** 94 : : * Sets whether the annotation is visible and should be rendered. 95 : : * \see isVisible() 96 : : */ 97 : : void setVisible( bool visible ); 98 : : 99 : : /** 100 : : * Returns TRUE if the annotation is attached to a fixed map position, or 101 : : * FALSE if the annotation uses a position relative to the current map 102 : : * extent. 103 : : * \see setHasFixedMapPosition() 104 : : * \see mapPosition() 105 : : * \see relativePosition() 106 : : */ 107 : 0 : bool hasFixedMapPosition() const { return mHasFixedMapPosition; } 108 : : 109 : : /** 110 : : * Sets whether the annotation is attached to a fixed map position, or 111 : : * uses a position relative to the current map extent. 112 : : * \see hasFixedMapPosition() 113 : : */ 114 : : void setHasFixedMapPosition( bool fixed ); 115 : : 116 : : /** 117 : : * Returns the map position of the annotation, if it is attached to a fixed map 118 : : * position. 119 : : * \see setMapPosition() 120 : : * \see hasFixedMapPosition() 121 : : * \see mapPositionCrs() 122 : : */ 123 : 0 : QgsPointXY mapPosition() const { return mMapPosition; } 124 : : 125 : : /** 126 : : * Sets the map position of the annotation, if it is attached to a fixed map 127 : : * position. 128 : : * \see mapPosition() 129 : : */ 130 : : void setMapPosition( const QgsPointXY &position ); 131 : : 132 : : /** 133 : : * Returns the CRS of the map position, or an invalid CRS if the annotation does 134 : : * not have a fixed map position. 135 : : * \see setMapPositionCrs() 136 : : */ 137 : 0 : QgsCoordinateReferenceSystem mapPositionCrs() const { return mMapPositionCrs; } 138 : : 139 : : /** 140 : : * Sets the CRS of the map position. 141 : : * \see mapPositionCrs() 142 : : */ 143 : : void setMapPositionCrs( const QgsCoordinateReferenceSystem &crs ); 144 : : 145 : : /** 146 : : * Returns the relative position of the annotation, if it is not attached to a fixed map 147 : : * position. The coordinates in the return point should be between 0 and 1, and represent 148 : : * the relative percentage for the position compared to the map width and height. 149 : : * \see setRelativePosition() 150 : : */ 151 : 0 : QPointF relativePosition() const { return mRelativePosition; } 152 : : 153 : : /** 154 : : * Sets the relative position of the annotation, if it is not attached to a fixed map 155 : : * position. The coordinates in the return point should be between 0 and 1, and represent 156 : : * the relative percentage for the position compared to the map width and height. 157 : : * \see relativePosition() 158 : : */ 159 : : void setRelativePosition( QPointF position ); 160 : : 161 : : /** 162 : : * Sets the annotation's frame's offset (in pixels) from the mapPosition() reference point. 163 : : * \see frameOffsetFromReferencePoint() 164 : : * \deprecated use setFrameOffsetFromReferencePointMm() instead 165 : : */ 166 : : Q_DECL_DEPRECATED void setFrameOffsetFromReferencePoint( QPointF offset ) SIP_DEPRECATED; 167 : : 168 : : /** 169 : : * Returns the annotation's frame's offset (in pixels) from the mapPosition() reference point. 170 : : * \see setFrameOffsetFromReferencePoint() 171 : : * \deprecated use frameOffsetFromReferencePointMm() instead 172 : : */ 173 : : Q_DECL_DEPRECATED QPointF frameOffsetFromReferencePoint() const SIP_DEPRECATED; 174 : : 175 : : /** 176 : : * Sets the annotation's frame's offset (in millimeters) from the mapPosition() reference point. 177 : : * \see frameOffsetFromReferencePointMm() 178 : : * \since QGIS 3.4.8 179 : : */ 180 : : void setFrameOffsetFromReferencePointMm( QPointF offset ); 181 : : 182 : : /** 183 : : * Returns the annotation's frame's offset (in millimeters) from the mapPosition() reference point. 184 : : * \see setFrameOffsetFromReferencePointMm() 185 : : * \since QGIS 3.4.8 186 : : */ 187 : : QPointF frameOffsetFromReferencePointMm() const { return mOffsetFromReferencePoint; } 188 : : 189 : : /** 190 : : * Sets the size (in pixels) of the annotation's frame (the main area in which 191 : : * the annotation's content is drawn). 192 : : * \see frameSize() 193 : : * \deprecated use setFrameSizeMm() instead 194 : : */ 195 : : Q_DECL_DEPRECATED void setFrameSize( QSizeF size ) SIP_DEPRECATED; 196 : : 197 : : /** 198 : : * Returns the size (in pixels) of the annotation's frame (the main area in which 199 : : * the annotation's content is drawn). 200 : : * \see setFrameSize() 201 : : * \deprecated use frameSizeMm() instead 202 : : */ 203 : : Q_DECL_DEPRECATED QSizeF frameSize() const SIP_DEPRECATED; 204 : : 205 : : /** 206 : : * Sets the size (in millimeters) of the annotation's frame (the main area in which 207 : : * the annotation's content is drawn). 208 : : * \see frameSizeMm() 209 : : * \since QGIS 3.4.8 210 : : */ 211 : : void setFrameSizeMm( QSizeF size ); 212 : : 213 : : /** 214 : : * Returns the size (in millimeters) of the annotation's frame (the main area in which 215 : : * the annotation's content is drawn). 216 : : * \see setFrameSizeMm() 217 : : * \since QGIS 3.4.8 218 : : */ 219 : : QSizeF frameSizeMm() const { return mFrameSize; } 220 : : 221 : : /** 222 : : * Sets the margins (in millimeters) between the outside of the frame and the annotation 223 : : * content. 224 : : * \see contentsMargin() 225 : : */ 226 : : void setContentsMargin( const QgsMargins &margins ); 227 : : 228 : : /** 229 : : * Returns the margins (in millimeters) between the outside of the frame and the annotation 230 : : * content. 231 : : * \see setContentsMargin() 232 : : */ 233 : 0 : QgsMargins contentsMargin() const { return mContentsMargins; } 234 : : 235 : : /** 236 : : * Sets the fill symbol used for rendering the annotation frame. Ownership 237 : : * of the symbol is transferred to the annotation. 238 : : * \see fillSymbol() 239 : : */ 240 : : void setFillSymbol( QgsFillSymbol *symbol SIP_TRANSFER ); 241 : : 242 : : /** 243 : : * Returns the symbol that is used for rendering the annotation frame. 244 : : * \see setFillSymbol() 245 : : */ 246 : : QgsFillSymbol *fillSymbol() const { return mFillSymbol.get(); } 247 : : 248 : : /** 249 : : * Renders the annotation to a target render context. 250 : : */ 251 : : void render( QgsRenderContext &context ) const; 252 : : 253 : : /** 254 : : * Writes the annotation state to a DOM element. Derived classes should 255 : : * call _writeXml() within their implementation of this method. 256 : : * \see readXml() 257 : : * \see _writeXml() 258 : : */ 259 : : virtual void writeXml( QDomElement &elem, QDomDocument &doc, const QgsReadWriteContext &context ) const = 0; 260 : : 261 : : /** 262 : : * Restores the annotation's state from a DOM element. Derived classes should 263 : : * call _readXml() within their implementation of this method. 264 : : * \see writeXml() 265 : : * \see _readXml() 266 : : */ 267 : : virtual void readXml( const QDomElement &itemElem, const QgsReadWriteContext &context ) = 0; 268 : : 269 : : /** 270 : : * Sets the symbol that is drawn at the annotation's map position. Ownership 271 : : * of the symbol is transferred to the annotation. 272 : : * \see markerSymbol() 273 : : */ 274 : : void setMarkerSymbol( QgsMarkerSymbol *symbol SIP_TRANSFER ); 275 : : 276 : : /** 277 : : * Returns the symbol that is drawn at the annotation's map position. 278 : : * \see setMarkerSymbol() 279 : : */ 280 : : QgsMarkerSymbol *markerSymbol() const { return mMarkerSymbol.get(); } 281 : : 282 : : /** 283 : : * Returns the map layer associated with the annotation. Annotations can be 284 : : * associated with a map layer if their visibility should be synchronized 285 : : * with the layer's visibility. 286 : : * \see setMapLayer() 287 : : */ 288 : 0 : QgsMapLayer *mapLayer() const { return mMapLayer.data(); } 289 : : 290 : : /** 291 : : * Sets the map layer associated with the annotation. Annotations can be 292 : : * associated with a map layer if their visibility should be synchronized 293 : : * with the layer's visibility. 294 : : * \see mapLayer() 295 : : */ 296 : : void setMapLayer( QgsMapLayer *layer ); 297 : : 298 : : /** 299 : : * Returns the feature associated with the annotation, or an invalid 300 : : * feature if none has been set. 301 : : * \see setAssociatedFeature() 302 : : */ 303 : 0 : QgsFeature associatedFeature() const { return mFeature; } 304 : : 305 : : /** 306 : : * Sets the feature associated with the annotation. 307 : : * \see associatedFeature() 308 : : */ 309 : : virtual void setAssociatedFeature( const QgsFeature &feature ); 310 : : 311 : : /** 312 : : * Accepts the specified style entity \a visitor, causing it to visit all style entities associated 313 : : * within the annotation. 314 : : * 315 : : * Returns TRUE if the visitor should continue visiting other objects, or FALSE if visiting 316 : : * should be canceled. 317 : : * 318 : : * \since QGIS 3.10 319 : : */ 320 : : virtual bool accept( QgsStyleEntityVisitorInterface *visitor ) const; 321 : : 322 : : signals: 323 : : 324 : : //! Emitted whenever the annotation's appearance changes 325 : : void appearanceChanged(); 326 : : 327 : : /** 328 : : * Emitted when the annotation's position has changed and items need 329 : : * to be moved to reflect this. 330 : : */ 331 : : void moved(); 332 : : 333 : : /** 334 : : * Emitted when the map layer associated with the annotation changes. 335 : : */ 336 : : void mapLayerChanged(); 337 : : 338 : : protected: 339 : : 340 : : /** 341 : : * Renders the annotation's contents to a target /a context at the specified /a size. 342 : : * Derived classes should implement their custom annotation drawing logic here. 343 : : */ 344 : : virtual void renderAnnotation( QgsRenderContext &context, QSizeF size ) const = 0; 345 : : 346 : : /** 347 : : * Returns the minimum frame size for the annotation. Subclasses should implement this if they 348 : : * cannot be resized smaller than a certain minimum size. 349 : : */ 350 : : virtual QSizeF minimumFrameSize() const; 351 : : 352 : : /** 353 : : * Writes common annotation properties to a DOM element. 354 : : * This method should be called from subclasses in their writeXml method. 355 : : * \see writeXml() 356 : : * \see _readXml() 357 : : */ 358 : : void _writeXml( QDomElement &itemElem, QDomDocument &doc, const QgsReadWriteContext &context ) const; 359 : : 360 : : /** 361 : : * Reads common annotation properties from a DOM element. 362 : : * This method should be called from subclasses in their readXml method. 363 : : * \see readXml() 364 : : * \see _writeXml() 365 : : */ 366 : : void _readXml( const QDomElement &annotationElem, const QgsReadWriteContext &context ); 367 : : 368 : : /** 369 : : * Copies common annotation properties to the \a targe 370 : : * annotation. 371 : : * Can be used within QgsAnnotation::clone() implementations 372 : : * to assist with creating copies. 373 : : */ 374 : : void copyCommonProperties( QgsAnnotation *target ) const; 375 : : 376 : : private: 377 : : 378 : : //! Draws the annotation frame to a destination painter 379 : : void drawFrame( QgsRenderContext &context ) const; 380 : : 381 : : //! Draws the map position marker symbol to a destination painter 382 : : void drawMarkerSymbol( QgsRenderContext &context ) const; 383 : : 384 : : bool mVisible = true; 385 : : 386 : : //! True if the item stays at the same map position, FALSE if the item stays on same screen position 387 : : bool mHasFixedMapPosition = true; 388 : : 389 : : //! Map position (for fixed position items) 390 : : QgsPointXY mMapPosition; 391 : : 392 : : //! CRS of the map position 393 : : QgsCoordinateReferenceSystem mMapPositionCrs; 394 : : 395 : : //! Relative position (for non-fixed items) (0-1) 396 : : QPointF mRelativePosition; 397 : : 398 : : //! Describes the shift of the item content box to the reference point in mm 399 : : QPointF mOffsetFromReferencePoint = QPointF( 13, -13 ); 400 : : 401 : : //! Size of the frame in mm (without balloon) 402 : : QSizeF mFrameSize; 403 : : 404 : : //! Point symbol that is to be drawn at the map reference location 405 : : std::unique_ptr<QgsMarkerSymbol> mMarkerSymbol; 406 : : 407 : : QgsMargins mContentsMargins; 408 : : 409 : : //! Fill symbol used for drawing annotation 410 : : std::unique_ptr<QgsFillSymbol> mFillSymbol; 411 : : 412 : : //! Associated layer (or NULLPTR if not attached to a layer) 413 : : QgsWeakMapLayerPointer mMapLayer; 414 : : 415 : : //! Associated feature, or invalid feature if no feature associated 416 : : QgsFeature mFeature; 417 : : 418 : : //! Roughly 10 pixels at 96 dpi, to match earlier version rendering 419 : : double mSegmentPointWidthMm = 2.64; 420 : : 421 : : }; 422 : : 423 : : #endif // QGSANNOTATION_H 424 : :