Branch data Line data Source code
1 : : /***************************************************************************
2 : : qgslegendrenderer.h
3 : : --------------------------------------
4 : : Date : July 2014
5 : : Copyright : (C) 2014 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 QGSLEGENDRENDERER_H
17 : : #define QGSLEGENDRENDERER_H
18 : :
19 : : #include "qgis_core.h"
20 : : #include <QPointF>
21 : :
22 : : class QRectF;
23 : : class QStandardItem;
24 : : class QJsonObject;
25 : :
26 : : class QgsLayerTreeGroup;
27 : : class QgsLayerTreeLayer;
28 : : class QgsLayerTreeModel;
29 : : class QgsLayerTreeModelLegendNode;
30 : : class QgsLayerTreeNode;
31 : : class QgsSymbol;
32 : : class QgsRenderContext;
33 : :
34 : : #include "qgslegendsettings.h"
35 : :
36 : : /**
37 : : * \ingroup core
38 : : * \brief The QgsLegendRenderer class handles automatic layout and rendering of legend.
39 : : * The content is given by QgsLayerTreeModel instance. Various layout properties can be configured
40 : : * within QgsLegendRenderer.
41 : : *
42 : : * All spacing and sizes are in millimeters.
43 : : *
44 : : * \since QGIS 2.6
45 : : */
46 : 0 : class CORE_EXPORT QgsLegendRenderer
47 : : {
48 : : public:
49 : :
50 : : /**
51 : : * Constructor for QgsLegendRenderer. The ownership of the legend model is not changed,
52 : : * and the model must exist for the lifetime of this renderer.
53 : : */
54 : : QgsLegendRenderer( QgsLayerTreeModel *legendModel, const QgsLegendSettings &settings );
55 : :
56 : : /**
57 : : * Runs the layout algorithm and returns the minimum size required for the legend.
58 : : * \see setLegendSize()
59 : : * \see legendSize()
60 : : */
61 : : QSizeF minimumSize( QgsRenderContext *renderContext = nullptr );
62 : :
63 : : /**
64 : : * Sets the preferred resulting legend size.
65 : : *
66 : : * If the size is null, the legend will be drawn with the minimum possible size to fit its content.
67 : : *
68 : : * \see legendSize()
69 : : * \see minimumSize()
70 : : */
71 : 0 : void setLegendSize( QSizeF s ) { mLegendSize = s; }
72 : :
73 : : /**
74 : : * Returns the preferred legend size set by the client.
75 : : *
76 : : * If the returned size is null, the legend will be drawn with the minimum possible size to fit its content.
77 : : *
78 : : * \see minimumSize()
79 : : * \see setLegendSize()
80 : : */
81 : : QSizeF legendSize() const { return mLegendSize; }
82 : :
83 : : /**
84 : : * Draws the legend with given \a painter. The legend will occupy the area reported in legendSize().
85 : : * The \a painter should be scaled beforehand so that units correspond to millimeters.
86 : : *
87 : : * \deprecated Use the variant which accepts a QgsRenderContext instead.
88 : : */
89 : : Q_DECL_DEPRECATED void drawLegend( QPainter *painter ) SIP_DEPRECATED;
90 : :
91 : : /**
92 : : * Draws the legend using a given render \a context. The legend will occupy the area reported in legendSize().
93 : : *
94 : : * \since QGIS 3.6
95 : : */
96 : : void drawLegend( QgsRenderContext &context );
97 : :
98 : : /**
99 : : * Renders the legend in a \a json object.
100 : : *
101 : : * \since QGIS 3.8
102 : : */
103 : : QJsonObject exportLegendToJson( const QgsRenderContext &context );
104 : :
105 : : /**
106 : : * Sets the \a style of a \a node.
107 : : *
108 : : * \see nodeLegendStyle()
109 : : */
110 : : static void setNodeLegendStyle( QgsLayerTreeNode *node, QgsLegendStyle::Style style );
111 : :
112 : : /**
113 : : * Returns the style for the given \a node, within the specified \a model.
114 : : *
115 : : * \see setNodeLegendStyle()
116 : : */
117 : : static QgsLegendStyle::Style nodeLegendStyle( QgsLayerTreeNode *node, QgsLayerTreeModel *model );
118 : :
119 : : private:
120 : :
121 : : #ifndef SIP_RUN
122 : :
123 : : /**
124 : : * A legend component is either a group title, a layer title or a layer child item.
125 : : *
126 : : * E.g. a layer title component is just the layer's title, it does not
127 : : * include all of that layer's subitems. Similarly, a group's title component is just
128 : : * the group title, and does not include the actual content of that group.
129 : : */
130 : : class LegendComponent
131 : : {
132 : : public:
133 : :
134 : 0 : LegendComponent() = default;
135 : :
136 : 0 : QObject *item = nullptr;
137 : :
138 : : //! Symbol size, not including any preset padding space around the symbol
139 : : QSizeF symbolSize;
140 : :
141 : : //! Label size, not including any preset padding space around the label
142 : : QSizeF labelSize;
143 : :
144 : : //! Component size
145 : : QSizeF size;
146 : :
147 : : /**
148 : : * Horizontal offset for the symbol label.
149 : : *
150 : : * This offset is the same for all symbol labels belonging to the same layer,
151 : : * within the same legend column.
152 : : */
153 : 0 : double labelXOffset = 0.0;
154 : :
155 : : /**
156 : : * Largest symbol width, considering all other sibling components associated with
157 : : * this component.
158 : : */
159 : 0 : double maxSiblingSymbolWidth = 0.0;
160 : : };
161 : :
162 : : /**
163 : : * An component group is an indivisible set of legend components (i.e. it is indivisible into more columns).
164 : : *
165 : : * A group may consist of one or more component(s), depending on the layer splitting mode:
166 : : *
167 : : * 1) no layer split: [group_title ...] layer_title layer_item [layer_item ...]
168 : : * 2) layer split: [group_title ...] layer_title layer_item
169 : : * or: layer_item
170 : : *
171 : : * This means that group titles must not be split from layer titles and layer titles
172 : : * must not be split from the first layer item, because this results in a poor layout
173 : : * and it would not be logical to leave a group or layer title at the bottom of a column,
174 : : * separated from the actual content of that group or layer.
175 : : */
176 : 0 : class LegendComponentGroup
177 : : {
178 : : public:
179 : :
180 : : //! List of child components belonging to this group.
181 : : QList<LegendComponent> components;
182 : :
183 : : //! Group size, including internal spacing between components, but excluding any padding space around the group itself.
184 : 0 : QSizeF size = QSizeF( 0, 0 );
185 : :
186 : : //! Corresponding column index
187 : 0 : int column = 0;
188 : :
189 : : /**
190 : : * TRUE if a forced column break should be placed just before the group
191 : : */
192 : 0 : bool placeColumnBreakBeforeGroup = false;
193 : :
194 : : };
195 : :
196 : : /**
197 : : * Contains contextual information about the current column being rendered
198 : : */
199 : : class ColumnContext
200 : : {
201 : : public:
202 : :
203 : 0 : ColumnContext()
204 : 0 : : left( 0 )
205 : 0 : , right( 0 )
206 : 0 : {}
207 : :
208 : : //! Left edge of column
209 : : double left = 0;
210 : : //! Right edge of column
211 : : double right = 0;
212 : : };
213 : :
214 : : /**
215 : : * Returns a list of component groups for the specified \a parentGroup, respecting the current layer's
216 : : * splitting settings.
217 : : */
218 : : QList<LegendComponentGroup> createComponentGroupList( QgsLayerTreeGroup *parentGroup, QgsRenderContext &context );
219 : :
220 : : /**
221 : : * Divides a list of component groups into columns, and sets the column index for each group in the list.
222 : : *
223 : : * Returns the calculated number of columns.
224 : : */
225 : : int setColumns( QList<LegendComponentGroup> &groupList );
226 : :
227 : : /**
228 : : * Returns the calculated padding space required above the given component \a group.
229 : : */
230 : : double spaceAboveGroup( const LegendComponentGroup &group );
231 : :
232 : : /**
233 : : * Renders a group item in a \a json object.
234 : : *
235 : : * \since QGIS 3.8
236 : : */
237 : : QJsonObject exportLegendToJson( const QgsRenderContext &context, QgsLayerTreeGroup *nodeGroup );
238 : :
239 : : /**
240 : : * Draws the legend using the specified render \a context, and returns the actual size of the legend.
241 : : *
242 : : * If \a context is NULLPTR, only the size of the legend will be calculated and no
243 : : * painting will be attempted.
244 : : */
245 : : QSizeF paintAndDetermineSize( QgsRenderContext &context );
246 : :
247 : : /**
248 : : * Draws a title in the legend using the specified render \a context, with the title font and the specified alignment settings.
249 : : *
250 : : * Returns the size required to draw the complete title.
251 : : *
252 : : * If \a context is NULLPTR, no painting will be attempted, but the required size will still be calculated and returned.
253 : : */
254 : : QSizeF drawTitle( QgsRenderContext &context, double top, Qt::AlignmentFlag halignment = Qt::AlignLeft, double legendWidth = 0 );
255 : :
256 : : /**
257 : : * Draws an \a group and return its actual size, using the specified render \a context.
258 : : *
259 : : * The \a group is drawn with the space above it, so that the first groups in a column are all
260 : : * aligned to the same line regardless of their style top spacing.
261 : : *
262 : : * If \a context is NULLPTR, no painting will be attempted, but the required size will still be calculated and returned.
263 : : */
264 : : QSizeF drawGroup( const LegendComponentGroup &group, QgsRenderContext &context, ColumnContext columnContext, double top = 0 );
265 : :
266 : : /**
267 : : * Draws the symbol of a given symbol QgsLayerTreeModelLegendNode, using the specified render \a context.
268 : : */
269 : : LegendComponent drawSymbolItem( QgsLayerTreeModelLegendNode *symbolItem, QgsRenderContext &context, ColumnContext columnContext, double top, double maxSiblingSymbolWidth = 0 );
270 : :
271 : : /**
272 : : * Draws the title of a layer, given a QgsLayerTreeLayer, and a destination render \a context.
273 : : *
274 : : * Returns the size of the title.
275 : : *
276 : : * The \a context may be NULLPTR, in which case on the size is calculated and no painting is attempted.
277 : : */
278 : : QSizeF drawLayerTitle( QgsLayerTreeLayer *nodeLayer, QgsRenderContext &context, ColumnContext columnContext = ColumnContext(), double top = 0 );
279 : :
280 : : /**
281 : : * Draws a group's title, using the specified render \a context.
282 : : *
283 : : * Returns the size of the title.
284 : : */
285 : : QSizeF drawGroupTitle( QgsLayerTreeGroup *nodeGroup, QgsRenderContext &context, ColumnContext columnContext = ColumnContext(), double top = 0 );
286 : :
287 : : /**
288 : : * Returns the style of the given \a node.
289 : : */
290 : : QgsLegendStyle::Style nodeLegendStyle( QgsLayerTreeNode *node );
291 : :
292 : : QgsLayerTreeModel *mLegendModel = nullptr;
293 : :
294 : : QgsLegendSettings mSettings;
295 : :
296 : : QSizeF mLegendSize;
297 : :
298 : : #endif
299 : :
300 : : void widthAndOffsetForTitleText( const Qt::AlignmentFlag halignment, double legendWidth, double &width, double &offset );
301 : : };
302 : :
303 : : #endif // QGSLEGENDRENDERER_H
|