32 , mSettings( settings )
38 std::unique_ptr< QgsRenderContext > tmpContext;
45 tmpContext->setRendererScale( mSettings.
mapScale() );
48 renderContext = tmpContext.get();
53 return paintAndDetermineSize( *renderContext );
62 context.setRendererScale( mSettings.
mapScale() );
66 paintAndDetermineSize( context );
78 json[QStringLiteral(
"title" )] = mSettings.
title();
86 const QList<QgsLayerTreeNode *> childNodes = nodeGroup->
children();
92 const QModelIndex idx = mLegendModel->
node2index( nodeGroup );
93 const QString text = mLegendModel->
data( idx, Qt::DisplayRole ).toString();
96 group[ QStringLiteral(
"type" ) ] = QStringLiteral(
"group" );
97 group[ QStringLiteral(
"title" ) ] = text;
98 nodes.append( group );
107 const QModelIndex idx = mLegendModel->
node2index( nodeLayer );
108 text = mLegendModel->
data( idx, Qt::DisplayRole ).toString();
111 QList<QgsLayerTreeModelLegendNode *> legendNodes = mLegendModel->
layerLegendNodes( nodeLayer );
116 if ( legendNodes.count() == 1 )
118 QJsonObject group = legendNodes.at( 0 )->exportToJson( mSettings, context );
119 group[ QStringLiteral(
"type" ) ] = QStringLiteral(
"layer" );
120 nodes.append( group );
122 else if ( legendNodes.count() > 1 )
125 group[ QStringLiteral(
"type" ) ] = QStringLiteral(
"layer" );
126 group[ QStringLiteral(
"title" ) ] = text;
129 for (
int j = 0; j < legendNodes.count(); j++ )
133 symbols.append( symbol );
135 group[ QStringLiteral(
"symbols" ) ] = symbols;
137 nodes.append( group );
142 json[QStringLiteral(
"nodes" )] = nodes;
157 QList<LegendComponentGroup> componentGroups = createComponentGroupList( rootGroup, context );
159 const int columnCount = setColumns( componentGroups );
161 QMap< int, double > maxColumnWidths;
162 qreal maxEqualColumnWidth = 0;
170 for (
const LegendComponentGroup &group : std::as_const( componentGroups ) )
172 const QSizeF actualSize = drawGroup( group, context, ColumnContext() );
173 maxEqualColumnWidth = std::max( actualSize.width(), maxEqualColumnWidth );
174 maxColumnWidths[ group.column ] = std::max( actualSize.width(), maxColumnWidths.value( group.column, 0 ) );
177 if ( columnCount == 1 )
180 maxEqualColumnWidth = std::max( maxEqualColumnWidth, mLegendSize.width() - 2 * mSettings.
boxSpace() );
181 maxColumnWidths[ 0 ] = maxEqualColumnWidth;
185 QSizeF titleSize = drawTitle( context, 0 );
187 titleSize.rwidth() += mSettings.
boxSpace() * 2.0;
192 bool firstInColumn =
true;
193 double columnMaxHeight = 0;
194 qreal columnWidth = 0;
196 ColumnContext columnContext;
197 columnContext.left = mSettings.
boxSpace();
198 columnContext.right = std::max( mLegendSize.width() - mSettings.
boxSpace(), mSettings.
boxSpace() );
199 double currentY = columnTop;
201 for (
const LegendComponentGroup &group : std::as_const( componentGroups ) )
203 if ( group.column > column )
206 columnContext.left = group.column > 0 ? ( columnContext.right + mSettings.
columnSpace() ) : mSettings.
boxSpace();
207 columnWidth = mSettings.
equalColumnWidth() ? maxEqualColumnWidth : maxColumnWidths.value( group.column );
208 columnContext.right = columnContext.left + columnWidth;
209 currentY = columnTop;
211 firstInColumn =
true;
213 if ( !firstInColumn )
215 currentY += spaceAboveGroup( group );
218 drawGroup( group, context, columnContext, currentY );
220 currentY += group.size.height();
221 columnMaxHeight = std::max( currentY - columnTop, columnMaxHeight );
223 firstInColumn =
false;
225 const double totalWidth = columnContext.right + mSettings.
boxSpace();
227 size.rheight() = columnTop + columnMaxHeight + mSettings.
boxSpace();
228 size.rwidth() = totalWidth;
229 if ( !mSettings.
title().isEmpty() )
231 size.rwidth() = std::max( titleSize.width(), size.width() );
235 if ( mLegendSize.isValid() )
237 qreal w = std::max( size.width(), mLegendSize.width() );
238 qreal h = std::max( size.height(), mLegendSize.height() );
239 size = QSizeF( w, h );
243 if ( !mSettings.
title().isEmpty() )
251void QgsLegendRenderer::widthAndOffsetForTitleText(
const Qt::AlignmentFlag halignment,
const double legendWidth,
double &textBoxWidth,
double &textBoxLeft )
const
253 switch ( halignment )
257 textBoxWidth = legendWidth - 2 * mSettings.
boxSpace();
260 case Qt::AlignHCenter:
263 const double centerX = legendWidth / 2;
264 textBoxWidth = ( std::min(
static_cast< double >( centerX ), legendWidth - centerX ) - mSettings.
boxSpace() ) * 2.0;
265 textBoxLeft = centerX - textBoxWidth / 2.;
271QList<QgsLegendRenderer::LegendComponentGroup> QgsLegendRenderer::createComponentGroupList(
QgsLayerTreeGroup *parentGroup,
QgsRenderContext &context,
double indent )
273 QList<LegendComponentGroup> componentGroups;
276 return componentGroups;
278 const QList<QgsLayerTreeNode *> childNodes = parentGroup->
children();
284 QString style = node->customProperty( QStringLiteral(
"legend/title-style" ) ).toString();
286 double newIndent = indent;
287 if ( style == QLatin1String(
"subgroup" ) )
297 QList<LegendComponentGroup> subgroups = createComponentGroupList( nodeGroup, context, newIndent );
299 bool hasSubItems = !subgroups.empty();
303 LegendComponent component;
304 component.item = node;
305 component.indent = newIndent;
306 component.size = drawGroupTitle( nodeGroup, context );
308 if ( !subgroups.isEmpty() )
311 subgroups[0].size.rheight() += spaceAboveGroup( subgroups[0] );
313 subgroups[0].components.prepend( component );
314 subgroups[0].size.rheight() += component.size.height();
315 subgroups[0].size.rwidth() = std::max( component.size.width(), subgroups[0].size.width() );
316 if ( nodeGroup->
customProperty( QStringLiteral(
"legend/column-break" ) ).toInt() )
317 subgroups[0].placeColumnBreakBeforeGroup =
true;
322 LegendComponentGroup group;
323 group.placeColumnBreakBeforeGroup = nodeGroup->
customProperty( QStringLiteral(
"legend/column-break" ) ).toInt();
324 group.components.append( component );
325 group.size.rwidth() += component.size.width();
326 group.size.rheight() += component.size.height();
327 group.size.rwidth() = std::max( component.size.width(), group.size.width() );
328 subgroups.append( group );
334 componentGroups.append( subgroups );
342 bool allowColumnSplit =
false;
349 allowColumnSplit =
true;
352 allowColumnSplit =
false;
356 LegendComponentGroup group;
357 group.placeColumnBreakBeforeGroup = nodeLayer->
customProperty( QStringLiteral(
"legend/column-break" ) ).toInt();
361 LegendComponent component;
362 component.item = node;
363 component.size = drawLayerTitle( nodeLayer, context );
364 component.indent = indent;
365 group.components.append( component );
366 group.size.rwidth() = component.size.width();
367 group.size.rheight() = component.size.height();
370 QList<QgsLayerTreeModelLegendNode *> legendNodes = mLegendModel->
layerLegendNodes( nodeLayer );
378 QList<LegendComponentGroup> layerGroups;
379 layerGroups.reserve( legendNodes.count() );
381 bool groupIsLayerGroup =
true;
382 double symbolIndent = indent;
383 switch ( layerStyle )
387 symbolIndent += mSettings.
style( layerStyle ).
indent( );
392 for (
int j = 0; j < legendNodes.count(); j++ )
396 LegendComponent symbolComponent = drawSymbolItem(
legendNode, context, ColumnContext(), 0 );
400 if ( !allowColumnSplit || j == 0 )
404 if ( groupIsLayerGroup )
405 layerGroups.prepend( group );
407 layerGroups.append( group );
409 group = LegendComponentGroup();
410 group.placeColumnBreakBeforeGroup =
true;
411 groupIsLayerGroup =
false;
416 group.size.rwidth() = std::max( symbolComponent.size.width(), group.size.width() );
418 if ( !group.components.isEmpty() )
423 group.size.rheight() += symbolComponent.size.height();
424 symbolComponent.indent = symbolIndent;
425 group.components.append( symbolComponent );
429 if ( group.size.height() > 0 )
431 if ( groupIsLayerGroup )
432 layerGroups.prepend( group );
434 layerGroups.append( group );
435 group = LegendComponentGroup();
436 groupIsLayerGroup =
false;
438 LegendComponentGroup symbolGroup;
439 symbolGroup.placeColumnBreakBeforeGroup = forceBreak;
440 symbolComponent.indent = symbolIndent;
441 symbolGroup.components.append( symbolComponent );
442 symbolGroup.size.rwidth() = symbolComponent.size.width();
443 symbolGroup.size.rheight() = symbolComponent.size.height();
444 layerGroups.append( symbolGroup );
447 if ( group.size.height() > 0 )
449 if ( groupIsLayerGroup )
450 layerGroups.prepend( group );
452 layerGroups.append( group );
454 componentGroups.append( layerGroups );
458 return componentGroups;
462int QgsLegendRenderer::setColumns( QList<LegendComponentGroup> &componentGroups )
465 double totalHeight = 0;
466 qreal maxGroupHeight = 0;
467 int forcedColumnBreaks = 0;
468 double totalSpaceAboveGroups = 0;
470 for (
const LegendComponentGroup &group : std::as_const( componentGroups ) )
472 const double topMargin = spaceAboveGroup( group );
473 totalHeight += topMargin;
474 totalSpaceAboveGroups += topMargin;
476 const double groupHeight = group.size.height();
477 totalHeight += groupHeight;
478 maxGroupHeight = std::max( groupHeight, maxGroupHeight );
480 if ( group.placeColumnBreakBeforeGroup )
481 forcedColumnBreaks++;
483 const double totalGroupHeight = ( totalHeight - totalSpaceAboveGroups );
484 double averageGroupHeight = totalGroupHeight / componentGroups.size();
486 if ( mSettings.
columnCount() == 0 && forcedColumnBreaks == 0 )
491 const int targetNumberColumns = std::max( forcedColumnBreaks + 1, mSettings.
columnCount() );
492 const int numberAutoPlacedBreaks = targetNumberColumns - forcedColumnBreaks - 1;
499 double maxColumnHeight = 0;
500 int currentColumn = 0;
501 int currentColumnGroupCount = 0;
502 double currentColumnHeight = 0;
503 int autoPlacedBreaks = 0;
506 double averageSpaceAboveGroups = 0;
507 if ( componentGroups.size() > targetNumberColumns )
508 averageSpaceAboveGroups = totalSpaceAboveGroups / ( componentGroups.size() );
510 double totalRemainingGroupHeight = totalGroupHeight;
511 double totalRemainingSpaceAboveGroups = totalSpaceAboveGroups;
512 for (
int i = 0; i < componentGroups.size(); i++ )
514 const LegendComponentGroup &group = componentGroups.at( i );
515 const double currentGroupHeight = group.size.height();
516 const double spaceAboveCurrentGroup = spaceAboveGroup( group );
518 totalRemainingGroupHeight -= currentGroupHeight;
519 totalRemainingSpaceAboveGroups -= spaceAboveCurrentGroup;
521 double currentColumnHeightIfGroupIsIncluded = currentColumnHeight;
522 if ( currentColumnGroupCount > 0 )
523 currentColumnHeightIfGroupIsIncluded += spaceAboveCurrentGroup;
524 currentColumnHeightIfGroupIsIncluded += currentGroupHeight;
526 const int numberRemainingGroupsIncludingThisOne = componentGroups.size() - i;
527 const int numberRemainingColumnsIncludingThisOne = numberAutoPlacedBreaks + 1 - autoPlacedBreaks;
528 const int numberRemainingColumnBreaks = numberRemainingColumnsIncludingThisOne - 1;
530 const double averageRemainingSpaceAboveGroups = numberRemainingGroupsIncludingThisOne > 1 ? ( totalRemainingSpaceAboveGroups / ( numberRemainingGroupsIncludingThisOne - 1 ) ) : 0;
531 const double estimatedRemainingSpaceAboveGroupsWhichWontBeUsedBecauseGroupsAreFirstInColumn = numberRemainingColumnBreaks * averageRemainingSpaceAboveGroups;
532 const double estimatedRemainingTotalHeightAfterThisGroup = totalRemainingGroupHeight
533 + totalRemainingSpaceAboveGroups
534 - estimatedRemainingSpaceAboveGroupsWhichWontBeUsedBecauseGroupsAreFirstInColumn;
536 const double estimatedTotalHeightOfRemainingColumnsIncludingThisOne = currentColumnHeightIfGroupIsIncluded
537 + estimatedRemainingTotalHeightAfterThisGroup;
540 double averageRemainingColumnHeightIncludingThisOne = estimatedTotalHeightOfRemainingColumnsIncludingThisOne / numberRemainingColumnsIncludingThisOne;
544 const int averageGroupsPerRemainingColumnsIncludingThisOne = std::ceil( averageRemainingColumnHeightIncludingThisOne / ( averageGroupHeight + averageSpaceAboveGroups ) );
546 averageRemainingColumnHeightIncludingThisOne = averageGroupsPerRemainingColumnsIncludingThisOne * ( averageGroupHeight + averageSpaceAboveGroups ) - averageSpaceAboveGroups;
548 bool canCreateNewColumn = ( currentColumnGroupCount > 0 )
549 && ( currentColumn < targetNumberColumns - 1 )
550 && ( autoPlacedBreaks < numberAutoPlacedBreaks );
552 bool shouldCreateNewColumn = currentColumnHeightIfGroupIsIncluded > averageRemainingColumnHeightIncludingThisOne
553 && currentColumnGroupCount > 0
554 && currentColumnHeightIfGroupIsIncluded > maxGroupHeight
555 && currentColumnHeightIfGroupIsIncluded > maxColumnHeight;
557 shouldCreateNewColumn |= group.placeColumnBreakBeforeGroup;
558 canCreateNewColumn |= group.placeColumnBreakBeforeGroup;
562 shouldCreateNewColumn |= ( componentGroups.size() - i < targetNumberColumns - currentColumn );
564 if ( canCreateNewColumn && shouldCreateNewColumn )
568 if ( !group.placeColumnBreakBeforeGroup )
570 currentColumnGroupCount = 0;
571 currentColumnHeight = group.size.height();
575 currentColumnHeight = currentColumnHeightIfGroupIsIncluded;
577 componentGroups[i].column = currentColumn;
578 currentColumnGroupCount++;
579 maxColumnHeight = std::max( currentColumnHeight, maxColumnHeight );
582 auto refineColumns = [&componentGroups,
this]() ->
bool
584 QHash< int, double > columnHeights;
585 QHash< int, int > columnGroupCounts;
586 double currentColumnHeight = 0;
587 int currentColumn = -1;
590 double maxCurrentColumnHeight = 0;
591 for (
int i = 0; i < componentGroups.size(); i++ )
593 const LegendComponentGroup &group = componentGroups.at( i );
594 if ( group.column != currentColumn )
596 if ( currentColumn >= 0 )
598 columnHeights.insert( currentColumn, currentColumnHeight );
599 columnGroupCounts.insert( currentColumn, groupCount );
602 currentColumn = group.column;
603 currentColumnHeight = 0;
605 columnCount = std::max( columnCount, currentColumn + 1 );
608 const double spaceAbove = spaceAboveGroup( group );
609 currentColumnHeight += spaceAbove + group.size.height();
612 columnHeights.insert( currentColumn, currentColumnHeight );
613 columnGroupCounts.insert( currentColumn, groupCount );
615 double totalColumnHeights = 0;
616 for (
int i = 0; i < columnCount; ++ i )
618 totalColumnHeights += columnHeights[i];
619 maxCurrentColumnHeight = std::max( maxCurrentColumnHeight, columnHeights[i] );
622 const double averageColumnHeight = totalColumnHeights / columnCount;
624 bool changed =
false;
625 int nextCandidateColumnForShift = 1;
626 for (
int i = 0; i < componentGroups.size(); i++ )
628 LegendComponentGroup &group = componentGroups[ i ];
629 if ( group.column < nextCandidateColumnForShift )
633 const bool canShift = !group.placeColumnBreakBeforeGroup
634 && columnGroupCounts[ group.column ] >= 2;
637 && columnHeights[ group.column - 1 ] < averageColumnHeight
638 && ( columnHeights[ group.column - 1 ] + group.size.height() ) * 0.9 < maxCurrentColumnHeight
642 columnHeights[ group.column ] += group.size.height() + spaceAboveGroup( group );
643 columnGroupCounts[ group.column ]++;
644 columnHeights[ group.column + 1 ] -= group.size.height();
645 columnGroupCounts[ group.column + 1]--;
650 nextCandidateColumnForShift = group.column + 1;
656 bool wasRefined =
true;
658 while ( wasRefined && iterations < 2 )
660 wasRefined = refineColumns();
665 QMap<QString, qreal> maxSymbolWidth;
666 for (
int i = 0; i < componentGroups.size(); i++ )
668 LegendComponentGroup &group = componentGroups[i];
669 for (
int j = 0; j < group.components.size(); j++ )
673 QString key = QStringLiteral(
"%1-%2" ).arg(
reinterpret_cast< qulonglong
>(
legendNode->
layerNode() ) ).arg( group.column );
674 maxSymbolWidth[key] = std::max( group.components.at( j ).symbolSize.width(), maxSymbolWidth[key] );
678 for (
int i = 0; i < componentGroups.size(); i++ )
680 LegendComponentGroup &group = componentGroups[i];
681 for (
int j = 0; j < group.components.size(); j++ )
685 QString key = QStringLiteral(
"%1-%2" ).arg(
reinterpret_cast< qulonglong
>(
legendNode->
layerNode() ) ).arg( group.column );
688 group.components[j].labelXOffset = maxSymbolWidth[key] + space;
689 group.components[j].maxSiblingSymbolWidth = maxSymbolWidth[key];
690 group.components[j].size.rwidth() = maxSymbolWidth[key] + space + group.components.at( j ).labelSize.width();
694 return targetNumberColumns;
697QSizeF QgsLegendRenderer::drawTitle(
QgsRenderContext &context,
double top, Qt::AlignmentFlag halignment,
double legendWidth )
const
700 if ( mSettings.
title().isEmpty() )
710 widthAndOffsetForTitleText( halignment, legendWidth, textBoxWidth, textBoxLeft );
715 double overallTextHeight = 0;
716 double overallTextWidth = 0;
724 size.rheight() = overallTextHeight / dotsPerMM;
725 size.rwidth() = overallTextWidth / dotsPerMM;
731 const QRectF r( textBoxLeft * dotsPerMM, top * dotsPerMM, textBoxWidth * dotsPerMM, overallTextHeight );
734 halignment == Qt::AlignRight ? Qgis::TextHorizontalAlignment::Right : Qgis::TextHorizontalAlignment::Center;
743double QgsLegendRenderer::spaceAboveGroup(
const LegendComponentGroup &group )
745 if ( group.components.isEmpty() )
return 0;
747 LegendComponent component = group.components.first();
749 if (
QgsLayerTreeGroup *nodeGroup = qobject_cast<QgsLayerTreeGroup *>( component.item ) )
753 else if (
QgsLayerTreeLayer *nodeLayer = qobject_cast<QgsLayerTreeLayer *>( component.item ) )
757 else if ( qobject_cast<QgsLayerTreeModelLegendNode *>( component.item ) )
766QSizeF QgsLegendRenderer::drawGroup(
const LegendComponentGroup &group,
QgsRenderContext &context, ColumnContext columnContext,
double top )
769 QSizeF size = QSizeF( group.size );
770 double currentY = top;
771 for (
const LegendComponent &component : std::as_const( group.components ) )
773 if (
QgsLayerTreeGroup *groupItem = qobject_cast<QgsLayerTreeGroup *>( component.item ) )
783 ColumnContext columnContextForItem = columnContext;
784 double indentWidth = component.indent;
797 columnContextForItem.left += indentWidth;
801 columnContextForItem.right -= indentWidth;
803 groupSize = drawGroupTitle( groupItem, context, columnContextForItem, currentY );
804 size.rwidth() = std::max( groupSize.width(), size.width() );
807 else if (
QgsLayerTreeLayer *layerItem = qobject_cast<QgsLayerTreeLayer *>( component.item ) )
818 ColumnContext columnContextForItem = columnContext;
819 double indentWidth = component.indent;
820 columnContextForItem.left += indentWidth;
821 subGroupSize = drawLayerTitle( layerItem, context, columnContextForItem, currentY );
822 size.rwidth() = std::max( subGroupSize.width(), size.width() );
832 ColumnContext columnContextForItem = columnContext;
833 double indentWidth = 0;
834 indentWidth = component.indent;
837 columnContextForItem.left += indentWidth;
841 columnContextForItem.right -= indentWidth;
844 LegendComponent symbolComponent = drawSymbolItem(
legendNode, context, columnContextForItem, currentY, component.maxSiblingSymbolWidth );
846 size.rwidth() = std::max( symbolComponent.size.width() + indentWidth, size.width() );
848 currentY += component.size.height();
869 ctx.
point = QPointF( columnContext.left, top );
902 LegendComponent component;
903 component.item = symbolItem;
910 double width = std::max(
static_cast< double >( im.
symbolSize.width() ), maxSiblingSymbolWidth )
917 component.size = QSizeF( width, height );
924 QModelIndex idx = mLegendModel->
node2index( nodeLayer );
925 QString titleString = mLegendModel->
data( idx, Qt::DisplayRole ).toString();
927 if ( titleString.isEmpty() )
933 if ( nodeLayer->
layer() )
943 double overallTextHeight = 0;
944 double overallTextWidth = 0;
952 size.rheight() = overallTextHeight / dotsPerMM;
953 size.rwidth() = overallTextWidth / dotsPerMM + sideMargin *
960 mSettings.
style(
nodeLegendStyle( nodeLayer ) ).
alignment() == Qt::AlignRight ? Qgis::TextHorizontalAlignment::Right : Qgis::TextHorizontalAlignment::Center;
962 const QRectF r( ( columnContext.left + ( halign == Qgis::TextHorizontalAlignment::Left ? sideMargin : 0 ) ) * dotsPerMM, top * dotsPerMM,
963 ( ( columnContext.right - columnContext.left ) - ( halign == Qgis::TextHorizontalAlignment::Right ? sideMargin : 0 ) ) * dotsPerMM, overallTextHeight );
978 QModelIndex idx = mLegendModel->
node2index( nodeGroup );
984 double overallTextHeight = 0;
985 double overallTextWidth = 0;
996 size.rheight() = overallTextHeight / dotsPerMM;
997 size.rwidth() = overallTextWidth / dotsPerMM + sideMargin *
1005 mSettings.
style(
nodeLegendStyle( nodeGroup ) ).
alignment() == Qt::AlignRight ? Qgis::TextHorizontalAlignment::Right : Qgis::TextHorizontalAlignment::Center;
1007 const QRectF r( dotsPerMM * ( columnContext.left + ( halign == Qgis::TextHorizontalAlignment::Left ? sideMargin : 0 ) ), top * dotsPerMM,
1008 dotsPerMM * ( ( columnContext.right - columnContext.left ) - ( halign == Qgis::TextHorizontalAlignment::Right ? sideMargin : 0 ) ), overallTextHeight );
1018 QString style = node->
customProperty( QStringLiteral(
"legend/title-style" ) ).toString();
1019 if ( style == QLatin1String(
"hidden" ) )
1021 else if ( style == QLatin1String(
"group" ) )
1023 else if ( style == QLatin1String(
"subgroup" ) )
1050 str = QStringLiteral(
"hidden" );
1053 str = QStringLiteral(
"group" );
1056 str = QStringLiteral(
"subgroup" );
1062 if ( !
str.isEmpty() )
1070 paintAndDetermineSize( context );
@ RectangleAscentBased
Similar to Rectangle mode, but uses ascents only when calculating font and line heights....
@ ApplyScalingWorkaroundForTextRendering
Whether a scaling workaround designed to stablise the rendering of small font sizes (or for painters ...
TextHorizontalAlignment
Text horizontal alignment.
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.
QgsLegendStyle style(QgsLegendStyle::Style s) const
Returns the style for a legend component.
Qt::AlignmentFlag titleAlignment() const
Returns the alignment of the legend title.
QString title() const
Returns the title for the legend, which will be rendered above all legend items.
double columnSpace() const
Returns the margin space between adjacent columns (in millimeters).
double boxSpace() const
Returns the legend box space (in millimeters), which is the empty margin around the inside of the leg...
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.
QgsTextFormat & textFormat()
Returns the text format 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.
double scaleFactor() const
Returns the scaling factor for the render to convert painter units to physical sizes.
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.
Scoped object for temporary scaling of a QgsRenderContext for pixel based rendering.
Implementation of legend node interface for displaying preview of vector symbols and their labels and...
Container for all settings relating to text rendering.
static double textWidth(const QgsRenderContext &context, const QgsTextFormat &format, const QStringList &textLines, QFontMetricsF *fontMetrics=nullptr)
Returns the width of a text based on a given format.
static void drawText(const QRectF &rect, double rotation, Qgis::TextHorizontalAlignment alignment, const QStringList &textLines, QgsRenderContext &context, const QgsTextFormat &format, bool drawAsOutlines=true, Qgis::TextVerticalAlignment vAlignment=Qgis::TextVerticalAlignment::Top, Qgis::TextRendererFlags flags=Qgis::TextRendererFlags(), Qgis::TextLayoutMode mode=Qgis::TextLayoutMode::Rectangle)
Draws text within a rectangle using the specified settings.
static double textHeight(const QgsRenderContext &context, const QgsTextFormat &format, const QStringList &textLines, Qgis::TextLayoutMode mode=Qgis::TextLayoutMode::Point, QFontMetricsF *fontMetrics=nullptr, Qgis::TextRendererFlags flags=Qgis::TextRendererFlags(), double maxLineWidth=0)
Returns the height of a text based on a given format.
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.