33     : mLegendModel( legendModel )
    34     , mSettings( settings )
    40   return paintAndDetermineSize( 
nullptr );
    45   paintAndDetermineSize( painter );
    49 QSizeF QgsLegendRenderer::paintAndDetermineSize( 
QPainter* painter )
    53   if ( !rootGroup ) 
return size;
    57   setColumns( atomList );
    59   qreal maxColumnWidth = 0;
    62     Q_FOREACH ( 
const Atom& atom, atomList )
    64       maxColumnWidth = qMax( atom.size.width(), maxColumnWidth );
    69   QSizeF titleSize = drawTitle();
    71   titleSize.rwidth() += mSettings.
boxSpace() * 2.0;
    75   bool firstInColumn = 
true;
    76   double columnMaxHeight = 0;
    77   qreal columnWidth = 0;
    79   Q_FOREACH ( 
const Atom& atom, atomList )
    81     if ( atom.column > column )
    90         point.rx() += mSettings.
columnSpace() + columnWidth;
    92       point.ry() = columnTop;
    99       point.ry() += spaceAboveAtom( atom );
   102     QSizeF atomSize = drawAtom( atom, painter, point );
   103     columnWidth = qMax( atomSize.
width(), columnWidth );
   105     point.ry() += atom.size.height();
   106     columnMaxHeight = qMax( point.y() - columnTop, columnMaxHeight );
   108     firstInColumn = 
false;
   110   point.rx() += columnWidth + mSettings.
boxSpace();
   113   size.
rwidth() = point.x();
   116     size.
rwidth() = qMax( titleSize.width(), size.
width() );
   122     qreal w = qMax( size.
width(), mLegendSize.
width() );
   136       point.rx() = size.
width() / 2;
   154   if ( !parentGroup ) 
return atoms;
   163       QList<Atom> groupAtoms = createAtomList( nodeGroup, splitLayer );
   164       bool hasSubItems = groupAtoms.
size() > 0;
   170         nucleon.size = drawGroupTitle( nodeGroup );
   175           groupAtoms[0].
size.rheight() += spaceAboveAtom( groupAtoms[0] );
   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() );
   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 );
   195         atoms.
append( groupAtoms );
   209         nucleon.size = drawLayerTitle( nodeLayer );
   210         atom.nucleons.append( nucleon );
   211         atom.size.rwidth() = nucleon.size.width();
   212         atom.size.rheight() = nucleon.size.height();
   225       for ( 
int j = 0; j < legendNodes.
count(); j++ )
   229         Nucleon symbolNucleon = drawSymbolItem( legendNode );
   235           atom.size.rwidth() = qMax( symbolNucleon.size.width(), atom.size.width() );
   237           if ( !atom.nucleons.isEmpty() )
   242           atom.size.rheight() += symbolNucleon.size.height();
   243           atom.nucleons.append( symbolNucleon );
   248           symbolAtom.nucleons.append( symbolNucleon );
   249           symbolAtom.size.rwidth() = symbolNucleon.size.width();
   250           symbolAtom.size.rheight() = symbolNucleon.size.height();
   251           layerAtoms.
append( symbolAtom );
   255       atoms.
append( layerAtoms );
   263 void QgsLegendRenderer::setColumns( 
QList<Atom>& atomList )
   268   double totalHeight = 0;
   269   qreal maxAtomHeight = 0;
   270   Q_FOREACH ( 
const Atom& atom, atomList )
   272     totalHeight += spaceAboveAtom( atom );
   273     totalHeight += atom.size.height();
   274     maxAtomHeight = qMax( atom.size.height(), maxAtomHeight );
   282   double maxColumnHeight = 0;
   283   int currentColumn = 0;
   284   int currentColumnAtomCount = 0; 
   285   double currentColumnHeight = 0;
   286   double closedColumnsHeight = 0;
   288   for ( 
int i = 0; i < atomList.
size(); i++ )
   291     double avgColumnHeight = ( totalHeight - closedColumnsHeight ) / ( mSettings.
columnCount() - currentColumn );
   293     Atom atom = atomList.
