QGIS API Documentation  3.9.0-Master (8986ea2301)
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 "qgslayoutitemregistry.h"
21 #include "qgslayoutitemmap.h"
22 #include "qgslayout.h"
23 #include "qgslayoutmodel.h"
24 #include "qgslayertree.h"
25 #include "qgslayertreemodel.h"
26 #include "qgslegendrenderer.h"
27 #include "qgslegendstyle.h"
28 #include "qgslogger.h"
29 #include "qgsmapsettings.h"
30 #include "qgsproject.h"
31 #include "qgssymbollayerutils.h"
32 #include "qgslayertreeutils.h"
33 #include "qgslayoututils.h"
34 #include <QDomDocument>
35 #include <QDomElement>
36 #include <QPainter>
37 #include "qgsexpressioncontext.h"
38 
40  : QgsLayoutItem( layout )
41  , mLegendModel( new QgsLegendModel( layout->project()->layerTreeRoot(), this ) )
42 {
43 #if 0 //no longer required?
44  connect( &layout->atlasComposition(), &QgsAtlasComposition::renderEnded, this, &QgsLayoutItemLegend::onAtlasEnded );
45 #endif
46 
47  mTitle = mSettings.title();
48 
49  // Connect to the main layertreeroot.
50  // It serves in "auto update mode" as a medium between the main app legend and this one
51  connect( mLayout->project()->layerTreeRoot(), &QgsLayerTreeNode::customPropertyChanged, this, &QgsLayoutItemLegend::nodeCustomPropertyChanged );
52 
53  // If project colors change, we need to redraw legend, as legend symbols may rely on project colors
54  connect( mLayout->project(), &QgsProject::projectColorsChanged, this, [ = ]
55  {
57  update();
58  } );
59  connect( mLegendModel.get(), &QgsLegendModel::refreshLegend, this, &QgsLayoutItemLegend::refresh );
60 }
61 
63 {
64  return new QgsLayoutItemLegend( layout );
65 }
66 
68 {
70 }
71 
73 {
74  return QgsApplication::getThemeIcon( QStringLiteral( "/mLayoutItemLegend.svg" ) );
75 }
76 
77 QgsLayoutItem::Flags QgsLayoutItemLegend::itemFlags() const
78 {
80 }
81 
82 void QgsLayoutItemLegend::paint( QPainter *painter, const QStyleOptionGraphicsItem *itemStyle, QWidget *pWidget )
83 {
84  if ( !painter )
85  return;
86 
87  if ( mFilterAskedForUpdate )
88  {
89  mFilterAskedForUpdate = false;
90  doUpdateFilterByMap();
91  }
92 
93  int dpi = painter->device()->logicalDpiX();
94  double dotsPerMM = dpi / 25.4;
95 
96  if ( mLayout )
97  {
99  mSettings.setDpi( dpi );
100  }
101  if ( mMap && mLayout )
102  {
103  mSettings.setMmPerMapUnit( mLayout->convertFromLayoutUnits( mMap->mapUnitsToLayoutUnits(), QgsUnitTypes::LayoutMillimeters ).length() );
104 
105  // use a temporary QgsMapSettings to find out real map scale
106  QSizeF mapSizePixels = QSizeF( mMap->rect().width() * dotsPerMM, mMap->rect().height() * dotsPerMM );
107  QgsRectangle mapExtent = mMap->extent();
108 
109  QgsMapSettings ms = mMap->mapSettings( mapExtent, mapSizePixels, dpi, false );
110  mSettings.setMapScale( ms.scale() );
111  }
112  mInitialMapScaleCalculated = true;
113 
114  QgsLegendRenderer legendRenderer( mLegendModel.get(), mSettings );
115  legendRenderer.setLegendSize( mForceResize && mSizeToContents ? QSize() : rect().size() );
116 
117  //adjust box if width or height is too small
118  if ( mSizeToContents )
119  {
121  QSizeF size = legendRenderer.minimumSize( &context );
122  if ( mForceResize )
123  {
124  mForceResize = false;
125 
126  //set new rect, respecting position mode and data defined size/position
127  QgsLayoutSize newSize = mLayout->convertFromLayoutUnits( size, sizeWithUnits().units() );
128  attemptResize( newSize );
129  }
130  else if ( size.height() > rect().height() || size.width() > rect().width() )
131  {
132  //need to resize box
133  QSizeF targetSize = rect().size();
134  if ( size.height() > targetSize.height() )
135  targetSize.setHeight( size.height() );
136  if ( size.width() > targetSize.width() )
137  targetSize.setWidth( size.width() );
138 
139  QgsLayoutSize newSize = mLayout->convertFromLayoutUnits( targetSize, sizeWithUnits().units() );
140  //set new rect, respecting position mode and data defined size/position
141  attemptResize( newSize );
142  }
143  }
144 
145  QgsLayoutItem::paint( painter, itemStyle, pWidget );
146 }
147 
149 {
150  if ( !mMapUuid.isEmpty() )
151  {
152  setLinkedMap( qobject_cast< QgsLayoutItemMap * >( mLayout->itemByUuid( mMapUuid, true ) ) );
153  }
154 }
155 
157 {
159  onAtlasFeature();
160 }
161 
163 {
164  QPainter *painter = context.renderContext().painter();
165  painter->save();
166 
167  // painter is scaled to dots, so scale back to layout units
168  painter->scale( context.renderContext().scaleFactor(), context.renderContext().scaleFactor() );
169 
170  painter->setPen( QPen( QColor( 0, 0, 0 ) ) );
171 
172  if ( !mSizeToContents )
173  {
174  // set a clip region to crop out parts of legend which don't fit
175  QRectF thisPaintRect = QRectF( 0, 0, rect().width(), rect().height() );
176  painter->setClipRect( thisPaintRect );
177  }
178 
179  QgsLegendRenderer legendRenderer( mLegendModel.get(), mSettings );
180  legendRenderer.setLegendSize( rect().size() );
181 
182  legendRenderer.drawLegend( context.renderContext() );
183 
184  painter->restore();
185 }
186 
188 {
189  if ( !mSizeToContents )
190  return;
191 
192  if ( !mInitialMapScaleCalculated )
193  {
194  // this is messy - but until we have painted the item we have no knowledge of the current DPI
195  // and so cannot correctly calculate the map scale. This results in incorrect size calculations
196  // for marker symbols with size in map units, causing the legends to initially expand to huge
197  // sizes if we attempt to calculate the box size first.
198  return;
199  }
200 
202  QgsLegendRenderer legendRenderer( mLegendModel.get(), mSettings );
203  QSizeF size = legendRenderer.minimumSize( &context );
204  QgsDebugMsg( QStringLiteral( "width = %1 height = %2" ).arg( size.width() ).arg( size.height() ) );
205  if ( size.isValid() )
206  {
207  QgsLayoutSize newSize = mLayout->convertFromLayoutUnits( size, sizeWithUnits().units() );
208  //set new rect, respecting position mode and data defined size/position
209  attemptResize( newSize );
210  }
211 }
212 
214 {
215  mSizeToContents = enabled;
216 }
217 
219 {
220  return mSizeToContents;
221 }
222 
223 void QgsLayoutItemLegend::setCustomLayerTree( QgsLayerTree *rootGroup )
224 {
225  mLegendModel->setRootGroup( rootGroup ? rootGroup : ( mLayout ? mLayout->project()->layerTreeRoot() : nullptr ) );
226 
227  mCustomLayerTree.reset( rootGroup );
228 }
229 
230 
232 {
233  if ( autoUpdate == autoUpdateModel() )
234  return;
235 
236  setCustomLayerTree( autoUpdate ? nullptr : mLayout->project()->layerTreeRoot()->clone() );
237  adjustBoxSize();
238  updateFilterByMap( false );
239 }
240 
241 void QgsLayoutItemLegend::nodeCustomPropertyChanged( QgsLayerTreeNode *, const QString & )
242 {
243  if ( autoUpdateModel() )
244  {
245  // in "auto update" mode, some parameters on the main app legend may have been changed (expression filtering)
246  // we must then call updateItem to reflect the changes
247  updateFilterByMap( false );
248  }
249 }
250 
252 {
253  return !mCustomLayerTree;
254 }
255 
257 {
258  mLegendFilterByMap = enabled;
259  updateFilterByMap( false );
260 }
261 
262 void QgsLayoutItemLegend::setTitle( const QString &t )
263 {
264  mTitle = t;
265  mSettings.setTitle( t );
266 
267  if ( mLayout && id().isEmpty() )
268  {
269  //notify the model that the display name has changed
270  mLayout->itemsModel()->updateItemDisplayName( this );
271  }
272 }
274 {
275  return mTitle;
276 }
277 
278 Qt::AlignmentFlag QgsLayoutItemLegend::titleAlignment() const
279 {
280  return mSettings.titleAlignment();
281 }
282 
283 void QgsLayoutItemLegend::setTitleAlignment( Qt::AlignmentFlag alignment )
284 {
285  mSettings.setTitleAlignment( alignment );
286 }
287 
289 {
290  return mSettings.rstyle( s );
291 }
292 
294 {
295  return mSettings.style( s );
296 }
297 
299 {
300  mSettings.setStyle( s, style );
301 }
302 
304 {
305  return mSettings.style( s ).font();
306 }
307 
309 {
310  rstyle( s ).setFont( f );
311 }
312 
314 {
315  rstyle( s ).setMargin( margin );
316 }
317 
319 {
320  rstyle( s ).setMargin( side, margin );
321 }
322 
324 {
325  return mSettings.lineSpacing();
326 }
327 
329 {
330  mSettings.setLineSpacing( spacing );
331 }
332 
334 {
335  return mSettings.boxSpace();
336 }
337 
339 {
340  mSettings.setBoxSpace( s );
341 }
342 
344 {
345  return mSettings.columnSpace();
346 }
347 
349 {
350  mSettings.setColumnSpace( s );
351 }
352 
354 {
355  return mSettings.fontColor();
356 }
357 
359 {
360  mSettings.setFontColor( c );
361 }
362 
364 {
365  return mSettings.symbolSize().width();
366 }
367 
369 {
370  mSettings.setSymbolSize( QSizeF( w, mSettings.symbolSize().height() ) );
371 }
372 
373 void QgsLayoutItemLegend::setSymbolAlignment( Qt::AlignmentFlag alignment )
374 {
375  mSettings.setSymbolAlignment( alignment );
376 }
377 
378 Qt::AlignmentFlag QgsLayoutItemLegend::symbolAlignment() const
379 {
380  return mSettings.symbolAlignment();
381 }
382 
384 {
385  return mSettings.symbolSize().height();
386 }
387 
389 {
390  mSettings.setSymbolSize( QSizeF( mSettings.symbolSize().width(), h ) );
391 }
392 
394 {
395  return mSettings.wmsLegendSize().width();
396 }
397 
399 {
400  mSettings.setWmsLegendSize( QSizeF( w, mSettings.wmsLegendSize().height() ) );
401 }
402 
404 {
405  return mSettings.wmsLegendSize().height();
406 }
408 {
409  mSettings.setWmsLegendSize( QSizeF( mSettings.wmsLegendSize().width(), h ) );
410 }
411 
412 void QgsLayoutItemLegend::setWrapString( const QString &t )
413 {
414  mSettings.setWrapChar( t );
415 }
416 
418 {
419  return mSettings.wrapChar();
420 }
421 
423 {
424  return mColumnCount;
425 }
426 
428 {
429  mColumnCount = c;
430  mSettings.setColumnCount( c );
431 }
432 
434 {
435  return mSettings.splitLayer();
436 }
437 
439 {
440  mSettings.setSplitLayer( s );
441 }
442 
444 {
445  return mSettings.equalColumnWidth();
446 }
447 
449 {
450  mSettings.setEqualColumnWidth( s );
451 }
452 
454 {
455  return mSettings.drawRasterStroke();
456 }
457 
459 {
460  mSettings.setDrawRasterStroke( enabled );
461 }
462 
464 {
465  return mSettings.rasterStrokeColor();
466 }
467 
468 void QgsLayoutItemLegend::setRasterStrokeColor( const QColor &color )
469 {
470  mSettings.setRasterStrokeColor( color );
471 }
472 
474 {
475  return mSettings.rasterStrokeWidth();
476 }
477 
479 {
480  mSettings.setRasterStrokeWidth( width );
481 }
482 
483 
485 {
486  adjustBoxSize();
487  updateFilterByMap( false );
488 }
489 
490 bool QgsLayoutItemLegend::writePropertiesToElement( QDomElement &legendElem, QDomDocument &doc, const QgsReadWriteContext &context ) const
491 {
492 
493  //write general properties
494  legendElem.setAttribute( QStringLiteral( "title" ), mTitle );
495  legendElem.setAttribute( QStringLiteral( "titleAlignment" ), QString::number( static_cast< int >( mSettings.titleAlignment() ) ) );
496  legendElem.setAttribute( QStringLiteral( "columnCount" ), QString::number( mColumnCount ) );
497  legendElem.setAttribute( QStringLiteral( "splitLayer" ), QString::number( mSettings.splitLayer() ) );
498  legendElem.setAttribute( QStringLiteral( "equalColumnWidth" ), QString::number( mSettings.equalColumnWidth() ) );
499 
500  legendElem.setAttribute( QStringLiteral( "boxSpace" ), QString::number( mSettings.boxSpace() ) );
501  legendElem.setAttribute( QStringLiteral( "columnSpace" ), QString::number( mSettings.columnSpace() ) );
502 
503  legendElem.setAttribute( QStringLiteral( "symbolWidth" ), QString::number( mSettings.symbolSize().width() ) );
504  legendElem.setAttribute( QStringLiteral( "symbolHeight" ), QString::number( mSettings.symbolSize().height() ) );
505 
506  legendElem.setAttribute( QStringLiteral( "symbolAlignment" ), mSettings.symbolAlignment() );
507 
508  legendElem.setAttribute( QStringLiteral( "symbolAlignment" ), mSettings.symbolAlignment() );
509  legendElem.setAttribute( QStringLiteral( "lineSpacing" ), QString::number( mSettings.lineSpacing() ) );
510 
511  legendElem.setAttribute( QStringLiteral( "rasterBorder" ), mSettings.drawRasterStroke() );
512  legendElem.setAttribute( QStringLiteral( "rasterBorderColor" ), QgsSymbolLayerUtils::encodeColor( mSettings.rasterStrokeColor() ) );
513  legendElem.setAttribute( QStringLiteral( "rasterBorderWidth" ), QString::number( mSettings.rasterStrokeWidth() ) );
514 
515  legendElem.setAttribute( QStringLiteral( "wmsLegendWidth" ), QString::number( mSettings.wmsLegendSize().width() ) );
516  legendElem.setAttribute( QStringLiteral( "wmsLegendHeight" ), QString::number( mSettings.wmsLegendSize().height() ) );
517  legendElem.setAttribute( QStringLiteral( "wrapChar" ), mSettings.wrapChar() );
518  legendElem.setAttribute( QStringLiteral( "fontColor" ), mSettings.fontColor().name() );
519 
520  legendElem.setAttribute( QStringLiteral( "resizeToContents" ), mSizeToContents );
521 
522  if ( mMap )
523  {
524  legendElem.setAttribute( QStringLiteral( "map_uuid" ), mMap->uuid() );
525  }
526 
527  QDomElement legendStyles = doc.createElement( QStringLiteral( "styles" ) );
528  legendElem.appendChild( legendStyles );
529 
530  style( QgsLegendStyle::Title ).writeXml( QStringLiteral( "title" ), legendStyles, doc );
531  style( QgsLegendStyle::Group ).writeXml( QStringLiteral( "group" ), legendStyles, doc );
532  style( QgsLegendStyle::Subgroup ).writeXml( QStringLiteral( "subgroup" ), legendStyles, doc );
533  style( QgsLegendStyle::Symbol ).writeXml( QStringLiteral( "symbol" ), legendStyles, doc );
534  style( QgsLegendStyle::SymbolLabel ).writeXml( QStringLiteral( "symbolLabel" ), legendStyles, doc );
535 
536  if ( mCustomLayerTree )
537  {
538  // if not using auto-update - store the custom layer tree
539  mCustomLayerTree->writeXml( legendElem, context );
540  }
541 
542  if ( mLegendFilterByMap )
543  {
544  legendElem.setAttribute( QStringLiteral( "legendFilterByMap" ), QStringLiteral( "1" ) );
545  }
546  legendElem.setAttribute( QStringLiteral( "legendFilterByAtlas" ), mFilterOutAtlas ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
547 
548  return true;
549 }
550 
551 bool QgsLayoutItemLegend::readPropertiesFromElement( const QDomElement &itemElem, const QDomDocument &doc, const QgsReadWriteContext &context )
552 {
553  //read general properties
554  mTitle = itemElem.attribute( QStringLiteral( "title" ) );
555  mSettings.setTitle( mTitle );
556  if ( !itemElem.attribute( QStringLiteral( "titleAlignment" ) ).isEmpty() )
557  {
558  mSettings.setTitleAlignment( static_cast< Qt::AlignmentFlag >( itemElem.attribute( QStringLiteral( "titleAlignment" ) ).toInt() ) );
559  }
560  int colCount = itemElem.attribute( QStringLiteral( "columnCount" ), QStringLiteral( "1" ) ).toInt();
561  if ( colCount < 1 ) colCount = 1;
562  mColumnCount = colCount;
563  mSettings.setColumnCount( mColumnCount );
564  mSettings.setSplitLayer( itemElem.attribute( QStringLiteral( "splitLayer" ), QStringLiteral( "0" ) ).toInt() == 1 );
565  mSettings.setEqualColumnWidth( itemElem.attribute( QStringLiteral( "equalColumnWidth" ), QStringLiteral( "0" ) ).toInt() == 1 );
566 
567  QDomNodeList stylesNodeList = itemElem.elementsByTagName( QStringLiteral( "styles" ) );
568  if ( !stylesNodeList.isEmpty() )
569  {
570  QDomNode stylesNode = stylesNodeList.at( 0 );
571  for ( int i = 0; i < stylesNode.childNodes().size(); i++ )
572  {
573  QDomElement styleElem = stylesNode.childNodes().at( i ).toElement();
575  style.readXml( styleElem, doc );
576  QString name = styleElem.attribute( QStringLiteral( "name" ) );
578  if ( name == QLatin1String( "title" ) ) s = QgsLegendStyle::Title;
579  else if ( name == QLatin1String( "group" ) ) s = QgsLegendStyle::Group;
580  else if ( name == QLatin1String( "subgroup" ) ) s = QgsLegendStyle::Subgroup;
581  else if ( name == QLatin1String( "symbol" ) ) s = QgsLegendStyle::Symbol;
582  else if ( name == QLatin1String( "symbolLabel" ) ) s = QgsLegendStyle::SymbolLabel;
583  else continue;
584  setStyle( s, style );
585  }
586  }
587 
588  //font color
589  QColor fontClr;
590  fontClr.setNamedColor( itemElem.attribute( QStringLiteral( "fontColor" ), QStringLiteral( "#000000" ) ) );
591  mSettings.setFontColor( fontClr );
592 
593  //spaces
594  mSettings.setBoxSpace( itemElem.attribute( QStringLiteral( "boxSpace" ), QStringLiteral( "2.0" ) ).toDouble() );
595  mSettings.setColumnSpace( itemElem.attribute( QStringLiteral( "columnSpace" ), QStringLiteral( "2.0" ) ).toDouble() );
596 
597  mSettings.setSymbolSize( QSizeF( itemElem.attribute( QStringLiteral( "symbolWidth" ), QStringLiteral( "7.0" ) ).toDouble(), itemElem.attribute( QStringLiteral( "symbolHeight" ), QStringLiteral( "14.0" ) ).toDouble() ) );
598  mSettings.setSymbolAlignment( static_cast< Qt::AlignmentFlag >( itemElem.attribute( QStringLiteral( "symbolAlignment" ), QString::number( Qt::AlignLeft ) ).toInt() ) );
599 
600  mSettings.setWmsLegendSize( QSizeF( itemElem.attribute( QStringLiteral( "wmsLegendWidth" ), QStringLiteral( "50" ) ).toDouble(), itemElem.attribute( QStringLiteral( "wmsLegendHeight" ), QStringLiteral( "25" ) ).toDouble() ) );
601  mSettings.setLineSpacing( itemElem.attribute( QStringLiteral( "lineSpacing" ), QStringLiteral( "1.0" ) ).toDouble() );
602 
603  mSettings.setDrawRasterStroke( itemElem.attribute( QStringLiteral( "rasterBorder" ), QStringLiteral( "1" ) ) != QLatin1String( "0" ) );
604  mSettings.setRasterStrokeColor( QgsSymbolLayerUtils::decodeColor( itemElem.attribute( QStringLiteral( "rasterBorderColor" ), QStringLiteral( "0,0,0" ) ) ) );
605  mSettings.setRasterStrokeWidth( itemElem.attribute( QStringLiteral( "rasterBorderWidth" ), QStringLiteral( "0" ) ).toDouble() );
606 
607  mSettings.setWrapChar( itemElem.attribute( QStringLiteral( "wrapChar" ) ) );
608 
609  mSizeToContents = itemElem.attribute( QStringLiteral( "resizeToContents" ), QStringLiteral( "1" ) ) != QLatin1String( "0" );
610 
611  // map
612  mLegendFilterByMap = itemElem.attribute( QStringLiteral( "legendFilterByMap" ), QStringLiteral( "0" ) ).toInt();
613 
614  mMapUuid.clear();
615  if ( !itemElem.attribute( QStringLiteral( "map_uuid" ) ).isEmpty() )
616  {
617  mMapUuid = itemElem.attribute( QStringLiteral( "map_uuid" ) );
618  }
619  // disconnect current map
620  setupMapConnections( mMap, false );
621  mMap = nullptr;
622 
623  mFilterOutAtlas = itemElem.attribute( QStringLiteral( "legendFilterByAtlas" ), QStringLiteral( "0" ) ).toInt();
624 
625  // QGIS >= 2.6
626  QDomElement layerTreeElem = itemElem.firstChildElement( QStringLiteral( "layer-tree" ) );
627  if ( layerTreeElem.isNull() )
628  layerTreeElem = itemElem.firstChildElement( QStringLiteral( "layer-tree-group" ) );
629 
630  if ( !layerTreeElem.isNull() )
631  {
632  std::unique_ptr< QgsLayerTree > tree( QgsLayerTree::readXml( layerTreeElem, context ) );
633  if ( mLayout )
634  tree->resolveReferences( mLayout->project(), true );
635  setCustomLayerTree( tree.release() );
636  }
637  else
638  setCustomLayerTree( nullptr );
639 
640  return true;
641 }
642 
644 {
645  if ( !id().isEmpty() )
646  {
647  return id();
648  }
649 
650  //if no id, default to portion of title text
651  QString text = mSettings.title();
652  if ( text.isEmpty() )
653  {
654  return tr( "<Legend>" );
655  }
656  if ( text.length() > 25 )
657  {
658  return tr( "%1…" ).arg( text.left( 25 ) );
659  }
660  else
661  {
662  return text;
663  }
664 }
665 
666 
667 void QgsLayoutItemLegend::setupMapConnections( QgsLayoutItemMap *map, bool connectSlots )
668 {
669  if ( !map )
670  return;
671 
672  if ( !connectSlots )
673  {
674  disconnect( map, &QObject::destroyed, this, &QgsLayoutItemLegend::invalidateCurrentMap );
675  disconnect( map, &QgsLayoutObject::changed, this, &QgsLayoutItemLegend::updateFilterByMapAndRedraw );
676  disconnect( map, &QgsLayoutItemMap::extentChanged, this, &QgsLayoutItemLegend::updateFilterByMapAndRedraw );
677  disconnect( map, &QgsLayoutItemMap::layerStyleOverridesChanged, this, &QgsLayoutItemLegend::mapLayerStyleOverridesChanged );
678  }
679  else
680  {
681  connect( map, &QObject::destroyed, this, &QgsLayoutItemLegend::invalidateCurrentMap );
682  connect( map, &QgsLayoutObject::changed, this, &QgsLayoutItemLegend::updateFilterByMapAndRedraw );
683  connect( map, &QgsLayoutItemMap::extentChanged, this, &QgsLayoutItemLegend::updateFilterByMapAndRedraw );
684  connect( map, &QgsLayoutItemMap::layerStyleOverridesChanged, this, &QgsLayoutItemLegend::mapLayerStyleOverridesChanged );
685  }
686 }
687 
689 {
690  if ( mMap )
691  {
692  setupMapConnections( mMap, false );
693  }
694 
695  mMap = map;
696 
697  if ( mMap )
698  {
699  setupMapConnections( mMap, true );
700  }
701 
703 
704 }
705 
706 void QgsLayoutItemLegend::invalidateCurrentMap()
707 {
708  setLinkedMap( nullptr );
709 }
710 
712 {
714 
715  bool forceUpdate = false;
716  //updates data defined properties and redraws item to match
717  if ( property == QgsLayoutObject::LegendTitle || property == QgsLayoutObject::AllProperties )
718  {
719  bool ok = false;
720  QString t = mDataDefinedProperties.valueAsString( QgsLayoutObject::LegendTitle, context, mTitle, &ok );
721  if ( ok )
722  {
723  mSettings.setTitle( t );
724  forceUpdate = true;
725  }
726  }
728  {
729  bool ok = false;
730  int cols = mDataDefinedProperties.valueAsInt( QgsLayoutObject::LegendColumnCount, context, mColumnCount, &ok );
731  if ( ok && cols >= 0 )
732  {
733  mSettings.setColumnCount( cols );
734  forceUpdate = true;
735  }
736  }
737  if ( forceUpdate )
738  {
739  adjustBoxSize();
740  update();
741  }
742 
744 }
745 
746 
747 void QgsLayoutItemLegend::updateFilterByMapAndRedraw()
748 {
749  updateFilterByMap( true );
750 }
751 
752 void QgsLayoutItemLegend::mapLayerStyleOverridesChanged()
753 {
754  if ( !mMap )
755  return;
756 
757  // map's style has been changed, so make sure to update the legend here
758  if ( mLegendFilterByMap )
759  {
760  // legend is being filtered by map, so we need to re run the hit test too
761  // as the style overrides may also have affected the visible symbols
762  updateFilterByMap( false );
763  }
764  else
765  {
766  mLegendModel->setLayerStyleOverrides( mMap->layerStyleOverrides() );
767  const QList< QgsLayerTreeLayer * > layers = mLegendModel->rootGroup()->findLayers();
768  for ( QgsLayerTreeLayer *nodeLayer : layers )
769  mLegendModel->refreshLayerLegend( nodeLayer );
770  }
771 
772  adjustBoxSize();
773  updateFilterByMap( false );
774 }
775 
777 {
778  // ask for update
779  // the actual update will take place before the redraw.
780  // This is to avoid multiple calls to the filter
781  mFilterAskedForUpdate = true;
782 
783  if ( redraw )
784  update();
785 }
786 
787 void QgsLayoutItemLegend::doUpdateFilterByMap()
788 {
789  if ( mMap )
790  mLegendModel->setLayerStyleOverrides( mMap->layerStyleOverrides() );
791  else
792  mLegendModel->setLayerStyleOverrides( QMap<QString, QString>() );
793 
794 
795  bool filterByExpression = QgsLayerTreeUtils::hasLegendFilterExpression( *( mCustomLayerTree ? mCustomLayerTree.get() : mLayout->project()->layerTreeRoot() ) );
796 
797  if ( mMap && ( mLegendFilterByMap || filterByExpression || mInAtlas ) )
798  {
799  double dpi = mLayout->renderContext().dpi();
800 
801  QgsRectangle requestRectangle = mMap->requestedExtent();
802 
803  QSizeF size( requestRectangle.width(), requestRectangle.height() );
804  size *= mLayout->convertFromLayoutUnits( mMap->mapUnitsToLayoutUnits(), QgsUnitTypes::LayoutMillimeters ).length() * dpi / 25.4;
805 
806  QgsMapSettings ms = mMap->mapSettings( requestRectangle, size, dpi, true );
807 
808  QgsGeometry filterPolygon;
809  if ( mInAtlas )
810  {
811  filterPolygon = mLayout->reportContext().currentGeometry( mMap->crs() );
812  }
813  mLegendModel->setLegendFilter( &ms, /* useExtent */ mInAtlas || mLegendFilterByMap, filterPolygon, /* useExpressions */ true );
814  }
815  else
816  mLegendModel->setLegendFilterByMap( nullptr );
817 
818  mForceResize = true;
819 }
820 
822 {
823  mFilterOutAtlas = doFilter;
824 }
825 
827 {
828  return mFilterOutAtlas;
829 }
830 
831 void QgsLayoutItemLegend::onAtlasFeature()
832 {
833  if ( !mLayout->reportContext().feature().isValid() )
834  return;
835  mInAtlas = mFilterOutAtlas;
837 }
838 
839 void QgsLayoutItemLegend::onAtlasEnded()
840 {
841  mInAtlas = false;
843 }
844 
846 {
848 
849  // We only want the last scope from the map's expression context, as this contains
850  // the map specific variables. We don't want the rest of the map's context, because that
851  // will contain duplicate global, project, layout, etc scopes.
852  if ( mMap )
853  context.appendScope( mMap->createExpressionContext().popScope() );
854 
855  QgsExpressionContextScope *scope = new QgsExpressionContextScope( tr( "Legend Settings" ) );
856 
857  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "legend_title" ), title(), true ) );
858  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "legend_column_count" ), columnCount(), true ) );
859  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "legend_split_layers" ), splitLayer(), true ) );
860  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "legend_wrap_string" ), wrapString(), true ) );
861  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "legend_filter_by_map" ), legendFilterByMapEnabled(), true ) );
862  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "legend_filter_out_atlas" ), legendFilterOutAtlas(), true ) );
863 
864  context.appendScope( scope );
865  return context;
866 }
867 
868 
869 // -------------------------------------------------------------------------
871 #include "qgsvectorlayer.h"
872 #include "qgsmaplayerlegend.h"
873 
875  : QgsLayerTreeModel( rootNode, parent )
876  , mLayoutLegend( layout )
877 {
880 }
881 
883  : QgsLayerTreeModel( rootNode )
884  , mLayoutLegend( layout )
885 {
888 }
889 
890 QVariant QgsLegendModel::data( const QModelIndex &index, int role ) const
891 {
892  // handle custom layer node labels
893 
894  QgsLayerTreeNode *node = index2node( index );
895  QgsLayerTreeLayer *nodeLayer = QgsLayerTree::isLayer( node ) ? QgsLayerTree::toLayer( node ) : nullptr;
896  if ( nodeLayer && ( role == Qt::DisplayRole || role == Qt::EditRole ) )
897  {
898  QString name;
899  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( nodeLayer->layer() );
900 
901  //finding the first label that is stored
902  name = nodeLayer->customProperty( QStringLiteral( "legend/title-label" ) ).toString();
903  if ( name.isEmpty() )
904  name = nodeLayer->name();
905  if ( name.isEmpty() )
906  name = node->customProperty( QStringLiteral( "legend/title-label" ) ).toString();
907  if ( name.isEmpty() )
908  name = node->name();
909  if ( nodeLayer->customProperty( QStringLiteral( "showFeatureCount" ), 0 ).toInt() )
910  {
911  if ( vlayer && vlayer->featureCount() >= 0 )
912  {
913  name += QStringLiteral( " [%1]" ).arg( vlayer->featureCount() );
914  return name;
915  }
916  }
917 
918  bool evaluate = vlayer ? !nodeLayer->labelExpression().isEmpty() : false;
919 
920  if ( evaluate || name.contains( "[%" ) )
921  {
922  QgsExpressionContext expressionContext;
923  if ( vlayer )
924  {
925  connect( vlayer, &QgsVectorLayer::symbolFeatureCountMapChanged, this, &QgsLegendModel::forceRefresh, Qt::UniqueConnection );
926  // counting is done here to ensure that a valid vector layer needs to be evaluated, count is used to validate previous count or update the count if invalidated
927  vlayer->countSymbolFeatures();
928  }
929 
930  if ( mLayoutLegend )
931  expressionContext = mLayoutLegend->createExpressionContext();
932  else
933  expressionContext = QgsExpressionContext();
934 
935  const QList<QgsLayerTreeModelLegendNode *> legendnodes = layerLegendNodes( nodeLayer, false );
936  if ( legendnodes.count() > 1 ) // evaluate all existing legend nodes but leave the name for the legend evaluator
937  {
938  for ( QgsLayerTreeModelLegendNode *treenode : legendnodes )
939  {
940  if ( QgsSymbolLegendNode *symnode = qobject_cast<QgsSymbolLegendNode *>( treenode ) )
941  symnode->evaluateLabel( expressionContext );
942  }
943  }
944  else if ( QgsSymbolLegendNode *symnode = qobject_cast<QgsSymbolLegendNode *>( legendnodes.first() ) )
945  name = symnode->evaluateLabel( expressionContext, name );
946  }
947  return name;
948  }
949  return QgsLayerTreeModel::data( index, role );
950 }
951 
952 Qt::ItemFlags QgsLegendModel::flags( const QModelIndex &index ) const
953 {
954  // make the legend nodes selectable even if they are not by default
955  if ( index2legendNode( index ) )
956  return QgsLayerTreeModel::flags( index ) | Qt::ItemIsSelectable;
957 
958  return QgsLayerTreeModel::flags( index );
959 }
960 
961 QList<QgsLayerTreeModelLegendNode *> QgsLegendModel::layerLegendNodes( QgsLayerTreeLayer *nodeLayer, bool skipNodeEmbeddedInParent ) const
962 {
963  if ( !mLegend.contains( nodeLayer ) )
964  return QList<QgsLayerTreeModelLegendNode *>();
965 
966  const LayerLegendData &data = mLegend[nodeLayer];
967  QList<QgsLayerTreeModelLegendNode *> lst( data.activeNodes );
968  if ( !skipNodeEmbeddedInParent && data.embeddedNodeInParent )
969  lst.prepend( data.embeddedNodeInParent );
970  return lst;
971 }
972 
973 void QgsLegendModel::forceRefresh()
974 {
975  emit refreshLegend();
976 }
977 
978 
void setTitleAlignment(Qt::AlignmentFlag alignment)
Sets the alignment of the legend title.
void setColumnSpace(double spacing)
Sets the legend column spacing.
bool splitLayer() const
Returns whether the legend items from a single layer can be split over multiple columns.
void setWrapChar(const QString &t)
The class is used as a container of context for various read/write operations on other objects...
void setEqualColumnWidth(bool equalize)
Sets whether column widths should be equalized.
void setLegendSize(QSizeF s)
Sets the preferred resulting legend size.
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
QMap< QgsLayerTreeLayer *, LayerLegendData > mLegend
Per layer data about layer&#39;s legend nodes.
Single variable definition for use within a QgsExpressionContextScope.
void setFontColor(const QColor &color)
Sets the legend font color.
void setLegendFilterOutAtlas(bool doFilter)
When set to true, during an atlas rendering, it will filter out legend elements where features are ou...
static QgsLayerTreeLayer * toLayer(QgsLayerTreeNode *node)
Cast node to a layer.
Definition: qgslayertree.h:75
A rectangle specified with double values.
Definition: qgsrectangle.h:41
void setTitle(const QString &title)
Sets the legend title.
void setEqualColumnWidth(bool s)
double lineSpacing() const
Returns the spacing in-between lines in layout units.
double boxSpace() const
Returns the legend box space.
QgsVectorLayerFeatureCounter * countSymbolFeatures()
Count features for symbols.
Item model implementation based on layer tree model for layout legend.
virtual QString name() const =0
Returns name of the node.
double columnSpace() const
Returns the legend column spacing.
void setBoxSpace(double s)
QString labelExpression() const
Returns the expression member of the LayerTreeNode.
void setMmPerMapUnit(double mmPerMapUnit)
void setSplitLayer(bool enabled)
Sets whether the legend items from a single layer can be split over multiple columns.
QColor rasterStrokeColor() const
Returns the stroke color for the stroke drawn around raster symbol items.
Base class for graphical items within a QgsLayout.
void setSymbolWidth(double width)
Sets the legend symbol width.
bool writePropertiesToElement(QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context) const override
Stores item state within an XML DOM element.
QString wrapChar() const
void paint(QPainter *painter, const QStyleOptionGraphicsItem *itemStyle, QWidget *pWidget) override
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
void setSymbolAlignment(Qt::AlignmentFlag alignment)
Sets the alignment for placement of legend symbols.
int type() const override
void setSymbolSize(QSizeF s)
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 extentChanged()
Emitted when the map&#39;s extent changes.
QgsLayoutSize sizeWithUnits() const
Returns the item&#39;s current size, including units.
QFont font() const
Returns the font used for rendering this legend component.
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
Qt::AlignmentFlag symbolAlignment() const
Returns the alignment for placement of legend symbols.
Implementation of legend node interface for displaying preview of vector symbols and their labels and...
bool legendFilterByMapEnabled() const
Find out whether legend items are filtered to show just the ones visible in the associated map...
QgsLayerTreeModelLegendNode * embeddedNodeInParent
A legend node that is not displayed separately, its icon is instead shown within the layer node&#39;s ite...
Contains detailed styling information relating to how a layout legend should be rendered.
void updateFilterByMap(bool redraw=true)
Updates the legend content when filtered by map.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:111
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
void projectColorsChanged()
Emitted whenever the project&#39;s color scheme has been changed.
QString title() const
Returns the legend title.
void setStyle(QgsLegendStyle::Style component, const QgsLegendStyle &style)
Sets the style of component to style for the legend.
bool drawRasterStroke() const
Returns whether a stroke will be drawn around raster symbol items.
void setLegendFilterByMapEnabled(bool enabled)
Set whether legend items should be filtered to show just the ones visible in the associated map...
bool resizeToContents() const
Returns whether the legend should automatically resize to fit its contents.
double rasterStrokeWidth() const
Returns the stroke width (in layout units) for the stroke drawn around raster symbol items...
int columnCount() const
Returns the legend column count.
Qt::AlignmentFlag titleAlignment() const
Returns the alignment of the legend title.
void addVariable(const QgsExpressionContextScope::StaticVariable &variable)
Adds a variable into the context scope.
virtual void refreshDataDefinedProperty(QgsLayoutObject::DataDefinedProperty property=QgsLayoutObject::AllProperties)
Refreshes a data defined property for the item by reevaluating the property&#39;s value and redrawing the...
bool equalColumnWidth() const
Returns whether column widths should be equalized.
QColor rasterStrokeColor() const
Returns the stroke color for the stroke drawn around raster symbol items.
QgsLegendModel(QgsLayerTree *rootNode, QObject *parent=nullptr, QgsLayoutItemLegend *layout=nullptr)
Construct the model based on the given layer tree.
Allow check boxes for legend nodes (if supported by layer&#39;s legend)
void setDrawRasterStroke(bool enabled)
Sets whether a stroke will be drawn around raster symbol items.
The QgsMapSettings class contains configuration for rendering of the map.
static QString encodeColor(const QColor &color)
QString displayName() const override
Gets item display name.
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
The QgsLayerTreeModel class is model implementation for Qt item views framework.
QSizeF wmsLegendSize() const
QgsLegendStyle style(QgsLegendStyle::Style s) const
Returns style.
void adjustBoxSize()
Sets the legend&#39;s item bounds to fit the whole legend content.
virtual void invalidateCache()
Forces a deferred update of any cached image the item uses.
QgsRectangle extent() const
Returns the current map extent.
Layout graphical items for displaying a map.
void setFont(const QFont &font)
Sets the font used for rendering this legend component.
QString name() const override
Returns the layer&#39;s name.
QgsPropertyCollection mDataDefinedProperties
const QgsLayout * layout() const
Returns the layout the object is attached to.
void draw(QgsLayoutItemRenderContext &context) override
Draws the item&#39;s contents using the specified item render context.
double symbolWidth() const
Returns the legend symbol width.
Namespace with helper functions for layer tree operations.
Definition: qgslayertree.h:32
void finalizeRestoreFromXml() override
Called after all pending items have been restored from XML.
QColor fontColor() const
Returns the legend font color.
void paint(QPainter *painter, const QStyleOptionGraphicsItem *itemStyle, QWidget *pWidget) override
Handles preparing a paint surface for the layout item and painting the item&#39;s content.
double scale() const
Returns the calculated map scale.
long featureCount(const QString &legendKey) const
Number of features rendered with specified legend key.
double width() const
Returns the width of the rectangle.
Definition: qgsrectangle.h:202
static QgsLayerTreeModelLegendNode * index2legendNode(const QModelIndex &index)
Returns legend node for given index.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void setMapScale(double scale)
Sets the legend map scale.
QgsRenderContext & renderContext()
Returns a reference to the context&#39;s render context.
Definition: qgslayoutitem.h:72
double symbolHeight() const
Returns the legend symbol height.
QVariant data(const QModelIndex &index, int role) const override
QgsLegendStyle & rstyle(QgsLegendStyle::Style s)
Returns reference to modifiable legend style.
double rasterStrokeWidth() const
Returns the stroke width (in millimeters) for the stroke drawn around raster symbol items...
bool readPropertiesFromElement(const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context) override
Sets item state from a DOM element.
double mapUnitsToLayoutUnits() const
Returns the conversion factor from map units to layout units.
static QgsRenderContext createRenderContextForLayout(QgsLayout *layout, QPainter *painter, double dpi=-1)
Creates a render context suitable for the specified layout and painter destination.
QPointer< QgsLayout > mLayout
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...
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.
void setRasterStrokeColor(const QColor &color)
Sets the stroke color for the stroke drawn around raster symbol items.
Symbol icon (excluding label)
void setTitle(const QString &t)
static bool isLayer(const QgsLayerTreeNode *node)
Check whether the node is a valid layer node.
Definition: qgslayertree.h:53
This class is a base class for nodes in a layer tree.
void setRasterStrokeWidth(double width)
Sets the stroke width for the stroke drawn around raster symbol items.
Legend subgroup title.
void setMargin(Side side, double margin)
Sets the margin (in mm) for the specified side of the component.
QgsLegendStyle style(QgsLegendStyle::Style s) const
Returns legend style.
QString id() const
Returns the item&#39;s ID name.
Qt::AlignmentFlag titleAlignment() const
Returns the alignment of the legend title.
QgsLayoutItemLegend(QgsLayout *layout)
Constructor for QgsLayoutItemLegend, with the specified parent layout.
void setLineSpacing(double spacing)
Sets the spacing in-between multiple lines.
void setDpi(int dpi)
double boxSpace() const
QgsRectangle requestedExtent() const
Calculates the extent to request and the yShift of the top-left point in case of rotation.
Side
Margin sides.
void setFontColor(const QColor &c)
Single scope for storing variables and functions for use within a QgsExpressionContext.
static bool hasLegendFilterExpression(const QgsLayerTreeGroup &group)
Test if one of the layers in a group has an expression filter.
void refreshLegend()
Emitted to refresh the legend.
void setColumnSpace(double s)
void setFlag(Flag f, bool on=true)
Enable or disable a model flag.
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
Definition: qgslayout.h:49
void updateLegend()
Updates the model and all legend entries.
void symbolFeatureCountMapChanged()
Emitted when the feature count for symbols on this layer has been recalculated.
void setWrapString(const QString &string)
Sets the legend text wrapping string.
Style
Component of legends which can be styled.
void setStyleFont(QgsLegendStyle::Style component, const QFont &font)
Sets the style font for a legend component.
void setResizeToContents(bool enabled)
Sets whether the legend should automatically resize to fit its contents.
virtual void redraw()
Triggers a redraw (update) of the item.
void setAutoUpdateModel(bool autoUpdate)
Sets whether the legend content should auto update to reflect changes in the project&#39;s layer tree...
void setColumnCount(int count)
Sets the legend column count.
Qt::AlignmentFlag symbolAlignment() const
Returns the alignment for placement of legend symbols.
QSizeF symbolSize() const
Contains settings and helpers relating to a render of a QgsLayoutItem.
Definition: qgslayoutitem.h:44
void setLineSpacing(double s)
QgsMapLayer * layer() const
Returns the map layer associated with this node.
void readXml(const QDomElement &elem, const QDomDocument &doc)
Reads the component&#39;s style definition from an XML element.
static QgsLayoutItemLegend * create(QgsLayout *layout)
Returns a new legend item for the specified layout.
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...
void setWmsLegendSize(QSizeF s)
QgsLegendStyle & rstyle(QgsLegendStyle::Style s)
Returns reference to modifiable style.
Contains information about the context of a rendering operation.
void setUseAdvancedEffects(bool use)
void setLinkedMap(QgsLayoutItemMap *map)
Sets the map to associate with the legend.
QPainter * painter()
Returns the destination QPainter for the render operation.
QgsLayerTreeNode * index2node(const QModelIndex &index) const
Returns layer tree node for given index.
QgsCoordinateReferenceSystem crs() const
Returns coordinate reference system used for rendering the map.
void setStyle(QgsLegendStyle::Style s, const QgsLegendStyle &style)
Enable advanced effects such as blend modes.
QString wrapString() const
Returns the legend text wrapping string.
static QgsLayerTree * readXml(QDomElement &element, const QgsReadWriteContext &context)
Load the layer tree from an XML element.
double wmsLegendHeight() const
Returns the WMS legend height.
bool equalColumnWidth() const
void setStyleMargin(QgsLegendStyle::Style component, double margin)
Set the margin for a legend component.
void setColumnCount(int c)
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
double columnSpace() const
virtual QString uuid() const
Returns the item identification string.
void setDrawRasterStroke(bool enabled)
Sets whether a stroke will be drawn around raster symbol items.
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
bool autoUpdateModel() const
Returns whether the legend content should auto update to reflect changes in the project&#39;s layer tree...
void refreshDataDefinedProperty(QgsLayoutObject::DataDefinedProperty property=QgsLayoutObject::AllProperties) override
The QgsLegendRendererItem class is abstract interface for legend items returned from QgsMapLayerLegen...
void setRasterStrokeWidth(double width)
Sets the stroke width for the stroke drawn around raster symbol items.
void writeXml(const QString &name, QDomElement &elem, QDomDocument &doc) const
Writes the component&#39;s style definition to an XML element.
void setWmsLegendHeight(double height)
Sets the WMS legend height.
QSizeF minimumSize(QgsRenderContext *renderContext=nullptr)
Runs the layout algorithm and returns the minimum size required for the legend.
QList< QgsLayerTreeModelLegendNode * > activeNodes
Active legend nodes.
void layerStyleOverridesChanged()
Emitted when layer style overrides are changed...
void setWmsLegendWidth(double width)
Sets the WMS legend width.
Item overrides the default layout item painting method.
Flags flags() const
Returns OR-ed combination of model flags.
QgsExpressionContextScope * popScope()
Removes the last scope from the expression context and return it.
A layout item subclass for map legends.
void customPropertyChanged(QgsLayerTreeNode *node, const QString &key)
Emitted when a custom property of a node within the tree has been changed or removed.
void setSymbolHeight(double height)
Sets the legend symbol height.
Symbol label (excluding icon)
double lineSpacing() const
This class provides a method of storing sizes, consisting of a width and height, for use in QGIS layo...
Definition: qgslayoutsize.h:40
void setBoxSpace(double space)
Sets the legend box space.
QColor fontColor() const
void changed()
Emitted when the object&#39;s properties change.
QgsLayoutItem::Flags itemFlags() const override
Returns the item&#39;s flags, which indicate how the item behaves.
bool legendFilterOutAtlas() const
Returns whether to filter out legend elements outside of the current atlas feature.
double scaleFactor() const
Returns the scaling factor for the render to convert painter units to physical sizes.
Represents a vector layer which manages a vector based data sets.
bool splitLayer() const
DataDefinedProperty
Data defined properties for different item types.
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...
void setRasterStrokeColor(const QColor &color)
Sets the stroke color for the stroke drawn around raster symbol items.
void setTitleAlignment(Qt::AlignmentFlag alignment)
Sets the alignment of the legend title.
void refresh() override
Refreshes the item, causing a recalculation of any property overrides and recalculation of its positi...
bool drawRasterStroke() const
Returns whether a stroke will be drawn around raster symbol items.
void setSymbolAlignment(Qt::AlignmentFlag alignment)
Sets the alignment for placement of legend symbols.
QIcon icon() const override
Returns the item&#39;s icon.
double wmsLegendWidth() const
Returns the WMS legend width.
Allow reordering with drag&#39;n&#39;drop.
Legend group title.
void setSplitLayer(bool s)
static QColor decodeColor(const QString &str)
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
double height() const
Returns the height of the rectangle.
Definition: qgsrectangle.h:209
Layer tree node points to a map layer.
The QgsLegendRenderer class handles automatic layout and rendering of legend.
QString title() const
All properties for item.
QMap< QString, QString > layerStyleOverrides() const
Returns stored overrides of styles for layers.
Structure that stores all data associated with one map layer.
QFont styleFont(QgsLegendStyle::Style component) const
Returns the font settings for a legend component.