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;
215 QList<LegendComponentGroup> componentGroups = createComponentGroupList( rootGroup, context );
217 const int columnCount = setColumns( componentGroups );
219 QMap< int, double > maxColumnWidths;
220 qreal maxEqualColumnWidth = 0;
228 for (
const LegendComponentGroup &group : std::as_const( componentGroups ) )
230 const QSizeF actualSize = drawGroup( group, context, ColumnContext() );
231 maxEqualColumnWidth = std::max( actualSize.width(), maxEqualColumnWidth );
232 maxColumnWidths[ group.column ] = std::max( actualSize.width(), maxColumnWidths.value( group.column, 0 ) );
235 if ( columnCount == 1 )
238 maxEqualColumnWidth = std::max( maxEqualColumnWidth, mLegendSize.width() - 2 * mSettings.
boxSpace() );
239 maxColumnWidths[ 0 ] = maxEqualColumnWidth;
243 QSizeF titleSize = drawTitle( context, 0 );
245 titleSize.rwidth() += mSettings.
boxSpace() * 2.0;
250 bool firstInColumn =
true;
251 double columnMaxHeight = 0;
252 qreal columnWidth = 0;
254 ColumnContext columnContext;
255 columnContext.left = mSettings.
boxSpace();
256 columnContext.right = std::max( mLegendSize.width() - mSettings.
boxSpace(), mSettings.
boxSpace() );
257 double currentY = columnTop;
259 for (
const LegendComponentGroup &group : std::as_const( componentGroups ) )
261 if ( group.column > column )
264 columnContext.left = group.column > 0 ? ( columnContext.right + mSettings.
columnSpace() ) : mSettings.boxSpace();
265 columnWidth = mSettings.
equalColumnWidth() ? maxEqualColumnWidth : maxColumnWidths.value( group.column );
266 columnContext.right = columnContext.left + columnWidth;
267 currentY = columnTop;
269 firstInColumn =
true;
271 if ( !firstInColumn )
273 currentY += spaceAboveGroup( group );
276 drawGroup( group, context, columnContext, currentY );
278 currentY += group.size.height();
279 columnMaxHeight = std::max( currentY - columnTop, columnMaxHeight );
281 firstInColumn =
false;
283 const double totalWidth = columnContext.right + mSettings.
boxSpace();
285 size.rheight() = columnTop + columnMaxHeight + mSettings.
boxSpace();
286 size.rwidth() = totalWidth;
287 if ( !mSettings.
title().isEmpty() )
289 size.rwidth() = std::max( titleSize.width(), size.width() );
293 if ( mLegendSize.isValid() )
295 qreal w = std::max( size.width(), mLegendSize.width() );
296 qreal h = std::max( size.height(), mLegendSize.height() );
297 size = QSizeF( w, h );
301 if ( !mSettings.
title().isEmpty() )
309void QgsLegendRenderer::widthAndOffsetForTitleText(
const Qt::AlignmentFlag halignment,
const double legendWidth,
double &textBoxWidth,
double &textBoxLeft )
const
311 switch ( halignment )
315 textBoxWidth = legendWidth - 2 * mSettings.
boxSpace();
318 case Qt::AlignHCenter:
321 const double centerX = legendWidth / 2;
322 textBoxWidth = ( std::min(
static_cast< double >( centerX ), legendWidth - centerX ) - mSettings.
boxSpace() ) * 2.0;
323 textBoxLeft = centerX - textBoxWidth / 2.;
329QList<QgsLegendRenderer::LegendComponentGroup> QgsLegendRenderer::createComponentGroupList(
QgsLayerTreeGroup *parentGroup,
QgsRenderContext &context,
double indent )
331 QList<LegendComponentGroup> componentGroups;
334 return componentGroups;
336 const QList<QgsLayerTreeNode *> childNodes = parentGroup->
children();
339 if ( !mProxyModel->nodeShown( node ) )
345 QString style = node->customProperty( QStringLiteral(
"legend/title-style" ) ).toString();
347 double newIndent = indent;
348 if ( style == QLatin1String(
"subgroup" ) )
358 QList<LegendComponentGroup> subgroups = createComponentGroupList( nodeGroup, context, newIndent );
360 bool hasSubItems = !subgroups.empty();
364 LegendComponent component;
365 component.item = node;
366 component.indent = newIndent;
367 component.size = drawGroupTitle( nodeGroup, context );
369 if ( !subgroups.isEmpty() )
372 subgroups[0].size.rheight() += spaceAboveGroup( subgroups[0] );
374 subgroups[0].components.prepend( component );
375 subgroups[0].size.rheight() += component.size.height();
376 subgroups[0].size.rwidth() = std::max( component.size.width(), subgroups[0].size.width() );
377 if ( nodeGroup->
customProperty( QStringLiteral(
"legend/column-break" ) ).toInt() )
378 subgroups[0].placeColumnBreakBeforeGroup =
true;
383 LegendComponentGroup group;
384 group.placeColumnBreakBeforeGroup = nodeGroup->
customProperty( QStringLiteral(
"legend/column-break" ) ).toInt();
385 group.components.append( component );
386 group.size.rwidth() += component.size.width();
387 group.size.rheight() += component.size.height();
388 group.size.rwidth() = std::max( component.size.width(), group.size.width() );
389 subgroups.append( group );
395 componentGroups.append( subgroups );
403 bool allowColumnSplit =
false;
410 allowColumnSplit =
true;
413 allowColumnSplit =
false;
417 LegendComponentGroup group;
418 group.placeColumnBreakBeforeGroup = nodeLayer->
customProperty( QStringLiteral(
"legend/column-break" ) ).toInt();
422 LegendComponent component;
423 component.item = node;
424 component.size = drawLayerTitle( nodeLayer, context );
425 component.indent = indent;
426 group.components.append( component );
427 group.size.rwidth() = component.size.width();
428 group.size.rheight() = component.size.height();
431 QList<QgsLayerTreeModelLegendNode *> legendNodes = mLegendModel->
layerLegendNodes( nodeLayer );
439 QList<LegendComponentGroup> layerGroups;
440 layerGroups.reserve( legendNodes.count() );
442 bool groupIsLayerGroup =
true;
443 double symbolIndent = indent;
444 switch ( layerStyle )
448 symbolIndent += mSettings.
style( layerStyle ).
indent( );
453 for (
int j = 0; j < legendNodes.count(); j++ )
457 LegendComponent symbolComponent = drawSymbolItem( legendNode, context, ColumnContext(), 0 );
461 if ( !allowColumnSplit || j == 0 )
465 if ( groupIsLayerGroup )
466 layerGroups.prepend( group );
468 layerGroups.append( group );
470 group = LegendComponentGroup();
471 group.placeColumnBreakBeforeGroup =
true;
472 groupIsLayerGroup =
false;
477 group.size.rwidth() = std::max( symbolComponent.size.width(), group.size.width() );
479 if ( !group.components.isEmpty() )
484 group.size.rheight() += symbolComponent.size.height();
485 symbolComponent.indent = symbolIndent;
486 group.components.append( symbolComponent );
490 if ( group.size.height() > 0 )
492 if ( groupIsLayerGroup )
493 layerGroups.prepend( group );
495 layerGroups.append( group );
496 group = LegendComponentGroup();
497 groupIsLayerGroup =
false;
499 LegendComponentGroup symbolGroup;
500 symbolGroup.placeColumnBreakBeforeGroup = forceBreak;
501 symbolComponent.indent = symbolIndent;
502 symbolGroup.components.append( symbolComponent );
503 symbolGroup.size.rwidth() = symbolComponent.size.width();
504 symbolGroup.size.rheight() = symbolComponent.size.height();
505 layerGroups.append( symbolGroup );
508 if ( group.size.height() > 0 )
510 if ( groupIsLayerGroup )
511 layerGroups.prepend( group );
513 layerGroups.append( group );
515 componentGroups.append( layerGroups );
519 return componentGroups;
523int QgsLegendRenderer::setColumns( QList<LegendComponentGroup> &componentGroups )
526 double totalHeight = 0;
527 qreal maxGroupHeight = 0;
528 int forcedColumnBreaks = 0;
529 double totalSpaceAboveGroups = 0;
531 for (
const LegendComponentGroup &group : std::as_const( componentGroups ) )
533 const double topMargin = spaceAboveGroup( group );
534 totalHeight += topMargin;
535 totalSpaceAboveGroups += topMargin;
537 const double groupHeight = group.size.height();
538 totalHeight += groupHeight;
539 maxGroupHeight = std::max( groupHeight, maxGroupHeight );
541 if ( group.placeColumnBreakBeforeGroup )
542 forcedColumnBreaks++;
544 const double totalGroupHeight = ( totalHeight - totalSpaceAboveGroups );
545 double averageGroupHeight = totalGroupHeight / componentGroups.size();
547 if ( mSettings.
columnCount() == 0 && forcedColumnBreaks == 0 )
552 const int targetNumberColumns = std::max( forcedColumnBreaks + 1, mSettings.
columnCount() );
553 const int numberAutoPlacedBreaks = targetNumberColumns - forcedColumnBreaks - 1;
560 double maxColumnHeight = 0;
561 int currentColumn = 0;
562 int currentColumnGroupCount = 0;
563 double currentColumnHeight = 0;
564 int autoPlacedBreaks = 0;
567 double averageSpaceAboveGroups = 0;
568 if ( componentGroups.size() > targetNumberColumns )
569 averageSpaceAboveGroups = totalSpaceAboveGroups / ( componentGroups.size() );
571 double totalRemainingGroupHeight = totalGroupHeight;
572 double totalRemainingSpaceAboveGroups = totalSpaceAboveGroups;
573 for (
int i = 0; i < componentGroups.size(); i++ )
575 const LegendComponentGroup &group = componentGroups.at( i );
576 const double currentGroupHeight = group.size.height();
577 const double spaceAboveCurrentGroup = spaceAboveGroup( group );
579 totalRemainingGroupHeight -= currentGroupHeight;
580 totalRemainingSpaceAboveGroups -= spaceAboveCurrentGroup;
582 double currentColumnHeightIfGroupIsIncluded = currentColumnHeight;
583 if ( currentColumnGroupCount > 0 )
584 currentColumnHeightIfGroupIsIncluded += spaceAboveCurrentGroup;
585 currentColumnHeightIfGroupIsIncluded += currentGroupHeight;
587 const int numberRemainingGroupsIncludingThisOne = componentGroups.size() - i;
588 const int numberRemainingColumnsIncludingThisOne = numberAutoPlacedBreaks + 1 - autoPlacedBreaks;
589 const int numberRemainingColumnBreaks = numberRemainingColumnsIncludingThisOne - 1;
591 const double averageRemainingSpaceAboveGroups = numberRemainingGroupsIncludingThisOne > 1 ? ( totalRemainingSpaceAboveGroups / ( numberRemainingGroupsIncludingThisOne - 1 ) ) : 0;
592 const double estimatedRemainingSpaceAboveGroupsWhichWontBeUsedBecauseGroupsAreFirstInColumn = numberRemainingColumnBreaks * averageRemainingSpaceAboveGroups;
593 const double estimatedRemainingTotalHeightAfterThisGroup = totalRemainingGroupHeight
594 + totalRemainingSpaceAboveGroups
595 - estimatedRemainingSpaceAboveGroupsWhichWontBeUsedBecauseGroupsAreFirstInColumn;
597 const double estimatedTotalHeightOfRemainingColumnsIncludingThisOne = currentColumnHeightIfGroupIsIncluded
598 + estimatedRemainingTotalHeightAfterThisGroup;
601 double averageRemainingColumnHeightIncludingThisOne = estimatedTotalHeightOfRemainingColumnsIncludingThisOne / numberRemainingColumnsIncludingThisOne;
605 const int averageGroupsPerRemainingColumnsIncludingThisOne = std::ceil( averageRemainingColumnHeightIncludingThisOne / ( averageGroupHeight + averageSpaceAboveGroups ) );
607 averageRemainingColumnHeightIncludingThisOne = averageGroupsPerRemainingColumnsIncludingThisOne * ( averageGroupHeight + averageSpaceAboveGroups ) - averageSpaceAboveGroups;
609 bool canCreateNewColumn = ( currentColumnGroupCount > 0 )
610 && ( currentColumn < targetNumberColumns - 1 )
611 && ( autoPlacedBreaks < numberAutoPlacedBreaks );
613 bool shouldCreateNewColumn = currentColumnHeightIfGroupIsIncluded > averageRemainingColumnHeightIncludingThisOne
614 && currentColumnGroupCount > 0
615 && currentColumnHeightIfGroupIsIncluded > maxGroupHeight
616 && currentColumnHeightIfGroupIsIncluded > maxColumnHeight;
618 shouldCreateNewColumn |= group.placeColumnBreakBeforeGroup;
619 canCreateNewColumn |= group.placeColumnBreakBeforeGroup;
623 shouldCreateNewColumn |= ( componentGroups.size() - i < targetNumberColumns - currentColumn );
625 if ( canCreateNewColumn && shouldCreateNewColumn )
629 if ( !group.placeColumnBreakBeforeGroup )
631 currentColumnGroupCount = 0;
632 currentColumnHeight = group.size.height();
636 currentColumnHeight = currentColumnHeightIfGroupIsIncluded;
638 componentGroups[i].column = currentColumn;
639 currentColumnGroupCount++;
640 maxColumnHeight = std::max( currentColumnHeight, maxColumnHeight );
643 auto refineColumns = [&componentGroups,
this]() ->
bool
645 QHash< int, double > columnHeights;
646 QHash< int, int > columnGroupCounts;
647 double currentColumnHeight = 0;
648 int currentColumn = -1;
651 double maxCurrentColumnHeight = 0;
652 for (
int i = 0; i < componentGroups.size(); i++ )
654 const LegendComponentGroup &group = componentGroups.at( i );
655 if ( group.column != currentColumn )
657 if ( currentColumn >= 0 )
659 columnHeights.insert( currentColumn, currentColumnHeight );
660 columnGroupCounts.insert( currentColumn, groupCount );
663 currentColumn = group.column;
664 currentColumnHeight = 0;
666 columnCount = std::max( columnCount, currentColumn + 1 );
669 const double spaceAbove = spaceAboveGroup( group );
670 currentColumnHeight += spaceAbove + group.size.height();
673 columnHeights.insert( currentColumn, currentColumnHeight );
674 columnGroupCounts.insert( currentColumn, groupCount );
676 double totalColumnHeights = 0;
677 for (
int i = 0; i < columnCount; ++ i )
679 totalColumnHeights += columnHeights[i];
680 maxCurrentColumnHeight = std::max( maxCurrentColumnHeight, columnHeights[i] );
683 const double averageColumnHeight = totalColumnHeights / columnCount;
685 bool changed =
false;
686 int nextCandidateColumnForShift = 1;
687 for (
int i = 0; i < componentGroups.size(); i++ )
689 LegendComponentGroup &group = componentGroups[ i ];
690 if ( group.column < nextCandidateColumnForShift )
694 const bool canShift = !group.placeColumnBreakBeforeGroup
695 && columnGroupCounts[ group.column ] >= 2;
698 && columnHeights[ group.column - 1 ] < averageColumnHeight
699 && ( columnHeights[ group.column - 1 ] + group.size.height() ) * 0.9 < maxCurrentColumnHeight
703 columnHeights[ group.column ] += group.size.height() + spaceAboveGroup( group );
704 columnGroupCounts[ group.column ]++;
705 columnHeights[ group.column + 1 ] -= group.size.height();
706 columnGroupCounts[ group.column + 1]--;
711 nextCandidateColumnForShift = group.column + 1;
717 bool wasRefined =
true;
719 while ( wasRefined && iterations < 2 )
721 wasRefined = refineColumns();
726 QMap<QString, qreal> maxSymbolWidth;
727 for (
int i = 0; i < componentGroups.size(); i++ )
729 LegendComponentGroup &group = componentGroups[i];
730 for (
int j = 0; j < group.components.size(); j++ )
734 QString key = QStringLiteral(
"%1-%2" ).arg(
reinterpret_cast< qulonglong
>(
legendNode->
layerNode() ) ).arg( group.column );
735 maxSymbolWidth[key] = std::max( group.components.at( j ).symbolSize.width(), maxSymbolWidth[key] );
739 for (
int i = 0; i < componentGroups.size(); i++ )
741 LegendComponentGroup &group = componentGroups[i];
742 for (
int j = 0; j < group.components.size(); j++ )
746 QString key = QStringLiteral(
"%1-%2" ).arg(
reinterpret_cast< qulonglong
>(
legendNode->
layerNode() ) ).arg( group.column );
749 group.components[j].labelXOffset = maxSymbolWidth[key] + space;
750 group.components[j].maxSiblingSymbolWidth = maxSymbolWidth[key];
751 group.components[j].size.rwidth() = maxSymbolWidth[key] + space + group.components.at( j ).labelSize.width();
755 return targetNumberColumns;
758QSizeF QgsLegendRenderer::drawTitle(
QgsRenderContext &context,
double top, Qt::AlignmentFlag halignment,
double legendWidth )
const
761 if ( mSettings.
title().isEmpty() )
771 widthAndOffsetForTitleText( halignment, legendWidth, textBoxWidth, textBoxLeft );
776 double overallTextHeight = 0;
777 double overallTextWidth = 0;
785 size.rheight() = overallTextHeight / dotsPerMM;
786 size.rwidth() = overallTextWidth / dotsPerMM;
792 const QRectF r( textBoxLeft * dotsPerMM, top * dotsPerMM, textBoxWidth * dotsPerMM, overallTextHeight );
804double QgsLegendRenderer::spaceAboveGroup(
const LegendComponentGroup &group )
806 if ( group.components.isEmpty() )
return 0;
808 LegendComponent component = group.components.first();
810 if (
QgsLayerTreeGroup *nodeGroup = qobject_cast<QgsLayerTreeGroup *>( component.item ) )
814 else if (
QgsLayerTreeLayer *nodeLayer = qobject_cast<QgsLayerTreeLayer *>( component.item ) )
818 else if ( qobject_cast<QgsLayerTreeModelLegendNode *>( component.item ) )
827QSizeF QgsLegendRenderer::drawGroup(
const LegendComponentGroup &group,
QgsRenderContext &context, ColumnContext columnContext,
double top )
830 QSizeF size = QSizeF( group.size );
831 double currentY = top;
832 for (
const LegendComponent &component : std::as_const( group.components ) )
834 if (
QgsLayerTreeGroup *groupItem = qobject_cast<QgsLayerTreeGroup *>( component.item ) )
844 ColumnContext columnContextForItem = columnContext;
845 double indentWidth = component.indent;
858 columnContextForItem.left += indentWidth;
862 columnContextForItem.right -= indentWidth;
864 groupSize = drawGroupTitle( groupItem, context, columnContextForItem, currentY );
865 size.rwidth() = std::max( groupSize.width(), size.width() );
868 else if (
QgsLayerTreeLayer *layerItem = qobject_cast<QgsLayerTreeLayer *>( component.item ) )
879 ColumnContext columnContextForItem = columnContext;
880 double indentWidth = component.indent;
881 columnContextForItem.left += indentWidth;
882 subGroupSize = drawLayerTitle( layerItem, context, columnContextForItem, currentY );
883 size.rwidth() = std::max( subGroupSize.width(), size.width() );
893 ColumnContext columnContextForItem = columnContext;
894 double indentWidth = 0;
895 indentWidth = component.indent;
898 columnContextForItem.left += indentWidth;
902 columnContextForItem.right -= indentWidth;
905 LegendComponent symbolComponent = drawSymbolItem( legendNode, context, columnContextForItem, currentY, component.maxSiblingSymbolWidth );
907 size.rwidth() = std::max( symbolComponent.size.width() + indentWidth, size.width() );
909 currentY += component.size.height();
930 ctx.
point = QPointF( columnContext.left, top );
956 symbolScope = symbolNode->createSymbolScope();
971 LegendComponent component;
972 component.item = symbolItem;
979 double width = std::max(
static_cast< double >( im.
symbolSize.width() ), maxSiblingSymbolWidth )
986 component.size = QSizeF( width, height );
993 QModelIndex idx = mLegendModel->
node2index( nodeLayer );
994 QString titleString = mLegendModel->
data( idx, Qt::DisplayRole ).toString();
996 if ( titleString.isEmpty() )
1002 if ( nodeLayer->
layer() )
1012 double overallTextHeight = 0;
1013 double overallTextWidth = 0;
1021 size.rheight() = overallTextHeight / dotsPerMM;
1022 size.rwidth() = overallTextWidth / dotsPerMM + sideMargin *
1032 ( ( columnContext.right - columnContext.left ) - ( halign ==
Qgis::TextHorizontalAlignment::
Right ? sideMargin : 0 ) ) * dotsPerMM, overallTextHeight );
1046 QSizeF size( 0, 0 );
1047 QModelIndex idx = mLegendModel->
node2index( nodeGroup );
1053 double overallTextHeight = 0;
1054 double overallTextWidth = 0;
1065 size.rheight() = overallTextHeight / dotsPerMM;
1066 size.rwidth() = overallTextWidth / dotsPerMM + sideMargin *
1077 dotsPerMM * ( ( columnContext.right - columnContext.left ) - ( halign ==
Qgis::TextHorizontalAlignment::
Right ? sideMargin : 0 ) ), overallTextHeight );
1087 QString style = node->
customProperty( QStringLiteral(
"legend/title-style" ) ).toString();
1088 if ( style == QLatin1String(
"hidden" ) )
1090 else if ( style == QLatin1String(
"group" ) )
1092 else if ( style == QLatin1String(
"subgroup" ) )
1115 return mProxyModel.get();
1124 str = QStringLiteral(
"hidden" );
1127 str = QStringLiteral(
"group" );
1130 str = QStringLiteral(
"subgroup" );
1136 if ( !str.isEmpty() )
1144 paintAndDetermineSize( context );
The Qgis class provides global constants for use throughout the application.
LegendComponent
Component of legends which can be styled.
@ Symbol
Symbol icon (excluding label)
@ Group
Legend group title.
@ Hidden
Special style, item is hidden including margins around.
@ Subgroup
Legend subgroup title.
@ SymbolLabel
Symbol label (excluding icon)
@ Undefined
Should not happen, only if corrupted project file.
@ 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.
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.
Q_DECL_DEPRECATED void drawLegend(QPainter *painter)
Draws the legend with given painter.
static void setNodeLegendStyle(QgsLayerTreeNode *node, Qgis::LegendComponent style)
Sets the style of a node.
static Qgis::LegendComponent nodeLegendStyle(QgsLayerTreeNode *node, QgsLayerTreeModel *model)
Returns the style for the given node, within the specified model.
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.
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).
void updateDataDefinedProperties(QgsRenderContext &context)
Updates any data-defined properties in the settings, using the specified render context.
QgsLegendStyle style(Qgis::LegendComponent s) const
Returns the style for a legend component.
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.
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.