Branch data Line data Source code
1 : : /***************************************************************************
2 : : qgsrenderer.h
3 : : ---------------------
4 : : begin : November 2009
5 : : copyright : (C) 2009 by Martin Dobias
6 : : email : wonder dot sk at gmail dot com
7 : : ***************************************************************************
8 : : * *
9 : : * This program is free software; you can redistribute it and/or modify *
10 : : * it under the terms of the GNU General Public License as published by *
11 : : * the Free Software Foundation; either version 2 of the License, or *
12 : : * (at your option) any later version. *
13 : : * *
14 : : ***************************************************************************/
15 : :
16 : : #ifndef QGSRENDERER_H
17 : : #define QGSRENDERER_H
18 : :
19 : : #include "qgis_core.h"
20 : : #include "qgis_sip.h"
21 : : #include "qgis.h"
22 : : #include "qgsrectangle.h"
23 : : #include "qgsrendercontext.h"
24 : : #include "qgssymbol.h"
25 : : #include "qgsfields.h"
26 : : #include "qgsfeaturerequest.h"
27 : : #include "qgssymbollayerreference.h"
28 : :
29 : : #include <QList>
30 : : #include <QString>
31 : : #include <QVariant>
32 : : #include <QPair>
33 : : #include <QPixmap>
34 : : #include <QDomDocument>
35 : : #include <QDomElement>
36 : :
37 : : class QgsFeature;
38 : : class QgsVectorLayer;
39 : : class QgsPaintEffect;
40 : : class QgsReadWriteContext;
41 : : class QgsStyleEntityVisitorInterface;
42 : :
43 : : typedef QMap<QString, QString> QgsStringMap SIP_SKIP;
44 : :
45 : : typedef QList<QgsSymbol *> QgsSymbolList;
46 : : typedef QMap<QString, QgsSymbol * > QgsSymbolMap SIP_SKIP;
47 : :
48 : : #include "qgslegendsymbolitem.h"
49 : :
50 : :
51 : : #define RENDERER_TAG_NAME "renderer-v2"
52 : :
53 : : ////////
54 : : // symbol levels
55 : :
56 : : /**
57 : : * \ingroup core
58 : : * \class QgsSymbolLevelItem
59 : : */
60 : : class CORE_EXPORT QgsSymbolLevelItem
61 : : {
62 : : public:
63 : 0 : QgsSymbolLevelItem( QgsSymbol *symbol, int layer )
64 : 0 : : mSymbol( symbol )
65 : 0 : , mLayer( layer )
66 : 0 : {}
67 : :
68 : : /**
69 : : * The symbol of this symbol level
70 : : */
71 : : QgsSymbol *symbol() const;
72 : :
73 : : /**
74 : : * The layer of this symbol level
75 : : */
76 : : int layer() const;
77 : :
78 : : // TODO QGIS 4.0 -> make private
79 : : protected:
80 : : QgsSymbol *mSymbol = nullptr;
81 : : int mLayer;
82 : : };
83 : :
84 : : // every level has list of items: symbol + symbol layer num
85 : : typedef QList< QgsSymbolLevelItem > QgsSymbolLevel;
86 : :
87 : : // this is a list of levels
88 : : #ifndef SIP_RUN
89 : : typedef QList< QgsSymbolLevel > QgsSymbolLevelOrder;
90 : : #else
91 : : typedef QList< QList< QgsSymbolLevelItem > > QgsSymbolLevelOrder;
92 : : #endif
93 : :
94 : :
95 : : //////////////
96 : : // renderers
97 : :
98 : : /**
99 : : * \ingroup core
100 : : * \class QgsFeatureRenderer
101 : : */
102 : : class CORE_EXPORT QgsFeatureRenderer
103 : : {
104 : :
105 : : #ifdef SIP_RUN
106 : : SIP_CONVERT_TO_SUBCLASS_CODE
107 : :
108 : : const QString type = sipCpp->type();
109 : :
110 : : if ( type == QLatin1String( "singleSymbol" ) )
111 : : sipType = sipType_QgsSingleSymbolRenderer;
112 : : else if ( type == QLatin1String( "categorizedSymbol" ) )
113 : : sipType = sipType_QgsCategorizedSymbolRenderer;
114 : : else if ( type == QLatin1String( "graduatedSymbol" ) )
115 : : sipType = sipType_QgsGraduatedSymbolRenderer;
116 : : else if ( type == QLatin1String( "RuleRenderer" ) )
117 : : sipType = sipType_QgsRuleBasedRenderer;
118 : : else if ( type == QLatin1String( "heatmapRenderer" ) )
119 : : sipType = sipType_QgsHeatmapRenderer;
120 : : else if ( type == QLatin1String( "invertedPolygonRenderer" ) )
121 : : sipType = sipType_QgsInvertedPolygonRenderer;
122 : : else if ( type == QLatin1String( "pointCluster" ) )
123 : : sipType = sipType_QgsPointClusterRenderer;
124 : : else if ( type == QLatin1String( "pointDisplacement" ) )
125 : : sipType = sipType_QgsPointDisplacementRenderer;
126 : : else if ( type == QLatin1String( "25dRenderer" ) )
127 : : sipType = sipType_Qgs25DRenderer;
128 : : else if ( type == QLatin1String( "nullSymbol" ) )
129 : : sipType = sipType_QgsNullSymbolRenderer;
130 : : else if ( type == QLatin1String( "embeddedSymbol" ) )
131 : : sipType = sipType_QgsEmbeddedSymbolRenderer;
132 : : else
133 : : sipType = 0;
134 : : SIP_END
135 : : #endif
136 : :
137 : : public:
138 : : // renderer takes ownership of its symbols!
139 : :
140 : : //! Returns a new renderer - used by default in vector layers
141 : : static QgsFeatureRenderer *defaultRenderer( QgsWkbTypes::GeometryType geomType ) SIP_FACTORY;
142 : :
143 : 0 : QString type() const { return mType; }
144 : :
145 : : /**
146 : : * To be overridden
147 : : *
148 : : * Must be called between startRender() and stopRender() calls.
149 : : * \param feature feature
150 : : * \param context render context
151 : : * \returns returns pointer to symbol or 0 if symbol was not found
152 : : * \since QGIS 2.12
153 : : */
154 : : virtual QgsSymbol *symbolForFeature( const QgsFeature &feature, QgsRenderContext &context ) const = 0;
155 : :
156 : : /**
157 : : * Returns symbol for feature. The difference compared to symbolForFeature() is that it returns original
158 : : * symbol which can be used as an identifier for renderer's rule - the former may return a temporary replacement
159 : : * of a symbol for use in rendering.
160 : : * \since QGIS 2.12
161 : : */
162 : : virtual QgsSymbol *originalSymbolForFeature( const QgsFeature &feature, QgsRenderContext &context ) const;
163 : :
164 : : /**
165 : : * Returns legend keys matching a specified feature.
166 : : * \since QGIS 2.14
167 : : */
168 : : virtual QSet< QString > legendKeysForFeature( const QgsFeature &feature, QgsRenderContext &context ) const;
169 : :
170 : : /**
171 : : * Must be called when a new render cycle is started. A call to startRender() must always
172 : : * be followed by a corresponding call to stopRender() after all features have been rendered.
173 : : *
174 : : * \param context Additional information passed to the renderer about the job which will be rendered
175 : : * \param fields The fields available for rendering
176 : : *
177 : : * \see stopRender()
178 : : *
179 : : * \warning This method is not thread safe. Before calling startRender() in a non-main thread,
180 : : * the renderer should instead be cloned and startRender()/stopRender() called on the clone.
181 : : */
182 : : virtual void startRender( QgsRenderContext &context, const QgsFields &fields );
183 : :
184 : : /**
185 : : * Must be called when a render cycle has finished, to allow the renderer to clean up.
186 : : *
187 : : * Calls to stopRender() must always be preceded by a call to startRender().
188 : : *
189 : : * \warning This method is not thread safe. Before calling startRender() in a non-main thread,
190 : : * the renderer should instead be cloned and startRender()/stopRender() called on the clone.
191 : : *
192 : : * \see startRender()
193 : : */
194 : : virtual void stopRender( QgsRenderContext &context );
195 : :
196 : : /**
197 : : * If a renderer does not require all the features this method may be overridden
198 : : * and return an expression used as where clause.
199 : : * This will be called once after startRender() and before the first call
200 : : * to renderFeature().
201 : : * By default this returns a null string and all features will be requested.
202 : : * You do not need to specify the extent in here, this is taken care of separately and
203 : : * will be combined with a filter returned from this method.
204 : : *
205 : : * \returns An expression used as where clause
206 : : */
207 : 0 : virtual QString filter( const QgsFields &fields = QgsFields() ) { Q_UNUSED( fields ) return QString(); }
208 : :
209 : : /**
210 : : * Returns a list of attributes required by this renderer. Attributes not listed in here may
211 : : * not have been requested from the provider at rendering time.
212 : : *
213 : : * \returns A set of attributes
214 : : */
215 : : virtual QSet<QString> usedAttributes( const QgsRenderContext &context ) const = 0;
216 : :
217 : : /**
218 : : * Returns TRUE if the renderer uses embedded symbols for features.
219 : : * The default implementation returns FALSE.
220 : : *
221 : : * \since QGIS 3.20
222 : : */
223 : : virtual bool usesEmbeddedSymbols() const;
224 : :
225 : : /**
226 : : * Returns TRUE if this renderer requires the geometry to apply the filter.
227 : : */
228 : : virtual bool filterNeedsGeometry() const;
229 : :
230 : : virtual ~QgsFeatureRenderer();
231 : :
232 : : /**
233 : : * Create a deep copy of this renderer. Should be implemented by all subclasses
234 : : * and generate a proper subclass.
235 : : *
236 : : * \returns A copy of this renderer
237 : : */
238 : : virtual QgsFeatureRenderer *clone() const = 0 SIP_FACTORY;
239 : :
240 : : /**
241 : : * Render a feature using this renderer in the given context.
242 : : * Must be called between startRender() and stopRender() calls.
243 : : * Default implementation renders a symbol as determined by symbolForFeature() call.
244 : : * Returns TRUE if the feature has been returned (this is used for example
245 : : * to determine whether the feature may be labelled).
246 : : *
247 : : * If layer is not -1, the renderer should draw only a particular layer from symbols
248 : : * (in order to support symbol level rendering).
249 : : *
250 : : * \see startRender()
251 : : * \see stopRender()
252 : : */
253 : : virtual bool renderFeature( const QgsFeature &feature, QgsRenderContext &context, int layer = -1, bool selected = false, bool drawVertexMarker = false ) SIP_THROW( QgsCsException );
254 : :
255 : : //! Returns debug information about this renderer
256 : : virtual QString dump() const;
257 : :
258 : : /**
259 : : * Used to specify details about a renderer.
260 : : * Is returned from the capabilities() method.
261 : : */
262 : : enum Capability
263 : : {
264 : : SymbolLevels = 1, //!< Rendering with symbol levels (i.e. implements symbols(), symbolForFeature())
265 : : MoreSymbolsPerFeature = 1 << 2, //!< May use more than one symbol to render a feature: symbolsForFeature() will return them
266 : : Filter = 1 << 3, //!< Features may be filtered, i.e. some features may not be rendered (categorized, rule based ...)
267 : : ScaleDependent = 1 << 4 //!< Depends on scale if feature will be rendered (rule based )
268 : : };
269 : :
270 : : Q_DECLARE_FLAGS( Capabilities, Capability )
271 : :
272 : : /**
273 : : * Returns details about internals of this renderer.
274 : : *
275 : : * E.g. if you only want to deal with visible features:
276 : : *
277 : : * \code{.py}
278 : : * if not renderer.capabilities().testFlag(QgsFeatureRenderer.Filter) or renderer.willRenderFeature(feature, context):
279 : : * deal_with_my_feature()
280 : : * else:
281 : : * skip_the_curren_feature()
282 : : * \endcode
283 : : */
284 : 0 : virtual QgsFeatureRenderer::Capabilities capabilities() { return QgsFeatureRenderer::Capabilities(); }
285 : :
286 : : /**
287 : : * Returns list of symbols used by the renderer.
288 : : * \param context render context
289 : : * \since QGIS 2.12
290 : : */
291 : : virtual QgsSymbolList symbols( QgsRenderContext &context ) const;
292 : :
293 : 0 : bool usingSymbolLevels() const { return mUsingSymbolLevels; }
294 : 0 : void setUsingSymbolLevels( bool usingSymbolLevels ) { mUsingSymbolLevels = usingSymbolLevels; }
295 : :
296 : : //! create a renderer from XML element
297 : : static QgsFeatureRenderer *load( QDomElement &symbologyElem, const QgsReadWriteContext &context ) SIP_FACTORY;
298 : :
299 : : //! store renderer info to XML element
300 : : virtual QDomElement save( QDomDocument &doc, const QgsReadWriteContext &context );
301 : :
302 : : /**
303 : : * create the SLD UserStyle element following the SLD v1.1 specs with the given name
304 : : * \since QGIS 2.8
305 : : */
306 : : virtual QDomElement writeSld( QDomDocument &doc, const QString &styleName, const QVariantMap &props = QVariantMap() ) const;
307 : :
308 : : /**
309 : : * Create a new renderer according to the information contained in
310 : : * the UserStyle element of a SLD style document
311 : : * \param node the node in the SLD document whose the UserStyle element
312 : : * is a child
313 : : * \param geomType the geometry type of the features, used to convert
314 : : * Symbolizer elements
315 : : * \param errorMessage it will contain the error message if something
316 : : * went wrong
317 : : * \returns the renderer
318 : : */
319 : : static QgsFeatureRenderer *loadSld( const QDomNode &node, QgsWkbTypes::GeometryType geomType, QString &errorMessage ) SIP_FACTORY;
320 : :
321 : : //! used from subclasses to create SLD Rule elements following SLD v1.1 specs
322 : 0 : virtual void toSld( QDomDocument &doc, QDomElement &element, const QVariantMap &props = QVariantMap() ) const
323 : : {
324 : 0 : element.appendChild( doc.createComment( QStringLiteral( "FeatureRenderer %1 not implemented yet" ).arg( type() ) ) );
325 : 0 : ( void ) props; // warning avoidance
326 : 0 : }
327 : :
328 : : /**
329 : : * items of symbology items in legend should be checkable
330 : : * \since QGIS 2.5
331 : : */
332 : : virtual bool legendSymbolItemsCheckable() const;
333 : :
334 : : /**
335 : : * items of symbology items in legend is checked
336 : : * \since QGIS 2.5
337 : : */
338 : : virtual bool legendSymbolItemChecked( const QString &key );
339 : :
340 : : /**
341 : : * item in symbology was checked
342 : : * \since QGIS 2.5
343 : : */
344 : : virtual void checkLegendSymbolItem( const QString &key, bool state = true );
345 : :
346 : : /**
347 : : * Sets the symbol to be used for a legend symbol item.
348 : : * \param key rule key for legend symbol
349 : : * \param symbol new symbol for legend item. Ownership is transferred to renderer.
350 : : * \since QGIS 2.14
351 : : */
352 : : virtual void setLegendSymbolItem( const QString &key, QgsSymbol *symbol SIP_TRANSFER );
353 : :
354 : : /**
355 : : * Returns a list of symbology items for the legend
356 : : * \since QGIS 2.6
357 : : */
358 : : virtual QgsLegendSymbolList legendSymbolItems() const;
359 : :
360 : : /**
361 : : * If supported by the renderer, return classification attribute for the use in legend
362 : : * \since QGIS 2.6
363 : : */
364 : 0 : virtual QString legendClassificationAttribute() const { return QString(); }
365 : :
366 : : //! Sets type and size of editing vertex markers for subsequent rendering
367 : : void setVertexMarkerAppearance( int type, double size );
368 : :
369 : : /**
370 : : * Returns whether the renderer will render a feature or not.
371 : : * Must be called between startRender() and stopRender() calls.
372 : : * Default implementation uses symbolForFeature().
373 : : * \since QGIS 2.12
374 : : */
375 : : virtual bool willRenderFeature( const QgsFeature &feature, QgsRenderContext &context ) const;
376 : :
377 : : /**
378 : : * Returns list of symbols used for rendering the feature.
379 : : * For renderers that do not support MoreSymbolsPerFeature it is more efficient
380 : : * to use symbolForFeature()
381 : : * \since QGIS 2.12
382 : : */
383 : : virtual QgsSymbolList symbolsForFeature( const QgsFeature &feature, QgsRenderContext &context ) const;
384 : :
385 : : /**
386 : : * Equivalent of originalSymbolsForFeature() call
387 : : * extended to support renderers that may use more symbols per feature - similar to symbolsForFeature()
388 : : * \since QGIS 2.12
389 : : */
390 : : virtual QgsSymbolList originalSymbolsForFeature( const QgsFeature &feature, QgsRenderContext &context ) const;
391 : :
392 : : /**
393 : : * Allows for a renderer to modify the extent of a feature request prior to rendering
394 : : * \param extent reference to request's filter extent. Modify extent to change the
395 : : * extent of feature request
396 : : * \param context render context
397 : : * \since QGIS 2.7
398 : : */
399 : : virtual void modifyRequestExtent( QgsRectangle &extent, QgsRenderContext &context );
400 : :
401 : : /**
402 : : * Returns the current paint effect for the renderer.
403 : : * \returns paint effect
404 : : * \see setPaintEffect
405 : : * \since QGIS 2.9
406 : : */
407 : : QgsPaintEffect *paintEffect() const;
408 : :
409 : : /**
410 : : * Sets the current paint effect for the renderer.
411 : : * \param effect paint effect. Ownership is transferred to the renderer.
412 : : * \see paintEffect
413 : : * \since QGIS 2.9
414 : : */
415 : : void setPaintEffect( QgsPaintEffect *effect );
416 : :
417 : : /**
418 : : * Returns whether the renderer must render as a raster.
419 : : * \see setForceRasterRender
420 : : * \since QGIS 2.12
421 : : */
422 : 0 : bool forceRasterRender() const { return mForceRaster; }
423 : :
424 : : /**
425 : : * Sets whether the renderer should be rendered to a raster destination.
426 : : * \param forceRaster set to TRUE if renderer must be drawn on a raster surface.
427 : : * This may be desirable for highly detailed layers where rendering as a vector
428 : : * would result in a large, complex vector output.
429 : : * \see forceRasterRender
430 : : * \since QGIS 2.12
431 : : */
432 : 0 : void setForceRasterRender( bool forceRaster ) { mForceRaster = forceRaster; }
433 : :
434 : : /**
435 : : * Gets the order in which features shall be processed by this renderer.
436 : : * \note this property has no effect if orderByEnabled() is FALSE
437 : : * \see orderByEnabled()
438 : : * \since QGIS 2.14
439 : : */
440 : : QgsFeatureRequest::OrderBy orderBy() const;
441 : :
442 : : /**
443 : : * Define the order in which features shall be processed by this renderer.
444 : : * \note this property has no effect if orderByEnabled() is FALSE
445 : : * \see setOrderByEnabled()
446 : : * \since QGIS 2.14
447 : : */
448 : : void setOrderBy( const QgsFeatureRequest::OrderBy &orderBy );
449 : :
450 : : /**
451 : : * Returns whether custom ordering will be applied before features are processed by this renderer.
452 : : * \see orderBy()
453 : : * \see setOrderByEnabled()
454 : : * \since QGIS 2.14
455 : : */
456 : : bool orderByEnabled() const;
457 : :
458 : : /**
459 : : * Sets whether custom ordering should be applied before features are processed by this renderer.
460 : : * \param enabled set to TRUE to enable custom feature ordering
461 : : * \see setOrderBy()
462 : : * \see orderByEnabled()
463 : : * \since QGIS 2.14
464 : : */
465 : : void setOrderByEnabled( bool enabled );
466 : :
467 : : /**
468 : : * Sets an embedded renderer (subrenderer) for this feature renderer. The base class implementation
469 : : * does nothing with subrenderers, but individual derived classes can use these to modify their behavior.
470 : : * \param subRenderer the embedded renderer. Ownership will be transferred.
471 : : * \see embeddedRenderer()
472 : : * \since QGIS 2.16
473 : : */
474 : : virtual void setEmbeddedRenderer( QgsFeatureRenderer *subRenderer SIP_TRANSFER );
475 : :
476 : : /**
477 : : * Returns the current embedded renderer (subrenderer) for this feature renderer. The base class
478 : : * implementation does not use subrenderers and will always return NULLPTR.
479 : : * \see setEmbeddedRenderer()
480 : : * \since QGIS 2.16
481 : : */
482 : : virtual const QgsFeatureRenderer *embeddedRenderer() const;
483 : :
484 : : /**
485 : : * Accepts the specified symbology \a visitor, causing it to visit all symbols associated
486 : : * with the renderer.
487 : : *
488 : : * Returns TRUE if the visitor should continue visiting other objects, or FALSE if visiting
489 : : * should be canceled.
490 : : *
491 : : * \since QGIS 3.10
492 : : */
493 : : virtual bool accept( QgsStyleEntityVisitorInterface *visitor ) const;
494 : :
495 : : protected:
496 : : QgsFeatureRenderer( const QString &type );
497 : :
498 : : /**
499 : : * Render the \a feature with the \a symbol using \a context.
500 : : * Use \a layer to specify the symbol layer, \a selected to
501 : : * specify if it should be rendered as selected and \a drawVertexMarker
502 : : * to specify if vertex markers should be rendered.
503 : : */
504 : : void renderFeatureWithSymbol( const QgsFeature &feature, QgsSymbol *symbol, QgsRenderContext &context, int layer, bool selected, bool drawVertexMarker ) SIP_THROW( QgsCsException );
505 : :
506 : : //! render editing vertex marker at specified point
507 : : void renderVertexMarker( QPointF pt, QgsRenderContext &context );
508 : : //! render editing vertex marker for a polyline
509 : : void renderVertexMarkerPolyline( QPolygonF &pts, QgsRenderContext &context );
510 : : //! render editing vertex marker for a polygon
511 : : void renderVertexMarkerPolygon( QPolygonF &pts, QList<QPolygonF> *rings, QgsRenderContext &context );
512 : :
513 : : /**
514 : : * Creates a point in screen coordinates from a wkb string in map
515 : : * coordinates
516 : : */
517 : : static QPointF _getPoint( QgsRenderContext &context, const QgsPoint &point );
518 : :
519 : : /**
520 : : * Clones generic renderer data to another renderer.
521 : : * Currently clones
522 : : *
523 : : * - Order By
524 : : * - Paint Effect
525 : : *
526 : : * \param destRenderer destination renderer for copied effect
527 : : */
528 : : void copyRendererData( QgsFeatureRenderer *destRenderer ) const;
529 : :
530 : : QString mType;
531 : :
532 : : bool mUsingSymbolLevels;
533 : :
534 : : //! The current type of editing marker
535 : : int mCurrentVertexMarkerType;
536 : : //! The current size of editing marker
537 : : double mCurrentVertexMarkerSize;
538 : :
539 : : QgsPaintEffect *mPaintEffect = nullptr;
540 : :
541 : : bool mForceRaster;
542 : :
543 : : /**
544 : : * \note this function is used to convert old sizeScale expressions to symbol
545 : : * level DataDefined size
546 : : */
547 : : static void convertSymbolSizeScale( QgsSymbol *symbol, QgsSymbol::ScaleMethod method, const QString &field );
548 : :
549 : : /**
550 : : * \note this function is used to convert old rotations expressions to symbol
551 : : * level DataDefined angle
552 : : */
553 : : static void convertSymbolRotation( QgsSymbol *symbol, const QString &field );
554 : :
555 : : QgsFeatureRequest::OrderBy mOrderBy;
556 : :
557 : : bool mOrderByEnabled;
558 : :
559 : : private:
560 : : #ifdef SIP_RUN
561 : : QgsFeatureRenderer( const QgsFeatureRenderer & );
562 : : QgsFeatureRenderer &operator=( const QgsFeatureRenderer & );
563 : : #endif
564 : :
565 : : #ifdef QGISDEBUG
566 : : //! Pointer to thread in which startRender was first called
567 : : QThread *mThread = nullptr;
568 : : #endif
569 : :
570 : : Q_DISABLE_COPY( QgsFeatureRenderer )
571 : : };
572 : :
573 : 0 : Q_DECLARE_OPERATORS_FOR_FLAGS( QgsFeatureRenderer::Capabilities )
574 : :
575 : : // for some reason SIP compilation fails if these lines are not included:
576 : : class QgsRendererWidget;
577 : : class QgsPaintEffectWidget;
578 : :
579 : : #endif // QGSRENDERER_H
|