QGIS API Documentation 3.43.0-Master (0bee5d6404c)
qgslayoutitemlegend.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgslayoutitemlegend.cpp
3 -----------------------
4 begin : October 2017
5 copyright : (C) 2017 by Nyall Dawson
6 email : nyall dot dawson at gmail dot com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17#include <limits>
18
19#include "qgslayoutitemlegend.h"
20#include "moc_qgslayoutitemlegend.cpp"
22#include "qgslayoutitemmap.h"
23#include "qgslayoutmodel.h"
24#include "qgslayertree.h"
25#include "qgslayertreemodel.h"
27#include "qgslegendrenderer.h"
28#include "qgslegendstyle.h"
29#include "qgslogger.h"
30#include "qgsmapsettings.h"
31#include "qgsproject.h"
32#include "qgscolorutils.h"
33#include "qgslayertreeutils.h"
34#include "qgslayoututils.h"
35#include "qgslayout.h"
38#include "qgsvectorlayer.h"
43
44#include <QDomDocument>
45#include <QDomElement>
46#include <QPainter>
48
50 : QgsLayoutItem( layout )
51 , mLegendModel( new QgsLegendModel( nullptr, this ) )
52{
53#if 0 //no longer required?
54 connect( &layout->atlasComposition(), &QgsAtlasComposition::renderEnded, this, &QgsLayoutItemLegend::onAtlasEnded );
55#endif
56
57 mTitle = mSettings.title();
58
59 connect( mLegendModel.get(), &QgsLayerTreeModel::hitTestStarted, this, [this] { emit backgroundTaskCountChanged( 1 ); } );
60 connect( mLegendModel.get(), &QgsLayerTreeModel::hitTestCompleted, this, [this]
61 {
62 adjustBoxSize();
63 emit backgroundTaskCountChanged( 0 );
64 } );
65
66 // Connect to the main layertreeroot.
67 // It serves in "auto update mode" as a medium between the main app legend and this one
68 connect( mLayout->project()->layerTreeRoot(), &QgsLayerTreeNode::customPropertyChanged, this, &QgsLayoutItemLegend::nodeCustomPropertyChanged );
69
70 // If project colors change, we need to redraw legend, as legend symbols may rely on project colors
71 connect( mLayout->project(), &QgsProject::projectColorsChanged, this, [this]
72 {
73 invalidateCache();
74 update();
75 } );
76 connect( mLegendModel.get(), &QgsLegendModel::refreshLegend, this, [this]
77 {
78 // NOTE -- we do NOT connect to ::refresh here, as we don't want to trigger the call to onAtlasFeature() which sets mFilterAskedForUpdate to true,
79 // causing an endless loop.
80 invalidateCache();
81 update();
82 } );
83}
84
89
94
96{
97 return QgsApplication::getThemeIcon( QStringLiteral( "/mLayoutItemLegend.svg" ) );
98}
99
104
105void QgsLayoutItemLegend::paint( QPainter *painter, const QStyleOptionGraphicsItem *itemStyle, QWidget *pWidget )
106{
107 if ( !painter )
108 return;
109
110 const QPointF oldPos = pos();
111
112 ensureModelIsInitialized();
113
114 if ( mFilterAskedForUpdate )
115 {
116 mFilterAskedForUpdate = false;
117 doUpdateFilterByMap();
118 }
119
120 const int dpi = painter->device()->logicalDpiX();
121 const double dotsPerMM = dpi / 25.4;
122
123 if ( mLayout )
124 {
126 // no longer required, but left set for api stability
128 mSettings.setDpi( dpi );
131 }
132 if ( mMap && mLayout )
133 {
135 // no longer required, but left set for api stability
136 mSettings.setMmPerMapUnit( mLayout->convertFromLayoutUnits( mMap->mapUnitsToLayoutUnits(), Qgis::LayoutUnit::Millimeters ).length() );
138
139 // use a temporary QgsMapSettings to find out real map scale
140 const QSizeF mapSizePixels = QSizeF( mMap->rect().width() * dotsPerMM, mMap->rect().height() * dotsPerMM );
141 const QgsRectangle mapExtent = mMap->extent();
142
143 const QgsMapSettings ms = mMap->mapSettings( mapExtent, mapSizePixels, dpi, false );
144
145 // no longer required, but left set for api stability
147 mSettings.setMapScale( ms.scale() );
149 }
150 mInitialMapScaleCalculated = true;
151
152 QgsLegendRenderer legendRenderer = createRenderer();
153 legendRenderer.setLegendSize( mForceResize && mSizeToContents ? QSize() : rect().size() );
154
155 //adjust box if width or height is too small
156 if ( mSizeToContents )
157 {
158 QgsRenderContext context = mMap ? QgsLayoutUtils::createRenderContextForMap( mMap, painter )
161
162 const QSizeF size = legendRenderer.minimumSize( &context );
163 if ( mForceResize )
164 {
165 mForceResize = false;
166
167 //set new rect, respecting position mode and data defined size/position
168 const QgsLayoutSize newSize = mLayout->convertFromLayoutUnits( size, sizeWithUnits().units() );
169 attemptResize( newSize );
170 }
171 else if ( size.height() > rect().height() || size.width() > rect().width() )
172 {
173 //need to resize box
174 QSizeF targetSize = rect().size();
175 if ( size.height() > targetSize.height() )
176 targetSize.setHeight( size.height() );
177 if ( size.width() > targetSize.width() )
178 targetSize.setWidth( size.width() );
179
180 const QgsLayoutSize newSize = mLayout->convertFromLayoutUnits( targetSize, sizeWithUnits().units() );
181 //set new rect, respecting position mode and data defined size/position
182 attemptResize( newSize );
183 }
184 }
185
186 // attemptResize may change the legend position and would call setPos
187 // BUT the position is actually changed for the next draw, so we need to translate of the difference
188 // between oldPos and newPos
189 // the issue doesn't appear in desktop rendering but only in export because in the first one,
190 // Qt triggers a redraw on position change
191 painter->save();
192 painter->translate( pos() - oldPos );
193 QgsLayoutItem::paint( painter, itemStyle, pWidget );
194 painter->restore();
195}
196
198{
199 if ( !mMapUuid.isEmpty() )
200 {
201 setLinkedMap( qobject_cast< QgsLayoutItemMap * >( mLayout->itemByUuid( mMapUuid, true ) ) );
202 }
203
204 if ( !mFilterByMapUuids.isEmpty() )
205 {
206 QList< QgsLayoutItemMap * > maps;
207 maps.reserve( mFilterByMapUuids.size() );
208 for ( const QString &uuid : std::as_const( mFilterByMapUuids ) )
209 {
210 if ( QgsLayoutItemMap *map = qobject_cast< QgsLayoutItemMap * >( mLayout->itemByUuid( uuid, true ) ) )
211 {
212 maps << map;
213 }
214 }
215 setFilterByMapItems( maps );
216 }
217}
218
220{
222 clearLegendCachedData();
223 onAtlasFeature();
224}
225
227{
228 clearLegendCachedData();
230}
231
233{
234 QPainter *painter = context.renderContext().painter();
235
236 QgsRenderContext rc = mMap ? QgsLayoutUtils::createRenderContextForMap( mMap, painter, context.renderContext().scaleFactor() * 25.4 )
238
241
242 const QgsScopedQPainterState painterState( painter );
243
244 // painter is scaled to dots, so scale back to layout units
245 painter->scale( rc.scaleFactor(), rc.scaleFactor() );
246
247 painter->setPen( QPen( QColor( 0, 0, 0 ) ) );
248
249 if ( !mSizeToContents )
250 {
251 // set a clip region to crop out parts of legend which don't fit
252 const QRectF thisPaintRect = QRectF( 0, 0, rect().width(), rect().height() );
253 painter->setClipRect( thisPaintRect );
254 }
255
256 if ( mLayout )
257 {
258 // no longer required, but left for API compatibility
260 mSettings.setDpi( mLayout->renderContext().dpi() );
262 }
263
264 QgsLegendRenderer legendRenderer = createRenderer();
265 legendRenderer.setLegendSize( rect().size() );
266
267 legendRenderer.drawLegend( rc );
268}
269
271{
272 if ( !mSizeToContents )
273 return;
274
275 if ( !mInitialMapScaleCalculated )
276 {
277 // this is messy - but until we have painted the item we have no knowledge of the current DPI
278 // and so cannot correctly calculate the map scale. This results in incorrect size calculations
279 // for marker symbols with size in map units, causing the legends to initially expand to huge
280 // sizes if we attempt to calculate the box size first.
281 return;
282 }
283
284 QgsRenderContext context = mMap ? QgsLayoutUtils::createRenderContextForMap( mMap, nullptr ) :
287
288 QgsLegendRenderer legendRenderer = createRenderer();
289 const QSizeF size = legendRenderer.minimumSize( &context );
290 QgsDebugMsgLevel( QStringLiteral( "width = %1 height = %2" ).arg( size.width() ).arg( size.height() ), 2 );
291 if ( size.isValid() )
292 {
293 const QgsLayoutSize newSize = mLayout->convertFromLayoutUnits( size, sizeWithUnits().units() );
294 //set new rect, respecting position mode and data defined size/position
295 attemptResize( newSize );
296 }
297}
298
300{
301 mSizeToContents = enabled;
302}
303
305{
306 return mSizeToContents;
307}
308
309void QgsLayoutItemLegend::setCustomLayerTree( QgsLayerTree *rootGroup )
310{
311 if ( !mDeferLegendModelInitialization )
312 {
313 mLegendModel->setRootGroup( rootGroup ? rootGroup : ( mLayout ? mLayout->project()->layerTreeRoot() : nullptr ) );
314 }
315
316 mCustomLayerTree.reset( rootGroup );
317}
318
319void QgsLayoutItemLegend::ensureModelIsInitialized() const
320{
321 if ( mDeferLegendModelInitialization )
322 {
323 QgsLayoutItemLegend *mutableThis = const_cast< QgsLayoutItemLegend * >( this );
324 mutableThis->mDeferLegendModelInitialization = false;
325 mutableThis->setCustomLayerTree( mutableThis->mCustomLayerTree.release() );
326 }
327}
328
329QgsLegendRenderer QgsLayoutItemLegend::createRenderer() const
330{
331 QgsLegendRenderer res( mLegendModel.get(), mSettings );
332
333 // only show private layers when not in auto update mode
334 res.proxyModel()->setShowPrivateLayers( static_cast< bool >( mCustomLayerTree ) );
335
336 return res;
337}
338
340{
341 ensureModelIsInitialized();
342 return mLegendModel.get();
343}
344
346{
347 ensureModelIsInitialized();
348 return mLegendModel.get();
349}
350
352{
353 if ( autoUpdate == autoUpdateModel() )
354 return;
355
356 setCustomLayerTree( autoUpdate ? nullptr : mLayout->project()->layerTreeRoot()->clone() );
358 updateFilterByMap( false );
359}
360
361void QgsLayoutItemLegend::nodeCustomPropertyChanged( QgsLayerTreeNode *, const QString &key )
362{
363 if ( key == QLatin1String( "cached_name" ) )
364 return;
365
366 if ( autoUpdateModel() )
367 {
368 // in "auto update" mode, some parameters on the main app legend may have been changed (expression filtering)
369 // we must then call updateItem to reflect the changes
370 updateFilterByMap( false );
371 }
372}
373
375{
376 return !mCustomLayerTree;
377}
378
380{
381 if ( mLegendFilterByMap == enabled )
382 return;
383
384 mLegendFilterByMap = enabled;
385 updateFilterByMap( false );
386}
387
388void QgsLayoutItemLegend::setTitle( const QString &t )
389{
390 mTitle = t;
391 mSettings.setTitle( t );
392
393 if ( mLayout && id().isEmpty() )
394 {
395 //notify the model that the display name has changed
396 mLayout->itemsModel()->updateItemDisplayName( this );
397 }
398}
400{
401 return mTitle;
402}
403
404Qt::AlignmentFlag QgsLayoutItemLegend::titleAlignment() const
405{
406 return mSettings.titleAlignment();
407}
408
409void QgsLayoutItemLegend::setTitleAlignment( Qt::AlignmentFlag alignment )
410{
411 mSettings.setTitleAlignment( alignment );
412}
413
418
420{
421 return mSettings.style( s );
422}
423
425{
426 mSettings.setStyle( s, style );
427}
428
435
442
444{
445 rstyle( s ).setMargin( margin );
446}
447
449{
450 rstyle( s ).setMargin( side, margin );
451}
452
459
461{
463 mSettings.setLineSpacing( spacing );
465}
466
468{
469 return mSettings.boxSpace();
470}
471
473{
474 mSettings.setBoxSpace( s );
475}
476
478{
479 return mSettings.columnSpace();
480}
481
483{
484 mSettings.setColumnSpace( s );
485}
486
488{
490 return mSettings.fontColor();
492}
493
500
502{
503 return mSettings.symbolSize().width();
504}
505
507{
508 mSettings.setSymbolSize( QSizeF( w, mSettings.symbolSize().height() ) );
509}
510
512{
513 return mSettings.maximumSymbolSize();
514}
515
517{
518 mSettings.setMaximumSymbolSize( size );
519}
520
522{
523 return mSettings.minimumSymbolSize();
524}
525
527{
528 mSettings.setMinimumSymbolSize( size );
529}
530
531void QgsLayoutItemLegend::setSymbolAlignment( Qt::AlignmentFlag alignment )
532{
533 mSettings.setSymbolAlignment( alignment );
534}
535
537{
538 return mSettings.symbolAlignment();
539}
540
542{
543 return mSettings.symbolSize().height();
544}
545
547{
548 mSettings.setSymbolSize( QSizeF( mSettings.symbolSize().width(), h ) );
549}
550
552{
553 return mSettings.wmsLegendSize().width();
554}
555
557{
558 mSettings.setWmsLegendSize( QSizeF( w, mSettings.wmsLegendSize().height() ) );
559}
560
562{
563 return mSettings.wmsLegendSize().height();
564}
566{
567 mSettings.setWmsLegendSize( QSizeF( mSettings.wmsLegendSize().width(), h ) );
568}
569
571{
572 mSettings.setWrapChar( t );
573}
574
576{
577 return mSettings.wrapChar();
578}
579
581{
582 return mColumnCount;
583}
584
586{
587 mColumnCount = c;
588 mSettings.setColumnCount( c );
589}
590
592{
593 return mSettings.splitLayer();
594}
595
597{
598 mSettings.setSplitLayer( s );
599}
600
602{
603 return mSettings.equalColumnWidth();
604}
605
607{
608 mSettings.setEqualColumnWidth( s );
609}
610
612{
613 return mSettings.drawRasterStroke();
614}
615
617{
618 mSettings.setDrawRasterStroke( enabled );
619}
620
622{
623 return mSettings.rasterStrokeColor();
624}
625
627{
628 mSettings.setRasterStrokeColor( color );
629}
630
632{
633 return mSettings.rasterStrokeWidth();
634}
635
637{
638 mSettings.setRasterStrokeWidth( width );
639}
640
642{
643 return mSettings.autoWrapLinesAfter();
644}
645
647{
648 mSettings.setAutoWrapLinesAfter( length );
649}
650
656
657bool QgsLayoutItemLegend::writePropertiesToElement( QDomElement &legendElem, QDomDocument &doc, const QgsReadWriteContext &context ) const
658{
659
660 //write general properties
661 legendElem.setAttribute( QStringLiteral( "title" ), mTitle );
662 legendElem.setAttribute( QStringLiteral( "titleAlignment" ), QString::number( static_cast< int >( mSettings.titleAlignment() ) ) );
663 legendElem.setAttribute( QStringLiteral( "columnCount" ), QString::number( mColumnCount ) );
664 legendElem.setAttribute( QStringLiteral( "splitLayer" ), QString::number( mSettings.splitLayer() ) );
665 legendElem.setAttribute( QStringLiteral( "equalColumnWidth" ), QString::number( mSettings.equalColumnWidth() ) );
666
667 legendElem.setAttribute( QStringLiteral( "boxSpace" ), QString::number( mSettings.boxSpace() ) );
668 legendElem.setAttribute( QStringLiteral( "columnSpace" ), QString::number( mSettings.columnSpace() ) );
669
670 legendElem.setAttribute( QStringLiteral( "symbolWidth" ), QString::number( mSettings.symbolSize().width() ) );
671 legendElem.setAttribute( QStringLiteral( "symbolHeight" ), QString::number( mSettings.symbolSize().height() ) );
672 legendElem.setAttribute( QStringLiteral( "maxSymbolSize" ), QString::number( mSettings.maximumSymbolSize() ) );
673 legendElem.setAttribute( QStringLiteral( "minSymbolSize" ), QString::number( mSettings.minimumSymbolSize() ) );
674
675 legendElem.setAttribute( QStringLiteral( "symbolAlignment" ), mSettings.symbolAlignment() );
676
677 legendElem.setAttribute( QStringLiteral( "symbolAlignment" ), mSettings.symbolAlignment() );
678
679 legendElem.setAttribute( QStringLiteral( "rasterBorder" ), mSettings.drawRasterStroke() );
680 legendElem.setAttribute( QStringLiteral( "rasterBorderColor" ), QgsColorUtils::colorToString( mSettings.rasterStrokeColor() ) );
681 legendElem.setAttribute( QStringLiteral( "rasterBorderWidth" ), QString::number( mSettings.rasterStrokeWidth() ) );
682
683 if ( mSettings.autoWrapLinesAfter() > 0 )
684 {
685 legendElem.setAttribute( QStringLiteral( "autoWrapLinesAfter" ), mSettings.autoWrapLinesAfter() );
686 }
687
688 legendElem.setAttribute( QStringLiteral( "wmsLegendWidth" ), QString::number( mSettings.wmsLegendSize().width() ) );
689 legendElem.setAttribute( QStringLiteral( "wmsLegendHeight" ), QString::number( mSettings.wmsLegendSize().height() ) );
690 legendElem.setAttribute( QStringLiteral( "wrapChar" ), mSettings.wrapChar() );
691
692 legendElem.setAttribute( QStringLiteral( "resizeToContents" ), mSizeToContents );
693
694 if ( mMap )
695 {
696 legendElem.setAttribute( QStringLiteral( "map_uuid" ), mMap->uuid() );
697 }
698
699 if ( !mFilterByMapItems.empty() )
700 {
701 QDomElement filterByMapsElem = doc.createElement( QStringLiteral( "filterByMaps" ) );
702 for ( QgsLayoutItemMap *map : mFilterByMapItems )
703 {
704 if ( map )
705 {
706 QDomElement mapElem = doc.createElement( QStringLiteral( "map" ) );
707 mapElem.setAttribute( QStringLiteral( "uuid" ), map->uuid() );
708 filterByMapsElem.appendChild( mapElem );
709 }
710 }
711 legendElem.appendChild( filterByMapsElem );
712 }
713
714 QDomElement legendStyles = doc.createElement( QStringLiteral( "styles" ) );
715 legendElem.appendChild( legendStyles );
716
717 style( Qgis::LegendComponent::Title ).writeXml( QStringLiteral( "title" ), legendStyles, doc, context );
718 style( Qgis::LegendComponent::Group ).writeXml( QStringLiteral( "group" ), legendStyles, doc, context );
719 style( Qgis::LegendComponent::Subgroup ).writeXml( QStringLiteral( "subgroup" ), legendStyles, doc, context );
720 style( Qgis::LegendComponent::Symbol ).writeXml( QStringLiteral( "symbol" ), legendStyles, doc, context );
721 style( Qgis::LegendComponent::SymbolLabel ).writeXml( QStringLiteral( "symbolLabel" ), legendStyles, doc, context );
722
723 if ( mCustomLayerTree )
724 {
725 // if not using auto-update - store the custom layer tree
726 mCustomLayerTree->writeXml( legendElem, context );
727 }
728
729 if ( mLegendFilterByMap )
730 {
731 legendElem.setAttribute( QStringLiteral( "legendFilterByMap" ), QStringLiteral( "1" ) );
732 }
733 legendElem.setAttribute( QStringLiteral( "legendFilterByAtlas" ), mFilterOutAtlas ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
734
735 return true;
736}
737
738bool QgsLayoutItemLegend::readPropertiesFromElement( const QDomElement &itemElem, const QDomDocument &doc, const QgsReadWriteContext &context )
739{
740 //read general properties
741 mTitle = itemElem.attribute( QStringLiteral( "title" ) );
742 mSettings.setTitle( mTitle );
743 if ( !itemElem.attribute( QStringLiteral( "titleAlignment" ) ).isEmpty() )
744 {
745 mSettings.setTitleAlignment( static_cast< Qt::AlignmentFlag >( itemElem.attribute( QStringLiteral( "titleAlignment" ) ).toInt() ) );
746 }
747 int colCount = itemElem.attribute( QStringLiteral( "columnCount" ), QStringLiteral( "1" ) ).toInt();
748 if ( colCount < 1 ) colCount = 1;
749 mColumnCount = colCount;
750 mSettings.setColumnCount( mColumnCount );
751 mSettings.setSplitLayer( itemElem.attribute( QStringLiteral( "splitLayer" ), QStringLiteral( "0" ) ).toInt() == 1 );
752 mSettings.setEqualColumnWidth( itemElem.attribute( QStringLiteral( "equalColumnWidth" ), QStringLiteral( "0" ) ).toInt() == 1 );
753
754 const QDomNodeList stylesNodeList = itemElem.elementsByTagName( QStringLiteral( "styles" ) );
755 if ( !stylesNodeList.isEmpty() )
756 {
757 const QDomNode stylesNode = stylesNodeList.at( 0 );
758 for ( int i = 0; i < stylesNode.childNodes().size(); i++ )
759 {
760 const QDomElement styleElem = stylesNode.childNodes().at( i ).toElement();
762 style.readXml( styleElem, doc, context );
763 const QString name = styleElem.attribute( QStringLiteral( "name" ) );
765 if ( name == QLatin1String( "title" ) ) s = Qgis::LegendComponent::Title;
766 else if ( name == QLatin1String( "group" ) ) s = Qgis::LegendComponent::Group;
767 else if ( name == QLatin1String( "subgroup" ) ) s = Qgis::LegendComponent::Subgroup;
768 else if ( name == QLatin1String( "symbol" ) ) s = Qgis::LegendComponent::Symbol;
769 else if ( name == QLatin1String( "symbolLabel" ) ) s = Qgis::LegendComponent::SymbolLabel;
770 else continue;
771 setStyle( s, style );
772 }
773 }
774
775 //font color
776 if ( itemElem.hasAttribute( QStringLiteral( "fontColor" ) ) )
777 {
778 QColor fontClr;
779 fontClr.setNamedColor( itemElem.attribute( QStringLiteral( "fontColor" ), QStringLiteral( "#000000" ) ) );
784 }
785
786 //spaces
787 mSettings.setBoxSpace( itemElem.attribute( QStringLiteral( "boxSpace" ), QStringLiteral( "2.0" ) ).toDouble() );
788 mSettings.setColumnSpace( itemElem.attribute( QStringLiteral( "columnSpace" ), QStringLiteral( "2.0" ) ).toDouble() );
789
790 mSettings.setSymbolSize( QSizeF( itemElem.attribute( QStringLiteral( "symbolWidth" ), QStringLiteral( "7.0" ) ).toDouble(), itemElem.attribute( QStringLiteral( "symbolHeight" ), QStringLiteral( "14.0" ) ).toDouble() ) );
791 mSettings.setSymbolAlignment( static_cast< Qt::AlignmentFlag >( itemElem.attribute( QStringLiteral( "symbolAlignment" ), QString::number( Qt::AlignLeft ) ).toInt() ) );
792
793 mSettings.setMaximumSymbolSize( itemElem.attribute( QStringLiteral( "maxSymbolSize" ), QStringLiteral( "0.0" ) ).toDouble() );
794 mSettings.setMinimumSymbolSize( itemElem.attribute( QStringLiteral( "minSymbolSize" ), QStringLiteral( "0.0" ) ).toDouble() );
795
796 mSettings.setWmsLegendSize( QSizeF( itemElem.attribute( QStringLiteral( "wmsLegendWidth" ), QStringLiteral( "50" ) ).toDouble(), itemElem.attribute( QStringLiteral( "wmsLegendHeight" ), QStringLiteral( "25" ) ).toDouble() ) );
797
798 if ( itemElem.hasAttribute( QStringLiteral( "lineSpacing" ) ) )
799 {
800 const double spacing = itemElem.attribute( QStringLiteral( "lineSpacing" ), QStringLiteral( "1.0" ) ).toDouble();
801 // line spacing *was* a fixed amount (in mm) added between each line of text.
803 // assume font sizes in points, since that was what we always had from before this method was deprecated
804 f.setLineHeight( f.size() * 0.352778 + spacing );
807
809 f.setLineHeight( f.size() * 0.352778 + spacing );
812
814 f.setLineHeight( f.size() * 0.352778 + spacing );
817
819 f.setLineHeight( f.size() * 0.352778 + spacing );
822 }
823
824 mSettings.setDrawRasterStroke( itemElem.attribute( QStringLiteral( "rasterBorder" ), QStringLiteral( "1" ) ) != QLatin1String( "0" ) );
825 mSettings.setRasterStrokeColor( QgsColorUtils::colorFromString( itemElem.attribute( QStringLiteral( "rasterBorderColor" ), QStringLiteral( "0,0,0" ) ) ) );
826 mSettings.setRasterStrokeWidth( itemElem.attribute( QStringLiteral( "rasterBorderWidth" ), QStringLiteral( "0" ) ).toDouble() );
827
828 mSettings.setAutoWrapLinesAfter( itemElem.attribute( QStringLiteral( "autoWrapLinesAfter" ), QStringLiteral( "0" ) ).toDouble() );
829
830 mSettings.setWrapChar( itemElem.attribute( QStringLiteral( "wrapChar" ) ) );
831
832 mSizeToContents = itemElem.attribute( QStringLiteral( "resizeToContents" ), QStringLiteral( "1" ) ) != QLatin1String( "0" );
833
834 // map
835 mLegendFilterByMap = itemElem.attribute( QStringLiteral( "legendFilterByMap" ), QStringLiteral( "0" ) ).toInt();
836
837 mMapUuid.clear();
838 if ( !itemElem.attribute( QStringLiteral( "map_uuid" ) ).isEmpty() )
839 {
840 mMapUuid = itemElem.attribute( QStringLiteral( "map_uuid" ) );
841 }
842
843 mFilterByMapUuids.clear();
844 {
845 const QDomElement filterByMapsElem = itemElem.firstChildElement( QStringLiteral( "filterByMaps" ) );
846 if ( !filterByMapsElem.isNull() )
847 {
848 QDomElement mapsElem = filterByMapsElem.firstChildElement( QStringLiteral( "map" ) );
849 while ( !mapsElem.isNull() )
850 {
851 mFilterByMapUuids << mapsElem.attribute( QStringLiteral( "uuid" ) );
852 mapsElem = mapsElem.nextSiblingElement( QStringLiteral( "map" ) );
853 }
854 }
855 else if ( !mMapUuid.isEmpty() )
856 {
857 // for compatibility with < QGIS 3.32 projects
858 mFilterByMapUuids << mMapUuid;
859 }
860 }
861
862 // disconnect current map
863 setupMapConnections( mMap, false );
864 mMap = nullptr;
865
866 mFilterOutAtlas = itemElem.attribute( QStringLiteral( "legendFilterByAtlas" ), QStringLiteral( "0" ) ).toInt();
867
868 // QGIS >= 2.6
869 QDomElement layerTreeElem = itemElem.firstChildElement( QStringLiteral( "layer-tree" ) );
870 if ( layerTreeElem.isNull() )
871 layerTreeElem = itemElem.firstChildElement( QStringLiteral( "layer-tree-group" ) );
872
873 if ( !layerTreeElem.isNull() )
874 {
875 std::unique_ptr< QgsLayerTree > tree( QgsLayerTree::readXml( layerTreeElem, context ) );
876 if ( mLayout )
877 tree->resolveReferences( mLayout->project(), true );
878 setCustomLayerTree( tree.release() );
879 }
880 else
881 setCustomLayerTree( nullptr );
882
883 return true;
884}
885
887{
888 if ( !id().isEmpty() )
889 {
890 return id();
891 }
892
893 //if no id, default to portion of title text
894 QString text = mSettings.title();
895 if ( text.isEmpty() )
896 {
897 return tr( "<Legend>" );
898 }
899 if ( text.length() > 25 )
900 {
901 return tr( "%1…" ).arg( text.left( 25 ) );
902 }
903 else
904 {
905 return text;
906 }
907}
908
910{
911 return blendMode() != QPainter::CompositionMode_SourceOver;
912}
913
915{
916 return mEvaluatedOpacity < 1.0;
917}
918
919void QgsLayoutItemLegend::setupMapConnections( QgsLayoutItemMap *map, bool connectSlots )
920{
921 if ( !map )
922 return;
923
924 if ( !connectSlots )
925 {
926 disconnect( map, &QObject::destroyed, this, &QgsLayoutItemLegend::invalidateCurrentMap );
927 disconnect( map, &QgsLayoutObject::changed, this, &QgsLayoutItemLegend::updateFilterByMapAndRedraw );
928 disconnect( map, &QgsLayoutItemMap::extentChanged, this, &QgsLayoutItemLegend::updateFilterByMapAndRedraw );
929 disconnect( map, &QgsLayoutItemMap::mapRotationChanged, this, &QgsLayoutItemLegend::updateFilterByMapAndRedraw );
930 disconnect( map, &QgsLayoutItemMap::layerStyleOverridesChanged, this, &QgsLayoutItemLegend::mapLayerStyleOverridesChanged );
931 disconnect( map, &QgsLayoutItemMap::themeChanged, this, &QgsLayoutItemLegend::mapThemeChanged );
932 }
933 else
934 {
935 connect( map, &QObject::destroyed, this, &QgsLayoutItemLegend::invalidateCurrentMap );
936 connect( map, &QgsLayoutObject::changed, this, &QgsLayoutItemLegend::updateFilterByMapAndRedraw );
937 connect( map, &QgsLayoutItemMap::extentChanged, this, &QgsLayoutItemLegend::updateFilterByMapAndRedraw );
938 connect( map, &QgsLayoutItemMap::mapRotationChanged, this, &QgsLayoutItemLegend::updateFilterByMapAndRedraw );
939 connect( map, &QgsLayoutItemMap::layerStyleOverridesChanged, this, &QgsLayoutItemLegend::mapLayerStyleOverridesChanged );
940 connect( map, &QgsLayoutItemMap::themeChanged, this, &QgsLayoutItemLegend::mapThemeChanged );
941 }
942}
943
945{
946 if ( mMap == map )
947 return;
948
949 if ( mMap )
950 {
951 setupMapConnections( mMap, false );
952 }
953
954 mMap = map;
955
956 if ( mMap )
957 {
958 setupMapConnections( mMap, true );
959 mapThemeChanged( mMap->themeToRender( mMap->createExpressionContext() ) );
960 }
961
963}
964
965void QgsLayoutItemLegend::setFilterByMapItems( const QList<QgsLayoutItemMap *> &maps )
966{
967 if ( filterByMapItems() == maps )
968 return;
969
970 for ( QgsLayoutItemMap *map : std::as_const( mFilterByMapItems ) )
971 {
972 setupMapConnections( map, false );
973 }
974
975 mFilterByMapItems.clear();
976 mFilterByMapItems.reserve( maps.size() );
977 for ( QgsLayoutItemMap *map : maps )
978 {
979 if ( map )
980 {
981 mFilterByMapItems.append( map );
982 setupMapConnections( map, true );
983 }
984 }
985
987}
988
989QList<QgsLayoutItemMap *> QgsLayoutItemLegend::filterByMapItems() const
990{
991 QList<QgsLayoutItemMap *> res;
992 res.reserve( mFilterByMapItems.size() );
993 for ( QgsLayoutItemMap *map : mFilterByMapItems )
994 {
995 if ( map )
996 res.append( map );
997 }
998 return res;
999}
1000
1001void QgsLayoutItemLegend::invalidateCurrentMap()
1002{
1003 setLinkedMap( nullptr );
1004}
1005
1007{
1009
1010 bool forceUpdate = false;
1011 //updates data defined properties and redraws item to match
1013 {
1014 bool ok = false;
1016 if ( ok )
1017 {
1018 mSettings.setTitle( t );
1019 forceUpdate = true;
1020 }
1021 }
1023 {
1024 bool ok = false;
1026 if ( ok && cols >= 0 )
1027 {
1028 mSettings.setColumnCount( cols );
1029 forceUpdate = true;
1030 }
1031 }
1033 {
1034 bool ok = false;
1036 if ( ok && width >= 0 )
1037 {
1038 mSettings.setAutoWrapLinesAfter( width );
1039 forceUpdate = true;
1040 }
1041 }
1042 if ( forceUpdate )
1043 {
1044 adjustBoxSize();
1045 update();
1046 }
1047
1049}
1050
1051
1052void QgsLayoutItemLegend::updateFilterByMapAndRedraw()
1053{
1054 updateFilterByMap( true );
1055}
1056
1057void QgsLayoutItemLegend::setModelStyleOverrides( const QMap<QString, QString> &overrides )
1058{
1059 mLegendModel->setLayerStyleOverrides( overrides );
1060 if ( QgsLayerTree *rootGroup = mLegendModel->rootGroup() )
1061 {
1062 const QList< QgsLayerTreeLayer * > layers = rootGroup->findLayers();
1063 for ( QgsLayerTreeLayer *nodeLayer : std::as_const( layers ) )
1064 mLegendModel->refreshLayerLegend( nodeLayer );
1065 }
1066}
1067
1068void QgsLayoutItemLegend::clearLegendCachedData()
1069{
1070 std::function< void( QgsLayerTreeNode * ) > clearNodeCache;
1071 clearNodeCache = [&]( QgsLayerTreeNode * node )
1072 {
1073 mLegendModel->clearCachedData( node );
1074 if ( QgsLayerTree::isGroup( node ) )
1075 {
1077 const QList< QgsLayerTreeNode * > children = group->children();
1078 for ( QgsLayerTreeNode *child : children )
1079 {
1080 clearNodeCache( child );
1081 }
1082 }
1083 };
1084
1085 if ( QgsLayerTree *rootGroup = mLegendModel->rootGroup() )
1086 {
1087 clearNodeCache( rootGroup );
1088 }
1089}
1090
1091void QgsLayoutItemLegend::mapLayerStyleOverridesChanged()
1092{
1093 if ( !mMap )
1094 return;
1095
1096 // map's style has been changed, so make sure to update the legend here
1097 if ( mLegendFilterByMap )
1098 {
1099 // legend is being filtered by map, so we need to re run the hit test too
1100 // as the style overrides may also have affected the visible symbols
1101 updateFilterByMap( false );
1102 }
1103 else
1104 {
1105 setModelStyleOverrides( mMap->layerStyleOverrides() );
1106 }
1107
1108 adjustBoxSize();
1109
1110 updateFilterByMap( false );
1111}
1112
1113void QgsLayoutItemLegend::mapThemeChanged( const QString &theme )
1114{
1115 if ( mThemeName == theme )
1116 return;
1117
1118 mThemeName = theme;
1119
1120 // map's theme has been changed, so make sure to update the legend here
1121
1122 // legend is being filtered by map, so we need to re run the hit test too
1123 // as the style overrides may also have affected the visible symbols
1124 updateFilterByMap( false );
1125
1126 adjustBoxSize();
1127
1129}
1130
1132{
1133 // ask for update
1134 // the actual update will take place before the redraw.
1135 // This is to avoid multiple calls to the filter
1136 mFilterAskedForUpdate = true;
1137
1138 if ( redraw )
1139 update();
1140}
1141
1142void QgsLayoutItemLegend::doUpdateFilterByMap()
1143{
1144 // There's an incompatibility here between legend handling of linked map themes and layer style overrides vs
1145 // how expression evaluation is made in legend content text. The logic below is hacked together to get
1146 // all the existing unit tests passing, but these two features are incompatible with each other and fixing
1147 // this is extremely non-trivial. Let's just hope no-one tries to use those features together!
1148 // Ideally, all the branches below would be consistently using either "setModelStyleOverrides" (which forces
1149 // a rebuild of each layer's legend, and breaks legend text expression evaluation) OR
1150 // "mLegendModel->setLayerStyleOverrides" which just handles the expression updates but which doesn't correctly
1151 // generate the legend content from the associated theme settings.
1152 if ( mMap && !mThemeName.isEmpty() )
1153 {
1154 // get style overrides for theme
1155 const QMap<QString, QString> overrides = mLayout->project()->mapThemeCollection()->mapThemeStyleOverrides( mThemeName );
1156 setModelStyleOverrides( overrides );
1157 }
1158 else if ( mMap )
1159 {
1160 mLegendModel->setLayerStyleOverrides( mMap->layerStyleOverrides() );
1161 }
1162 else
1163 {
1164 mLegendModel->setLayerStyleOverrides( QMap<QString, QString>() );
1165 }
1166
1167 // only use thread hit tests for preview renders. In other cases we'll need a blocking hit test anyway, and we run a risk
1168 // of deadlocks if a non-preview render is then started on the main thread.
1169 mLegendModel->setFlag( QgsLayerTreeModel::UseThreadedHitTest, mLayout->renderContext().isPreviewRender() );
1170
1171 const bool filterByExpression = QgsLayerTreeUtils::hasLegendFilterExpression( *( mCustomLayerTree ? mCustomLayerTree.get() : mLayout->project()->layerTreeRoot() ) );
1172
1173 const bool hasValidFilter = filterByExpression
1174 || ( mLegendFilterByMap && ( mMap || !mFilterByMapItems.empty() ) )
1175 || mInAtlas;
1176
1177 if ( hasValidFilter )
1178 {
1179 const double dpi = mLayout->renderContext().dpi();
1180
1181 QSet< QgsLayoutItemMap * > linkedFilterMaps;
1182 if ( mLegendFilterByMap )
1183 {
1184 linkedFilterMaps = qgis::listToSet( filterByMapItems() );
1185 if ( mMap )
1186 linkedFilterMaps.insert( mMap );
1187 }
1188
1189 QgsMapSettings mapSettings;
1190 QgsGeometry filterGeometry;
1191 if ( mMap )
1192 {
1193 // if a specific linked map has been set, use it for the reference scale and extent
1194 const QgsRectangle requestRectangle = mMap->requestedExtent();
1195 QSizeF size( requestRectangle.width(), requestRectangle.height() );
1196 size *= mLayout->convertFromLayoutUnits( mMap->mapUnitsToLayoutUnits(), Qgis::LayoutUnit::Millimeters ).length() * dpi / 25.4;
1197 mapSettings = mMap->mapSettings( requestRectangle, size, dpi, true );
1198
1199 filterGeometry = QgsGeometry::fromQPolygonF( mMap->visibleExtentPolygon() );
1200 }
1201 else if ( !linkedFilterMaps.empty() )
1202 {
1203 // otherwise just take the first linked filter map
1204 const QgsRectangle requestRectangle = ( *linkedFilterMaps.constBegin() )->requestedExtent();
1205 QSizeF size( requestRectangle.width(), requestRectangle.height() );
1206 size *= mLayout->convertFromLayoutUnits( ( *linkedFilterMaps.constBegin() )->mapUnitsToLayoutUnits(), Qgis::LayoutUnit::Millimeters ).length() * dpi / 25.4;
1207 mapSettings = ( *linkedFilterMaps.constBegin() )->mapSettings( requestRectangle, size, dpi, true );
1208
1209 filterGeometry = QgsGeometry::fromQPolygonF( ( *linkedFilterMaps.constBegin() )->visibleExtentPolygon() );
1210 }
1211
1213
1214 const QgsGeometry atlasGeometry { mLayout->reportContext().currentGeometry( mapSettings.destinationCrs() ) };
1215
1216 QgsLayerTreeFilterSettings filterSettings( mapSettings );
1217
1218 QList<QgsMapLayer *> layersToClip;
1219 if ( !atlasGeometry.isNull() && mMap->atlasClippingSettings()->enabled() )
1220 {
1221 layersToClip = mMap->atlasClippingSettings()->layersToClip();
1222 for ( QgsMapLayer *layer : std::as_const( layersToClip ) )
1223 {
1224 QList<QgsMapLayer *> mapLayers { filterSettings.mapSettings().layers( true ) };
1225 mapLayers.removeAll( layer );
1226 filterSettings.mapSettings().setLayers( mapLayers );
1227 filterSettings.addVisibleExtentForLayer( layer, QgsReferencedGeometry( atlasGeometry, mapSettings.destinationCrs() ) );
1228 }
1229 }
1230
1231
1232 if ( !linkedFilterMaps.empty() )
1233 {
1234 for ( QgsLayoutItemMap *map : std::as_const( linkedFilterMaps ) )
1235 {
1236
1237 if ( map == mMap )
1238 continue;
1239
1241
1242 //transform back to destination CRS
1243 const QgsCoordinateTransform mapTransform( map->crs(), mapSettings.destinationCrs(), mLayout->project() );
1244 try
1245 {
1246 mapExtent.transform( mapTransform );
1247 }
1248 catch ( QgsCsException & )
1249 {
1250 continue;
1251 }
1252
1253 const QList< QgsMapLayer * > layersForMap = map->layersToRender();
1254 for ( QgsMapLayer *layer : layersForMap )
1255 {
1256 if ( mInAtlas && !atlasGeometry.isNull() )
1257 {
1258 mapExtent = mapExtent.intersection( atlasGeometry );
1259 }
1260
1261 filterSettings.addVisibleExtentForLayer( layer, QgsReferencedGeometry( mapExtent, mapSettings.destinationCrs() ) );
1262 }
1263 }
1264 }
1265
1266 if ( mInAtlas )
1267 {
1268 if ( !filterGeometry.isEmpty() )
1269 filterGeometry = mLayout->reportContext().currentGeometry( mapSettings.destinationCrs() );
1270 else
1271 filterGeometry = filterGeometry.intersection( mLayout->reportContext().currentGeometry( mapSettings.destinationCrs() ) );
1272 }
1273
1274 filterSettings.setLayerFilterExpressionsFromLayerTree( mLegendModel->rootGroup() );
1275 if ( !filterGeometry.isNull() )
1276 {
1277 filterSettings.setFilterPolygon( filterGeometry );
1278 }
1279 else
1280 {
1281 filterSettings.setFlags( Qgis::LayerTreeFilterFlag::SkipVisibilityCheck );
1282 }
1283
1284 mLegendModel->setFilterSettings( &filterSettings );
1285 }
1286 else
1287 {
1288 mLegendModel->setFilterSettings( nullptr );
1289 }
1290
1291 clearLegendCachedData();
1292 mForceResize = true;
1293}
1294
1296{
1297 return mThemeName;
1298}
1299
1301{
1302 mFilterOutAtlas = doFilter;
1303}
1304
1306{
1307 return mFilterOutAtlas;
1308}
1309
1310void QgsLayoutItemLegend::onAtlasFeature()
1311{
1312 if ( !mLayout || !mLayout->reportContext().feature().isValid() )
1313 return;
1314 mInAtlas = mFilterOutAtlas;
1316}
1317
1318void QgsLayoutItemLegend::onAtlasEnded()
1319{
1320 mInAtlas = false;
1322}
1323
1325{
1327
1328 // We only want the last scope from the map's expression context, as this contains
1329 // the map specific variables. We don't want the rest of the map's context, because that
1330 // will contain duplicate global, project, layout, etc scopes.
1331 if ( mMap )
1332 context.appendScope( mMap->createExpressionContext().popScope() );
1333
1334 QgsExpressionContextScope *scope = new QgsExpressionContextScope( tr( "Legend Settings" ) );
1335
1336 scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "legend_title" ), title(), true ) );
1337 scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "legend_column_count" ), columnCount(), true ) );
1338 scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "legend_split_layers" ), splitLayer(), true ) );
1339 scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "legend_wrap_string" ), wrapString(), true ) );
1340 scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "legend_filter_by_map" ), legendFilterByMapEnabled(), true ) );
1341 scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "legend_filter_out_atlas" ), legendFilterOutAtlas(), true ) );
1342
1343 context.appendScope( scope );
1344 return context;
1345}
1346
1351
1353{
1354 std::function<bool( QgsLayerTreeGroup *group ) >visit;
1355
1356 visit = [this, visitor, &visit]( QgsLayerTreeGroup * group ) -> bool
1357 {
1358 const QList<QgsLayerTreeNode *> childNodes = group->children();
1359 for ( QgsLayerTreeNode *node : childNodes )
1360 {
1361 if ( QgsLayerTree::isGroup( node ) )
1362 {
1363 QgsLayerTreeGroup *nodeGroup = QgsLayerTree::toGroup( node );
1364 if ( !visit( nodeGroup ) )
1365 return false;
1366 }
1367 else if ( QgsLayerTree::isLayer( node ) )
1368 {
1369 QgsLayerTreeLayer *nodeLayer = QgsLayerTree::toLayer( node );
1370 if ( !nodeLayer->patchShape().isNull() )
1371 {
1372 QgsStyleLegendPatchShapeEntity entity( nodeLayer->patchShape() );
1373 if ( !visitor->visit( QgsStyleEntityVisitorInterface::StyleLeaf( &entity, uuid(), displayName() ) ) )
1374 return false;
1375 }
1376 const QList<QgsLayerTreeModelLegendNode *> legendNodes = mLegendModel->layerLegendNodes( nodeLayer );
1377 for ( QgsLayerTreeModelLegendNode *legendNode : legendNodes )
1378 {
1379 if ( QgsSymbolLegendNode *symbolNode = dynamic_cast< QgsSymbolLegendNode * >( legendNode ) )
1380 {
1381 if ( !symbolNode->patchShape().isNull() )
1382 {
1383 QgsStyleLegendPatchShapeEntity entity( symbolNode->patchShape() );
1384 if ( !visitor->visit( QgsStyleEntityVisitorInterface::StyleLeaf( &entity, uuid(), displayName() ) ) )
1385 return false;
1386 }
1387 }
1388 }
1389 }
1390 }
1391 return true;
1392 };
1393 return visit( model()->rootGroup( ) );
1394}
1395
1397{
1398 return mLegendModel->hitTestInProgress();
1399}
1400
1401
1402// -------------------------------------------------------------------------
1403
1405 : QgsLayerTreeModel( rootNode, parent )
1406 , mLayoutLegend( layout )
1407{
1411 connect( this, &QgsLegendModel::dataChanged, this, &QgsLegendModel::refreshLegend );
1412}
1413
1415 : QgsLayerTreeModel( rootNode )
1416 , mLayoutLegend( layout )
1417{
1421 connect( this, &QgsLegendModel::dataChanged, this, &QgsLegendModel::refreshLegend );
1422}
1423
1424QVariant QgsLegendModel::data( const QModelIndex &index, int role ) const
1425{
1426 // handle custom layer node labels
1427
1429 QgsLayerTreeLayer *nodeLayer = QgsLayerTree::isLayer( node ) ? QgsLayerTree::toLayer( node ) : nullptr;
1430 if ( nodeLayer && ( role == Qt::DisplayRole || role == Qt::EditRole ) )
1431 {
1432 QString name = node->customProperty( QStringLiteral( "cached_name" ) ).toString();
1433 if ( !name.isEmpty() )
1434 return name;
1435
1436 QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( nodeLayer->layer() );
1437
1438 //finding the first label that is stored
1439 name = nodeLayer->customProperty( QStringLiteral( "legend/title-label" ) ).toString();
1440 if ( name.isEmpty() )
1441 name = nodeLayer->name();
1442 if ( name.isEmpty() )
1443 name = node->customProperty( QStringLiteral( "legend/title-label" ) ).toString();
1444 if ( name.isEmpty() )
1445 name = node->name();
1446 if ( nodeLayer->customProperty( QStringLiteral( "showFeatureCount" ), 0 ).toInt() )
1447 {
1448 if ( vlayer && vlayer->featureCount() >= 0 )
1449 {
1450 name += QStringLiteral( " [%1]" ).arg( vlayer->featureCount() );
1451 node->setCustomProperty( QStringLiteral( "cached_name" ), name );
1452 return name;
1453 }
1454 }
1455 node->setCustomProperty( QStringLiteral( "cached_name" ), name );
1456 return name;
1457 }
1458 return QgsLayerTreeModel::data( index, role );
1459}
1460
1461Qt::ItemFlags QgsLegendModel::flags( const QModelIndex &index ) const
1462{
1463 // make the legend nodes selectable even if they are not by default
1464 if ( index2legendNode( index ) )
1465 return QgsLayerTreeModel::flags( index ) | Qt::ItemIsSelectable;
1466
1468}
1469
1470QList<QgsLayerTreeModelLegendNode *> QgsLegendModel::layerLegendNodes( QgsLayerTreeLayer *nodeLayer, bool skipNodeEmbeddedInParent ) const
1471{
1472 if ( !mLegend.contains( nodeLayer ) )
1473 return QList<QgsLayerTreeModelLegendNode *>();
1474
1475 const LayerLegendData &data = mLegend[nodeLayer];
1476 QList<QgsLayerTreeModelLegendNode *> lst( data.activeNodes );
1477 if ( !skipNodeEmbeddedInParent && data.embeddedNodeInParent )
1478 lst.prepend( data.embeddedNodeInParent );
1479 return lst;
1480}
1481
1483{
1484 node->removeCustomProperty( QStringLiteral( "cached_name" ) );
1485}
1486
1487void QgsLegendModel::forceRefresh()
1488{
1489 emit refreshLegend();
1490}
@ Millimeters
Millimeters.
LegendComponent
Component of legends which can be styled.
Definition qgis.h:4406
@ Symbol
Symbol icon (excluding label)
@ Group
Legend group title.
@ Subgroup
Legend subgroup title.
@ Title
Legend title.
@ SymbolLabel
Symbol label (excluding icon)
@ SkipVisibilityCheck
If set, the standard visibility check should be skipped.
@ Millimeters
Millimeters.
@ ApplyScalingWorkaroundForTextRendering
Whether a scaling workaround designed to stablise the rendering of small font sizes (or for painters ...
int valueAsInt(int key, const QgsExpressionContext &context, int defaultValue=0, bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as an integer.
double valueAsDouble(int key, const QgsExpressionContext &context, double defaultValue=0.0, bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a double.
QString valueAsString(int key, const QgsExpressionContext &context, const QString &defaultString=QString(), bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a string.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
static QColor colorFromString(const QString &string)
Decodes a string into a color value.
static QString colorToString(const QColor &color)
Encodes a color into a string value.
Handles coordinate transforms between two coordinate systems.
Custom exception class for Coordinate Reference System related exceptions.
Single scope for storing variables and functions for use within a QgsExpressionContext.
void addVariable(const QgsExpressionContextScope::StaticVariable &variable)
Adds a variable into the context scope.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
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.
void appendScopes(const QList< QgsExpressionContextScope * > &scopes)
Appends a list of scopes to the end of the context.
A geometry is the spatial representation of a feature.
static QgsGeometry fromQPolygonF(const QPolygonF &polygon)
Construct geometry from a QPolygonF.
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false)
Transforms this geometry as described by the coordinate transform ct.
QgsGeometry intersection(const QgsGeometry &geometry, const QgsGeometryParameters &parameters=QgsGeometryParameters()) const
Returns a geometry representing the points shared by this geometry and other.
bool isEmpty() const
Returns true if the geometry is empty (eg a linestring with no vertices, or a collection with no geom...
Contains settings relating to filtering the contents of QgsLayerTreeModel and views.
Layer tree group node serves as a container for layers and further groups.
QList< QgsLayerTreeLayer * > findLayers() const
Find all layer nodes.
Layer tree node points to a map layer.
QgsLegendPatchShape patchShape() const
Returns the symbol patch shape to use when rendering the legend node symbol.
QString name() const override
Returns the layer's name.
QgsMapLayer * layer() const
Returns the map layer associated with this node.
An abstract interface for legend items returned from QgsMapLayerLegend implementation.
A model representing the layer tree, including layers and groups of layers.
Flags flags() const
Returns OR-ed combination of model flags.
void hitTestStarted()
Emitted when a hit test for visible legend items starts.
void hitTestCompleted()
Emitted when a hit test for visible legend items completes.
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
void setFlag(Flag f, bool on=true)
Enable or disable a model flag.
QHash< QgsLayerTreeLayer *, LayerLegendData > mLegend
Per layer data about layer's legend nodes.
QgsLayerTreeNode * index2node(const QModelIndex &index) const
Returns layer tree node for given index.
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
static QgsLayerTreeModelLegendNode * index2legendNode(const QModelIndex &index)
Returns legend node for given index.
@ AllowNodeReorder
Allow reordering with drag'n'drop.
@ AllowLegendChangeState
Allow check boxes for legend nodes (if supported by layer's legend)
@ UseThreadedHitTest
Run legend hit tests in a background thread.
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.
virtual QString name() const =0
Returns name of the node.
void customPropertyChanged(QgsLayerTreeNode *node, const QString &key)
Emitted when a custom property of a node within the tree has been changed or removed.
static bool hasLegendFilterExpression(const QgsLayerTreeGroup &group)
Test if one of the layers in a group has an expression filter.
Namespace with helper functions for layer tree operations.
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 QgsLayerTree * readXml(QDomElement &element, const QgsReadWriteContext &context)
Load the layer tree from an XML element.
static QgsLayerTreeGroup * toGroup(QgsLayerTreeNode *node)
Cast node to a group.
A layout item subclass for map legends.
bool autoUpdateModel() const
Returns whether the legend content should auto update to reflect changes in the project's layer tree.
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
bool accept(QgsStyleEntityVisitorInterface *visitor) const override
Accepts the specified style entity visitor, causing it to visit all style entities associated with th...
QString title() const
Returns the legend title.
void setSplitLayer(bool enabled)
Sets whether the legend items from a single layer can be split over multiple columns.
QgsLegendModel * model()
Returns the legend model.
QgsLegendStyle & rstyle(Qgis::LegendComponent s)
Returns reference to modifiable legend style.
void adjustBoxSize()
Sets the legend's item bounds to fit the whole legend content.
double wmsLegendWidth() const
Returns the WMS legend width.
void setColumnSpace(double spacing)
Sets the legend column spacing.
void setBoxSpace(double space)
Sets the legend box space.
bool splitLayer() const
Returns whether the legend items from a single layer can be split over multiple columns.
double symbolHeight() const
Returns the legend symbol height.
void updateFilterByMap(bool redraw=true)
Updates the legend content when filtered by map.
void setEqualColumnWidth(bool equalize)
Sets whether column widths should be equalized.
void setDrawRasterStroke(bool enabled)
Sets whether a stroke will be drawn around raster symbol items.
void refreshDataDefinedProperty(QgsLayoutObject::DataDefinedProperty property=QgsLayoutObject::DataDefinedProperty::AllProperties) override
static QgsLayoutItemLegend * create(QgsLayout *layout)
Returns a new legend item for the specified layout.
bool requiresRasterization() const override
Returns true if the item is drawn in such a way that forces the whole layout to be rasterized when ex...
void setLegendFilterOutAtlas(bool doFilter)
When set to true, during an atlas rendering, it will filter out legend elements where features are ou...
void setSymbolWidth(double width)
Sets the legend symbol width.
QString wrapString() const
Returns the legend text wrapping string.
bool resizeToContents() const
Returns whether the legend should automatically resize to fit its contents.
void setResizeToContents(bool enabled)
Sets whether the legend should automatically resize to fit its contents.
void updateLegend()
Updates the model and all legend entries.
QgsLayoutItemLegend(QgsLayout *layout)
Constructor for QgsLayoutItemLegend, with the specified parent layout.
void setLinkedMap(QgsLayoutItemMap *map)
Sets the map to associate with the legend.
bool writePropertiesToElement(QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context) const override
Stores item state within an XML DOM element.
void setSymbolAlignment(Qt::AlignmentFlag alignment)
Sets the alignment for placement of legend symbols.
double autoWrapLinesAfter() const
Returns the maximum line length (in millimeters) allowed before lines of text in the legend will be a...
Q_DECL_DEPRECATED QColor fontColor() const
Returns the legend font color.
Qt::AlignmentFlag symbolAlignment() const
Returns the alignment for placement of legend symbols.
double maximumSymbolSize() const
Returns the maximum symbol size (in mm).
void setWmsLegendWidth(double width)
Sets the WMS legend width.
void setTitle(const QString &title)
Sets the legend title.
Q_DECL_DEPRECATED void setFontColor(const QColor &color)
Sets the legend font color.
double boxSpace() const
Returns the legend box space.
void setRasterStrokeColor(const QColor &color)
Sets the stroke color for the stroke drawn around raster symbol items.
QString displayName() const override
Gets item display name.
bool isRefreshing() const override
Returns true if the item is currently refreshing content in the background.
void paint(QPainter *painter, const QStyleOptionGraphicsItem *itemStyle, QWidget *pWidget) override
double symbolWidth() const
Returns the legend symbol width.
QColor rasterStrokeColor() const
Returns the stroke color for the stroke drawn around raster symbol items.
bool drawRasterStroke() const
Returns whether a stroke will be drawn around raster symbol items.
void draw(QgsLayoutItemRenderContext &context) override
Draws the item's contents using the specified item render context.
void finalizeRestoreFromXml() override
Called after all pending items have been restored from XML.
int type() const override
bool readPropertiesFromElement(const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context) override
Sets item state from a DOM element.
bool legendFilterOutAtlas() const
Returns whether to filter out legend elements outside of the current atlas feature.
ExportLayerBehavior exportLayerBehavior() const override
Returns the behavior of this item during exporting to layered exports (e.g.
Q_DECL_DEPRECATED QFont styleFont(Qgis::LegendComponent component) const
Returns the font settings for a legend component.
Q_DECL_DEPRECATED void setLineSpacing(double spacing)
Sets the spacing in-between multiple lines.
double columnSpace() const
Returns the legend column spacing.
QgsLayoutItem::Flags itemFlags() const override
Returns the item's flags, which indicate how the item behaves.
Qt::AlignmentFlag titleAlignment() const
Returns the alignment of the legend title.
void setFilterByMapItems(const QList< QgsLayoutItemMap * > &maps)
Sets the maps to use when filtering legend content by map extents.
void setAutoWrapLinesAfter(double length)
Sets the maximum line length (in millimeters) allowed before lines of text in the legend will be auto...
void setLegendFilterByMapEnabled(bool enabled)
Set whether legend items should be filtered to show just the ones visible in the associated map.
QList< QgsLayoutItemMap * > filterByMapItems() const
Returns the maps to use when filtering legend content by map extents.
void setSymbolHeight(double height)
Sets the legend symbol height.
void setMinimumSymbolSize(double size)
Set the minimum symbol size for symbol (in millimeters).
void setStyleMargin(Qgis::LegendComponent component, double margin)
Set the margin for a legend component.
void setAutoUpdateModel(bool autoUpdate)
Sets whether the legend content should auto update to reflect changes in the project's layer tree.
void setMaximumSymbolSize(double size)
Set the maximum symbol size for symbol (in millimeters).
QIcon icon() const override
Returns the item's icon.
double wmsLegendHeight() const
Returns the WMS legend height.
void setWmsLegendHeight(double height)
Sets the WMS legend height.
QgsLegendStyle style(Qgis::LegendComponent s) const
Returns legend style.
void setRasterStrokeWidth(double width)
Sets the stroke width for the stroke drawn around raster symbol items.
bool containsAdvancedEffects() const override
Returns true if the item contains contents with blend modes or transparency effects which can only be...
double minimumSymbolSize() const
Returns the minimum symbol size (in mm).
void setStyle(Qgis::LegendComponent component, const QgsLegendStyle &style)
Sets the style of component to style for the legend.
double rasterStrokeWidth() const
Returns the stroke width (in layout units) for the stroke drawn around raster symbol items.
Q_DECL_DEPRECATED double lineSpacing() const
Returns the spacing in-between lines in layout units.
void invalidateCache() override
Q_DECL_DEPRECATED void setStyleFont(Qgis::LegendComponent component, const QFont &font)
Sets the style font for a legend component.
void setTitleAlignment(Qt::AlignmentFlag alignment)
Sets the alignment of the legend title.
void setWrapString(const QString &string)
Sets the legend text wrapping string.
QString themeName() const
Returns the name of the theme currently linked to the legend.
void setColumnCount(int count)
Sets the legend column count.
bool equalColumnWidth() const
Returns whether column widths should be equalized.
int columnCount() const
Returns the legend column count.
bool legendFilterByMapEnabled() const
Find out whether legend items are filtered to show just the ones visible in the associated map.
QList< QgsMapLayer * > layersToClip() const
Returns the list of map layers to clip to the atlas feature.
bool enabled() const
Returns true if the map content should be clipped to the current atlas feature.
Layout graphical items for displaying a map.
void extentChanged()
Emitted when the map's extent changes.
QgsMapSettings mapSettings(const QgsRectangle &extent, QSizeF size, double dpi, bool includeLayerSettings) const
Returns map settings that will be used for drawing of the map.
void layerStyleOverridesChanged()
Emitted when layer style overrides are changed... a means to let associated legend items know they sh...
void mapRotationChanged(double newRotation)
Emitted when the map's rotation changes.
QPolygonF visibleExtentPolygon() const
Returns a polygon representing the current visible map extent, considering map extents and rotation.
QgsRectangle requestedExtent() const
Calculates the extent to request and the yShift of the top-left point in case of rotation.
QList< QgsMapLayer * > layersToRender(const QgsExpressionContext *context=nullptr) const
Returns a list of the layers which will be rendered within this map item, considering any locked laye...
QMap< QString, QString > layerStyleOverrides() const
Returns stored overrides of styles for layers.
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
double mapUnitsToLayoutUnits() const
Returns the conversion factor from map units to layout units.
void themeChanged(const QString &theme)
Emitted when the map's associated theme is changed.
QgsRectangle extent() const
Returns the current map extent.
QgsLayoutItemMapAtlasClippingSettings * atlasClippingSettings()
Returns the map's atlas clipping settings.
QgsCoordinateReferenceSystem crs() const
Returns coordinate reference system used for rendering the map.
Contains settings and helpers relating to a render of a QgsLayoutItem.
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
Base class for graphical items within a QgsLayout.
virtual void refreshDataDefinedProperty(QgsLayoutObject::DataDefinedProperty property=QgsLayoutObject::DataDefinedProperty::AllProperties)
Refreshes a data defined property for the item by reevaluating the property's value and redrawing the...
QgsLayoutSize sizeWithUnits() const
Returns the item's current size, including units.
void paint(QPainter *painter, const QStyleOptionGraphicsItem *itemStyle, QWidget *pWidget) override
Handles preparing a paint surface for the layout item and painting the item's content.
virtual void redraw()
Triggers a redraw (update) of the item.
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
virtual void attemptResize(const QgsLayoutSize &size, bool includesFrame=false)
Attempts to resize the item to a specified target size.
@ FlagOverridesPaint
Item overrides the default layout item painting method.
virtual void invalidateCache()
Forces a deferred update of any cached image the item uses.
virtual QString uuid() const
Returns the item identification string.
QString id() const
Returns the item's ID name.
ExportLayerBehavior
Behavior of item when exporting to layered outputs.
@ MustPlaceInOwnLayer
Item must be placed in its own individual layer.
QFlags< Flag > Flags
void refresh() override
Refreshes the item, causing a recalculation of any property overrides and recalculation of its positi...
QPainter::CompositionMode blendMode() const
Returns the item's composition blending mode.
QgsPropertyCollection mDataDefinedProperties
const QgsLayout * layout() const
Returns the layout the object is attached to.
void changed()
Emitted when the object's properties change.
QPointer< QgsLayout > mLayout
DataDefinedProperty
Data defined properties for different item types.
@ LegendAutoWrapWidth
Legend text automatic wrapping width.
@ LegendColumnCount
Legend column count.
@ AllProperties
All properties for item.
@ FlagUseAdvancedEffects
Enable advanced effects such as blend modes.
@ FlagSynchronousLegendGraphics
Query legend graphics synchronously.
Provides a method of storing sizes, consisting of a width and height, for use in QGIS layouts.
static QgsRenderContext createRenderContextForLayout(QgsLayout *layout, QPainter *painter, double dpi=-1)
Creates a render context suitable for the specified layout and painter destination.
static QgsRenderContext createRenderContextForMap(QgsLayoutItemMap *map, QPainter *painter, double dpi=-1)
Creates a render context suitable for the specified layout map and painter destination.
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
Definition qgslayout.h:49
Item model implementation based on layer tree model for layout legend.
void clearCachedData(QgsLayerTreeNode *node) const
Clears any previously cached data for the specified node.
void refreshLegend()
Emitted to refresh the legend.
QgsLegendModel(QgsLayerTree *rootNode, QObject *parent=nullptr, QgsLayoutItemLegend *layout=nullptr)
Construct the model based on the given layer tree.
QVariant data(const QModelIndex &index, int role) const override
QList< QgsLayerTreeModelLegendNode * > layerLegendNodes(QgsLayerTreeLayer *nodeLayer, bool skipNodeEmbeddedInParent=false) const
Returns filtered list of active legend nodes attached to a particular layer node (by default it retur...
bool isNull() const
Returns true if the patch shape is a null QgsLegendPatchShape, which indicates that the default legen...
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.
void setLegendSize(QSizeF s)
Sets the preferred resulting legend size.
Q_DECL_DEPRECATED void drawLegend(QPainter *painter)
Draws the legend with given painter.
void setSymbolAlignment(Qt::AlignmentFlag alignment)
Sets the alignment for placement of legend symbols.
QString wrapChar() const
Returns the string used as a wrapping character.
Q_DECL_DEPRECATED void setFontColor(const QColor &c)
Sets the font color used for legend items.
void setWrapChar(const QString &t)
Sets a string to use as a wrapping character.
void setRasterStrokeColor(const QColor &color)
Sets the stroke color for the stroke drawn around raster symbol items.
void setColumnSpace(double s)
Sets the margin space between adjacent columns (in millimeters).
QgsLegendStyle & rstyle(Qgis::LegendComponent s)
Returns modifiable reference to the style for a legend component.
Q_DECL_DEPRECATED void setMapScale(double scale)
Sets the legend map scale.
void setTitle(const QString &t)
Sets the title for the legend, which will be rendered above all legend items.
bool drawRasterStroke() const
Returns whether a stroke will be drawn around raster symbol items.
void setDrawRasterStroke(bool enabled)
Sets whether a stroke will be drawn around raster symbol items.
QSizeF wmsLegendSize() const
Returns the size (in millimeters) of WMS legend graphics shown in the legend.
double minimumSymbolSize() const
Returns the minimum symbol size (in mm).
double autoWrapLinesAfter() const
Returns the maximum line length (in millimeters) allowed before lines of text in the legend will be a...
double rasterStrokeWidth() const
Returns the stroke width (in millimeters) for the stroke drawn around raster symbol items.
Q_DECL_DEPRECATED void setLineSpacing(double s)
Sets the line spacing to use between lines of legend text.
void setColumnCount(int c)
Sets the desired minimum number of columns to show in the legend.
void setTitleAlignment(Qt::AlignmentFlag alignment)
Sets the alignment of the legend title.
Q_DECL_DEPRECATED void setMmPerMapUnit(double mmPerMapUnit)
Q_DECL_DEPRECATED void setDpi(int dpi)
void setStyle(Qgis::LegendComponent s, const QgsLegendStyle &style)
Sets the style for a legend component.
void setAutoWrapLinesAfter(double length)
Sets the maximum line length (in millimeters) allowed before lines of text in the legend will be auto...
Qt::AlignmentFlag titleAlignment() const
Returns the alignment of the legend title.
QSizeF symbolSize() const
Returns the default symbol size (in millimeters) used for legend items.
Q_DECL_DEPRECATED QColor fontColor() const
Returns the font color used for legend items.
double maximumSymbolSize() const
Returns the maximum symbol size (in mm).
QString title() const
Returns the title for the legend, which will be rendered above all legend items.
QColor rasterStrokeColor() const
Returns the stroke color for the stroke drawn around raster symbol items.
Q_DECL_DEPRECATED double lineSpacing() const
Returns the line spacing to use between lines of legend text.
Q_DECL_DEPRECATED void setUseAdvancedEffects(bool use)
void setSplitLayer(bool s)
Sets whether layer components can be split over multiple columns.
double columnSpace() const
Returns the margin space between adjacent columns (in millimeters).
QgsLegendStyle style(Qgis::LegendComponent s) const
Returns the style for a legend component.
void setEqualColumnWidth(bool s)
Sets whether all columns should have equal widths.
void setBoxSpace(double s)
Sets the legend box space (in millimeters), which is the empty margin around the inside of the legend...
void setSynchronousLegendRequests(bool b)
Sets whether to request legend graphics synchronously.
double boxSpace() const
Returns the legend box space (in millimeters), which is the empty margin around the inside of the leg...
void setMaximumSymbolSize(double size)
Set the maximum symbol size for symbol (in millimeters).
bool splitLayer() const
Returns true if layer components can be split over multiple columns.
void setMinimumSymbolSize(double size)
Set the minimum symbol size for symbol (in millimeters).
void setRasterStrokeWidth(double width)
Sets the stroke width for the stroke drawn around raster symbol items.
Qt::AlignmentFlag symbolAlignment() const
Returns the alignment for placement of legend symbols.
bool equalColumnWidth() const
Returns true if all columns should have equal widths.
void setSymbolSize(QSizeF s)
Sets the default symbol size (in millimeters) used for legend items.
void setWmsLegendSize(QSizeF s)
Sets the desired size (in millimeters) of WMS legend graphics shown in the legend.
Contains detailed styling information relating to how a layout legend should be rendered.
Q_DECL_DEPRECATED QFont font() const
Returns the font used for rendering this legend component.
QgsTextFormat & textFormat()
Returns the text format used for rendering this legend component.
void setMargin(Side side, double margin)
Sets the margin (in mm) for the specified side of the component.
Side
Margin sides.
void readXml(const QDomElement &elem, const QDomDocument &doc, const QgsReadWriteContext &context=QgsReadWriteContext())
Reads the component's style definition from an XML element.
Q_DECL_DEPRECATED void setFont(const QFont &font)
Sets the font used for rendering this legend component.
void writeXml(const QString &name, QDomElement &elem, QDomDocument &doc, const QgsReadWriteContext &context=QgsReadWriteContext()) const
Writes the component's style definition to an XML element.
void setTextFormat(const QgsTextFormat &format)
Sets the text format used for rendering this legend component.
Base class for all map layer types.
Definition qgsmaplayer.h:77
Contains configuration for rendering maps.
double scale() const
Returns the calculated map scale.
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
QgsCoordinateReferenceSystem destinationCrs() const
Returns the destination coordinate reference system for the map render.
void projectColorsChanged()
Emitted whenever the project's color scheme has been changed.
A container for the context for various read/write operations on objects.
A rectangle specified with double values.
A QgsGeometry with associated coordinate reference system.
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.
void setFlag(Qgis::RenderContextFlag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
Scoped object for saving and restoring a QPainter object's state.
An interface for classes which can visit style entity (e.g.
virtual bool visit(const QgsStyleEntityVisitorInterface::StyleLeaf &entity)
Called when the visitor will visit a style entity.
A legend patch shape entity for QgsStyle databases.
Definition qgsstyle.h:1520
Implementation of legend node interface for displaying preview of vector symbols and their labels and...
Container for all settings relating to text rendering.
void setColor(const QColor &color)
Sets the color that text will be rendered in.
void setLineHeightUnit(Qgis::RenderUnit unit)
Sets the unit for the line height for text.
double size() const
Returns the size for rendered text.
void setLineHeight(double height)
Sets the line height for text.
Represents a vector layer which manages a vector based dataset.
long long featureCount(const QString &legendKey) const
Number of features rendered with specified legend key.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
#define Q_NOWARN_DEPRECATED_POP
Definition qgis.h:6820
#define Q_NOWARN_DEPRECATED_PUSH
Definition qgis.h:6819
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:41
Single variable definition for use within a QgsExpressionContextScope.
Structure that stores all data associated with one map layer.
Contains information relating to the style entity currently being visited.