at( i );
   294     double currentHeight = currentColumnHeight;
   295     if ( currentColumnAtomCount > 0 )
   296       currentHeight += spaceAboveAtom( atom );
   297     currentHeight += atom.size.height();
   299     bool canCreateNewColumn = ( currentColumnAtomCount > 0 )  
   300                               && ( currentColumn < mSettings.
columnCount() - 1 ); 
   302     bool shouldCreateNewColumn = ( currentHeight - avgColumnHeight ) > atom.size.height() / 2  
   303                                  && currentColumnAtomCount > 0 
   304                                  && currentHeight > maxAtomHeight  
   305                                  && currentHeight > maxColumnHeight; 
   309     shouldCreateNewColumn |= ( atomList.
size() - i < mSettings.
columnCount() - currentColumn );
   311     if ( canCreateNewColumn && shouldCreateNewColumn )
   315       currentColumnAtomCount = 0;
   316       closedColumnsHeight += currentColumnHeight;
   317       currentColumnHeight = atom.size.height();
   321       currentColumnHeight = currentHeight;
   323     atomList[i].column = currentColumn;
   324     currentColumnAtomCount++;
   325     maxColumnHeight = qMax( currentColumnHeight, maxColumnHeight );
   330   for ( 
int i = 0; i < atomList.
size(); i++ )
   332     Atom& atom = atomList[i];
   333     for ( 
int j = 0; j < atom.nucleons.size(); j++ )
   337         QString key = 
QString( 
"%1-%2" ).
arg( reinterpret_cast< qulonglong >( legendNode->layerNode() ) ).
arg( atom.column );
   338         maxSymbolWidth[key] = qMax( atom.nucleons.at( j ).symbolSize.width(), maxSymbolWidth[key] );
   342   for ( 
int i = 0; i < atomList.
size(); i++ )
   344     Atom& atom = atomList[i];
   345     for ( 
int j = 0; j < atom.nucleons.size(); j++ )
   349         QString key = 
QString( 
"%1-%2" ).
arg( reinterpret_cast< qulonglong >( legendNode->layerNode() ) ).
arg( atom.column );
   352         atom.nucleons[j].labelXOffset =  maxSymbolWidth[key] + space;
   353         atom.nucleons[j].
size.rwidth() =  maxSymbolWidth[key] + space + atom.nucleons.at( j ).labelSize.width();
   360 QSizeF QgsLegendRenderer::drawTitle( 
QPainter* painter, 
QPointF point, Qt::AlignmentFlag halignment, 
double legendWidth )
   369   double y = point.
y();
   379   switch ( halignment )
   381     case Qt::AlignHCenter:
   382       textBoxWidth = ( qMin( static_cast< double >( point.
x() ), legendWidth - point.
x() ) - mSettings.
boxSpace() ) * 2.0;
   383       textBoxLeft = point.
x() - textBoxWidth / 2.;
   387       textBoxWidth = point.
x() - mSettings.
boxSpace();
   391       textBoxLeft = point.
x();
   392       textBoxWidth = legendWidth - point.
x() - mSettings.
boxSpace();
   405     QRectF r( textBoxLeft, y, textBoxWidth, height );
   409       mSettings.
drawText( painter, r, *titlePart, titleFont, halignment, Qt::AlignVCenter, Qt::TextDontClip );
   416     if ( titlePart != lines.
end() )
   427 double QgsLegendRenderer::spaceAboveAtom( 
const Atom& atom )
   429   if ( atom.nucleons.isEmpty() ) 
return 0;
   431   Nucleon nucleon = atom.nucleons.first();
   433   if ( 
QgsLayerTreeGroup* nodeGroup = qobject_cast<QgsLayerTreeGroup*>( nucleon.item ) )
   437   else if ( 
QgsLayerTreeLayer* nodeLayer = qobject_cast<QgsLayerTreeLayer*>( nucleon.item ) )
   441   else if ( qobject_cast<QgsLayerTreeModelLegendNode*>( nucleon.item ) )
   456   Q_FOREACH ( 
const Nucleon& nucleon, atom.nucleons )
   458     if ( 
QgsLayerTreeGroup* groupItem = qobject_cast<QgsLayerTreeGroup*>( nucleon.item ) )
   467         drawGroupTitle( groupItem, painter, point );
   470     else if ( 
QgsLayerTreeLayer* layerItem = qobject_cast<QgsLayerTreeLayer*>( nucleon.item ) )
   479         drawLayerTitle( layerItem, painter, point );
   489       Nucleon symbolNucleon = drawSymbolItem( legendNode, painter, point, nucleon.labelXOffset );
   491       size.
