33 : mLegendModel( legendModel )
35 , mSettings( settings )
37 mProxyModel->setLayerTreeModel( mLegendModel );
41 : mLegendModel( other.mLegendModel )
42 , mProxyModel( std::move( other.mProxyModel ) )
43 , mSettings( std::move( other.mSettings ) )
44 , mLegendSize( other.mLegendSize )
46 mProxyModel->setLayerTreeModel( mLegendModel );
53 std::unique_ptr< QgsRenderContext > tmpContext;
60 tmpContext->setRendererScale( mSettings.
mapScale() );
63 renderContext = tmpContext.get();
68 return paintAndDetermineSize( *renderContext );
77 context.setRendererScale( mSettings.
mapScale() );
81 paintAndDetermineSize( context );
93 json[QStringLiteral(
"title" )] = mSettings.
title();
101 const QList<QgsLayerTreeNode *> childNodes = nodeGroup->
children();
104 if ( !mProxyModel->nodeShown( node ) )
110 const QModelIndex idx = mLegendModel->
node2index( nodeGroup );
111 const QString text = mLegendModel->
data( idx, Qt::DisplayRole ).toString();
114 group[ QStringLiteral(
"type" ) ] = QStringLiteral(
"group" );
115 group[ QStringLiteral(
"title" ) ] = text;
116 nodes.append( group );
125 const QModelIndex idx = mLegendModel->
node2index( nodeLayer );
126 text = mLegendModel->
data( idx, Qt::DisplayRole ).toString();
129 QList<QgsLayerTreeModelLegendNode *> legendNodes = mLegendModel->
layerLegendNodes( nodeLayer );
134 if ( legendNodes.count() == 1 )
136 QJsonObject group = legendNodes.at( 0 )->exportToJson( mSettings, context );
137 group[ QStringLiteral(
"type" ) ] = QStringLiteral(
"layer" );
142 if ( vLayer->renderer() )
145 if ( ! ruleKey.isEmpty() )
148 const QString ruleExp { vLayer->renderer()->legendKeyToExpression( ruleKey, vLayer, ok ) };
151 group[ QStringLiteral(
"rule" ) ] = ruleExp;
157 nodes.append( group );
159 else if ( legendNodes.count() > 1 )
162 group[ QStringLiteral(
"type" ) ] = QStringLiteral(
"layer" );
163 group[ QStringLiteral(
"title" ) ] = text;
166 for (
int j = 0; j < legendNodes.count(); j++ )
174 if ( vLayer->renderer() )
177 if ( ! ruleKey.isEmpty() )
180 const QString ruleExp { vLayer->renderer()->legendKeyToExpression( ruleKey, vLayer, ok ) };
183 symbol[ QStringLiteral(
"rule" ) ] = ruleExp;
189 symbols.append( symbol );
191 group[ QStringLiteral(
"symbols" ) ] = symbols;
193 nodes.append( group );
198 json[QStringLiteral(
"nodes" )] = nodes;
213 QList<LegendComponentGroup> componentGroups = createComponentGroupList( rootGroup, context );
215 const int columnCount = setColumns( componentGroups );
217 QMap< int, double > maxColumnWidths;
218 qreal maxEqualColumnWidth = 0;
226 for (
const LegendComponentGroup &group : std::as_const( componentGroups ) )
228 const QSizeF actualSize = drawGroup( group, context, ColumnContext() );
229 maxEqualColumnWidth = std::max( actualSize.width(), maxEqualColumnWidth );
230 maxColumnWidths[ group.column ] = std::max( actualSize.width(), maxColumnWidths.value( group.column, 0 ) );
233 if ( columnCount == 1 )
236 maxEqualColumnWidth = std::max( maxEqualColumnWidth, mLegendSize.width() - 2 * mSettings.
boxSpace() );
237 maxColumnWidths[ 0 ] = maxEqualColumnWidth;
241 QSizeF titleSize = drawTitle( context, 0 );
243 titleSize.rwidth() += mSettings.
boxSpace() * 2.0;
248 bool firstInColumn =
true;
249 double columnMaxHeight = 0;
250 qreal columnWidth = 0;
252 ColumnContext columnContext;
253 columnContext.left = mSettings.
boxSpace();
254 columnContext.right = std::max( mLegendSize.width() - mSettings.
boxSpace(), mSettings.
boxSpace() );
255 double currentY = columnTop;
257 for (
const LegendComponentGroup &group : std::as_const( componentGroups ) )
259 if ( group.column > column )
262 columnContext.left = group.column > 0 ? ( columnContext.right + mSettings.
columnSpace() ) : mSettings.boxSpace();
263 columnWidth = mSettings.
equalColumnWidth() ? maxEqualColumnWidth : maxColumnWidths.value( group.column );
264 columnContext.right = columnContext.left + columnWidth;
265 currentY = columnTop;
267 firstInColumn =
true;
269 if ( !firstInColumn )
271 currentY += spaceAboveGroup( group );
274 drawGroup( group, context, columnContext, currentY );
276 currentY += group.size.height();
277 columnMaxHeight = std::max( currentY - columnTop, columnMaxHeight );
279 firstInColumn =
false;
281 const double totalWidth = columnContext.right + mSettings.
boxSpace();
283 size.rheight() = columnTop + columnMaxHeight + mSettings.
boxSpace();
284 size.rwidth() = totalWidth;
285 if ( !mSettings.
title().isEmpty() )
287 size.rwidth() = std::max( titleSize.width(), size.width() );
291 if ( mLegendSize.isValid() )
293 qreal w = std::max( size.width(), mLegendSize.width() );
294 qreal h = std::max( size.height(), mLegendSize.height() );
295 size = QSizeF( w, h );
299 if ( !mSettings.
title().isEmpty() )
307void QgsLegendRenderer::widthAndOffsetForTitleText(
const Qt::AlignmentFlag halignment,
const double legendWidth,
double &textBoxWidth,
double &textBoxLeft )
const
309 switch ( halignment )
313 textBoxWidth = legendWidth - 2 * mSettings.
boxSpace();
316 case Qt::AlignHCenter:
319 const double centerX = legendWidth / 2;
320 textBoxWidth = ( std::min(
static_cast< double >( centerX ), legendWidth - centerX ) - mSettings.
boxSpace() ) * 2.0;
321 textBoxLeft = centerX - textBoxWidth / 2.;
327QList<QgsLegendRenderer::LegendComponentGroup> QgsLegendRenderer::createComponentGroupList(
QgsLayerTreeGroup *parentGroup,
QgsRenderContext &context,
double indent )
329 QList<LegendComponentGroup> componentGroups;
332 return componentGroups;
334 const QList<QgsLayerTreeNode *> childNodes = parentGroup->
children();
337 if ( !mProxyModel->nodeShown( node ) )
343 QString style = node->customProperty( QStringLiteral(
"legend/title-style" ) ).toString();
345 double newIndent = indent;
346 if ( style == QLatin1String(
"subgroup" ) )
356 QList<LegendComponentGroup> subgroups = createComponentGroupList( nodeGroup, context, newIndent );
358 bool hasSubItems = !subgroups.empty();
362 LegendComponent component;
363 component.item = node;
364 component.indent = newIndent;
365 component.size = drawGroupTitle( nodeGroup, context );
367 if ( !subgroups.isEmpty() )
370 subgroups[0].size.rheight() += spaceAboveGroup( subgroups[0] );
372 subgroups[0].components.prepend( component );
373 subgroups[0].size.rheight() += component.size.height();
374 subgroups[0].size.rwidth() = std::max( component.size.width(), subgroups[0].size.width() );
375 if ( nodeGroup->
customProperty( QStringLiteral(
"legend/column-break" ) ).toInt() )
376 subgroups[0].placeColumnBreakBeforeGroup =
true;
381 LegendComponentGroup group;
382 group.placeColumnBreakBeforeGroup = nodeGroup->
customProperty( QStringLiteral(
"legend/column-break" ) ).toInt();
383 group.components.append( component );
384 group.size.rwidth() += component.size.width();
385 group.size.rheight() += component.size.height();
386 group.size.rwidth() = std::max( component.size.width(), group.size.width() );
387 subgroups.append( group );
393 componentGroups.append( subgroups );
401 bool allowColumnSplit =
false;
408 allowColumnSplit =
true;
411 allowColumnSplit =
false;
415 LegendComponentGroup group;
416 group.placeColumnBreakBeforeGroup = nodeLayer->
customProperty( QStringLiteral(
"legend/column-break" ) ).toInt();
420 LegendComponent component;
421 component.item = node;
422 component.size = drawLayerTitle( nodeLayer, context );
423 component.indent = indent;
424 group.components.append( component );
425 group.size.rwidth() = component.size.width();
426 group.size.rheight() = component.size.height();
429 QList<QgsLayerTreeModelLegendNode *> legendNodes = mLegendModel->
layerLegendNodes( nodeLayer );
437 QList<LegendComponentGroup> layerGroups;
438 layerGroups.reserve( legendNodes.count() );
440 bool groupIsLayerGroup =
true;
441 double symbolIndent = indent;
442 switch ( layerStyle )
446 symbolIndent += mSettings.
style( layerStyle ).
indent( );
451 for (
int j = 0; j < legendNodes.count(); j++ )
455 LegendComponent symbolComponent = drawSymbolItem( legendNode, context, ColumnContext(), 0 );
459 if ( !allowColumnSplit || j == 0 )
463 if ( groupIsLayerGroup )
464 layerGroups.prepend( group );
466 layerGroups.append( group );
468 group = LegendComponentGroup();
469 group.placeColumnBreakBeforeGroup =
true;
470 groupIsLayerGroup =
false;
475 group.size.rwidth() = std::max( symbolComponent.size.width(), group.size.width() );
477 if ( !group.components.isEmpty() )
482 group.size.rheight() += symbolComponent.size.height();
483 symbolComponent.indent = symbolIndent;
484 group.components.append( symbolComponent );
488 if ( group.size.height() > 0 )
490 if ( groupIsLayerGroup )
491 layerGroups.prepend( group );
493 layerGroups.append( group );
494 group = LegendComponentGroup();
495 groupIsLayerGroup =
false;
497 LegendComponentGroup symbolGroup;
498 symbolGroup.placeColumnBreakBeforeGroup = forceBreak;
499 symbolComponent.indent = symbolIndent;
500 symbolGroup.components.append( symbolComponent );
501 symbolGroup.size.rwidth() = symbolComponent.size.width();
502 symbolGroup.size.rheight() = symbolComponent.size.height();
503 layerGroups.append( symbolGroup );
506 if ( group.size.height() > 0 )
508 if ( groupIsLayerGroup )
509 layerGroups.prepend( group );
511 layerGroups.append( group );
513 componentGroups.append( layerGroups );
517 return componentGroups;
521int QgsLegendRenderer::setColumns( QList<LegendComponentGroup> &componentGroups )
524 double totalHeight = 0;
525 qreal maxGroupHeight = 0;
526 int forcedColumnBreaks = 0;
527 double totalSpaceAboveGroups = 0;
529 for (
const LegendComponentGroup &group : std::as_const( componentGroups ) )
531 const double topMargin = spaceAboveGroup( group );
532 totalHeight += topMargin;
533 totalSpaceAboveGroups += topMargin;
535 const double groupHeight = group.size.height();
536 totalHeight += groupHeight;
537 maxGroupHeight = std::max( groupHeight, maxGroupHeight );
539 if ( group.placeColumnBreakBeforeGroup )
540 forcedColumnBreaks++;
542 const double totalGroupHeight = ( totalHeight - totalSpaceAboveGroups );
543 double averageGroupHeight = totalGroupHeight / componentGroups.size();
545 if ( mSettings.
columnCount() == 0 && forcedColumnBreaks == 0 )
550 const int targetNumberColumns = std::max( forcedColumnBreaks + 1, mSettings.
columnCount() );
551 const int numberAutoPlacedBreaks = targetNumberColumns - forcedColumnBreaks - 1;
558 double maxColumnHeight = 0;
559 int currentColumn = 0;
560 int currentColumnGroupCount = 0;
561 double currentColumnHeight = 0;
562 int autoPlacedBreaks = 0;
565 double averageSpaceAboveGroups = 0;
566 if ( componentGroups.size() > targetNumberColumns )
567 averageSpaceAboveGroups = totalSpaceAboveGroups / ( componentGroups.size() );
569 double totalRemainingGroupHeight = totalGroupHeight;
570 double totalRemainingSpaceAboveGroups = totalSpaceAboveGroups;
571 for (
int i = 0; i < componentGroups.size(); i++ )
573 const LegendComponentGroup &group = componentGroups.at( i );
574 const double currentGroupHeight = group.size.height();
575 const double spaceAboveCurrentGroup = spaceAboveGroup( group );
577 totalRemainingGroupHeight -= currentGroupHeight;
578 totalRemainingSpaceAboveGroups -= spaceAboveCurrentGroup;
580 double currentColumnHeightIfGroupIsIncluded = currentColumnHeight;
581 if ( currentColumnGroupCount > 0 )
582 currentColumnHeightIfGroupIsIncluded += spaceAboveCurrentGroup;
583 currentColumnHeightIfGroupIsIncluded += currentGroupHeight;
585 const int numberRemainingGroupsIncludingThisOne = componentGroups.size() - i;
586 const int numberRemainingColumnsIncludingThisOne = numberAutoPlacedBreaks + 1 - autoPlacedBreaks;
587 const int numberRemainingColumnBreaks = numberRemainingColumnsIncludingThisOne - 1;
589 const double averageRemainingSpaceAboveGroups = numberRemainingGroupsIncludingThisOne > 1 ? ( totalRemainingSpaceAboveGroups / ( numberRemainingGroupsIncludingThisOne - 1 ) ) : 0;
590 const double estimatedRemainingSpaceAboveGroupsWhichWontBeUsedBecauseGroupsAreFirstInColumn = numberRemainingColumnBreaks * averageRemainingSpaceAboveGroups;
591 const double estimatedRemainingTotalHeightAfterThisGroup = totalRemainingGroupHeight
592 + totalRemainingSpaceAboveGroups
593 - estimatedRemainingSpaceAboveGroupsWhichWontBeUsedBecauseGroupsAreFirstInColumn;
595 const double estimatedTotalHeightOfRemainingColumnsIncludingThisOne = currentColumnHeightIfGroupIsIncluded
596 + estimatedRemainingTotalHeightAfterThisGroup;
599 double averageRemainingColumnHeightIncludingThisOne = estimatedTotalHeightOfRemainingColumnsIncludingThisOne / numberRemainingColumnsIncludingThisOne;
603 const int averageGroupsPerRemainingColumnsIncludingThisOne = std::ceil( averageRemainingColumnHeightIncludingThisOne / ( averageGroupHeight + averageSpaceAboveGroups ) );
605 averageRemainingColumnHeightIncludingThisOne = averageGroupsPerRemainingColumnsIncludingThisOne * ( averageGroupHeight + averageSpaceAboveGroups ) - averageSpaceAboveGroups;
607 bool canCreateNewColumn = ( currentColumnGroupCount > 0 )
608 && ( currentColumn < targetNumberColumns - 1 )
609 && ( autoPlacedBreaks < numberAutoPlacedBreaks );
611 bool shouldCreateNewColumn = currentColumnHeightIfGroupIsIncluded > averageRemainingColumnHeightIncludingThisOne
612 && currentColumnGroupCount > 0
613 && currentColumnHeightIfGroupIsIncluded > maxGroupHeight
614 && currentColumnHeightIfGroupIsIncluded > maxColumnHeight;
616 shouldCreateNewColumn |= group.placeColumnBreakBeforeGroup;
617 canCreateNewColumn |= group.placeColumnBreakBeforeGroup;
621 shouldCreateNewColumn |= ( componentGroups.size() - i < targetNumberColumns - currentColumn );
623 if ( canCreateNewColumn && shouldCreateNewColumn )
627 if ( !group.placeColumnBreakBeforeGroup )
629 currentColumnGroupCount = 0;
630 currentColumnHeight = group.size.height();
634 currentColumnHeight = currentColumnHeightIfGroupIsIncluded;
636 componentGroups[i].column = currentColumn;
637 currentColumnGroupCount++;
638 maxColumnHeight = std::max( currentColumnHeight, maxColumnHeight );
641 auto refineColumns = [&componentGroups,
this]() ->
bool
643 QHash< int, double > columnHeights;
644 QHash< int, int > columnGroupCounts;
645 double currentColumnHeight = 0;
646 int currentColumn = -1;
649 double maxCurrentColumnHeight = 0;
650 for (
int i = 0; i < componentGroups.size(); i++ )
652 const LegendComponentGroup &group = componentGroups.at( i );
653 if ( group.column != currentColumn )
655 if ( currentColumn >= 0 )
657 columnHeights.insert( currentColumn, currentColumnHeight );
658 columnGroupCounts.insert( currentColumn, groupCount );
661 currentColumn = group.column;
662 currentColumnHeight = 0;
664 columnCount = std::max( columnCount, currentColumn + 1 );
667 const double spaceAbove = spaceAboveGroup( group );
668 currentColumnHeight += spaceAbove + group.size.height();
671 columnHeights.insert( currentColumn, currentColumnHeight );
672 columnGroupCounts.insert( currentColumn, groupCount );
674 double totalColumnHeights = 0;
675 for (
int i = 0; i < columnCount; ++ i )
677 totalColumnHeights += columnHeights[i];
678 maxCurrentColumnHeight = std::max( maxCurrentColumnHeight, columnHeights[i] );
681 const double averageColumnHeight = totalColumnHeights / columnCount;
683 bool changed =
false;
684 int nextCandidateColumnForShift = 1;
685 for (
int i = 0; i < componentGroups.size(); i++ )
687 LegendComponentGroup &group = componentGroups[ i ];
688 if ( group.column < nextCandidateColumnForShift )
692 const bool canShift = !group.placeColumnBreakBeforeGroup
693 && columnGroupCounts[ group.column ] >= 2;
696 && columnHeights[ group.column - 1 ] < averageColumnHeight
697 && ( columnHeights[ group.column - 1 ] + group.size.height() ) * 0.9 < maxCurrentColumnHeight
701 columnHeights[ group.column ] += group.size.height() + spaceAboveGroup( group );
702 columnGroupCounts[ group.column ]++;
703 columnHeights[ group.column + 1 ] -= group.size.height();
704 columnGroupCounts[ group.column + 1]--;
709 nextCandidateColumnForShift = group.column + 1;
715 bool wasRefined =
true;
717 while ( wasRefined && iterations < 2 )
719 wasRefined = refineColumns();
724 QMap<QString, qreal> maxSymbolWidth;
725 for (
int i = 0; i < componentGroups.size(); i++ )
727 LegendComponentGroup &group = componentGroups[i];
728 for (
int j = 0; j < group.components.size(); j++ )
732 QString key = QStringLiteral(
"%1-%2" ).arg(
reinterpret_cast< qulonglong
>(
legendNode->
layerNode() ) ).arg( group.column );
733 maxSymbolWidth[key] = std::max( group.components.at( j ).symbolSize.width(), maxSymbolWidth[key] );
737 for (
int i = 0; i < componentGroups.size(); i++ )
739 LegendComponentGroup &group = componentGroups[i];
740 for (
int j = 0; j < group.components.size(); j++ )
744 QString key = QStringLiteral(
"%1-%2" ).arg(
reinterpret_cast< qulonglong
>(
legendNode->
layerNode() ) ).arg( group.column );
747 group.components[j].labelXOffset = maxSymbolWidth[key] + space;
748 group.components[j].maxSiblingSymbolWidth = maxSymbolWidth[key];
749 group.components[j].size.rwidth() = maxSymbolWidth[key] + space + group.components.at( j ).labelSize.width();
753 return targetNumberColumns;
756QSizeF QgsLegendRenderer::drawTitle(
QgsRenderContext &context,
double top, Qt::AlignmentFlag halignment,
double legendWidth )
const
759 if ( mSettings.
title().isEmpty() )
769 widthAndOffsetForTitleText( halignment, legendWidth, textBoxWidth, textBoxLeft );
774 double overallTextHeight = 0;
775 double overallTextWidth = 0;
783 size.rheight() = overallTextHeight / dotsPerMM;
784 size.rwidth() = overallTextWidth / dotsPerMM;
790 const QRectF r( textBoxLeft * dotsPerMM, top * dotsPerMM, textBoxWidth * dotsPerMM, overallTextHeight );
802double QgsLegendRenderer::spaceAboveGroup(
const LegendComponentGroup &group )
804 if ( group.components.isEmpty() )
return 0;
806 LegendComponent component = group.components.first();
808 if (
QgsLayerTreeGroup *nodeGroup = qobject_cast<QgsLayerTreeGroup *>( component.item ) )
812 else if (
QgsLayerTreeLayer *nodeLayer = qobject_cast<QgsLayerTreeLayer *>( component.item ) )
816 else if ( qobject_cast<QgsLayerTreeModelLegendNode *>( component.item ) )
825QSizeF QgsLegendRenderer::drawGroup(
const LegendComponentGroup &group,
QgsRenderContext &context, ColumnContext columnContext,
double top )
828 QSizeF size = QSizeF( group.size );
829 double currentY = top;
830 for (
const LegendComponent &component : std::as_const( group.components ) )
832 if (
QgsLayerTreeGroup *groupItem = qobject_cast<QgsLayerTreeGroup *>( component.item ) )
842 ColumnContext columnContextForItem = columnContext;
843 double indentWidth = component.indent;
856 columnContextForItem.left += indentWidth;
860 columnContextForItem.right -= indentWidth;
862 groupSize = drawGroupTitle( groupItem, context, columnContextForItem, currentY );
863 size.rwidth() = std::max( groupSize.width(), size.width() );
866 else if (
QgsLayerTreeLayer *layerItem = qobject_cast<QgsLayerTreeLayer *>( component.item ) )
877 ColumnContext columnContextForItem = columnContext;
878 double indentWidth = component.indent;
879 columnContextForItem.left += indentWidth;
880 subGroupSize = drawLayerTitle( layerItem, context, columnContextForItem, currentY );
881 size.rwidth() = std::max( subGroupSize.width(), size.width() );
891 ColumnContext columnContextForItem = columnContext;
892 double indentWidth = 0;
893 indentWidth = component.indent;
896 columnContextForItem.left += indentWidth;
900 columnContextForItem.right -= indentWidth;
903 LegendComponent symbolComponent = drawSymbolItem( legendNode, context, columnContextForItem, currentY, component.maxSiblingSymbolWidth );
905 size.rwidth() = std::max( symbolComponent.size.width() + indentWidth, size.width() );
907 currentY += component.size.height();
928 ctx.
point = QPointF( columnContext.left, top );
954 symbolScope = symbolNode->createSymbolScope();
969 LegendComponent component;
970 component.item = symbolItem;
977 double width = std::max(
static_cast< double >( im.
symbolSize.width() ), maxSiblingSymbolWidth )
984 component.size = QSizeF( width, height );
991 QModelIndex idx = mLegendModel->
node2index( nodeLayer );
992 QString titleString = mLegendModel->
data( idx, Qt::DisplayRole ).toString();
994 if ( titleString.isEmpty() )
1000 if ( nodeLayer->
layer() )
1010 double overallTextHeight = 0;
1011 double overallTextWidth = 0;
1019 size.rheight() = overallTextHeight / dotsPerMM;
1020 size.rwidth() = overallTextWidth / dotsPerMM + sideMargin *
1030 ( ( columnContext.right - columnContext.left ) - ( halign ==
Qgis::TextHorizontalAlignment::
Right ? sideMargin : 0 ) ) * dotsPerMM, overallTextHeight );
1044 QSizeF size( 0, 0 );
1045 QModelIndex idx = mLegendModel->
node2index( nodeGroup );
1051 double overallTextHeight = 0;
1052 double overallTextWidth = 0;
1063 size.rheight() = overallTextHeight / dotsPerMM;
1064 size.rwidth() = overallTextWidth / dotsPerMM + sideMargin *
1075 dotsPerMM * ( ( columnContext.right - columnContext.left ) - ( halign ==
Qgis::TextHorizontalAlignment::
Right ? sideMargin : 0 ) ), overallTextHeight );
1085 QString style = node->
customProperty( QStringLiteral(
"legend/title-style" ) ).toString();
1086 if ( style == QLatin1String(
"hidden" ) )
1088 else if ( style == QLatin1String(
"group" ) )
1090 else if ( style == QLatin1String(
"subgroup" ) )
1113 return mProxyModel.get();
1122 str = QStringLiteral(
"hidden" );
1125 str = QStringLiteral(
"group" );
1128 str = QStringLiteral(
"subgroup" );
1134 if ( !str.isEmpty() )
1142 paintAndDetermineSize( context );
The Qgis class provides global constants for use throughout the application.
@ 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.
QgsLayerTreeFilterProxyModel is a sort filter proxy model to easily reproduce the legend/layer tree i...
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.
Handles automatic layout and rendering of legends.
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.
QgsLayerTreeFilterProxyModel * proxyModel()
Returns the filter proxy model used for filtering the legend model content during rendering.
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.
Qt::Alignment alignment() const
Returns the alignment for the legend component.
QgsTextFormat & textFormat()
Returns the text format used for rendering this legend component.
double margin(Side side) const
Returns the margin (in mm) for the specified side of the 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)
#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.