QGIS API Documentation  2.5.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
qgslegendrenderer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgslegendrenderer.cpp
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 #include "qgslegendrenderer.h"
17 
18 #include "qgscomposerlegenditem.h"
19 #include "qgslayertree.h"
20 #include "qgslayertreemodel.h"
22 #include "qgslegendmodel.h"
23 #include "qgsmaplayerlegend.h"
24 #include "qgsmaplayerregistry.h"
25 #include "qgssymbolv2.h"
26 #include "qgsvectorlayer.h"
27 
28 #include <QPainter>
29 
30 
31 
33  : mLegendModel( legendModel )
34  , mSettings( settings )
35 {
36 }
37 
39 {
40  return paintAndDetermineSize( 0 );
41 }
42 
43 void QgsLegendRenderer::drawLegend( QPainter* painter )
44 {
45  paintAndDetermineSize( painter );
46 }
47 
48 
49 QSizeF QgsLegendRenderer::paintAndDetermineSize( QPainter* painter )
50 {
51  QSizeF size( 0, 0 );
53  if ( !rootGroup ) return size;
54 
55  QList<Atom> atomList = createAtomList( rootGroup, mSettings.splitLayer() );
56 
57  setColumns( atomList );
58 
59  qreal maxColumnWidth = 0;
61  {
62  foreach ( Atom atom, atomList )
63  {
64  maxColumnWidth = qMax( atom.size.width(), maxColumnWidth );
65  }
66  }
67 
68  //calculate size of title
69  QSizeF titleSize = drawTitle();
70  //add title margin to size of title text
71  titleSize.rwidth() += mSettings.boxSpace() * 2.0;
73 
74  QPointF point( mSettings.boxSpace(), columnTop );
75  bool firstInColumn = true;
76  double columnMaxHeight = 0;
77  qreal columnWidth = 0;
78  int column = 0;
79  foreach ( Atom atom, atomList )
80  {
81  if ( atom.column > column )
82  {
83  // Switch to next column
85  {
86  point.rx() += mSettings.columnSpace() + maxColumnWidth;
87  }
88  else
89  {
90  point.rx() += mSettings.columnSpace() + columnWidth;
91  }
92  point.ry() = columnTop;
93  columnWidth = 0;
94  column++;
95  firstInColumn = true;
96  }
97  if ( !firstInColumn )
98  {
99  point.ry() += spaceAboveAtom( atom );
100  }
101 
102  QSizeF atomSize = drawAtom( atom, painter, point );
103  columnWidth = qMax( atomSize.width(), columnWidth );
104 
105  point.ry() += atom.size.height();
106  columnMaxHeight = qMax( point.y() - columnTop, columnMaxHeight );
107 
108  firstInColumn = false;
109  }
110  point.rx() += columnWidth + mSettings.boxSpace();
111 
112  size.rheight() = columnTop + columnMaxHeight + mSettings.boxSpace();
113  size.rwidth() = point.x();
114  if ( !mSettings.title().isEmpty() )
115  {
116  size.rwidth() = qMax( titleSize.width(), size.width() );
117  }
118 
119  // override the size if it was set by the user
120  if ( mLegendSize.isValid() )
121  {
122  qreal w = qMax( size.width(), mLegendSize.width() );
123  qreal h = qMax( size.height(), mLegendSize.height() );
124  size = QSizeF( w, h );
125  }
126 
127  // Now we have set the correct total item width and can draw the title centered
128  if ( !mSettings.title().isEmpty() )
129  {
130  if ( mSettings.titleAlignment() == Qt::AlignLeft )
131  {
132  point.rx() = mSettings.boxSpace();
133  }
134  else if ( mSettings.titleAlignment() == Qt::AlignHCenter )
135  {
136  point.rx() = size.width() / 2;
137  }
138  else
139  {
140  point.rx() = size.width() - mSettings.boxSpace();
141  }
142  point.ry() = mSettings.boxSpace();
143  drawTitle( painter, point, mSettings.titleAlignment(), size.width() );
144  }
145 
146  return size;
147 }
148 
149 
150 
151 
152 
153 QList<QgsLegendRenderer::Atom> QgsLegendRenderer::createAtomList( QgsLayerTreeGroup* parentGroup, bool splitLayer )
154 {
155  QList<Atom> atoms;
156 
157  if ( !parentGroup ) return atoms;
158 
159  foreach ( QgsLayerTreeNode* node, parentGroup->children() )
160  {
161  if ( QgsLayerTree::isGroup( node ) )
162  {
163  QgsLayerTreeGroup* nodeGroup = QgsLayerTree::toGroup( node );
164 
165  // Group subitems
166  QList<Atom> groupAtoms = createAtomList( nodeGroup, splitLayer );
167 
168  Nucleon nucleon;
169  nucleon.item = node;
170  nucleon.size = drawGroupTitle( nodeGroup );
171 
172  if ( groupAtoms.size() > 0 )
173  {
174  // Add internal space between this group title and the next nucleon
175  groupAtoms[0].size.rheight() += spaceAboveAtom( groupAtoms[0] );
176  // Prepend this group title to the first atom
177  groupAtoms[0].nucleons.prepend( nucleon );
178  groupAtoms[0].size.rheight() += nucleon.size.height();
179  groupAtoms[0].size.rwidth() = qMax( nucleon.size.width(), groupAtoms[0].size.width() );
180  }
181  else
182  {
183  // no subitems, append new atom
184  Atom atom;
185  atom.nucleons.append( nucleon );
186  atom.size.rwidth() += nucleon.size.width();
187  atom.size.rheight() += nucleon.size.height();
188  atom.size.rwidth() = qMax( nucleon.size.width(), atom.size.width() );
189  groupAtoms.append( atom );
190  }
191  atoms.append( groupAtoms );
192  }
193  else if ( QgsLayerTree::isLayer( node ) )
194  {
195  QgsLayerTreeLayer* nodeLayer = QgsLayerTree::toLayer( node );
196 
197  Atom atom;
198 
199  if ( nodeLegendStyle( nodeLayer ) != QgsComposerLegendStyle::Hidden )
200  {
201  Nucleon nucleon;
202  nucleon.item = node;
203  nucleon.size = drawLayerTitle( nodeLayer );
204  atom.nucleons.append( nucleon );
205  atom.size.rwidth() = nucleon.size.width();
206  atom.size.rheight() = nucleon.size.height();
207  }
208 
209  QList<QgsLayerTreeModelLegendNode*> legendNodes = mLegendModel->layerLegendNodes( nodeLayer );
210 
211  QList<Atom> layerAtoms;
212 
213  for ( int j = 0; j < legendNodes.count(); j++ )
214  {
215  QgsLayerTreeModelLegendNode* legendNode = legendNodes.at( j );
216 
217  Nucleon symbolNucleon = drawSymbolItem( legendNode );
218 
219  if ( !mSettings.splitLayer() || j == 0 )
220  {
221  // append to layer atom
222  // the width is not correct at this moment, we must align all symbol labels
223  atom.size.rwidth() = qMax( symbolNucleon.size.width(), atom.size.width() );
224  // Add symbol space only if there is already title or another item above
225  if ( atom.nucleons.size() > 0 )
226  {
227  // TODO: for now we keep Symbol and SymbolLabel Top margin in sync
229  }
230  atom.size.rheight() += symbolNucleon.size.height();
231  atom.nucleons.append( symbolNucleon );
232  }
233  else
234  {
235  Atom symbolAtom;
236  symbolAtom.nucleons.append( symbolNucleon );
237  symbolAtom.size.rwidth() = symbolNucleon.size.width();
238  symbolAtom.size.rheight() = symbolNucleon.size.height();
239  layerAtoms.append( symbolAtom );
240  }
241  }
242  layerAtoms.prepend( atom );
243  atoms.append( layerAtoms );
244  }
245  }
246 
247  return atoms;
248 }
249 
250 
251 
252 void QgsLegendRenderer::setColumns( QList<Atom>& atomList )
253 {
254  if ( mSettings.columnCount() == 0 ) return;
255 
256  // Divide atoms to columns
257  double totalHeight = 0;
258  // bool first = true;
259  qreal maxAtomHeight = 0;
260  foreach ( Atom atom, atomList )
261  {
262  //if ( !first )
263  //{
264  totalHeight += spaceAboveAtom( atom );
265  //}
266  totalHeight += atom.size.height();
267  maxAtomHeight = qMax( atom.size.height(), maxAtomHeight );
268  // first = false;
269  }
270 
271  // We know height of each atom and we have to split them into columns
272  // minimizing max column height. It is sort of bin packing problem, NP-hard.
273  // We are using simple heuristic, brute fore appeared to be to slow,
274  // the number of combinations is N = n!/(k!*(n-k)!) where n = atomsCount-1
275  // and k = columnsCount-1
276 
277  double avgColumnHeight = totalHeight / mSettings.columnCount();
278  int currentColumn = 0;
279  int currentColumnAtomCount = 0; // number of atoms in current column
280  double currentColumnHeight = 0;
281  double maxColumnHeight = 0;
282  double closedColumnsHeight = 0;
283  // first = true; // first in column
284  for ( int i = 0; i < atomList.size(); i++ )
285  {
286  Atom atom = atomList[i];
287  double currentHeight = currentColumnHeight;
288  //if ( !first )
289  //{
290  currentHeight += spaceAboveAtom( atom );
291  //}
292  currentHeight += atom.size.height();
293 
294  // Recalc average height for remaining columns including current
295  avgColumnHeight = ( totalHeight - closedColumnsHeight ) / ( mSettings.columnCount() - currentColumn );
296  if (( currentHeight - avgColumnHeight ) > atom.size.height() / 2 // center of current atom is over average height
297  && currentColumnAtomCount > 0 // do not leave empty column
298  && currentHeight > maxAtomHeight // no sense to make smaller columns than max atom height
299  && currentHeight > maxColumnHeight // no sense to make smaller columns than max column already created
300  && currentColumn < mSettings.columnCount() - 1 ) // must not exceed max number of columns
301  {
302  // New column
303  currentColumn++;
304  currentColumnAtomCount = 0;
305  closedColumnsHeight += currentColumnHeight;
306  currentColumnHeight = atom.size.height();
307  }
308  else
309  {
310  currentColumnHeight = currentHeight;
311  }
312  atomList[i].column = currentColumn;
313  currentColumnAtomCount++;
314  maxColumnHeight = qMax( currentColumnHeight, maxColumnHeight );
315 
316  // first = false;
317  }
318 
319  // Alling labels of symbols for each layr/column to the same labelXOffset
320  QMap<QString, qreal> maxSymbolWidth;
321  for ( int i = 0; i < atomList.size(); i++ )
322  {
323  Atom& atom = atomList[i];
324  for ( int j = 0; j < atom.nucleons.size(); j++ )
325  {
326  if ( QgsLayerTreeModelLegendNode* legendNode = qobject_cast<QgsLayerTreeModelLegendNode*>( atom.nucleons[j].item ) )
327  {
328  QString key = QString( "%1-%2" ).arg(( qulonglong )legendNode->parent() ).arg( atom.column );
329  maxSymbolWidth[key] = qMax( atom.nucleons[j].symbolSize.width(), maxSymbolWidth[key] );
330  }
331  }
332  }
333  for ( int i = 0; i < atomList.size(); i++ )
334  {
335  Atom& atom = atomList[i];
336  for ( int j = 0; j < atom.nucleons.size(); j++ )
337  {
338  if ( QgsLayerTreeModelLegendNode* legendNode = qobject_cast<QgsLayerTreeModelLegendNode*>( atom.nucleons[j].item ) )
339  {
340  QString key = QString( "%1-%2" ).arg(( qulonglong )legendNode->parent() ).arg( atom.column );
343  atom.nucleons[j].labelXOffset = maxSymbolWidth[key] + space;
344  atom.nucleons[j].size.rwidth() = maxSymbolWidth[key] + space + atom.nucleons[j].labelSize.width();
345  }
346  }
347  }
348 }
349 
350 
351 
352 QSizeF QgsLegendRenderer::drawTitle( QPainter* painter, QPointF point, Qt::AlignmentFlag halignment, double legendWidth )
353 {
354  QSizeF size( 0, 0 );
355  if ( mSettings.title().isEmpty() )
356  {
357  return size;
358  }
359 
360  QStringList lines = mSettings.splitStringForWrapping( mSettings.title() );
361  double y = point.y();
362 
363  if ( painter )
364  {
365  painter->setPen( mSettings.fontColor() );
366  }
367 
368  //calculate width and left pos of rectangle to draw text into
369  double textBoxWidth;
370  double textBoxLeft;
371  switch ( halignment )
372  {
373  case Qt::AlignHCenter:
374  textBoxWidth = ( qMin( point.x(), legendWidth - point.x() ) - mSettings.boxSpace() ) * 2.0;
375  textBoxLeft = point.x() - textBoxWidth / 2.;
376  break;
377  case Qt::AlignRight:
378  textBoxLeft = mSettings.boxSpace();
379  textBoxWidth = point.x() - mSettings.boxSpace();
380  break;
381  case Qt::AlignLeft:
382  default:
383  textBoxLeft = point.x();
384  textBoxWidth = legendWidth - point.x() - mSettings.boxSpace();
385  break;
386  }
387 
388  QFont titleFont = mSettings.style( QgsComposerLegendStyle::Title ).font();
389 
390  for ( QStringList::Iterator titlePart = lines.begin(); titlePart != lines.end(); ++titlePart )
391  {
392  //last word is not drawn if rectangle width is exactly text width, so add 1
393  //TODO - correctly calculate size of italicized text, since QFontMetrics does not
394  qreal width = mSettings.textWidthMillimeters( titleFont, *titlePart ) + 1;
395  qreal height = mSettings.fontAscentMillimeters( titleFont ) + mSettings.fontDescentMillimeters( titleFont );
396 
397  QRectF r( textBoxLeft, y, textBoxWidth, height );
398 
399  if ( painter )
400  {
401  mSettings.drawText( painter, r, *titlePart, titleFont, halignment, Qt::AlignVCenter, Qt::TextDontClip );
402  }
403 
404  //update max width of title
405  size.rwidth() = qMax( width, size.rwidth() );
406 
407  y += height;
408  if ( titlePart != lines.end() )
409  {
410  y += mSettings.lineSpacing();
411  }
412  }
413  size.rheight() = y - point.y();
414 
415  return size;
416 }
417 
418 
420 {
421  if ( atom.nucleons.size() == 0 ) return 0;
422 
423  Nucleon nucleon = atom.nucleons.first();
424 
425  if ( QgsLayerTreeGroup* nodeGroup = qobject_cast<QgsLayerTreeGroup*>( nucleon.item ) )
426  {
428  }
429  else if ( QgsLayerTreeLayer* nodeLayer = qobject_cast<QgsLayerTreeLayer*>( nucleon.item ) )
430  {
432  }
433  else if ( qobject_cast<QgsLayerTreeModelLegendNode*>( nucleon.item ) )
434  {
435  // TODO: use Symbol or SymbolLabel Top margin
437  }
438 
439  return 0;
440 }
441 
442 
443 // Draw atom and expand its size (using actual nucleons labelXOffset)
444 QSizeF QgsLegendRenderer::drawAtom( Atom atom, QPainter* painter, QPointF point )
445 {
446  bool first = true;
447  QSizeF size = QSizeF( atom.size );
448  foreach ( Nucleon nucleon, atom.nucleons )
449  {
450  if ( QgsLayerTreeGroup* groupItem = qobject_cast<QgsLayerTreeGroup*>( nucleon.item ) )
451  {
454  {
455  if ( !first )
456  {
457  point.ry() += mSettings.style( s ).margin( QgsComposerLegendStyle::Top );
458  }
459  drawGroupTitle( groupItem, painter, point );
460  }
461  }
462  else if ( QgsLayerTreeLayer* layerItem = qobject_cast<QgsLayerTreeLayer*>( nucleon.item ) )
463  {
466  {
467  if ( !first )
468  {
469  point.ry() += mSettings.style( s ).margin( QgsComposerLegendStyle::Top );
470  }
471  drawLayerTitle( layerItem, painter, point );
472  }
473  }
474  else if ( QgsLayerTreeModelLegendNode* legendNode = qobject_cast<QgsLayerTreeModelLegendNode*>( nucleon.item ) )
475  {
476  if ( !first )
477  {
479  }
480 
481  Nucleon symbolNucleon = drawSymbolItem( legendNode, painter, point, nucleon.labelXOffset );
482  // expand width, it may be wider because of labelXOffset
483  size.rwidth() = qMax( symbolNucleon.size.width(), size.width() );
484  }
485  point.ry() += nucleon.size.height();
486  first = false;
487  }
488  return size;
489 }
490 
491 
492 QgsLegendRenderer::Nucleon QgsLegendRenderer::drawSymbolItem( QgsLayerTreeModelLegendNode* symbolItem, QPainter* painter, QPointF point, double labelXOffset )
493 {
495  ctx.painter = painter;
496  ctx.point = point;
497  ctx.labelXOffset = labelXOffset;
498 
499  QgsLayerTreeModelLegendNode::ItemMetrics im = symbolItem->draw( mSettings, painter ? &ctx : 0 );
500 
501  Nucleon nucleon;
502  nucleon.item = symbolItem;
503  nucleon.symbolSize = im.symbolSize;
504  nucleon.labelSize = im.labelSize;
505  //QgsDebugMsg( QString( "symbol height = %1 label height = %2").arg( symbolSize.height()).arg( labelSize.height() ));
506  double width = qMax(( double ) im.symbolSize.width(), labelXOffset ) + im.labelSize.width();
507  double height = qMax( im.symbolSize.height(), im.labelSize.height() );
508  nucleon.size = QSizeF( width, height );
509  return nucleon;
510 }
511 
512 
513 QSizeF QgsLegendRenderer::drawLayerTitle( QgsLayerTreeLayer* nodeLayer, QPainter* painter, QPointF point )
514 {
515  QSizeF size( 0, 0 );
516  QModelIndex idx = mLegendModel->node2index( nodeLayer );
517 
518  //Let the user omit the layer title item by having an empty layer title string
519  if ( mLegendModel->data( idx, Qt::DisplayRole ).toString().isEmpty() ) return size;
520 
521  double y = point.y();
522 
523  if ( painter ) painter->setPen( mSettings.fontColor() );
524 
525  QFont layerFont = mSettings.style( nodeLegendStyle( nodeLayer ) ).font();
526 
527  QStringList lines = mSettings.splitStringForWrapping( mLegendModel->data( idx, Qt::DisplayRole ).toString() );
528  for ( QStringList::Iterator layerItemPart = lines.begin(); layerItemPart != lines.end(); ++layerItemPart )
529  {
530  y += mSettings.fontAscentMillimeters( layerFont );
531  if ( painter ) mSettings.drawText( painter, point.x(), y, *layerItemPart , layerFont );
532  qreal width = mSettings.textWidthMillimeters( layerFont, *layerItemPart );
533  size.rwidth() = qMax( width, size.width() );
534  if ( layerItemPart != lines.end() )
535  {
536  y += mSettings.lineSpacing();
537  }
538  }
539  size.rheight() = y - point.y();
540 
541  return size;
542 }
543 
544 
545 QSizeF QgsLegendRenderer::drawGroupTitle( QgsLayerTreeGroup* nodeGroup, QPainter* painter, QPointF point )
546 {
547  QSizeF size( 0, 0 );
548  QModelIndex idx = mLegendModel->node2index( nodeGroup );
549 
550  double y = point.y();
551 
552  if ( painter ) painter->setPen( mSettings.fontColor() );
553 
554  QFont groupFont = mSettings.style( nodeLegendStyle( nodeGroup ) ).font();
555 
556  QStringList lines = mSettings.splitStringForWrapping( mLegendModel->data( idx, Qt::DisplayRole ).toString() );
557  for ( QStringList::Iterator groupPart = lines.begin(); groupPart != lines.end(); ++groupPart )
558  {
559  y += mSettings.fontAscentMillimeters( groupFont );
560  if ( painter ) mSettings.drawText( painter, point.x(), y, *groupPart, groupFont );
561  qreal width = mSettings.textWidthMillimeters( groupFont, *groupPart );
562  size.rwidth() = qMax( width, size.width() );
563  if ( groupPart != lines.end() )
564  {
565  y += mSettings.lineSpacing();
566  }
567  }
568  size.rheight() = y - point.y();
569  return size;
570 }
571 
572 
573 
575 {
576  QString style = node->customProperty( "legend/title-style" ).toString();
577  if ( style == "hidden" )
579  else if ( style == "group" )
581  else if ( style == "subgroup" )
583 
584  // use a default otherwise
585  if ( QgsLayerTree::isGroup( node ) )
587  else if ( QgsLayerTree::isLayer( node ) )
588  {
589  QList<QgsLayerTreeModelLegendNode*> legendNodes = model->layerLegendNodes( QgsLayerTree::toLayer( node ) );
590  if ( legendNodes.count() == 1 && legendNodes[0]->isEmbeddedInParent() )
593  }
594 
595  return QgsComposerLegendStyle::Undefined; // should not happen, only if corrupted project file
596 }
597 
599 {
600  return nodeLegendStyle( node, mLegendModel );
601 }
602 
604 {
605  QString str;
606  switch ( style )
607  {
608  case QgsComposerLegendStyle::Hidden: str = "hidden"; break;
609  case QgsComposerLegendStyle::Group: str = "group"; break;
610  case QgsComposerLegendStyle::Subgroup: str = "subgroup"; break;
611  default: break; // nothing
612  }
613 
614  if ( !str.isEmpty() )
615  node->setCustomProperty( "legend/title-style", str );
616  else
617  node->removeCustomProperty( "legend/title-style" );
618 }
Layer tree group node serves as a container for layers and further groups.
QStringList splitStringForWrapping(QString stringToSplt) const
Splits a string using the wrap char taking into account handling empty wrap char which means no wrapp...
QSizeF paintAndDetermineSize(QPainter *painter)
Nucleon drawSymbolItem(QgsLayerTreeModelLegendNode *symbolItem, QPainter *painter=0, QPointF point=QPointF(), double labelXOffset=0)
double boxSpace() const
QList< QgsLayerTreeModelLegendNode * > layerLegendNodes(QgsLayerTreeLayer *nodeLayer)
Return list of legend nodes attached to a particular layer node.
double lineSpacing() const
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const
double fontAscentMillimeters(const QFont &font) const
Returns the font ascent in Millimeters (considers upscaling and downscaling with FONT_WORKAROUND_SCAL...
QVariant customProperty(const QString &key, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer.
int columnCount() const
Atom is indivisible set (indivisible into more columns).
void drawLegend(QPainter *painter)
Draw the legend with given painter.
Nucleon is either group title, layer title or layer child item.
double columnSpace() const
QgsComposerLegendStyle style(QgsComposerLegendStyle::Style s) const
Returns style.
QgsLayerTreeModel * mLegendModel
QSizeF drawLayerTitle(QgsLayerTreeLayer *nodeLayer, QPainter *painter=0, QPointF point=QPointF())
Draws a layer item.
QgsLayerTreeGroup * toGroup(QgsLayerTreeNode *node)
Cast node to a group. No type checking is done - use isGroup() to find out whether this operation is ...
Definition: qgslayertree.h:46
QgsLegendRenderer(QgsLayerTreeModel *legendModel, const QgsLegendSettings &settings)
Construct legend renderer.
QgsLayerTreeGroup * rootGroup()
Return pointer to the root node of the layer tree. Always a non-null pointer.
QColor fontColor() const
The QgsLayerTreeModel class is model implementation for Qt item views framework.
QSizeF drawTitle(QPainter *painter=0, QPointF point=QPointF(), Qt::AlignmentFlag halignment=Qt::AlignLeft, double legendWidth=0)
Draws title in the legend using the title font and the specified alignment If no painter is specified...
static void setNodeLegendStyle(QgsLayerTreeNode *node, QgsComposerLegendStyle::Style style)
int splitLayer() const
double fontDescentMillimeters(const QFont &font) const
Returns the font descent in Millimeters (considers upscaling and downscaling with FONT_WORKAROUND_SCA...
The QgsLegendSettings class stores the appearance and layout settings for legend drawing with QgsLege...
QList< Atom > createAtomList(QgsLayerTreeGroup *parentGroup, bool splitLayer)
Create list of atoms according to current layer splitting mode.
This class is a base class for nodes in a layer tree.
QSizeF drawAtom(Atom atom, QPainter *painter=0, QPointF point=QPointF())
Draw atom and return its actual size, the atom is drawn with the space above it so that first atoms i...
void removeCustomProperty(const QString &key)
Remove a custom property from layer.
QList< QgsLayerTreeNode * > children()
Get list of children of the node. Children are owned by the parent.
bool isLayer(QgsLayerTreeNode *node)
Check whether the node is a valid layer node.
Definition: qgslayertree.h:40
QSizeF minimumSize()
Run the layout algorithm and determine the size required for legend.
virtual ItemMetrics draw(const QgsLegendSettings &settings, ItemContext *ctx)
Entry point called from QgsLegendRenderer to do the rendering.
QModelIndex node2index(QgsLayerTreeNode *node) const
Return index for a given node. If the node does not belong to the layer tree, the result is undefined...
Qt::AlignmentFlag titleAlignment() const
Returns the alignment of the legend title.
double spaceAboveAtom(Atom atom)
QgsLayerTreeLayer * toLayer(QgsLayerTreeNode *node)
Cast node to a layer. No type checking is done - use isLayer() to find out whether this operation is ...
Definition: qgslayertree.h:52
QPointF point
Top-left corner of the legend item.
static QgsComposerLegendStyle::Style nodeLegendStyle(QgsLayerTreeNode *node, QgsLayerTreeModel *model)
QgsLegendSettings mSettings
QString title() const
The QgsLegendRendererItem class is abstract interface for legend items returned from QgsMapLayerLegen...
double labelXOffset
offset from the left side where label should start
double size
Definition: qgssvgcache.cpp:77
bool isGroup(QgsLayerTreeNode *node)
Check whether the node is a valid group node.
Definition: qgslayertree.h:34
void setColumns(QList< Atom > &atomList)
Divide atoms to columns and set columns on atoms.
QSizeF drawGroupTitle(QgsLayerTreeGroup *nodeGroup, QPainter *painter=0, QPointF point=QPointF())
Draws a group item.
int equalColumnWidth() const
void setCustomProperty(const QString &key, const QVariant &value)
Set a custom property for the node.
Layer tree node points to a map layer.
void drawText(QPainter *p, double x, double y, const QString &text, const QFont &font) const
Draws Text.
double textWidthMillimeters(const QFont &font, const QString &text) const
Returns the font width in millimeters (considers upscaling and downscaling with FONT_WORKAROUND_SCALE...