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" );
124 if ( vLayer->renderer() )
127 if ( ! ruleKey.isEmpty() )
130 const QString ruleExp { vLayer->renderer()->legendKeyToExpression( ruleKey, vLayer, ok ) };
133 group[ QStringLiteral(
"rule" ) ] = ruleExp;
139 nodes.append( group );
141 else if ( legendNodes.count() > 1 )
144 group[ QStringLiteral(
"type" ) ] = QStringLiteral(
"layer" );
145 group[ QStringLiteral(
"title" ) ] = text;
148 for (
int j = 0; j < legendNodes.count(); j++ )
156 if ( vLayer->renderer() )
159 if ( ! ruleKey.isEmpty() )
162 const QString ruleExp { vLayer->renderer()->legendKeyToExpression( ruleKey, vLayer, ok ) };
165 symbol[ QStringLiteral(
"rule" ) ] = ruleExp;
171 symbols.append( symbol );
173 group[ QStringLiteral(
"symbols" ) ] = symbols;
175 nodes.append( group );
180 json[QStringLiteral(
"nodes" )] = nodes;
195 QList<LegendComponentGroup> componentGroups = createComponentGroupList( rootGroup, context );
197 const int columnCount = setColumns( componentGroups );
199 QMap< int, double > maxColumnWidths;
200 qreal maxEqualColumnWidth = 0;
208 for (
const LegendComponentGroup &group : std::as_const( componentGroups ) )
210 const QSizeF actualSize = drawGroup( group, context, ColumnContext() );
211 maxEqualColumnWidth = std::max( actualSize.width(), maxEqualColumnWidth );
212 maxColumnWidths[ group.column ] = std::max( actualSize.width(), maxColumnWidths.value( group.column, 0 ) );
215 if ( columnCount == 1 )
218 maxEqualColumnWidth = std::max( maxEqualColumnWidth, mLegendSize.width() - 2 * mSettings.
boxSpace() );
219 maxColumnWidths[ 0 ] = maxEqualColumnWidth;
223 QSizeF titleSize = drawTitle( context, 0 );
225 titleSize.rwidth() += mSettings.
boxSpace() * 2.0;
230 bool firstInColumn =
true;
231 double columnMaxHeight = 0;
232 qreal columnWidth = 0;
234 ColumnContext columnContext;
235 columnContext.left = mSettings.
boxSpace();
236 columnContext.right = std::max( mLegendSize.width() - mSettings.
boxSpace(), mSettings.
boxSpace() );
237 double currentY = columnTop;
239 for (
const LegendComponentGroup &group : std::as_const( componentGroups ) )
241 if ( group.column > column )
244 columnContext.left = group.column > 0 ? ( columnContext.right + mSettings.
columnSpace() ) : mSettings.
boxSpace();
245 columnWidth = mSettings.
equalColumnWidth() ? maxEqualColumnWidth : maxColumnWidths.value( group.column );
246 columnContext.right = columnContext.left + columnWidth;
247 currentY = columnTop;
249 firstInColumn =
true;
251 if ( !firstInColumn )
253 currentY += spaceAboveGroup( group );
256 drawGroup( group, context, columnContext, currentY );
258 currentY += group.size.height();
259 columnMaxHeight = std::max( currentY - columnTop, columnMaxHeight );
261 firstInColumn =
false;
263 const double totalWidth = columnContext.right + mSettings.
boxSpace();
265 size.rheight() = columnTop + columnMaxHeight + mSettings.
boxSpace();
266 size.rwidth() = totalWidth;
267 if ( !mSettings.
title().isEmpty() )
269 size.rwidth() = std::max( titleSize.width(), size.width() );
273 if ( mLegendSize.isValid() )
275 qreal w = std::max( size.width(), mLegendSize.width() );
276 qreal h = std::max( size.height(), mLegendSize.height() );
277 size = QSizeF( w, h );
281 if ( !mSettings.
title().isEmpty() )
289void QgsLegendRenderer::widthAndOffsetForTitleText(
const Qt::AlignmentFlag halignment,
const double legendWidth,
double &textBoxWidth,
double &textBoxLeft )
const
291 switch ( halignment )
295 textBoxWidth = legendWidth - 2 * mSettings.
boxSpace();
298 case Qt::AlignHCenter:
301 const double centerX = legendWidth / 2;
302 textBoxWidth = ( std::min(
static_cast< double >( centerX ), legendWidth - centerX ) - mSettings.
boxSpace() ) * 2.0;
303 textBoxLeft = centerX - textBoxWidth / 2.;
309QList<QgsLegendRenderer::LegendComponentGroup> QgsLegendRenderer::createComponentGroupList(
QgsLayerTreeGroup *parentGroup,
QgsRenderContext &context,
double indent )
311 QList<LegendComponentGroup> componentGroups;
314 return componentGroups;
316 const QList<QgsLayerTreeNode *> childNodes = parentGroup->
children();
322 QString style = node->customProperty( QStringLiteral(
"legend/title-style" ) ).toString();
324 double newIndent = indent;
325 if ( style == QLatin1String(
"subgroup" ) )
335 QList<LegendComponentGroup> subgroups = createComponentGroupList( nodeGroup, context, newIndent );
337 bool hasSubItems = !subgroups.empty();
341 LegendComponent component;
342 component.item = node;
343 component.indent = newIndent;
344 component.size = drawGroupTitle( nodeGroup, context );
346 if ( !subgroups.isEmpty() )
349 subgroups[0].size.rheight() += spaceAboveGroup( subgroups[0] );
351 subgroups[0].components.prepend( component );
352 subgroups[0].size.rheight() += component.size.height();
353 subgroups[0].size.rwidth() = std::max( component.size.width(), subgroups[0].size.width() );
354 if ( nodeGroup->
customProperty( QStringLiteral(
"legend/column-break" ) ).toInt() )
355 subgroups[0].placeColumnBreakBeforeGroup =
true;
360 LegendComponentGroup group;
361 group.placeColumnBreakBeforeGroup = nodeGroup->
customProperty( QStringLiteral(
"legend/column-break" ) ).toInt();
362 group.components.append( component );
363 group.size.rwidth() += component.size.width();
364 group.size.rheight() += component.size.height();
365 group.size.rwidth() = std::max( component.size.width(), group.size.width() );
366 subgroups.append( group );
372 componentGroups.append( subgroups );
380 bool allowColumnSplit =
false;
387 allowColumnSplit =
true;
390 allowColumnSplit =
false;
394 LegendComponentGroup group;
395 group.placeColumnBreakBeforeGroup = nodeLayer->
customProperty( QStringLiteral(
"legend/column-break" ) ).toInt();
399 LegendComponent component;
400 component.item = node;
401 component.size = drawLayerTitle( nodeLayer, context );
402 component.indent = indent;
403 group.components.append( component );
404 group.size.rwidth() = component.size.width();
405 group.size.rheight() = component.size.height();
408 QList<QgsLayerTreeModelLegendNode *> legendNodes = mLegendModel->
layerLegendNodes( nodeLayer );
416 QList<LegendComponentGroup> layerGroups;
417 layerGroups.reserve( legendNodes.count() );
419 bool groupIsLayerGroup =
true;
420 double symbolIndent = indent;
421 switch ( layerStyle )
425 symbolIndent += mSettings.
style( layerStyle ).
indent( );
430 for (
int j = 0; j < legendNodes.count(); j++ )
434 LegendComponent symbolComponent = drawSymbolItem(
legendNode, context, ColumnContext(), 0 );
438 if ( !allowColumnSplit || j == 0 )
442 if ( groupIsLayerGroup )
443 layerGroups.prepend( group );
445 layerGroups.append( group );
447 group = LegendComponentGroup();
448 group.placeColumnBreakBeforeGroup =
true;
449 groupIsLayerGroup =
false;
454 group.size.rwidth() = std::max( symbolComponent.size.width(), group.size.width() );
456 if ( !group.components.isEmpty() )
461 group.size.rheight() += symbolComponent.size.height();
462 symbolComponent.indent = symbolIndent;
463 group.components.append( symbolComponent );
467 if ( group.size.height() > 0 )
469 if ( groupIsLayerGroup )
470 layerGroups.prepend( group );
472 layerGroups.append( group );
473 group = LegendComponentGroup();
474 groupIsLayerGroup =
false;
476 LegendComponentGroup symbolGroup;
477 symbolGroup.placeColumnBreakBeforeGroup = forceBreak;
478 symbolComponent.indent = symbolIndent;
479 symbolGroup.components.append( symbolComponent );
480 symbolGroup.size.rwidth() = symbolComponent.size.width();
481 symbolGroup.size.rheight() = symbolComponent.size.height();
482 layerGroups.append( symbolGroup );
485 if ( group.size.height() > 0 )
487 if ( groupIsLayerGroup )
488 layerGroups.prepend( group );
490 layerGroups.append( group );
492 componentGroups.append( layerGroups );
496 return componentGroups;
500int QgsLegendRenderer::setColumns( QList<LegendComponentGroup> &componentGroups )
503 double totalHeight = 0;
504 qreal maxGroupHeight = 0;
505 int forcedColumnBreaks = 0;
506 double totalSpaceAboveGroups = 0;
508 for (
const LegendComponentGroup &group : std::as_const( componentGroups ) )
510 const double topMargin = spaceAboveGroup( group );
511 totalHeight += topMargin;
512 totalSpaceAboveGroups += topMargin;
514 const double groupHeight = group.size.height();
515 totalHeight += groupHeight;
516 maxGroupHeight = std::max( groupHeight, maxGroupHeight );
518 if ( group.placeColumnBreakBeforeGroup )
519 forcedColumnBreaks++;
521 const double totalGroupHeight = ( totalHeight - totalSpaceAboveGroups );
522 double averageGroupHeight = totalGroupHeight / componentGroups.size();
524 if ( mSettings.
columnCount() == 0 && forcedColumnBreaks == 0 )
529 const int targetNumberColumns = std::max( forcedColumnBreaks + 1, mSettings.
columnCount() );
530 const int numberAutoPlacedBreaks = targetNumberColumns - forcedColumnBreaks - 1;
537 double maxColumnHeight = 0;
538 int currentColumn = 0;
539 int currentColumnGroupCount = 0;
540 double currentColumnHeight = 0;
541 int autoPlacedBreaks = 0;
544 double averageSpaceAboveGroups = 0;
545 if ( componentGroups.size() > targetNumberColumns )
546 averageSpaceAboveGroups = totalSpaceAboveGroups / ( componentGroups.size() );
548 double totalRemainingGroupHeight = totalGroupHeight;
549 double totalRemainingSpaceAboveGroups = totalSpaceAboveGroups;
550 for (
int i = 0; i < componentGroups.size(); i++ )
552 const LegendComponentGroup &group = componentGroups.at( i );
553 const double currentGroupHeight = group.size.height();
554 const double spaceAboveCurrentGroup = spaceAboveGroup( group );
556 totalRemainingGroupHeight -= currentGroupHeight;
557 totalRemainingSpaceAboveGroups -= spaceAboveCurrentGroup;
559 double currentColumnHeightIfGroupIsIncluded = currentColumnHeight;
560 if ( currentColumnGroupCount > 0 )
561 currentColumnHeightIfGroupIsIncluded += spaceAboveCurrentGroup;
562 currentColumnHeightIfGroupIsIncluded += currentGroupHeight;
564 const int numberRemainingGroupsIncludingThisOne = componentGroups.size() - i;
565 const int numberRemainingColumnsIncludingThisOne = numberAutoPlacedBreaks + 1 - autoPlacedBreaks;
566 const int numberRemainingColumnBreaks = numberRemainingColumnsIncludingThisOne - 1;
568 const double averageRemainingSpaceAboveGroups = numberRemainingGroupsIncludingThisOne > 1 ? ( totalRemainingSpaceAboveGroups / ( numberRemainingGroupsIncludingThisOne - 1 ) ) : 0;
569 const double estimatedRemainingSpaceAboveGroupsWhichWontBeUsedBecauseGroupsAreFirstInColumn = numberRemainingColumnBreaks * averageRemainingSpaceAboveGroups;
570 const double estimatedRemainingTotalHeightAfterThisGroup = totalRemainingGroupHeight
571 + totalRemainingSpaceAboveGroups
572 - estimatedRemainingSpaceAboveGroupsWhichWontBeUsedBecauseGroupsAreFirstInColumn;
574 const double estimatedTotalHeightOfRemainingColumnsIncludingThisOne = currentColumnHeightIfGroupIsIncluded
575 + estimatedRemainingTotalHeightAfterThisGroup;
578 double averageRemainingColumnHeightIncludingThisOne = estimatedTotalHeightOfRemainingColumnsIncludingThisOne / numberRemainingColumnsIncludingThisOne;
582 const int averageGroupsPerRemainingColumnsIncludingThisOne = std::ceil( averageRemainingColumnHeightIncludingThisOne / ( averageGroupHeight + averageSpaceAboveGroups ) );
584 averageRemainingColumnHeightIncludingThisOne = averageGroupsPerRemainingColumnsIncludingThisOne * ( averageGroupHeight + averageSpaceAboveGroups ) - averageSpaceAboveGroups;
586 bool canCreateNewColumn = ( currentColumnGroupCount > 0 )
587 && ( currentColumn < targetNumberColumns - 1 )
588 && ( autoPlacedBreaks < numberAutoPlacedBreaks );
590 bool shouldCreateNewColumn = currentColumnHeightIfGroupIsIncluded > averageRemainingColumnHeightIncludingThisOne
591 && currentColumnGroupCount > 0
592 && currentColumnHeightIfGroupIsIncluded > maxGroupHeight
593 && currentColumnHeightIfGroupIsIncluded > maxColumnHeight;
595 shouldCreateNewColumn |= group.placeColumnBreakBeforeGroup;
596 canCreateNewColumn |= group.placeColumnBreakBeforeGroup;
600 shouldCreateNewColumn |= ( componentGroups.size() - i < targetNumberColumns - currentColumn );
602 if ( canCreateNewColumn && shouldCreateNewColumn )
606 if ( !group.placeColumnBreakBeforeGroup )
608 currentColumnGroupCount = 0;
609 currentColumnHeight = group.size.height();
613 currentColumnHeight = currentColumnHeightIfGroupIsIncluded;
615 componentGroups[i].column = currentColumn;
616 currentColumnGroupCount++;
617 maxColumnHeight = std::max( currentColumnHeight, maxColumnHeight );
620 auto refineColumns = [&componentGroups,
this]() ->
bool
622 QHash< int, double > columnHeights;
623 QHash< int, int > columnGroupCounts;
624 double currentColumnHeight = 0;
625 int currentColumn = -1;
628 double maxCurrentColumnHeight = 0;
629 for (
int i = 0; i < componentGroups.size(); i++ )
631 const LegendComponentGroup &group = componentGroups.at( i );
632 if ( group.column != currentColumn )
634 if ( currentColumn >= 0 )
636 columnHeights.insert( currentColumn, currentColumnHeight );
637 columnGroupCounts.insert( currentColumn, groupCount );
640 currentColumn = group.column;
641 currentColumnHeight = 0;
643 columnCount = std::max( columnCount, currentColumn + 1 );
646 const double spaceAbove = spaceAboveGroup( group );
647 currentColumnHeight += spaceAbove + group.size.height();
650 columnHeights.insert( currentColumn, currentColumnHeight );
651 columnGroupCounts.insert( currentColumn, groupCount );
653 double totalColumnHeights = 0;
654 for (
int i = 0; i < columnCount; ++ i )
656 totalColumnHeights += columnHeights[i];
657 maxCurrentColumnHeight = std::max( maxCurrentColumnHeight, columnHeights[i] );
660 const double averageColumnHeight = totalColumnHeights / columnCount;
662 bool changed =
false;
663 int nextCandidateColumnForShift = 1;
664 for (
int i = 0; i < componentGroups.size(); i++ )
666 LegendComponentGroup &group = componentGroups[ i ];
667 if ( group.column < nextCandidateColumnForShift )
671 const bool canShift = !group.placeColumnBreakBeforeGroup
672 && columnGroupCounts[ group.column ] >= 2;
675 && columnHeights[ group.column - 1 ] < averageColumnHeight
676 && ( columnHeights[ group.column - 1 ] + group.size.height() ) * 0.9 < maxCurrentColumnHeight
680 columnHeights[ group.column ] += group.size.height() + spaceAboveGroup( group );
681 columnGroupCounts[ group.column ]++;
682 columnHeights[ group.column + 1 ] -= group.size.height();
683 columnGroupCounts[ group.column + 1]--;
688 nextCandidateColumnForShift = group.column + 1;
694 bool wasRefined =
true;
696 while ( wasRefined && iterations < 2 )
698 wasRefined = refineColumns();
703 QMap<QString, qreal> maxSymbolWidth;
704 for (
int i = 0; i < componentGroups.size(); i++ )
706 LegendComponentGroup &group = componentGroups[i];
707 for (
int j = 0; j < group.components.size(); j++ )
711 QString key = QStringLiteral(
"%1-%2" ).arg(
reinterpret_cast< qulonglong
>(
legendNode->
layerNode() ) ).arg( group.column );
712 maxSymbolWidth[key] = std::max( group.components.at( j ).symbolSize.width(), maxSymbolWidth[key] );
716 for (
int i = 0; i < componentGroups.size(); i++ )
718 LegendComponentGroup &group = componentGroups[i];
719 for (
int j = 0; j < group.components.size(); j++ )
723 QString key = QStringLiteral(
"%1-%2" ).arg(
reinterpret_cast< qulonglong
>(
legendNode->
layerNode() ) ).arg( group.column );
726 group.components[j].labelXOffset = maxSymbolWidth[key] + space;
727 group.components[j].maxSiblingSymbolWidth = maxSymbolWidth[key];
728 group.components[j].size.rwidth() = maxSymbolWidth[key] + space + group.components.at( j ).labelSize.width();
732 return targetNumberColumns;
735QSizeF QgsLegendRenderer::drawTitle(
QgsRenderContext &context,
double top, Qt::AlignmentFlag halignment,
double legendWidth )
const
738 if ( mSettings.
title().isEmpty() )
748 widthAndOffsetForTitleText( halignment, legendWidth, textBoxWidth, textBoxLeft );
753 double overallTextHeight = 0;
754 double overallTextWidth = 0;
762 size.rheight() = overallTextHeight / dotsPerMM;
763 size.rwidth() = overallTextWidth / dotsPerMM;
769 const QRectF r( textBoxLeft * dotsPerMM, top * dotsPerMM, textBoxWidth * dotsPerMM, overallTextHeight );
781double QgsLegendRenderer::spaceAboveGroup(
const LegendComponentGroup &group )
783 if ( group.components.isEmpty() )
return 0;
785 LegendComponent component = group.components.first();
787 if (
QgsLayerTreeGroup *nodeGroup = qobject_cast<QgsLayerTreeGroup *>( component.item ) )
791 else if (
QgsLayerTreeLayer *nodeLayer = qobject_cast<QgsLayerTreeLayer *>( component.item ) )
795 else if ( qobject_cast<QgsLayerTreeModelLegendNode *>( component.item ) )
804QSizeF QgsLegendRenderer::drawGroup(
const LegendComponentGroup &group,
QgsRenderContext &context, ColumnContext columnContext,
double top )
807 QSizeF size = QSizeF( group.size );
808 double currentY = top;
809 for (
const LegendComponent &component : std::as_const( group.components ) )
811 if (
QgsLayerTreeGroup *groupItem = qobject_cast<QgsLayerTreeGroup *>( component.item ) )
821 ColumnContext columnContextForItem = columnContext;
822 double indentWidth = component.indent;
835 columnContextForItem.left += indentWidth;
839 columnContextForItem.right -= indentWidth;
841 groupSize = drawGroupTitle( groupItem, context, columnContextForItem, currentY );
842 size.rwidth() = std::max( groupSize.width(), size.width() );
845 else if (
QgsLayerTreeLayer *layerItem = qobject_cast<QgsLayerTreeLayer *>( component.item ) )
856 ColumnContext columnContextForItem = columnContext;
857 double indentWidth = component.indent;
858 columnContextForItem.left += indentWidth;
859 subGroupSize = drawLayerTitle( layerItem, context, columnContextForItem, currentY );
860 size.rwidth() = std::max( subGroupSize.width(), size.width() );
870 ColumnContext columnContextForItem = columnContext;
871 double indentWidth = 0;
872 indentWidth = component.indent;
875 columnContextForItem.left += indentWidth;
879 columnContextForItem.right -= indentWidth;
882 LegendComponent symbolComponent = drawSymbolItem(
legendNode, context, columnContextForItem, currentY, component.maxSiblingSymbolWidth );
884 size.rwidth() = std::max( symbolComponent.size.width() + indentWidth, size.width() );
886 currentY += component.size.height();
907 ctx.
point = QPointF( columnContext.left, top );
933 symbolScope = symbolNode->createSymbolScope();
948 LegendComponent component;
949 component.item = symbolItem;
956 double width = std::max(
static_cast< double >( im.
symbolSize.width() ), maxSiblingSymbolWidth )
963 component.size = QSizeF( width, height );
970 QModelIndex idx = mLegendModel->
node2index( nodeLayer );
971 QString titleString = mLegendModel->
data( idx, Qt::DisplayRole ).toString();
973 if ( titleString.isEmpty() )
979 if ( nodeLayer->
layer() )
989 double overallTextHeight = 0;
990 double overallTextWidth = 0;
998 size.rheight() = overallTextHeight / dotsPerMM;
999 size.rwidth() = overallTextWidth / dotsPerMM + sideMargin *
1023 QSizeF size( 0, 0 );
1024 QModelIndex idx = mLegendModel->
node2index( nodeGroup );
1030 double overallTextHeight = 0;
1031 double overallTextWidth = 0;
1042 size.rheight() = overallTextHeight / dotsPerMM;
1043 size.rwidth() = overallTextWidth / dotsPerMM + sideMargin *
1064 QString style = node->
customProperty( QStringLiteral(
"legend/title-style" ) ).toString();
1065 if ( style == QLatin1String(
"hidden" ) )
1067 else if ( style == QLatin1String(
"group" ) )
1069 else if ( style == QLatin1String(
"subgroup" ) )
1096 str = QStringLiteral(
"hidden" );
1099 str = QStringLiteral(
"group" );
1102 str = QStringLiteral(
"subgroup" );
1108 if ( !
str.isEmpty() )
1116 paintAndDetermineSize( context );
@ RectangleAscentBased
Similar to Rectangle mode, but uses ascents only when calculating font and line heights....
@ Rectangle
Text within rectangle layout mode.
@ ShowRuleDetails
If set, the rule expression of a rule based renderer legend item will be added to the JSON.
@ 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...
virtual QVariant data(int role) const =0
Returns data associated with the item. Must be implemented in derived class.
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.
@ RuleKey
Rule key of the node (QString)
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...
Qgis::LegendJsonRenderFlags jsonRenderFlags() const
Returns the JSON export flags.
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.
Represents a vector layer which manages a vector based data sets.
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.