35 , mSettings( settings )
41 std::unique_ptr< QgsRenderContext > tmpContext;
48 tmpContext->setRendererScale( mSettings.
mapScale() );
50 renderContext = tmpContext.get();
55 return paintAndDetermineSize( *renderContext );
64 context.setRendererScale( mSettings.
mapScale() );
68 paintAndDetermineSize( context );
80 json[QStringLiteral(
"title" )] = mSettings.
title();
88 const QList<QgsLayerTreeNode *> childNodes = nodeGroup->
children();
94 const QModelIndex idx = mLegendModel->
node2index( nodeGroup );
95 const QString text = mLegendModel->
data( idx, Qt::DisplayRole ).toString();
98 group[ QStringLiteral(
"type" ) ] = QStringLiteral(
"group" );
99 group[ QStringLiteral(
"title" ) ] = text;
100 nodes.append( group );
109 const QModelIndex idx = mLegendModel->
node2index( nodeLayer );
110 text = mLegendModel->
data( idx, Qt::DisplayRole ).toString();
113 QList<QgsLayerTreeModelLegendNode *> legendNodes = mLegendModel->
layerLegendNodes( nodeLayer );
118 if ( legendNodes.count() == 1 )
120 QJsonObject group = legendNodes.at( 0 )->exportToJson( mSettings, context );
121 group[ QStringLiteral(
"type" ) ] = QStringLiteral(
"layer" );
122 nodes.append( group );
124 else if ( legendNodes.count() > 1 )
127 group[ QStringLiteral(
"type" ) ] = QStringLiteral(
"layer" );
128 group[ QStringLiteral(
"title" ) ] = text;
131 for (
int j = 0; j < legendNodes.count(); j++ )
135 symbols.append( symbol );
137 group[ QStringLiteral(
"symbols" ) ] = symbols;
139 nodes.append( group );
144 json[QStringLiteral(
"nodes" )] = nodes;
159 QList<LegendComponentGroup> componentGroups = createComponentGroupList( rootGroup, context );
161 const int columnCount = setColumns( componentGroups );
163 QMap< int, double > maxColumnWidths;
164 qreal maxEqualColumnWidth = 0;
172 for (
const LegendComponentGroup &group : std::as_const( componentGroups ) )
174 const QSizeF actualSize = drawGroup( group, context, ColumnContext() );
175 maxEqualColumnWidth = std::max( actualSize.width(), maxEqualColumnWidth );
176 maxColumnWidths[ group.column ] = std::max( actualSize.width(), maxColumnWidths.value( group.column, 0 ) );
179 if ( columnCount == 1 )
182 maxEqualColumnWidth = std::max( maxEqualColumnWidth, mLegendSize.width() - 2 * mSettings.
boxSpace() );
183 maxColumnWidths[ 0 ] = maxEqualColumnWidth;
187 QSizeF titleSize = drawTitle( context, 0 );
189 titleSize.rwidth() += mSettings.
boxSpace() * 2.0;
194 bool firstInColumn =
true;
195 double columnMaxHeight = 0;
196 qreal columnWidth = 0;
198 ColumnContext columnContext;
199 columnContext.left = mSettings.
boxSpace();
200 columnContext.right = std::max( mLegendSize.width() - mSettings.
boxSpace(), mSettings.
boxSpace() );
201 double currentY = columnTop;
203 for (
const LegendComponentGroup &group : std::as_const( componentGroups ) )
205 if ( group.column > column )
208 columnContext.left = group.column > 0 ? columnContext.right + mSettings.
columnSpace() : mSettings.
boxSpace();
209 columnWidth = mSettings.
equalColumnWidth() ? maxEqualColumnWidth : maxColumnWidths.value( group.column );
210 columnContext.right = columnContext.left + columnWidth;
211 currentY = columnTop;
213 firstInColumn =
true;
215 if ( !firstInColumn )
217 currentY += spaceAboveGroup( group );
220 drawGroup( group, context, columnContext, currentY );
222 currentY += group.size.height();
223 columnMaxHeight = std::max( currentY - columnTop, columnMaxHeight );
225 firstInColumn =
false;
227 const double totalWidth = columnContext.right + mSettings.
boxSpace();
229 size.rheight() = columnTop + columnMaxHeight + mSettings.
boxSpace();
230 size.rwidth() = totalWidth;
231 if ( !mSettings.
title().isEmpty() )
233 size.rwidth() = std::max( titleSize.width(), size.width() );
237 if ( mLegendSize.isValid() )
239 qreal w = std::max( size.width(), mLegendSize.width() );
240 qreal h = std::max( size.height(), mLegendSize.height() );
241 size = QSizeF( w, h );
245 if ( !mSettings.
title().isEmpty() )
253void QgsLegendRenderer::widthAndOffsetForTitleText(
const Qt::AlignmentFlag halignment,
const double legendWidth,
double &textBoxWidth,
double &textBoxLeft )
const
255 switch ( halignment )
259 textBoxWidth = legendWidth - 2 * mSettings.
boxSpace();
262 case Qt::AlignHCenter:
265 const double centerX = legendWidth / 2;
266 textBoxWidth = ( std::min(
static_cast< double >( centerX ), legendWidth - centerX ) - mSettings.
boxSpace() ) * 2.0;
267 textBoxLeft = centerX - textBoxWidth / 2.;
273QList<QgsLegendRenderer::LegendComponentGroup> QgsLegendRenderer::createComponentGroupList(
QgsLayerTreeGroup *parentGroup,
QgsRenderContext &context,
double indent )
275 QList<LegendComponentGroup> componentGroups;
278 return componentGroups;
280 const QList<QgsLayerTreeNode *> childNodes = parentGroup->
children();
286 QString style = node->customProperty( QStringLiteral(
"legend/title-style" ) ).toString();
288 double newIndent = indent;
289 if ( style == QLatin1String(
"subgroup" ) )
299 QList<LegendComponentGroup> subgroups = createComponentGroupList( nodeGroup, context, newIndent );
301 bool hasSubItems = !subgroups.empty();
305 LegendComponent component;
306 component.item = node;
307 component.indent = newIndent;
308 component.size = drawGroupTitle( nodeGroup, context );
310 if ( !subgroups.isEmpty() )
313 subgroups[0].size.rheight() += spaceAboveGroup( subgroups[0] );
315 subgroups[0].components.prepend( component );
316 subgroups[0].size.rheight() += component.size.height();
317 subgroups[0].size.rwidth() = std::max( component.size.width(), subgroups[0].size.width() );
318 if ( nodeGroup->
customProperty( QStringLiteral(
"legend/column-break" ) ).toInt() )
319 subgroups[0].placeColumnBreakBeforeGroup =
true;
324 LegendComponentGroup group;
325 group.placeColumnBreakBeforeGroup = nodeGroup->
customProperty( QStringLiteral(
"legend/column-break" ) ).toInt();
326 group.components.append( component );
327 group.size.rwidth() += component.size.width();
328 group.size.rheight() += component.size.height();
329 group.size.rwidth() = std::max( component.size.width(), group.size.width() );
330 subgroups.append( group );
336 componentGroups.append( subgroups );
344 bool allowColumnSplit =
false;
351 allowColumnSplit =
true;
354 allowColumnSplit =
false;
358 LegendComponentGroup group;
359 group.placeColumnBreakBeforeGroup = nodeLayer->
customProperty( QStringLiteral(
"legend/column-break" ) ).toInt();
363 LegendComponent component;
364 component.item = node;
365 component.size = drawLayerTitle( nodeLayer, context );
366 component.indent = indent;
367 group.components.append( component );
368 group.size.rwidth() = component.size.width();
369 group.size.rheight() = component.size.height();
372 QList<QgsLayerTreeModelLegendNode *> legendNodes = mLegendModel->
layerLegendNodes( nodeLayer );
380 QList<LegendComponentGroup> layerGroups;
381 layerGroups.reserve( legendNodes.count() );
383 bool groupIsLayerGroup =
true;
385 for (
int j = 0; j < legendNodes.count(); j++ )
389 LegendComponent symbolComponent = drawSymbolItem(
legendNode, context, ColumnContext(), 0 );
393 if ( !allowColumnSplit || j == 0 )
397 if ( groupIsLayerGroup )
398 layerGroups.prepend( group );
400 layerGroups.append( group );
402 group = LegendComponentGroup();
403 group.placeColumnBreakBeforeGroup =
true;
404 groupIsLayerGroup =
false;
409 group.size.rwidth() = std::max( symbolComponent.size.width(), group.size.width() );
411 if ( !group.components.isEmpty() )
416 group.size.rheight() += symbolComponent.size.height();
417 symbolComponent.indent = indent;
418 group.components.append( symbolComponent );
422 if ( group.size.height() > 0 )
424 if ( groupIsLayerGroup )
425 layerGroups.prepend( group );
427 layerGroups.append( group );
428 group = LegendComponentGroup();
429 groupIsLayerGroup =
false;
431 LegendComponentGroup symbolGroup;
432 symbolGroup.placeColumnBreakBeforeGroup = forceBreak;
433 symbolComponent.indent = indent;
434 symbolGroup.components.append( symbolComponent );
435 symbolGroup.size.rwidth() = symbolComponent.size.width();
436 symbolGroup.size.rheight() = symbolComponent.size.height();
437 layerGroups.append( symbolGroup );
440 if ( group.size.height() > 0 )
442 if ( groupIsLayerGroup )
443 layerGroups.prepend( group );
445 layerGroups.append( group );
447 componentGroups.append( layerGroups );
451 return componentGroups;
455int QgsLegendRenderer::setColumns( QList<LegendComponentGroup> &componentGroups )
458 double totalHeight = 0;
459 qreal maxGroupHeight = 0;
460 int forcedColumnBreaks = 0;
461 double totalSpaceAboveGroups = 0;
463 for (
const LegendComponentGroup &group : std::as_const( componentGroups ) )
465 const double topMargin = spaceAboveGroup( group );
466 totalHeight += topMargin;
467 totalSpaceAboveGroups += topMargin;
469 const double groupHeight = group.size.height();
470 totalHeight += groupHeight;
471 maxGroupHeight = std::max( groupHeight, maxGroupHeight );
473 if ( group.placeColumnBreakBeforeGroup )
474 forcedColumnBreaks++;
476 const double totalGroupHeight = ( totalHeight - totalSpaceAboveGroups );
477 double averageGroupHeight = totalGroupHeight / componentGroups.size();
479 if ( mSettings.
columnCount() == 0 && forcedColumnBreaks == 0 )
484 const int targetNumberColumns = std::max( forcedColumnBreaks + 1, mSettings.
columnCount() );
485 const int numberAutoPlacedBreaks = targetNumberColumns - forcedColumnBreaks - 1;
492 double maxColumnHeight = 0;
493 int currentColumn = 0;
494 int currentColumnGroupCount = 0;
495 double currentColumnHeight = 0;
496 int autoPlacedBreaks = 0;
499 double averageSpaceAboveGroups = 0;
500 if ( componentGroups.size() > targetNumberColumns )
501 averageSpaceAboveGroups = totalSpaceAboveGroups / ( componentGroups.size() );
503 double totalRemainingGroupHeight = totalGroupHeight;
504 double totalRemainingSpaceAboveGroups = totalSpaceAboveGroups;
505 for (
int i = 0; i < componentGroups.size(); i++ )
507 const LegendComponentGroup &group = componentGroups.at( i );
508 const double currentGroupHeight = group.size.height();
509 const double spaceAboveCurrentGroup = spaceAboveGroup( group );
511 totalRemainingGroupHeight -= currentGroupHeight;
512 totalRemainingSpaceAboveGroups -= spaceAboveCurrentGroup;
514 double currentColumnHeightIfGroupIsIncluded = currentColumnHeight;
515 if ( currentColumnGroupCount > 0 )
516 currentColumnHeightIfGroupIsIncluded += spaceAboveCurrentGroup;
517 currentColumnHeightIfGroupIsIncluded += currentGroupHeight;
519 const int numberRemainingGroupsIncludingThisOne = componentGroups.size() - i;
520 const int numberRemainingColumnsIncludingThisOne = numberAutoPlacedBreaks + 1 - autoPlacedBreaks;
521 const int numberRemainingColumnBreaks = numberRemainingColumnsIncludingThisOne - 1;
523 const double averageRemainingSpaceAboveGroups = numberRemainingGroupsIncludingThisOne > 1 ? ( totalRemainingSpaceAboveGroups / ( numberRemainingGroupsIncludingThisOne - 1 ) ) : 0;
524 const double estimatedRemainingSpaceAboveGroupsWhichWontBeUsedBecauseGroupsAreFirstInColumn = numberRemainingColumnBreaks * averageRemainingSpaceAboveGroups;
525 const double estimatedRemainingTotalHeightAfterThisGroup = totalRemainingGroupHeight
526 + totalRemainingSpaceAboveGroups
527 - estimatedRemainingSpaceAboveGroupsWhichWontBeUsedBecauseGroupsAreFirstInColumn;
529 const double estimatedTotalHeightOfRemainingColumnsIncludingThisOne = currentColumnHeightIfGroupIsIncluded
530 + estimatedRemainingTotalHeightAfterThisGroup;
533 double averageRemainingColumnHeightIncludingThisOne = estimatedTotalHeightOfRemainingColumnsIncludingThisOne / numberRemainingColumnsIncludingThisOne;
537 const int averageGroupsPerRemainingColumnsIncludingThisOne = std::ceil( averageRemainingColumnHeightIncludingThisOne / ( averageGroupHeight + averageSpaceAboveGroups ) );
539 averageRemainingColumnHeightIncludingThisOne = averageGroupsPerRemainingColumnsIncludingThisOne * ( averageGroupHeight + averageSpaceAboveGroups ) - averageSpaceAboveGroups;
541 bool canCreateNewColumn = ( currentColumnGroupCount > 0 )
542 && ( currentColumn < targetNumberColumns - 1 )
543 && ( autoPlacedBreaks < numberAutoPlacedBreaks );
545 bool shouldCreateNewColumn = currentColumnHeightIfGroupIsIncluded > averageRemainingColumnHeightIncludingThisOne
546 && currentColumnGroupCount > 0
547 && currentColumnHeightIfGroupIsIncluded > maxGroupHeight
548 && currentColumnHeightIfGroupIsIncluded > maxColumnHeight;
550 shouldCreateNewColumn |= group.placeColumnBreakBeforeGroup;
551 canCreateNewColumn |= group.placeColumnBreakBeforeGroup;
555 shouldCreateNewColumn |= ( componentGroups.size() - i < targetNumberColumns - currentColumn );
557 if ( canCreateNewColumn && shouldCreateNewColumn )
561 if ( !group.placeColumnBreakBeforeGroup )
563 currentColumnGroupCount = 0;
564 currentColumnHeight = group.size.height();
568 currentColumnHeight = currentColumnHeightIfGroupIsIncluded;
570 componentGroups[i].column = currentColumn;
571 currentColumnGroupCount++;
572 maxColumnHeight = std::max( currentColumnHeight, maxColumnHeight );
575 auto refineColumns = [&componentGroups,
this]() ->
bool
577 QHash< int, double > columnHeights;
578 QHash< int, int > columnGroupCounts;
579 double currentColumnHeight = 0;
580 int currentColumn = -1;
583 double maxCurrentColumnHeight = 0;
584 for (
int i = 0; i < componentGroups.size(); i++ )
586 const LegendComponentGroup &group = componentGroups.at( i );
587 if ( group.column != currentColumn )
589 if ( currentColumn >= 0 )
591 columnHeights.insert( currentColumn, currentColumnHeight );
592 columnGroupCounts.insert( currentColumn, groupCount );
595 currentColumn = group.column;
596 currentColumnHeight = 0;
598 columnCount = std::max( columnCount, currentColumn + 1 );
601 const double spaceAbove = spaceAboveGroup( group );
602 currentColumnHeight += spaceAbove + group.size.height();
605 columnHeights.insert( currentColumn, currentColumnHeight );
606 columnGroupCounts.insert( currentColumn, groupCount );
608 double totalColumnHeights = 0;
609 for (
int i = 0; i < columnCount; ++ i )
611 totalColumnHeights += columnHeights[i];
612 maxCurrentColumnHeight = std::max( maxCurrentColumnHeight, columnHeights[i] );
615 const double averageColumnHeight = totalColumnHeights / columnCount;
617 bool changed =
false;
618 int nextCandidateColumnForShift = 1;
619 for (
int i = 0; i < componentGroups.size(); i++ )
621 LegendComponentGroup &group = componentGroups[ i ];
622 if ( group.column < nextCandidateColumnForShift )
626 const bool canShift = !group.placeColumnBreakBeforeGroup
627 && columnGroupCounts[ group.column ] >= 2;
630 && columnHeights[ group.column - 1 ] < averageColumnHeight
631 && ( columnHeights[ group.column - 1 ] + group.size.height() ) * 0.9 < maxCurrentColumnHeight
635 columnHeights[ group.column ] += group.size.height() + spaceAboveGroup( group );
636 columnGroupCounts[ group.column ]++;
637 columnHeights[ group.column + 1 ] -= group.size.height();
638 columnGroupCounts[ group.column + 1]--;
643 nextCandidateColumnForShift = group.column + 1;
649 bool wasRefined =
true;
651 while ( wasRefined && iterations < 2 )
653 wasRefined = refineColumns();
658 QMap<QString, qreal> maxSymbolWidth;
659 for (
int i = 0; i < componentGroups.size(); i++ )
661 LegendComponentGroup &group = componentGroups[i];
662 for (
int j = 0; j < group.components.size(); j++ )
666 QString key = QStringLiteral(
"%1-%2" ).arg(
reinterpret_cast< qulonglong
>(
legendNode->
layerNode() ) ).arg( group.column );
667 maxSymbolWidth[key] = std::max( group.components.at( j ).symbolSize.width(), maxSymbolWidth[key] );
671 for (
int i = 0; i < componentGroups.size(); i++ )
673 LegendComponentGroup &group = componentGroups[i];
674 for (
int j = 0; j < group.components.size(); j++ )
678 QString key = QStringLiteral(
"%1-%2" ).arg(
reinterpret_cast< qulonglong
>(
legendNode->
layerNode() ) ).arg( group.column );
681 group.components[j].labelXOffset = maxSymbolWidth[key] + space;
682 group.components[j].maxSiblingSymbolWidth = maxSymbolWidth[key];
683 group.components[j].size.rwidth() = maxSymbolWidth[key] + space + group.components.at( j ).labelSize.width();
687 return targetNumberColumns;
690QSizeF QgsLegendRenderer::drawTitle(
QgsRenderContext &context,
double top, Qt::AlignmentFlag halignment,
double legendWidth )
693 if ( mSettings.
title().isEmpty() )
701 if (
auto *lPainter = context.
painter() )
703 lPainter->setPen( mSettings.
fontColor() );
709 widthAndOffsetForTitleText( halignment, legendWidth, textBoxWidth, textBoxLeft );
713 for ( QStringList::Iterator titlePart = lines.begin(); titlePart != lines.end(); ++titlePart )
720 QRectF r( textBoxLeft, y, textBoxWidth, height );
724 mSettings.
drawText( context.
painter(), r, *titlePart, titleFont, halignment, Qt::AlignVCenter, Qt::TextDontClip );
728 size.rwidth() = std::max( width, size.rwidth() );
731 if ( titlePart != ( lines.end() - 1 ) )
736 size.rheight() = y - top;
742double QgsLegendRenderer::spaceAboveGroup(
const LegendComponentGroup &group )
744 if ( group.components.isEmpty() )
return 0;
746 LegendComponent component = group.components.first();
748 if (
QgsLayerTreeGroup *nodeGroup = qobject_cast<QgsLayerTreeGroup *>( component.item ) )
752 else if (
QgsLayerTreeLayer *nodeLayer = qobject_cast<QgsLayerTreeLayer *>( component.item ) )
756 else if ( qobject_cast<QgsLayerTreeModelLegendNode *>( component.item ) )
765QSizeF QgsLegendRenderer::drawGroup(
const LegendComponentGroup &group,
QgsRenderContext &context, ColumnContext columnContext,
double top )
768 QSizeF size = QSizeF( group.size );
769 double currentY = top;
770 for (
const LegendComponent &component : std::as_const( group.components ) )
772 if (
QgsLayerTreeGroup *groupItem = qobject_cast<QgsLayerTreeGroup *>( component.item ) )
782 ColumnContext columnContextForItem = columnContext;
783 double indentWidth = component.indent;
796 columnContextForItem.left += indentWidth;
800 columnContextForItem.right -= indentWidth;
802 groupSize = drawGroupTitle( groupItem, context, columnContextForItem, currentY );
803 size.rwidth() = std::max( groupSize.width(), size.width() );
806 else if (
QgsLayerTreeLayer *layerItem = qobject_cast<QgsLayerTreeLayer *>( component.item ) )
817 ColumnContext columnContextForItem = columnContext;
818 double indentWidth = component.indent;
819 columnContextForItem.left += indentWidth;
820 subGroupSize = drawLayerTitle( layerItem, context, columnContextForItem, currentY );
821 size.rwidth() = std::max( subGroupSize.width(), size.width() );
831 ColumnContext columnContextForItem = columnContext;
832 double indentWidth = 0;
833 indentWidth = component.indent;
836 columnContextForItem.left += indentWidth;
840 columnContextForItem.right -= indentWidth;
843 LegendComponent symbolComponent = drawSymbolItem(
legendNode, context, columnContextForItem, currentY, component.maxSiblingSymbolWidth );
845 size.rwidth() = std::max( symbolComponent.size.width() + indentWidth, size.width() );
847 currentY += component.size.height();
868 ctx.
point = QPointF( columnContext.left, top );
901 LegendComponent component;
902 component.item = symbolItem;
909 double width = std::max(
static_cast< double >( im.
symbolSize.width() ), maxSiblingSymbolWidth )
916 component.size = QSizeF( width, height );
923 QModelIndex idx = mLegendModel->
node2index( nodeLayer );
924 QString titleString = mLegendModel->
data( idx, Qt::DisplayRole ).toString();
926 if ( titleString.isEmpty() )
931 if (
auto *lPainter = context.
painter() )
937 if ( nodeLayer->
layer() )
947 for ( QStringList::ConstIterator layerItemPart = lines.constBegin(); layerItemPart != lines.constEnd(); ++layerItemPart )
950 if ( QPainter *destPainter = context.
painter() )
952 double x = columnContext.left + sideMargin;
957 x = columnContext.right - labelWidth - sideMargin;
959 x = columnContext.left + ( columnContext.right - columnContext.left - labelWidth ) / 2;
961 mSettings.
drawText( destPainter, x, y, *layerItemPart, layerFont );
965 size.rwidth() = std::max( width, size.width() );
966 if ( layerItemPart != ( lines.end() - 1 ) )
972 size.rheight() = y - top;
984 QModelIndex idx = mLegendModel->
node2index( nodeGroup );
988 if (
auto *lPainter = context.
painter() )
989 lPainter->setPen( mSettings.
fontColor() );
996 for ( QStringList::ConstIterator groupPart = lines.constBegin(); groupPart != lines.constEnd(); ++groupPart )
1000 if ( QPainter *destPainter = context.
painter() )
1002 double x = columnContext.left + sideMargin;
1007 x = columnContext.right - labelWidth - sideMargin;
1009 x = columnContext.left + ( columnContext.right - columnContext.left - labelWidth ) / 2;
1011 mSettings.
drawText( destPainter, x, y, *groupPart, groupFont );
1014 size.rwidth() = std::max( width, size.width() );
1015 if ( groupPart != ( lines.end() - 1 ) )
1026 QString style = node->
customProperty( QStringLiteral(
"legend/title-style" ) ).toString();
1027 if ( style == QLatin1String(
"hidden" ) )
1029 else if ( style == QLatin1String(
"group" ) )
1031 else if ( style == QLatin1String(
"subgroup" ) )
1058 str = QStringLiteral(
"hidden" );
1061 str = QStringLiteral(
"group" );
1064 str = QStringLiteral(
"subgroup" );
1070 if ( !
str.isEmpty() )
1078 paintAndDetermineSize( context );
Single scope for storing variables and functions for use within a QgsExpressionContext.
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
QgsExpressionContextScope * popScope()
Removes the last scope from the expression context and return it.
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
Layer tree group node serves as a container for layers and further groups.
Layer tree node points to a map layer.
@ AllowSplittingLegendNodesOverMultipleColumns
Allow splitting node's legend nodes across multiple columns.
@ PreventSplittingLegendNodesOverMultipleColumns
Prevent splitting node's legend nodes across multiple columns.
@ UseDefaultLegendSetting
Inherit default legend column splitting setting.
LegendNodesSplitBehavior legendSplitBehavior() const
Returns the column split behavior for the node.
QgsMapLayer * layer() const
Returns the map layer associated with this node.
The QgsLegendRendererItem class is abstract interface for legend items returned from QgsMapLayerLegen...
QJsonObject exportToJson(const QgsLegendSettings &settings, const QgsRenderContext &context)
Entry point called from QgsLegendRenderer to do the rendering in a JSON object.
virtual bool columnBreak() const
Returns whether a forced column break should occur before the node.
virtual QSizeF userPatchSize() const
Returns the user (overridden) size for the legend node.
virtual ItemMetrics draw(const QgsLegendSettings &settings, ItemContext *ctx)
Entry point called from QgsLegendRenderer to do the rendering.
QgsLayerTreeLayer * layerNode() const
Returns pointer to the parent layer node.
The QgsLayerTreeModel class is model implementation for Qt item views framework.
QModelIndex node2index(QgsLayerTreeNode *node) const
Returns index for a given node. If the node does not belong to the layer tree, the result is undefine...
QList< QgsLayerTreeModelLegendNode * > layerLegendNodes(QgsLayerTreeLayer *nodeLayer, bool skipNodeEmbeddedInParent=false)
Returns filtered list of active legend nodes attached to a particular layer node (by default it retur...
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
QgsLayerTree * rootGroup() const
Returns pointer to the root node of the layer tree. Always a non nullptr value.
QgsLayerTreeModelLegendNode * legendNodeEmbeddedInParent(QgsLayerTreeLayer *nodeLayer) const
Returns legend node that may be embedded in parent (i.e.
const QgsMapSettings * legendFilterMapSettings() const
Returns the current map settings used for the current legend filter (or nullptr if none is enabled)
This class is a base class for nodes in a layer tree.
void setCustomProperty(const QString &key, const QVariant &value)
Sets a custom property for the node. Properties are stored in a map and saved in project file.
QList< QgsLayerTreeNode * > children()
Gets list of children of the node. Children are owned by the parent.
void removeCustomProperty(const QString &key)
Remove a custom property from layer. Properties are stored in a map and saved in project file.
QVariant customProperty(const QString &key, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer. Properties are stored in a map and saved in project file.
static QgsLayerTreeLayer * toLayer(QgsLayerTreeNode *node)
Cast node to a layer.
static bool isLayer(const QgsLayerTreeNode *node)
Check whether the node is a valid layer node.
static bool isGroup(QgsLayerTreeNode *node)
Check whether the node is a valid group node.
static QgsLayerTreeGroup * toGroup(QgsLayerTreeNode *node)
Cast node to a group.
QSizeF minimumSize(QgsRenderContext *renderContext=nullptr)
Runs the layout algorithm and returns the minimum size required for the legend.
static void setNodeLegendStyle(QgsLayerTreeNode *node, QgsLegendStyle::Style style)
Sets the style of a node.
QJsonObject exportLegendToJson(const QgsRenderContext &context)
Renders the legend in a json object.
QgsLegendRenderer(QgsLayerTreeModel *legendModel, const QgsLegendSettings &settings)
Constructor for QgsLegendRenderer.
static QgsLegendStyle::Style nodeLegendStyle(QgsLayerTreeNode *node, QgsLayerTreeModel *model)
Returns the style for the given node, within the specified model.
Q_DECL_DEPRECATED void drawLegend(QPainter *painter)
Draws the legend with given painter.
The QgsLegendSettings class stores the appearance and layout settings for legend drawing with QgsLege...
int columnCount() const
Returns the desired minimum number of columns to show in the legend.
QColor layerFontColor() const
Returns layer font color, defaults to fontColor()
void drawText(QPainter *p, double x, double y, const QString &text, const QFont &font) const
Draws Text.
QgsLegendStyle style(QgsLegendStyle::Style s) const
Returns the style for a legend component.
double fontDescentMillimeters(const QFont &font) const
Returns the font descent in Millimeters (considers upscaling and downscaling with FONT_WORKAROUND_SCA...
Qt::AlignmentFlag titleAlignment() const
Returns the alignment of the legend title.
QColor fontColor() const
Returns the font color used for legend items.
QString title() const
Returns the title for the legend, which will be rendered above all legend items.
double textWidthMillimeters(const QFont &font, const QString &text) const
Returns the font width in millimeters (considers upscaling and downscaling with FONT_WORKAROUND_SCALE...
double columnSpace() const
Returns the margin space between adjacent columns (in millimeters).
double fontAscentMillimeters(const QFont &font) const
Returns the font ascent in Millimeters (considers upscaling and downscaling with FONT_WORKAROUND_SCAL...
double boxSpace() const
Returns the legend box space (in millimeters), which is the empty margin around the inside of the leg...
double lineSpacing() const
Returns the line spacing to use between lines of legend text.
Q_DECL_DEPRECATED double mmPerMapUnit() const
bool splitLayer() const
Returns true if layer components can be split over multiple columns.
QStringList evaluateItemText(const QString &text, const QgsExpressionContext &context) const
Splits a string using the wrap char taking into account handling empty wrap char which means no wrapp...
QStringList splitStringForWrapping(const QString &stringToSplt) const
Splits a string using the wrap char taking into account handling empty wrap char which means no wrapp...
Qt::AlignmentFlag symbolAlignment() const
Returns the alignment for placement of legend symbols.
bool equalColumnWidth() const
Returns true if all columns should have equal widths.
Q_DECL_DEPRECATED double mapScale() const
Returns the legend map scale.
double margin(Side side)
Returns the margin (in mm) for the specified side of the component.
Qt::Alignment alignment() const
Returns the alignment for the legend component.
QFont font() const
Returns the font used for rendering this legend component.
Style
Component of legends which can be styled.
@ Group
Legend group title.
@ Symbol
Symbol icon (excluding label)
@ Undefined
Should not happen, only if corrupted project file.
@ Subgroup
Legend subgroup title.
@ Hidden
Special style, item is hidden including margins around.
@ SymbolLabel
Symbol label (excluding icon)
double indent() const
Returns the indent (in mm) of a group or subgroup.
Perform transforms between map coordinates and device coordinates.
Contains information about the context of a rendering operation.
QPainter * painter()
Returns the destination QPainter for the render operation.
QgsExpressionContext & expressionContext()
Gets the expression context.
static QgsRenderContext fromQPainter(QPainter *painter)
Creates a default render context given a pixel based QPainter destination.
Scoped object for temporary replacement of a QgsRenderContext destination painter.
Scoped object for temporary scaling of a QgsRenderContext for millimeter based rendering.
Implementation of legend node interface for displaying preview of vector symbols and their labels and...
QgsLayerTreeModelLegendNode * legendNode(const QString &rule, QgsLayerTreeModel &model)
QgsLayerTreeModel * legendModel(const QgsWmsRenderContext &context, QgsLayerTree &tree)
#define Q_NOWARN_DEPRECATED_POP
#define Q_NOWARN_DEPRECATED_PUSH
QPainter * painter
Painter.
double top
Top y-position of legend item.
Q_DECL_DEPRECATED double labelXOffset
Offset from the left side where label should start.
QgsLegendPatchShape patchShape
The patch shape to render for the node.
double maxSiblingSymbolWidth
Largest symbol width, considering all other sibling legend components associated with the current com...
QSizeF patchSize
Symbol patch size to render for the node.
double columnLeft
Left side of current legend column.
double columnRight
Right side of current legend column.
Q_DECL_DEPRECATED QPointF point
Top-left corner of the legend item.
Q_NOWARN_DEPRECATED_POP QgsRenderContext * context
Render context, if available.