Branch data Line data Source code
1 : : /***************************************************************************
2 : : qgslayoutitemmap.h
3 : : -------------------
4 : : begin : July 2017
5 : : copyright : (C) 2017 by Nyall Dawson
6 : : email : nyall dot dawson at gmail dot com
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 : : #ifndef QGSLAYOUTITEMMAP_H
18 : : #define QGSLAYOUTITEMMAP_H
19 : :
20 : : #include "qgis_core.h"
21 : : #include "qgslayoutitem.h"
22 : : #include "qgslayoutitemregistry.h"
23 : : #include "qgsmaplayerref.h"
24 : : #include "qgsmaprenderercustompainterjob.h"
25 : : #include "qgslayoutitemmapgrid.h"
26 : : #include "qgslayoutitemmapoverview.h"
27 : : #include "qgsmaprendererstagedrenderjob.h"
28 : : #include "qgstemporalrangeobject.h"
29 : :
30 : : class QgsAnnotation;
31 : : class QgsRenderedFeatureHandlerInterface;
32 : :
33 : : /**
34 : : * \ingroup core
35 : : * \class QgsLayoutItemMapAtlasClippingSettings
36 : : * \brief Contains settings relating to clipping a layout map by the current atlas feature.
37 : : * \since QGIS 3.16
38 : : */
39 : : class CORE_EXPORT QgsLayoutItemMapAtlasClippingSettings : public QObject
40 : : {
41 : : Q_OBJECT
42 : :
43 : : public:
44 : :
45 : : /**
46 : : * Constructor for QgsLayoutItemMapAtlasClippingSettings, with the specified \a map parent.
47 : : */
48 : : QgsLayoutItemMapAtlasClippingSettings( QgsLayoutItemMap *map SIP_TRANSFERTHIS = nullptr );
49 : :
50 : : /**
51 : : * Returns TRUE if the map content should be clipped to the current atlas feature.
52 : : *
53 : : * \see setEnabled()
54 : : */
55 : : bool enabled() const;
56 : :
57 : : /**
58 : : * Sets whether the map content should be clipped to the current atlas feature.
59 : : *
60 : : * \see enabled()
61 : : */
62 : : void setEnabled( bool enabled );
63 : :
64 : : /**
65 : : * Returns the feature clipping type to apply when clipping to the current atlas feature.
66 : : *
67 : : * \see setFeatureClippingType()
68 : : */
69 : : QgsMapClippingRegion::FeatureClippingType featureClippingType() const;
70 : :
71 : : /**
72 : : * Sets the feature clipping \a type to apply when clipping to the current atlas feature.
73 : : *
74 : : * \see featureClippingType()
75 : : */
76 : : void setFeatureClippingType( QgsMapClippingRegion::FeatureClippingType type );
77 : :
78 : : /**
79 : : * Returns TRUE if labels should only be placed inside the atlas feature geometry.
80 : : *
81 : : * \see setForceLabelsInsideFeature()
82 : : */
83 : : bool forceLabelsInsideFeature() const;
84 : :
85 : : /**
86 : : * Sets whether labels should only be placed inside the atlas feature geometry.
87 : : *
88 : : * \see forceLabelsInsideFeature()
89 : : */
90 : : void setForceLabelsInsideFeature( bool forceInside );
91 : :
92 : : /**
93 : : * Returns TRUE if clipping should be restricted to a subset of layers.
94 : : *
95 : : * \see layersToClip()
96 : : * \see setRestrictToLayers()
97 : : */
98 : : bool restrictToLayers() const;
99 : :
100 : : /**
101 : : * Sets whether clipping should be restricted to a subset of layers.
102 : : *
103 : : * \see setLayersToClip()
104 : : * \see restrictToLayers()
105 : : */
106 : : void setRestrictToLayers( bool enabled );
107 : :
108 : : /**
109 : : * Returns the list of map layers to clip to the atlas feature.
110 : : *
111 : : * \note This setting is only used if restrictToLayers() is TRUE.
112 : : *
113 : : * \see restrictToLayers()
114 : : * \see setLayersToClip()
115 : : */
116 : : QList< QgsMapLayer * > layersToClip() const;
117 : :
118 : : /**
119 : : * Sets the list of map \a layers to clip to the atlas feature.
120 : : *
121 : : * \note This setting is only used if restrictToLayers() is TRUE.
122 : : *
123 : : * \see restrictToLayers()
124 : : * \see layersToClip()
125 : : */
126 : : void setLayersToClip( const QList< QgsMapLayer * > &layers );
127 : :
128 : : /**
129 : : * Stores settings in a DOM element, where \a element is the DOM element
130 : : * corresponding to a 'LayoutMap' tag.
131 : : * \see readXml()
132 : : */
133 : : bool writeXml( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const;
134 : :
135 : : /**
136 : : * Sets the setting's state from a DOM document, where \a element is the DOM
137 : : * node corresponding to a 'LayoutMap' tag.
138 : : * \see writeXml()
139 : : */
140 : : bool readXml( const QDomElement &element, const QDomDocument &doc, const QgsReadWriteContext &context );
141 : :
142 : : signals:
143 : :
144 : : /**
145 : : * Emitted when the atlas clipping settings are changed.
146 : : */
147 : : void changed();
148 : :
149 : : private slots:
150 : : void layersAboutToBeRemoved( const QList<QgsMapLayer *> &layers );
151 : :
152 : : private:
153 : :
154 : : QgsLayoutItemMap *mMap = nullptr;
155 : : bool mClipToAtlasFeature = false;
156 : : bool mRestrictToLayers = false;
157 : : QList< QgsMapLayerRef > mLayersToClip;
158 : : QgsMapClippingRegion::FeatureClippingType mFeatureClippingType = QgsMapClippingRegion::FeatureClippingType::ClipPainterOnly;
159 : : bool mForceLabelsInsideFeature = false;
160 : : };
161 : :
162 : :
163 : : /**
164 : : * \ingroup core
165 : : * \class QgsLayoutItemMapItemClipPathSettings
166 : : * \brief Contains settings relating to clipping a layout map by another layout item.
167 : : * \since QGIS 3.16
168 : : */
169 : : class CORE_EXPORT QgsLayoutItemMapItemClipPathSettings : public QObject
170 : : {
171 : : Q_OBJECT
172 : :
173 : : public:
174 : :
175 : : /**
176 : : * Constructor for QgsLayoutItemMapItemClipPathSettings, with the specified \a map parent.
177 : : */
178 : : QgsLayoutItemMapItemClipPathSettings( QgsLayoutItemMap *map SIP_TRANSFERTHIS = nullptr );
179 : :
180 : : /**
181 : : * Returns TRUE if the item clipping is enabled and set to a valid source item.
182 : : *
183 : : * \see enabled()
184 : : * \see sourceItem()
185 : : */
186 : : bool isActive() const;
187 : :
188 : : /**
189 : : * Returns TRUE if the map content should be clipped to the associated item.
190 : : *
191 : : * \see setEnabled()
192 : : */
193 : : bool enabled() const;
194 : :
195 : : /**
196 : : * Sets whether the map content should be clipped to the associated item.
197 : : *
198 : : * \see enabled()
199 : : */
200 : : void setEnabled( bool enabled );
201 : :
202 : : /**
203 : : * Returns the geometry to use for clipping the parent map, in the map item's CRS.
204 : : *
205 : : * \see clipPathInMapItemCoordinates()
206 : : */
207 : : QgsGeometry clippedMapExtent() const;
208 : :
209 : : /**
210 : : * Returns the clipping path geometry, in the map item's coordinate space.
211 : : *
212 : : * \warning The return path is not in geographic coordinates, rather the map
213 : : * layout item's QGraphicsItem coordinate space. Use clippedMapExtent() to retrieve
214 : : * the clip path in the map's CRS.
215 : : *
216 : : * \see clippedMapExtent()
217 : : */
218 : : QgsGeometry clipPathInMapItemCoordinates() const;
219 : :
220 : : /**
221 : : * Returns the clip path as a map clipping region.
222 : : */
223 : : QgsMapClippingRegion toMapClippingRegion() const;
224 : :
225 : : /**
226 : : * Sets the source \a item which will provide the clipping path for the map.
227 : : *
228 : : * The specified \a item must return the QgsLayoutItem::FlagProvidesClipPath flag.
229 : : *
230 : : * \see sourceItem()
231 : : */
232 : : void setSourceItem( QgsLayoutItem *item );
233 : :
234 : : /**
235 : : * Returns the source item which will provide the clipping path for the map, or NULLPTR
236 : : * if no item is set.
237 : : *
238 : : * \see setSourceItem()
239 : : */
240 : : QgsLayoutItem *sourceItem();
241 : :
242 : : /**
243 : : * Returns the feature clipping type to apply when clipping to the associated item.
244 : : *
245 : : * \see setFeatureClippingType()
246 : : */
247 : : QgsMapClippingRegion::FeatureClippingType featureClippingType() const;
248 : :
249 : : /**
250 : : * Sets the feature clipping \a type to apply when clipping to the associated item.
251 : : *
252 : : * \see featureClippingType()
253 : : */
254 : : void setFeatureClippingType( QgsMapClippingRegion::FeatureClippingType type );
255 : :
256 : : /**
257 : : * Returns TRUE if labels should only be placed inside the clip path geometry.
258 : : *
259 : : * \see setForceLabelsInsideClipPath()
260 : : */
261 : : bool forceLabelsInsideClipPath() const;
262 : :
263 : : /**
264 : : * Sets whether labels should only be placed inside the clip path geometry.
265 : : *
266 : : * \see forceLabelsInsideClipPath()
267 : : */
268 : : void setForceLabelsInsideClipPath( bool forceInside );
269 : :
270 : : /**
271 : : * Stores settings in a DOM element, where \a element is the DOM element
272 : : * corresponding to a 'LayoutMap' tag.
273 : : * \see readXml()
274 : : */
275 : : bool writeXml( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const;
276 : :
277 : : /**
278 : : * Sets the setting's state from a DOM document, where \a element is the DOM
279 : : * node corresponding to a 'LayoutMap' tag.
280 : : * \see writeXml()
281 : : * \see finalizeRestoreFromXml()
282 : : */
283 : : bool readXml( const QDomElement &element, const QDomDocument &doc, const QgsReadWriteContext &context );
284 : :
285 : : /**
286 : : * To be called after all pending items have been restored from XML.
287 : : * \see readXml()
288 : : */
289 : : void finalizeRestoreFromXml();
290 : :
291 : : signals:
292 : :
293 : : /**
294 : : * Emitted when the item clipping settings are changed.
295 : : */
296 : : void changed();
297 : :
298 : : private:
299 : :
300 : : QgsLayoutItemMap *mMap = nullptr;
301 : : bool mEnabled = false;
302 : : QgsMapClippingRegion::FeatureClippingType mFeatureClippingType = QgsMapClippingRegion::FeatureClippingType::ClipPainterOnly;
303 : : bool mForceLabelsInsideClipPath = false;
304 : :
305 : : QPointer< QgsLayoutItem > mClipPathSource;
306 : : QString mClipPathUuid;
307 : :
308 : : };
309 : :
310 : :
311 : : /**
312 : : * \ingroup core
313 : : * \class QgsLayoutItemMap
314 : : * \brief Layout graphical items for displaying a map.
315 : : * \since QGIS 3.0
316 : : */
317 : : class CORE_EXPORT QgsLayoutItemMap : public QgsLayoutItem, public QgsTemporalRangeObject
318 : : {
319 : :
320 : 0 : Q_OBJECT
321 : :
322 : : public:
323 : :
324 : : /**
325 : : * Scaling modes used for the serial rendering (atlas)
326 : : */
327 : : enum AtlasScalingMode
328 : : {
329 : : Fixed, //!< The current scale of the map is used for each feature of the atlas
330 : :
331 : : /**
332 : : * A scale is chosen from the predefined scales. The smallest scale from
333 : : * the list of scales where the atlas feature is fully visible is chosen.
334 : : * \see QgsAtlasComposition::setPredefinedScales.
335 : : * \note This mode is only valid for polygon or line atlas coverage layers
336 : : */
337 : : Predefined,
338 : :
339 : : /**
340 : : * The extent is adjusted so that each feature is fully visible.
341 : : * A margin is applied around the center \see setAtlasMargin
342 : : * \note This mode is only valid for polygon or line atlas coverage layers
343 : : */
344 : : Auto
345 : : };
346 : :
347 : : /**
348 : : * Various flags that affect drawing of map items.
349 : : * \since QGIS 3.6
350 : : */
351 : : enum MapItemFlag
352 : : {
353 : : ShowPartialLabels = 1 << 0, //!< Whether to draw labels which are partially outside of the map view
354 : : ShowUnplacedLabels = 1 << 1, //!< Whether to render unplaced labels in the map view
355 : : };
356 : : Q_DECLARE_FLAGS( MapItemFlags, MapItemFlag )
357 : :
358 : : /**
359 : : * Constructor for QgsLayoutItemMap, with the specified parent \a layout.
360 : : */
361 : : explicit QgsLayoutItemMap( QgsLayout *layout );
362 : : ~QgsLayoutItemMap() override;
363 : :
364 : : int type() const override;
365 : : QIcon icon() const override;
366 : : QgsLayoutItem::Flags itemFlags() const override;
367 : :
368 : : /**
369 : : * Returns the map item's flags, which control how the map content is drawn.
370 : : * \see setMapFlags()
371 : : * \since QGIS 3.6
372 : : */
373 : : QgsLayoutItemMap::MapItemFlags mapFlags() const;
374 : :
375 : : /**
376 : : * Sets the map item's \a flags, which control how the map content is drawn.
377 : : * \see mapFlags()
378 : : * \since QGIS 3.6
379 : : */
380 : : void setMapFlags( QgsLayoutItemMap::MapItemFlags flags );
381 : :
382 : : /**
383 : : * Sets the map id() to a number not yet used in the layout. The existing id() is kept if it is not in use.
384 : : */
385 : : void assignFreeId();
386 : :
387 : : //overridden to show "Map 1" type names
388 : : QString displayName() const override;
389 : :
390 : : /**
391 : : * Returns a new map item for the specified \a layout.
392 : : *
393 : : * The caller takes responsibility for deleting the returned object.
394 : : */
395 : : static QgsLayoutItemMap *create( QgsLayout *layout ) SIP_FACTORY;
396 : :
397 : : // for now, map items behave a bit differently and don't implement draw. TODO - see if we can avoid this
398 : : void paint( QPainter *painter, const QStyleOptionGraphicsItem *itemStyle, QWidget *pWidget ) override;
399 : : Q_DECL_DEPRECATED int numberExportLayers() const override SIP_DEPRECATED;
400 : : void startLayeredExport() override;
401 : : void stopLayeredExport() override;
402 : : bool nextExportPart() override;
403 : : ExportLayerBehavior exportLayerBehavior() const override;
404 : : QgsLayoutItem::ExportLayerDetail exportLayerDetails() const override;
405 : : void setFrameStrokeWidth( QgsLayoutMeasurement width ) override;
406 : :
407 : : /**
408 : : * Returns the map scale.
409 : : * The scale value indicates the scale denominator, e.g. 1000.0 for a 1:1000 map.
410 : : * \see setScale()
411 : : */
412 : : double scale() const;
413 : :
414 : : /**
415 : : * Sets new map \a scale and changes only the map extent.
416 : : *
417 : : * The \a scale value indicates the scale denominator, e.g. 1000.0 for a 1:1000 map.
418 : : *
419 : : * \see scale()
420 : : */
421 : : void setScale( double scale, bool forceUpdate = true );
422 : :
423 : : /**
424 : : * Sets a new \a extent for the map. This method may change the width or height of the map
425 : : * item to ensure that the extent exactly matches the specified extent, with no
426 : : * overlap or margin. This method implicitly alters the map scale.
427 : : * \see zoomToExtent()
428 : : * \see extentChanged()
429 : : */
430 : : void setExtent( const QgsRectangle &extent );
431 : :
432 : : /**
433 : : * Zooms the map so that the specified \a extent is fully visible within the map item.
434 : : * This method will not change the width or height of the map, and may result in
435 : : * an overlap or margin from the specified extent. This method implicitly alters the
436 : : * map scale.
437 : : * \see setExtent()
438 : : */
439 : : void zoomToExtent( const QgsRectangle &extent );
440 : :
441 : : /**
442 : : * Returns the current map extent.
443 : : * \see visibleExtentPolygon()
444 : : * \see extentChanged()
445 : : */
446 : : QgsRectangle extent() const;
447 : :
448 : :
449 : : /**
450 : : * Returns a polygon representing the current visible map extent, considering map extents and rotation.
451 : : * If the map rotation is 0, the result is the same as currentMapExtent
452 : : * \returns polygon with the four corner points representing the visible map extent. The points are
453 : : * clockwise, starting at the top-left point
454 : : * \see extent()
455 : : */
456 : : QPolygonF visibleExtentPolygon() const;
457 : :
458 : : /**
459 : : * Returns coordinate reference system used for rendering the map.
460 : : * This will match the presetCrs() if that is set, or if a preset
461 : : * CRS is not set then the map's CRS will follow the composition's
462 : : * project's CRS.
463 : : * \see presetCrs()
464 : : * \see setCrs()
465 : : */
466 : : QgsCoordinateReferenceSystem crs() const;
467 : :
468 : : /**
469 : : * Returns the map's preset coordinate reference system. If set, this
470 : : * CRS will be used to render the map regardless of any project CRS
471 : : * setting. If the returned CRS is not valid then the project CRS
472 : : * will be used to render the map.
473 : : * \see crs()
474 : : * \see setCrs()
475 : : */
476 : : QgsCoordinateReferenceSystem presetCrs() const { return mCrs; }
477 : :
478 : : /**
479 : : * Sets the map's preset \a crs (coordinate reference system). If a valid CRS is
480 : : * set, this CRS will be used to render the map regardless of any project CRS
481 : : * setting. If the CRS is not valid then the project CRS will be used to render the map.
482 : : * \see crs()
483 : : * \see presetCrs()
484 : : */
485 : : void setCrs( const QgsCoordinateReferenceSystem &crs );
486 : :
487 : : /**
488 : : * Returns whether a stored layer set should be used
489 : : * or the current layer set from the project associated with the layout. This is just a GUI flag,
490 : : * and itself does not change which layers are rendered in the map.
491 : : * Instead, use setLayers() to control which layers are rendered.
492 : : * \see setKeepLayerSet()
493 : : * \see layers()
494 : : */
495 : 0 : bool keepLayerSet() const { return mKeepLayerSet; }
496 : :
497 : : /**
498 : : * Sets whether the stored layer set should be used
499 : : * or the current layer set of the associated project. This is just a GUI flag,
500 : : * and itself does not change which layers are rendered in the map.
501 : : * Instead, use setLayers() to control which layers are rendered.
502 : : * \see keepLayerSet()
503 : : * \see layers()
504 : : */
505 : 0 : void setKeepLayerSet( bool enabled ) { mKeepLayerSet = enabled; }
506 : :
507 : : /**
508 : : * Returns the stored layer set. If empty, the current project layers will
509 : : * be used instead.
510 : : * \see setLayers()
511 : : * \see keepLayerSet()
512 : : */
513 : : QList<QgsMapLayer *> layers() const;
514 : :
515 : : /**
516 : : * Sets the stored \a layers set. If empty, the current project layers will
517 : : * be used instead.
518 : : * \see layers()
519 : : * \see keepLayerSet()
520 : : */
521 : : void setLayers( const QList<QgsMapLayer *> &layers );
522 : :
523 : : /**
524 : : * Returns whether current styles of layers should be overridden by previously stored styles.
525 : : * \see setKeepLayerStyles()
526 : : */
527 : : bool keepLayerStyles() const { return mKeepLayerStyles; }
528 : :
529 : : /**
530 : : * Sets whether current styles of layers should be overridden by previously stored styles.
531 : : * \see keepLayerStyles()
532 : : */
533 : : void setKeepLayerStyles( bool enabled ) { mKeepLayerStyles = enabled; }
534 : :
535 : : /**
536 : : * Returns stored overrides of styles for layers.
537 : : * \see setLayerStyleOverrides()
538 : : */
539 : 0 : QMap<QString, QString> layerStyleOverrides() const { return mLayerStyleOverrides; }
540 : :
541 : : /**
542 : : * Sets the stored overrides of styles for layers.
543 : : * \see layerStyleOverrides()
544 : : */
545 : : void setLayerStyleOverrides( const QMap<QString, QString> &overrides );
546 : :
547 : : /**
548 : : * Stores the current project layer styles into style overrides.
549 : : */
550 : : void storeCurrentLayerStyles();
551 : :
552 : : /**
553 : : * Returns whether the map should follow a map theme. If TRUE, the layers and layer styles
554 : : * will be used from given preset name (configured with setFollowVisibilityPresetName() method).
555 : : * This means when preset's settings are changed, the new settings are automatically
556 : : * picked up next time when rendering, without having to explicitly update them.
557 : : * At most one of the flags keepLayerSet() and followVisibilityPreset() should be enabled
558 : : * at any time since they are alternative approaches - if both are enabled,
559 : : * following map theme has higher priority. If neither is enabled (or if preset name is not set),
560 : : * map will use the same configuration as the map canvas uses.
561 : : */
562 : 0 : bool followVisibilityPreset() const { return mFollowVisibilityPreset; }
563 : :
564 : : /**
565 : : * Sets whether the map should follow a map theme. See followVisibilityPreset() for more details.
566 : : */
567 : : void setFollowVisibilityPreset( bool follow );
568 : :
569 : : /**
570 : : * Preset name that decides which layers and layer styles are used for map rendering. It is only
571 : : * used when followVisibilityPreset() returns TRUE.
572 : : * \see setFollowVisibilityPresetName()
573 : : *
574 : : * \see themeChanged()
575 : : */
576 : : QString followVisibilityPresetName() const { return mFollowVisibilityPresetName; }
577 : :
578 : : /**
579 : : * Sets preset name for map rendering. See followVisibilityPresetName() for more details.
580 : : * \see followVisibilityPresetName()
581 : : *
582 : : * \see themeChanged()
583 : : */
584 : : void setFollowVisibilityPresetName( const QString &name );
585 : :
586 : : void moveContent( double dx, double dy ) override;
587 : : void setMoveContentPreviewOffset( double dx, double dy ) override;
588 : :
589 : : void zoomContent( double factor, QPointF point ) override;
590 : :
591 : :
592 : : //! Returns TRUE if the map contains a WMS layer.
593 : : bool containsWmsLayer() const;
594 : :
595 : : bool requiresRasterization() const override;
596 : : bool containsAdvancedEffects() const override;
597 : :
598 : : /**
599 : : * Sets the \a rotation for the map - this does not affect the layout item shape, only the
600 : : * way the map is drawn within the item. Rotation is in degrees, clockwise.
601 : : * \see mapRotation()
602 : : * \see mapRotationChanged()
603 : : */
604 : : void setMapRotation( double rotation );
605 : :
606 : : /**
607 : : * Returns the rotation used for drawing the map within the layout item, in degrees clockwise.
608 : : * \param valueType controls whether the returned value is the user specified rotation,
609 : : * or the current evaluated rotation (which may be affected by data driven rotation
610 : : * settings).
611 : : * \see setMapRotation()
612 : : * \see mapRotationChanged()
613 : : */
614 : : double mapRotation( QgsLayoutObject::PropertyValueType valueType = QgsLayoutObject::EvaluatedValue ) const;
615 : :
616 : : /**
617 : : * Sets whether annotations are drawn within the map.
618 : : * \see drawAnnotations()
619 : : */
620 : 0 : void setDrawAnnotations( bool draw ) { mDrawAnnotations = draw; }
621 : :
622 : : /**
623 : : * Returns whether annotations are drawn within the map.
624 : : * \see setDrawAnnotations()
625 : : */
626 : : bool drawAnnotations() const { return mDrawAnnotations; }
627 : :
628 : :
629 : : /**
630 : : * Returns whether the map extent is set to follow the current atlas feature.
631 : : * \returns TRUE if map will follow the current atlas feature.
632 : : * \see setAtlasDriven
633 : : * \see atlasScalingMode
634 : : */
635 : 0 : bool atlasDriven() const { return mAtlasDriven; }
636 : :
637 : : /**
638 : : * Sets whether the map extent will follow the current atlas feature.
639 : : * \param enabled set to TRUE if the map extents should be set by the current atlas feature.
640 : : * \see atlasDriven
641 : : * \see setAtlasScalingMode
642 : : */
643 : : void setAtlasDriven( bool enabled );
644 : :
645 : : /**
646 : : * Returns the current atlas scaling mode. This controls how the map's extents
647 : : * are calculated for the current atlas feature when an atlas composition
648 : : * is enabled.
649 : : * \returns the current scaling mode
650 : : * \note this parameter is only used if atlasDriven() is TRUE
651 : : * \see setAtlasScalingMode
652 : : * \see atlasDriven
653 : : */
654 : : AtlasScalingMode atlasScalingMode() const { return mAtlasScalingMode; }
655 : :
656 : : /**
657 : : * Sets the current atlas scaling mode. This controls how the map's extents
658 : : * are calculated for the current atlas feature when an atlas composition
659 : : * is enabled.
660 : : * \param mode atlas scaling mode to set
661 : : * \note this parameter is only used if atlasDriven() is TRUE
662 : : * \see atlasScalingMode
663 : : * \see atlasDriven
664 : : */
665 : 0 : void setAtlasScalingMode( AtlasScalingMode mode ) { mAtlasScalingMode = mode; }
666 : :
667 : : /**
668 : : * Returns the margin size (percentage) used when the map is in atlas mode.
669 : : * \param valueType controls whether the returned value is the user specified atlas margin,
670 : : * or the current evaluated atlas margin (which may be affected by data driven atlas margin
671 : : * settings).
672 : : * \returns margin size in percentage to leave around the atlas feature's extent
673 : : * \note this is only used if atlasScalingMode() is Auto.
674 : : * \see atlasScalingMode
675 : : * \see setAtlasMargin
676 : : */
677 : : double atlasMargin( QgsLayoutObject::PropertyValueType valueType = QgsLayoutObject::EvaluatedValue );
678 : :
679 : : /**
680 : : * Sets the margin size (percentage) used when the map is in atlas mode.
681 : : * \param margin size in percentage to leave around the atlas feature's extent
682 : : * \note this is only used if atlasScalingMode() is Auto.
683 : : * \see atlasScalingMode
684 : : * \see atlasMargin
685 : : */
686 : 0 : void setAtlasMargin( double margin ) { mAtlasMargin = margin; }
687 : :
688 : : /**
689 : : * Returns the map item's grid stack, which is used to control how grids
690 : : * are drawn over the map's contents.
691 : : * \see grid()
692 : : */
693 : : QgsLayoutItemMapGridStack *grids() { return mGridStack.get(); }
694 : :
695 : : /**
696 : : * Returns the map item's first grid. This is a convenience function.
697 : : * \see grids()
698 : : */
699 : : QgsLayoutItemMapGrid *grid();
700 : :
701 : : /**
702 : : * Returns the map item's overview stack, which is used to control how overviews
703 : : * are drawn over the map's contents.
704 : : * \returns pointer to overview stack
705 : : * \see overview()
706 : : */
707 : : QgsLayoutItemMapOverviewStack *overviews() { return mOverviewStack.get(); }
708 : :
709 : : /**
710 : : * Returns the map item's first overview. This is a convenience function.
711 : : * \returns pointer to first overview for map item
712 : : * \see overviews()
713 : : */
714 : : QgsLayoutItemMapOverview *overview();
715 : :
716 : : /**
717 : : * Returns the margin from the map edges in which no labels may be placed.
718 : : *
719 : : * If the margin is 0 then labels can be placed right up to the edge (and possibly overlapping the edge)
720 : : * of the map.
721 : : *
722 : : * \see setLabelMargin()
723 : : *
724 : : * \since QGIS 3.6
725 : : */
726 : : QgsLayoutMeasurement labelMargin() const;
727 : :
728 : : /**
729 : : * Sets the \a margin from the map edges in which no labels may be placed.
730 : : *
731 : : * If the margin is 0 then labels can be placed right up to the edge (and possibly overlapping the edge)
732 : : * of the map.
733 : : *
734 : : * \see labelMargin()
735 : : *
736 : : * \since QGIS 3.6
737 : : */
738 : : void setLabelMargin( const QgsLayoutMeasurement &margin );
739 : :
740 : : QgsExpressionContext createExpressionContext() const override;
741 : :
742 : : /**
743 : : * Returns the conversion factor from map units to layout units.
744 : : * This is calculated using the width of the map item and the width of the
745 : : * current visible map extent.
746 : : */
747 : : double mapUnitsToLayoutUnits() const;
748 : :
749 : : /**
750 : : * Returns map settings that will be used for drawing of the map.
751 : : *
752 : : * If \a includeLayerSettings is TRUE, than settings specifically relating to map layers and map layer styles
753 : : * will be calculated. This can be expensive to calculate, so if they are not required in the map settings
754 : : * (e.g. for map settings which are used for scale related calculations only) then \a includeLayerSettings should be FALSE.
755 : : */
756 : : QgsMapSettings mapSettings( const QgsRectangle &extent, QSizeF size, double dpi, bool includeLayerSettings ) const;
757 : :
758 : : void finalizeRestoreFromXml() override;
759 : :
760 : : /**
761 : : * Returns a list of the layers which will be rendered within this map item, considering
762 : : * any locked layers, linked map theme, and data defined settings.
763 : : */
764 : : QList<QgsMapLayer *> layersToRender( const QgsExpressionContext *context = nullptr ) const;
765 : :
766 : : /**
767 : : * Sets the specified layout \a item as a "label blocking item" for this map.
768 : : *
769 : : * Items which are marked as label blocking items prevent any map labels from being placed
770 : : * in the area of the map item covered by the \a item.
771 : : *
772 : : * \see removeLabelBlockingItem()
773 : : * \see isLabelBlockingItem()
774 : : *
775 : : * \since QGIS 3.6
776 : : */
777 : : void addLabelBlockingItem( QgsLayoutItem *item );
778 : :
779 : : /**
780 : : * Removes the specified layout \a item from the map's "label blocking items".
781 : : *
782 : : * Items which are marked as label blocking items prevent any map labels from being placed
783 : : * in the area of the map item covered by the item.
784 : : *
785 : : * \see addLabelBlockingItem()
786 : : * \see isLabelBlockingItem()
787 : : *
788 : : * \since QGIS 3.6
789 : : */
790 : : void removeLabelBlockingItem( QgsLayoutItem *item );
791 : :
792 : : /**
793 : : * Returns TRUE if the specified \a item is a "label blocking item".
794 : : *
795 : : * Items which are marked as label blocking items prevent any map labels from being placed
796 : : * in the area of the map item covered by the item.
797 : : *
798 : : * \see addLabelBlockingItem()
799 : : * \see removeLabelBlockingItem()
800 : : *
801 : : * \since QGIS 3.6
802 : : */
803 : : bool isLabelBlockingItem( QgsLayoutItem *item ) const;
804 : :
805 : : /**
806 : : * \brief Returns map rendering errors
807 : : * \returns list of errors
808 : : */
809 : : QgsMapRendererJob::Errors renderingErrors() const { return mRenderingErrors; }
810 : :
811 : : bool accept( QgsStyleEntityVisitorInterface *visitor ) const override;
812 : :
813 : : /**
814 : : * Adds a rendered feature \a handler to use while rendering the map.
815 : : *
816 : : * Ownership of \a handler is NOT transferred, and it is the caller's responsibility to ensure
817 : : * that the handler exists for as long as it is registered with the map item.
818 : : *
819 : : * Callers should call removeRenderedFeatureHandler() to remove the handler before
820 : : * destroying the \a handler.
821 : : *
822 : : * \see removeRenderedFeatureHandler()
823 : : * \since QGIS 3.10
824 : : */
825 : : void addRenderedFeatureHandler( QgsRenderedFeatureHandlerInterface *handler );
826 : :
827 : : /**
828 : : * Removes a previously added rendered feature \a handler.
829 : : *
830 : : * \see addRenderedFeatureHandler()
831 : : * \since QGIS 3.10
832 : : */
833 : : void removeRenderedFeatureHandler( QgsRenderedFeatureHandlerInterface *handler );
834 : :
835 : : /**
836 : : * Creates a transform from layout coordinates to map coordinates.
837 : : */
838 : : QTransform layoutToMapCoordsTransform() const;
839 : :
840 : : /**
841 : : * Returns the map's atlas clipping settings.
842 : : *
843 : : * \since QGIS 3.16
844 : : */
845 : : QgsLayoutItemMapAtlasClippingSettings *atlasClippingSettings() { return mAtlasClippingSettings; }
846 : :
847 : : /**
848 : : * Returns the map's item based clip path settings.
849 : : *
850 : : * \since QGIS 3.16
851 : : */
852 : 0 : QgsLayoutItemMapItemClipPathSettings *itemClippingSettings() { return mItemClippingSettings; }
853 : :
854 : : protected:
855 : :
856 : : void draw( QgsLayoutItemRenderContext &context ) override;
857 : : bool writePropertiesToElement( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const override;
858 : : bool readPropertiesFromElement( const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context ) override;
859 : : QPainterPath framePath() const override;
860 : :
861 : : //! True if a draw is already in progress
862 : : bool isDrawing() const {return mDrawing;}
863 : :
864 : : // In case of annotations, the bounding rectangle can be larger than the map item rectangle
865 : : QRectF boundingRect() const override;
866 : :
867 : : //! Returns extent that considers rotation and shift with mOffsetX / mOffsetY
868 : : QPolygonF transformedMapPolygon() const;
869 : :
870 : : //! Transforms map coordinates to item coordinates (considering rotation and move offset)
871 : : QPointF mapToItemCoords( QPointF mapCoords ) const;
872 : :
873 : : /**
874 : : * Calculates the extent to request and the yShift of the top-left point in case of rotation.
875 : : */
876 : : QgsRectangle requestedExtent() const;
877 : :
878 : : signals:
879 : :
880 : : /**
881 : : * Emitted when the map's extent changes.
882 : : * \see setExtent()
883 : : * \see extent()
884 : : */
885 : : void extentChanged();
886 : :
887 : : /**
888 : : * Emitted when the map's rotation changes.
889 : : * \see setMapRotation()
890 : : * \see mapRotation()
891 : : */
892 : : void mapRotationChanged( double newRotation );
893 : :
894 : : //! Emitted when the map has been prepared for atlas rendering, just before actual rendering
895 : : void preparedForAtlas();
896 : :
897 : : /**
898 : : * Emitted when layer style overrides are changed... a means to let
899 : : * associated legend items know they should update
900 : : */
901 : : void layerStyleOverridesChanged();
902 : :
903 : : /**
904 : : * Emitted when the map's associated \a theme is changed.
905 : : *
906 : : * \note This signal is not emitted when the definition of the theme changes, only the map
907 : : * is linked to a different theme then it previously was.
908 : : *
909 : : * \since QGIS 3.14
910 : : */
911 : : void themeChanged( const QString &theme );
912 : :
913 : : /**
914 : : * Emitted when the map's coordinate reference system is changed.
915 : : *
916 : : * \since QGIS 3.18
917 : : */
918 : : void crsChanged();
919 : :
920 : : public slots:
921 : :
922 : : void refresh() override;
923 : :
924 : : void invalidateCache() override;
925 : :
926 : : //! Updates the bounding rect of this item. Call this function before doing any changes related to annotation out of the map rectangle
927 : : void updateBoundingRect();
928 : :
929 : : void refreshDataDefinedProperty( QgsLayoutObject::DataDefinedProperty property = QgsLayoutObject::AllProperties ) override;
930 : :
931 : : private slots:
932 : : void layersAboutToBeRemoved( const QList<QgsMapLayer *> &layers );
933 : :
934 : : void painterJobFinished();
935 : :
936 : : void shapeChanged();
937 : :
938 : : void mapThemeChanged( const QString &theme );
939 : :
940 : : //! Renames the active map theme called \a theme to \a newTheme
941 : : void currentMapThemeRenamed( const QString &theme, const QString &newTheme );
942 : :
943 : : //! Create cache image
944 : : void recreateCachedImageInBackground();
945 : :
946 : : void updateAtlasFeature();
947 : : private:
948 : :
949 : : QgsLayoutItemMap::MapItemFlags mMapFlags = QgsLayoutItemMap::MapItemFlags();
950 : :
951 : : //! Unique identifier
952 : : int mMapId = 1;
953 : :
954 : : std::unique_ptr< QgsLayoutItemMapGridStack > mGridStack;
955 : : std::unique_ptr< QgsLayoutItemMapOverviewStack > mOverviewStack;
956 : :
957 : : // Map region in map units really used for rendering
958 : : // It can be the same as mUserExtent, but it can be bigger in on dimension if mCalculate==Scale,
959 : : // so that full rectangle in paper is used.
960 : : QgsRectangle mExtent;
961 : :
962 : : //! Map CRS
963 : : QgsCoordinateReferenceSystem mCrs;
964 : :
965 : : // Current temporary map region in map units. This is overwritten when atlas feature changes. It's also
966 : : // used when the user changes the map extent and an atlas preview is enabled. This allows the user
967 : : // to manually tweak each atlas preview page without affecting the actual original map extent.
968 : : QgsRectangle mAtlasFeatureExtent;
969 : :
970 : : // We have two images used for rendering/storing cached map images.
971 : : // the first (mCacheFinalImage) is used ONLY for storing the most recent completed map render. It's always
972 : : // used when drawing map item previews. The second (mCacheRenderingImage) is used temporarily while
973 : : // rendering a new preview image in the background. If (and only if) the background render completes, then
974 : : // mCacheRenderingImage is pushed into mCacheFinalImage, and used from then on when drawing the item preview.
975 : : // This ensures that something is always shown in the map item, even while refreshing the preview image in the
976 : : // background
977 : : std::unique_ptr< QImage > mCacheFinalImage;
978 : : std::unique_ptr< QImage > mCacheRenderingImage;
979 : : bool mUpdatesEnabled = true;
980 : :
981 : : //! True if cached map image must be recreated
982 : : bool mCacheInvalidated = true;
983 : :
984 : : //! \brief Number of layers when cache was created
985 : : int mNumCachedLayers;
986 : :
987 : : // Set to true if in state of drawing. Concurrent requests to draw method are returned if set to true
988 : : bool mDrawing = false;
989 : :
990 : : QTimer *mBackgroundUpdateTimer = nullptr;
991 : : double mPreviewScaleFactor = 0;
992 : :
993 : : bool mDrawingPreview = false;
994 : :
995 : : //! Offset in x direction for showing map cache image
996 : : double mXOffset = 0.0;
997 : : //! Offset in y direction for showing map cache image
998 : : double mYOffset = 0.0;
999 : :
1000 : : double mLastRenderedImageOffsetX = 0.0;
1001 : : double mLastRenderedImageOffsetY = 0.0;
1002 : :
1003 : : //! Map rotation
1004 : : double mMapRotation = 0;
1005 : :
1006 : : /**
1007 : : * Temporary evaluated map rotation. Data defined rotation may mean this value
1008 : : * differs from mMapRotation
1009 : : */
1010 : : double mEvaluatedMapRotation = 0;
1011 : :
1012 : : //! Flag if layers to be displayed should be read from qgis canvas (TRUE) or from stored list in mLayerSet (FALSE)
1013 : : bool mKeepLayerSet = false;
1014 : :
1015 : : //! Stored layer list (used if layer live-link mKeepLayerSet is disabled)
1016 : : QList< QgsMapLayerRef > mLayers;
1017 : :
1018 : : bool mKeepLayerStyles = false;
1019 : : //! Stored style names (value) to be used with particular layer IDs (key) instead of default style
1020 : : QMap<QString, QString> mLayerStyleOverrides;
1021 : :
1022 : : //! Empty if no cached style overrides stored
1023 : : mutable QString mCachedLayerStyleOverridesPresetName;
1024 : : //! Cached style overrides, used to avoid frequent expensive lookups of the preset style override
1025 : : mutable QMap<QString, QString> mCachedPresetLayerStyleOverrides;
1026 : :
1027 : : /**
1028 : : * Whether layers and styles should be used from a preset (preset name is stored
1029 : : * in mVisibilityPresetName and may be overridden by data-defined expression).
1030 : : * This flag has higher priority than mKeepLayerSet.
1031 : : */
1032 : : bool mFollowVisibilityPreset = false;
1033 : :
1034 : : /**
1035 : : * Map theme name to be used for map's layers and styles in case mFollowVisibilityPreset
1036 : : * is TRUE. May be overridden by data-defined expression.
1037 : : */
1038 : : QString mFollowVisibilityPresetName;
1039 : :
1040 : : //! Name of the last data-defined evaluated theme name
1041 : : QString mLastEvaluatedThemeName;
1042 : :
1043 : : /**
1044 : : * \brief Draw to paint device
1045 : : * \param painter painter
1046 : : * \param extent map extent
1047 : : * \param size size in scene coordinates
1048 : : * \param dpi scene dpi
1049 : : */
1050 : : void drawMap( QPainter *painter, const QgsRectangle &extent, QSizeF size, double dpi );
1051 : :
1052 : : //! Establishes signal/slot connection for update in case of layer change
1053 : : void connectUpdateSlot();
1054 : :
1055 : : //! Removes layer ids from mLayerSet that are no longer present in the qgis main map
1056 : : void syncLayerSet();
1057 : :
1058 : : //! Returns first map grid or creates an empty one if none
1059 : : const QgsLayoutItemMapGrid *constFirstMapGrid() const;
1060 : :
1061 : : //! Returns first map overview or creates an empty one if none
1062 : : const QgsLayoutItemMapOverview *constFirstMapOverview() const;
1063 : :
1064 : : /**
1065 : : * Creates a list of label blocking regions for the map, which correspond to the
1066 : : * map areas covered by other layout items marked as label blockers for this map.
1067 : : */
1068 : : QList< QgsLabelBlockingRegion > createLabelBlockingRegions( const QgsMapSettings &mapSettings ) const;
1069 : :
1070 : : //! Current bounding rectangle. This is used to check if notification to the graphics scene is necessary
1071 : : QRectF mCurrentRectangle;
1072 : : //! True if annotation items, rubber band, etc. from the main canvas should be displayed
1073 : : bool mDrawAnnotations = true;
1074 : :
1075 : : //! True if map is being controlled by an atlas
1076 : : bool mAtlasDriven = false;
1077 : : //! Current atlas scaling mode
1078 : : AtlasScalingMode mAtlasScalingMode = Auto;
1079 : : //! Margin size for atlas driven extents (percentage of feature size) - when in auto scaling mode
1080 : : double mAtlasMargin = 0.10;
1081 : :
1082 : : std::unique_ptr< QPainter > mPainter;
1083 : : std::unique_ptr< QgsMapRendererCustomPainterJob > mPainterJob;
1084 : : bool mPainterCancelWait = false;
1085 : :
1086 : : QgsLayoutMeasurement mLabelMargin{ 0 };
1087 : : QgsLayoutMeasurement mEvaluatedLabelMargin{ 0 };
1088 : :
1089 : : QStringList mBlockingLabelItemUuids;
1090 : : QList< QPointer< QgsLayoutItem > > mBlockingLabelItems;
1091 : :
1092 : : //!layer id / error message
1093 : : QgsMapRendererJob::Errors mRenderingErrors;
1094 : :
1095 : : QList< QgsRenderedFeatureHandlerInterface * > mRenderedFeatureHandlers;
1096 : :
1097 : : std::unique_ptr< QgsMapRendererStagedRenderJob > mStagedRendererJob;
1098 : :
1099 : : void init();
1100 : :
1101 : : //! Resets the item tooltip to reflect current map id
1102 : : void updateToolTip();
1103 : :
1104 : : QString themeToRender( const QgsExpressionContext &context ) const;
1105 : :
1106 : : //! Returns current layer style overrides for this map item
1107 : : QMap<QString, QString> layerStyleOverridesToRender( const QgsExpressionContext &context ) const;
1108 : :
1109 : : //! Returns extent that considers mOffsetX / mOffsetY (during content move)
1110 : : QgsRectangle transformedExtent() const;
1111 : :
1112 : : //! MapPolygon variant using a given extent
1113 : : void mapPolygon( const QgsRectangle &extent, QPolygonF &poly ) const;
1114 : :
1115 : : /**
1116 : : * Scales a layout map shift (in layout units) and rotates it by mRotation
1117 : : * \param xShift in: shift in x direction (in item units), out: xShift in map units
1118 : : * \param yShift in: shift in y direction (in item units), out: yShift in map units
1119 : : */
1120 : : void transformShift( double &xShift, double &yShift ) const;
1121 : :
1122 : : void drawAnnotations( QPainter *painter );
1123 : : void drawAnnotation( const QgsAnnotation *item, QgsRenderContext &context );
1124 : : QPointF layoutMapPosForItem( const QgsAnnotation *item ) const;
1125 : :
1126 : : void drawMapFrame( QPainter *p );
1127 : : void drawMapBackground( QPainter *p );
1128 : :
1129 : : enum PartType
1130 : : {
1131 : : Start,
1132 : : Background,
1133 : : Layer,
1134 : : Grid,
1135 : : OverviewMapExtent,
1136 : : Frame,
1137 : : SelectionBoxes,
1138 : : End,
1139 : : NotLayered,
1140 : : };
1141 : :
1142 : : //! Test if a part of the item needs to be drawn, considering the context's current export layer
1143 : : bool shouldDrawPart( PartType part ) const;
1144 : :
1145 : : PartType mCurrentExportPart = NotLayered;
1146 : : QStringList mExportThemes;
1147 : : QStringList::iterator mExportThemeIt;
1148 : :
1149 : : QgsLayoutItemMapAtlasClippingSettings *mAtlasClippingSettings = nullptr;
1150 : : QgsLayoutItemMapItemClipPathSettings *mItemClippingSettings = nullptr;
1151 : :
1152 : : /**
1153 : : * Refresh the map's extents, considering data defined extent, scale and rotation
1154 : : * \param context expression context for evaluating data defined map parameters
1155 : : */
1156 : : void refreshMapExtents( const QgsExpressionContext *context = nullptr );
1157 : :
1158 : : void refreshLabelMargin( bool updateItem );
1159 : :
1160 : : QgsRectangle computeAtlasRectangle();
1161 : :
1162 : : void createStagedRenderJob( const QgsRectangle &extent, const QSizeF size, double dpi );
1163 : :
1164 : : QPolygonF calculateVisibleExtentPolygon( bool includeClipping ) const;
1165 : :
1166 : : friend class QgsLayoutItemMapGrid;
1167 : : friend class QgsLayoutItemMapOverview;
1168 : : friend class QgsLayoutItemLegend;
1169 : : friend class TestQgsLayoutMap;
1170 : : friend class QgsCompositionConverter;
1171 : : friend class QgsGeoPdfRenderedFeatureHandler;
1172 : :
1173 : : };
1174 : :
1175 : : Q_DECLARE_OPERATORS_FOR_FLAGS( QgsLayoutItemMap::MapItemFlags )
1176 : :
1177 : : #endif //QGSLAYOUTITEMMAP_H
|