rwidth() = qMax( symbolNucleon.size.width(), size.
width() );
   493     point.
ry() += nucleon.size.height();
   510   nucleon.item = symbolItem;
   516   nucleon.size = 
QSizeF( width, height );
   529   double y = point.
y();
   539     if ( painter ) mSettings.
drawText( painter, point.
x(), y, *layerItemPart, layerFont );
   542     if ( layerItemPart != lines.
end() )
   558   double y = point.
y();
   568     if ( painter ) mSettings.
drawText( painter, point.
x(), y, *groupPart, groupFont );
   571     if ( groupPart != lines.
end() )
   585   if ( style == 
"hidden" )
   587   else if ( style == 
"group" )
   589   else if ( style == 
"subgroup" )
 Layer tree group node serves as a container for layers and further groups. 
 
void drawText(QPainter *p, double x, double y, const QString &text, const QFont &font) const
Draws Text. 
 
QgsLayerTreeGroup * rootGroup() const
Return pointer to the root node of the layer tree. Always a non-null pointer. 
 
double fontAscentMillimeters(const QFont &font) const
Returns the font ascent in Millimeters (considers upscaling and downscaling with FONT_WORKAROUND_SCAL...
 
void drawLegend(QPainter *painter)
Draw the legend with given painter. 
 
QStringList splitStringForWrapping(const QString &stringToSplt) const
Splits a string using the wrap char taking into account handling empty wrap char which means no wrapp...
 
QgsLayerTreeModelLegendNode * legendNodeEmbeddedInParent(QgsLayerTreeLayer *nodeLayer) const
Return legend node that may be embbeded in parent (i.e. 
 
const T & at(int i) const
 
double textWidthMillimeters(const QFont &font, const QString &text) const
Returns the font width in millimeters (considers upscaling and downscaling with FONT_WORKAROUND_SCALE...
 
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...
 
QPainter * painter
Painter. 
 
QgsLayerTreeGroup * toGroup(QgsLayerTreeNode *node)
Cast node to a group. No type checking is done - use isGroup() to find out whether this operation is ...
 
QgsLegendRenderer(QgsLayerTreeModel *legendModel, const QgsLegendSettings &settings)
Construct legend renderer. 
 
The QgsLayerTreeModel class is model implementation for Qt item views framework. 
 
static void setNodeLegendStyle(QgsLayerTreeNode *node, QgsComposerLegendStyle::Style style)
 
int count(const T &value) const
 
void append(const T &value)
 
void setPen(const QColor &color)
 
The QgsLegendSettings class stores the appearance and layout settings for legend drawing with QgsLege...
 
QVariant customProperty(const QString &key, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer. 
 
QgsComposerLegendStyle style(QgsComposerLegendStyle::Style s) const
Returns style. 
 
This class is a base class for nodes in a layer tree. 
 
Qt::AlignmentFlag titleAlignment() const
Returns the alignment of the legend title. 
 
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. 
 
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. 
 
const QgsMapSettings * legendFilterMapSettings() const
Returns the current map settings used for the current legend filter (or null if none is enabled) ...
 
QgsLayerTreeLayer * toLayer(QgsLayerTreeNode *node)
Cast node to a layer. No type checking is done - use isLayer() to find out whether this operation is ...
 
QPointF point
Top-left corner of the legend item. 
 
bool equalColumnWidth() const
 
double columnSpace() const
 
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
 
static QgsComposerLegendStyle::Style nodeLegendStyle(QgsLayerTreeNode *node, QgsLayerTreeModel *model)
 
The QgsLegendRendererItem class is abstract interface for legend items returned from QgsMapLayerLegen...
 
QList< QgsLayerTreeModelLegendNode * > layerLegendNodes(QgsLayerTreeLayer *nodeLayer, bool skipNodeEmbeddedInParent=false)
Return filtered list of active legend nodes attached to a particular layer node (by default it return...
 
void prepend(const T &value)
 
double lineSpacing() const
 
double labelXOffset
offset from the left side where label should start 
 
bool isGroup(QgsLayerTreeNode *node)
Check whether the node is a valid group node. 
 
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
 
double fontDescentMillimeters(const QFont &font) const
Returns the font descent in Millimeters (considers upscaling and downscaling with FONT_WORKAROUND_SCA...
 
void setCustomProperty(const QString &key, const QVariant &value)
Set a custom property for the node. 
 
Layer tree node points to a map layer.