QGIS API Documentation  3.8.0-Zanzibar (11aff65)
qgslayertreemodellegendnode.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgslayertreemodellegendnode.cpp
3  --------------------------------------
4  Date : August 2014
5  Copyright : (C) 2014 by Martin Dobias
6  Email : wonder dot sk at gmail dot com
7 
8  QgsWMSLegendNode : Sandro Santilli < strk at keybit dot net >
9 
10  ***************************************************************************
11  * *
12  * This program is free software; you can redistribute it and/or modify *
13  * it under the terms of the GNU General Public License as published by *
14  * the Free Software Foundation; either version 2 of the License, or *
15  * (at your option) any later version. *
16  * *
17  ***************************************************************************/
18 
20 
22 #include "qgslayertree.h"
23 #include "qgslayertreemodel.h"
24 #include "qgslegendsettings.h"
25 #include "qgsrasterlayer.h"
26 #include "qgsrenderer.h"
27 #include "qgssymbollayerutils.h"
28 #include "qgsimageoperation.h"
29 #include "qgsvectorlayer.h"
30 #include "qgsrasterrenderer.h"
32 
34  : QObject( parent )
35  , mLayerNode( nodeL )
36  , mEmbeddedInParent( false )
37 {
38 }
39 
41 {
42  return qobject_cast<QgsLayerTreeModel *>( parent() );
43 }
44 
46 {
47  return Qt::ItemIsEnabled;
48 }
49 
50 bool QgsLayerTreeModelLegendNode::setData( const QVariant &value, int role )
51 {
52  Q_UNUSED( value )
53  Q_UNUSED( role )
54  return false;
55 }
56 
57 
59 {
60  QFont symbolLabelFont = settings.style( QgsLegendStyle::SymbolLabel ).font();
61 
62  double textHeight = settings.fontHeightCharacterMM( symbolLabelFont, QChar( '0' ) );
63  // itemHeight here is not really item height, it is only for symbol
64  // vertical alignment purpose, i.e. OK take single line height
65  // if there are more lines, thos run under the symbol
66  double itemHeight = std::max( static_cast< double >( settings.symbolSize().height() ), textHeight );
67 
68  ItemMetrics im;
69  im.symbolSize = drawSymbol( settings, ctx, itemHeight );
70  im.labelSize = drawSymbolText( settings, ctx, im.symbolSize );
71  return im;
72 }
73 
74 void QgsLayerTreeModelLegendNode::exportToJson( const QgsLegendSettings &settings, const QgsRenderContext &context, QJsonObject &json )
75 {
76  exportSymbolToJson( settings, context, json );
77  exportSymbolTextToJson( settings, json );
78 }
79 
80 QSizeF QgsLayerTreeModelLegendNode::drawSymbol( const QgsLegendSettings &settings, ItemContext *ctx, double itemHeight ) const
81 {
82  QIcon symbolIcon = data( Qt::DecorationRole ).value<QIcon>();
83  if ( symbolIcon.isNull() )
84  return QSizeF();
85 
86  if ( ctx && ctx->painter )
87  symbolIcon.paint( ctx->painter, ctx->point.x(), ctx->point.y() + ( itemHeight - settings.symbolSize().height() ) / 2,
88  settings.symbolSize().width(), settings.symbolSize().height() );
89  return settings.symbolSize();
90 }
91 
92 void QgsLayerTreeModelLegendNode::exportSymbolToJson( const QgsLegendSettings &settings, const QgsRenderContext &, QJsonObject &json ) const
93 {
94  const QIcon icon = data( Qt::DecorationRole ).value<QIcon>();
95  if ( icon.isNull() )
96  return;
97 
98  const QImage image( icon.pixmap( settings.symbolSize().width(), settings.symbolSize().height() ).toImage() );
99  QByteArray byteArray;
100  QBuffer buffer( &byteArray );
101  image.save( &buffer, "PNG" );
102  const QString base64 = QString::fromLatin1( byteArray.toBase64().data() );
103  json[ "icon" ] = base64;
104 }
105 
106 QSizeF QgsLayerTreeModelLegendNode::drawSymbolText( const QgsLegendSettings &settings, ItemContext *ctx, QSizeF symbolSize ) const
107 {
108  QSizeF labelSize( 0, 0 );
109 
110  QFont symbolLabelFont = settings.style( QgsLegendStyle::SymbolLabel ).font();
111  double textHeight = settings.fontHeightCharacterMM( symbolLabelFont, QChar( '0' ) );
112  double textDescent = settings.fontDescentMillimeters( symbolLabelFont );
113 
114  QgsExpressionContext tempContext;
115 
116  const QStringList lines = settings.evaluateItemText( data( Qt::DisplayRole ).toString(), ctx && ctx->context ? ctx->context->expressionContext() : tempContext );
117 
118  labelSize.rheight() = lines.count() * textHeight + ( lines.count() - 1 ) * ( settings.lineSpacing() + textDescent );
119 
120  double labelX = 0.0, labelY = 0.0;
121  if ( ctx && ctx->painter )
122  {
123  ctx->painter->setPen( settings.fontColor() );
124 
125  labelX = ctx->point.x() + std::max( static_cast< double >( symbolSize.width() ), ctx->labelXOffset );
126  labelY = ctx->point.y();
127 
128  // Vertical alignment of label with symbol
129  if ( labelSize.height() < symbolSize.height() )
130  labelY += symbolSize.height() / 2 - labelSize.height() / 2; // label centered with symbol
131 
132  labelY += textHeight;
133  }
134 
135  for ( QStringList::ConstIterator itemPart = lines.constBegin(); itemPart != lines.constEnd(); ++itemPart )
136  {
137  labelSize.rwidth() = std::max( settings.textWidthMillimeters( symbolLabelFont, *itemPart ), double( labelSize.width() ) );
138 
139  if ( ctx && ctx->painter )
140  {
141  settings.drawText( ctx->painter, labelX, labelY, *itemPart, symbolLabelFont );
142  if ( itemPart != ( lines.end() - 1 ) )
143  labelY += textDescent + settings.lineSpacing() + textHeight;
144  }
145  }
146 
147  return labelSize;
148 }
149 
151 {
152  const QString text = data( Qt::DisplayRole ).toString();
153  json[ "title" ] = text;
154 }
155 
156 // -------------------------------------------------------------------------
157 
159  : QgsLayerTreeModelLegendNode( nodeLayer, parent )
160  , mItem( item )
161  , mSymbolUsesMapUnits( false )
162 {
163  const int iconSize = QgsLayerTreeModel::scaleIconSize( 16 );
164  mIconSize = QSize( iconSize, iconSize );
165 
166  updateLabel();
167  connect( qobject_cast<QgsVectorLayer *>( nodeLayer->layer() ), &QgsVectorLayer::symbolFeatureCountMapChanged, this, &QgsSymbolLegendNode::updateLabel );
168  connect( nodeLayer, &QObject::destroyed, this, [ = ]() { mLayerNode = nullptr; } );
169 
170  if ( mItem.symbol() )
171  mSymbolUsesMapUnits = ( mItem.symbol()->outputUnit() != QgsUnitTypes::RenderMillimeters );
172 }
173 
174 Qt::ItemFlags QgsSymbolLegendNode::flags() const
175 {
176  if ( mItem.isCheckable() )
177  return Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
178  else
179  return Qt::ItemIsEnabled;
180 }
181 
182 
184 {
185  std::unique_ptr<QgsRenderContext> context( createTemporaryRenderContext() );
186  return minimumIconSize( context.get() );
187 }
188 
190 {
191  const int iconSize = QgsLayerTreeModel::scaleIconSize( 16 );
192  const int largeIconSize = QgsLayerTreeModel::scaleIconSize( 512 );
193  QSize minSz( iconSize, iconSize );
194  if ( mItem.symbol() && mItem.symbol()->type() == QgsSymbol::Marker )
195  {
197  QgsSymbolLayerUtils::symbolPreviewPixmap( mItem.symbol(), QSize( largeIconSize, largeIconSize ), 0,
198  context ).toImage(),
199  minSz,
200  true ).size();
201  }
202  else if ( mItem.symbol() && mItem.symbol()->type() == QgsSymbol::Line )
203  {
205  QgsSymbolLayerUtils::symbolPreviewPixmap( mItem.symbol(), QSize( minSz.width(), largeIconSize ), 0,
206  context ).toImage(),
207  minSz,
208  true ).size();
209  }
210 
211  if ( !mTextOnSymbolLabel.isEmpty() && context )
212  {
213  double w = QgsTextRenderer::textWidth( *context, mTextOnSymbolTextFormat, QStringList() << mTextOnSymbolLabel );
214  double h = QgsTextRenderer::textHeight( *context, mTextOnSymbolTextFormat, QStringList() << mTextOnSymbolLabel, QgsTextRenderer::Point );
215  int wInt = ceil( w ), hInt = ceil( h );
216  if ( wInt > minSz.width() ) minSz.setWidth( wInt );
217  if ( hInt > minSz.height() ) minSz.setHeight( hInt );
218  }
219 
220  if ( mItem.level() != 0 && !( model() && model()->testFlag( QgsLayerTreeModel::ShowLegendAsTree ) ) )
221  minSz.setWidth( mItem.level() * INDENT_SIZE + minSz.width() );
222 
223  return minSz;
224 }
225 
227 {
228  return mItem.symbol();
229 }
230 
232 {
233  if ( !symbol )
234  return;
235 
236  std::unique_ptr< QgsSymbol > s( symbol ); // this method takes ownership of symbol
237  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mLayerNode->layer() );
238  if ( !vlayer || !vlayer->renderer() )
239  return;
240 
241  mItem.setSymbol( s.get() ); // doesn't transfer ownership
242  vlayer->renderer()->setLegendSymbolItem( mItem.ruleKey(), s.release() ); // DOES transfer ownership!
243 
244  mPixmap = QPixmap();
245 
246  emit dataChanged();
247  vlayer->triggerRepaint();
248 }
249 
251 {
252  checkAll( true );
253 }
254 
256 {
257  checkAll( false );
258 }
259 
261 {
262  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mLayerNode->layer() );
263  if ( !vlayer || !vlayer->renderer() )
264  return;
265 
266  const QgsLegendSymbolList symbolList = vlayer->renderer()->legendSymbolItems();
267  for ( const auto &item : symbolList )
268  {
269  vlayer->renderer()->checkLegendSymbolItem( item.ruleKey(), ! vlayer->renderer()->legendSymbolItemChecked( item.ruleKey() ) );
270  }
271 
272  emit dataChanged();
273  vlayer->triggerRepaint();
274 }
275 
277 {
278  double scale = 0.0;
279  double mupp = 0.0;
280  int dpi = 0;
281  if ( model() )
282  model()->legendMapViewData( &mupp, &dpi, &scale );
283 
284  if ( qgsDoubleNear( mupp, 0.0 ) || dpi == 0 || qgsDoubleNear( scale, 0.0 ) )
285  return nullptr;
286 
287  // setup temporary render context
288  std::unique_ptr<QgsRenderContext> context = qgis::make_unique<QgsRenderContext>( );
289  context->setScaleFactor( dpi / 25.4 );
290  context->setRendererScale( scale );
291  context->setMapToPixel( QgsMapToPixel( mupp ) );
292  return context.release();
293 }
294 
295 void QgsSymbolLegendNode::checkAll( bool state )
296 {
297  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mLayerNode->layer() );
298  if ( !vlayer || !vlayer->renderer() )
299  return;
300 
301  const QgsLegendSymbolList symbolList = vlayer->renderer()->legendSymbolItems();
302  for ( const auto &item : symbolList )
303  {
304  vlayer->renderer()->checkLegendSymbolItem( item.ruleKey(), state );
305  }
306 
307  emit dataChanged();
308  vlayer->triggerRepaint();
309 }
310 
311 QVariant QgsSymbolLegendNode::data( int role ) const
312 {
313  if ( role == Qt::DisplayRole )
314  {
315  return mLabel;
316  }
317  else if ( role == Qt::EditRole )
318  {
319  return mUserLabel.isEmpty() ? mItem.label() : mUserLabel;
320  }
321  else if ( role == Qt::DecorationRole )
322  {
323  if ( mPixmap.isNull() || mPixmap.size() != mIconSize )
324  {
325  QPixmap pix;
326  if ( mItem.symbol() )
327  {
328  std::unique_ptr<QgsRenderContext> context( createTemporaryRenderContext() );
329  pix = QgsSymbolLayerUtils::symbolPreviewPixmap( mItem.symbol(), mIconSize, 0, context.get() );
330 
331  if ( !mTextOnSymbolLabel.isEmpty() && context )
332  {
333  QPainter painter( &pix );
334  painter.setRenderHint( QPainter::Antialiasing );
335  context->setPainter( &painter );
336  QFontMetricsF fm( mTextOnSymbolTextFormat.scaledFont( *context ) );
337  qreal yBaselineVCenter = ( mIconSize.height() + fm.ascent() - fm.descent() ) / 2;
338  QgsTextRenderer::drawText( QPointF( mIconSize.width() / 2, yBaselineVCenter ), 0, QgsTextRenderer::AlignCenter,
339  QStringList() << mTextOnSymbolLabel, *context, mTextOnSymbolTextFormat );
340  }
341  }
342  else
343  {
344  pix = QPixmap( mIconSize );
345  pix.fill( Qt::transparent );
346  }
347 
348  if ( mItem.level() == 0 || ( model() && model()->testFlag( QgsLayerTreeModel::ShowLegendAsTree ) ) )
349  mPixmap = pix;
350  else
351  {
352  // ident the symbol icon to make it look like a tree structure
353  QPixmap pix2( pix.width() + mItem.level() * INDENT_SIZE, pix.height() );
354  pix2.fill( Qt::transparent );
355  QPainter p( &pix2 );
356  p.drawPixmap( mItem.level() * INDENT_SIZE, 0, pix );
357  p.end();
358  mPixmap = pix2;
359  }
360  }
361  return mPixmap;
362  }
363  else if ( role == Qt::CheckStateRole )
364  {
365  if ( !mItem.isCheckable() )
366  return QVariant();
367 
368  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mLayerNode->layer() );
369  if ( !vlayer || !vlayer->renderer() )
370  return QVariant();
371 
372  return vlayer->renderer()->legendSymbolItemChecked( mItem.ruleKey() ) ? Qt::Checked : Qt::Unchecked;
373  }
374  else if ( role == RuleKeyRole )
375  {
376  return mItem.ruleKey();
377  }
378  else if ( role == ParentRuleKeyRole )
379  {
380  return mItem.parentRuleKey();
381  }
382 
383  return QVariant();
384 }
385 
386 bool QgsSymbolLegendNode::setData( const QVariant &value, int role )
387 {
388  if ( role != Qt::CheckStateRole )
389  return false;
390 
391  if ( !mItem.isCheckable() )
392  return false;
393 
394  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mLayerNode->layer() );
395  if ( !vlayer || !vlayer->renderer() )
396  return false;
397 
398  vlayer->renderer()->checkLegendSymbolItem( mItem.ruleKey(), value == Qt::Checked );
399 
400  emit dataChanged();
401  vlayer->emitStyleChanged();
402 
403  vlayer->triggerRepaint();
404 
405  return true;
406 }
407 
408 
409 
410 QSizeF QgsSymbolLegendNode::drawSymbol( const QgsLegendSettings &settings, ItemContext *ctx, double itemHeight ) const
411 {
412  QgsSymbol *s = mItem.symbol();
413  if ( !s )
414  {
415  return QSizeF();
416  }
417 
418  // setup temporary render context
419  QgsRenderContext context;
420  context.setScaleFactor( settings.dpi() / 25.4 );
421  context.setRendererScale( settings.mapScale() );
422  context.setFlag( QgsRenderContext::Antialiasing, true );
423  context.setMapToPixel( QgsMapToPixel( 1 / ( settings.mmPerMapUnit() * context.scaleFactor() ) ) );
424  context.setForceVectorOutput( true );
425  context.setPainter( ctx ? ctx->painter : nullptr );
426 
427  if ( ctx && ctx->context )
428  {
430  }
431  else
432  {
433  // setup a minimal expression context
434  QgsExpressionContext expContext;
436  context.setExpressionContext( expContext );
437  }
438 
439  //Consider symbol size for point markers
440  double height = settings.symbolSize().height();
441  double width = settings.symbolSize().width();
442 
443  //Center small marker symbols
444  double widthOffset = 0;
445  double heightOffset = 0;
446 
447  if ( QgsMarkerSymbol *markerSymbol = dynamic_cast<QgsMarkerSymbol *>( s ) )
448  {
449  // allow marker symbol to occupy bigger area if necessary
450  double size = markerSymbol->size( context ) / context.scaleFactor();
451  height = size;
452  width = size;
453  if ( width < settings.symbolSize().width() )
454  {
455  widthOffset = ( settings.symbolSize().width() - width ) / 2.0;
456  }
457  if ( height < settings.symbolSize().height() )
458  {
459  heightOffset = ( settings.symbolSize().height() - height ) / 2.0;
460  }
461  }
462 
463  if ( ctx && ctx->painter )
464  {
465  double currentXPosition = ctx->point.x();
466  double currentYCoord = ctx->point.y() + ( itemHeight - settings.symbolSize().height() ) / 2;
467  QPainter *p = ctx->painter;
468 
469  //setup painter scaling to dots so that raster symbology is drawn to scale
470  double dotsPerMM = context.scaleFactor();
471 
472  int opacity = 255;
473  if ( QgsVectorLayer *vectorLayer = qobject_cast<QgsVectorLayer *>( layerNode()->layer() ) )
474  opacity = ( 255 * vectorLayer->opacity() );
475 
476  p->save();
477  p->setRenderHint( QPainter::Antialiasing );
478  p->translate( currentXPosition + widthOffset, currentYCoord + heightOffset );
479  p->scale( 1.0 / dotsPerMM, 1.0 / dotsPerMM );
480  if ( opacity != 255 && settings.useAdvancedEffects() )
481  {
482  //semi transparent layer, so need to draw symbol to an image (to flatten it first)
483  //create image which is same size as legend rect, in case symbol bleeds outside its alloted space
484  QSize tempImageSize( width * dotsPerMM, height * dotsPerMM );
485  QImage tempImage = QImage( tempImageSize, QImage::Format_ARGB32 );
486  tempImage.fill( Qt::transparent );
487  QPainter imagePainter( &tempImage );
488  imagePainter.setRenderHint( QPainter::Antialiasing );
489  context.setPainter( &imagePainter );
490  s->drawPreviewIcon( &imagePainter, tempImageSize, &context );
491  context.setPainter( ctx->painter );
492  //reduce opacity of image
493  imagePainter.setCompositionMode( QPainter::CompositionMode_DestinationIn );
494  imagePainter.fillRect( tempImage.rect(), QColor( 0, 0, 0, opacity ) );
495  imagePainter.end();
496  //draw rendered symbol image
497  p->drawImage( 0, 0, tempImage );
498  }
499  else
500  {
501  s->drawPreviewIcon( p, QSize( width * dotsPerMM, height * dotsPerMM ), &context );
502  }
503 
504  if ( !mTextOnSymbolLabel.isEmpty() )
505  {
506  QFontMetricsF fm( mTextOnSymbolTextFormat.scaledFont( context ) );
507  qreal yBaselineVCenter = ( height * dotsPerMM + fm.ascent() - fm.descent() ) / 2;
508  QgsTextRenderer::drawText( QPointF( width * dotsPerMM / 2, yBaselineVCenter ), 0, QgsTextRenderer::AlignCenter,
509  QStringList() << mTextOnSymbolLabel, context, mTextOnSymbolTextFormat );
510  }
511 
512  p->restore();
513  }
514 
515  return QSizeF( std::max( width + 2 * widthOffset, static_cast< double >( settings.symbolSize().width() ) ),
516  std::max( height + 2 * heightOffset, static_cast< double >( settings.symbolSize().height() ) ) );
517 }
518 
519 void QgsSymbolLegendNode::exportSymbolToJson( const QgsLegendSettings &settings, const QgsRenderContext &context, QJsonObject &json ) const
520 {
521  const QgsSymbol *s = mItem.symbol();
522  if ( !s )
523  {
524  return;
525  }
526 
527  QgsRenderContext ctx;
528  ctx.setScaleFactor( settings.dpi() / 25.4 );
529  ctx.setRendererScale( settings.mapScale() );
530  ctx.setMapToPixel( QgsMapToPixel( 1 / ( settings.mmPerMapUnit() * ctx.scaleFactor() ) ) );
531  ctx.setForceVectorOutput( true );
532 
533  // ensure that a minimal expression context is available
534  QgsExpressionContext expContext = context.expressionContext();
536  ctx.setExpressionContext( expContext );
537 
538  const QPixmap pix = QgsSymbolLayerUtils::symbolPreviewPixmap( mItem.symbol(), minimumIconSize(), 0, &ctx );
539  QImage img( pix.toImage().convertToFormat( QImage::Format_ARGB32_Premultiplied ) );
540 
541  int opacity = 255;
542  if ( QgsVectorLayer *vectorLayer = qobject_cast<QgsVectorLayer *>( layerNode()->layer() ) )
543  opacity = ( 255 * vectorLayer->opacity() );
544 
545  if ( opacity != 255 )
546  {
547  QPainter painter;
548  painter.begin( &img );
549  painter.setCompositionMode( QPainter::CompositionMode_DestinationIn );
550  painter.fillRect( pix.rect(), QColor( 0, 0, 0, opacity ) );
551  painter.end();
552  }
553 
554  QByteArray byteArray;
555  QBuffer buffer( &byteArray );
556  img.save( &buffer, "PNG" );
557  const QString base64 = QString::fromLatin1( byteArray.toBase64().data() );
558  json[ "icon" ] = base64;
559 }
560 
562 {
564  updateLabel();
565 }
566 
567 
569 {
570  if ( mSymbolUsesMapUnits )
571  {
572  mPixmap = QPixmap();
573  emit dataChanged();
574  }
575 }
576 
577 
578 void QgsSymbolLegendNode::updateLabel()
579 {
580  if ( !mLayerNode )
581  return;
582 
583  bool showFeatureCount = mLayerNode->customProperty( QStringLiteral( "showFeatureCount" ), 0 ).toBool();
584  QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( mLayerNode->layer() );
585 
586  if ( mEmbeddedInParent )
587  {
588  QString layerName = mLayerNode->name();
589  if ( !mLayerNode->customProperty( QStringLiteral( "legend/title-label" ) ).isNull() )
590  layerName = mLayerNode->customProperty( QStringLiteral( "legend/title-label" ) ).toString();
591 
592  mLabel = mUserLabel.isEmpty() ? layerName : mUserLabel;
593  if ( showFeatureCount && vl && vl->featureCount() >= 0 )
594  mLabel += QStringLiteral( " [%1]" ).arg( vl->featureCount() );
595  }
596  else
597  {
598  mLabel = mUserLabel.isEmpty() ? mItem.label() : mUserLabel;
599  if ( showFeatureCount && vl )
600  {
601  qlonglong count = vl->featureCount( mItem.ruleKey() );
602  mLabel += QStringLiteral( " [%1]" ).arg( count != -1 ? QLocale().toString( count ) : tr( "N/A" ) );
603  }
604  }
605 
606  emit dataChanged();
607 }
608 
609 
610 
611 // -------------------------------------------------------------------------
612 
613 
614 QgsSimpleLegendNode::QgsSimpleLegendNode( QgsLayerTreeLayer *nodeLayer, const QString &label, const QIcon &icon, QObject *parent, const QString &key )
615  : QgsLayerTreeModelLegendNode( nodeLayer, parent )
616  , mLabel( label )
617  , mIcon( icon )
618  , mKey( key )
619 {
620 }
621 
622 QVariant QgsSimpleLegendNode::data( int role ) const
623 {
624  if ( role == Qt::DisplayRole || role == Qt::EditRole )
625  return mUserLabel.isEmpty() ? mLabel : mUserLabel;
626  else if ( role == Qt::DecorationRole )
627  return mIcon;
628  else if ( role == RuleKeyRole && !mKey.isEmpty() )
629  return mKey;
630  else
631  return QVariant();
632 }
633 
634 
635 // -------------------------------------------------------------------------
636 
637 QgsImageLegendNode::QgsImageLegendNode( QgsLayerTreeLayer *nodeLayer, const QImage &img, QObject *parent )
638  : QgsLayerTreeModelLegendNode( nodeLayer, parent )
639  , mImage( img )
640 {
641 }
642 
643 QVariant QgsImageLegendNode::data( int role ) const
644 {
645  if ( role == Qt::DecorationRole )
646  {
647  return QPixmap::fromImage( mImage );
648  }
649  else if ( role == Qt::SizeHintRole )
650  {
651  return mImage.size();
652  }
653  return QVariant();
654 }
655 
656 QSizeF QgsImageLegendNode::drawSymbol( const QgsLegendSettings &settings, ItemContext *ctx, double itemHeight ) const
657 {
658  Q_UNUSED( itemHeight )
659 
660  if ( ctx && ctx->painter )
661  {
662  ctx->painter->drawImage( QRectF( ctx->point.x(), ctx->point.y(), settings.wmsLegendSize().width(), settings.wmsLegendSize().height() ),
663  mImage, QRectF( 0, 0, mImage.width(), mImage.height() ) );
664  }
665  return settings.wmsLegendSize();
666 }
667 
669 {
670  QByteArray byteArray;
671  QBuffer buffer( &byteArray );
672  mImage.save( &buffer, "PNG" );
673  const QString base64 = QString::fromLatin1( byteArray.toBase64().data() );
674  json[ "icon" ] = base64;
675 }
676 
677 // -------------------------------------------------------------------------
678 
679 QgsRasterSymbolLegendNode::QgsRasterSymbolLegendNode( QgsLayerTreeLayer *nodeLayer, const QColor &color, const QString &label, QObject *parent )
680  : QgsLayerTreeModelLegendNode( nodeLayer, parent )
681  , mColor( color )
682  , mLabel( label )
683 {
684 }
685 
686 QVariant QgsRasterSymbolLegendNode::data( int role ) const
687 {
688  if ( role == Qt::DecorationRole )
689  {
690  const int iconSize = QgsLayerTreeModel::scaleIconSize( 16 ); // TODO: configurable?
691  QPixmap pix( iconSize, iconSize );
692  pix.fill( mColor );
693  return QIcon( pix );
694  }
695  else if ( role == Qt::DisplayRole || role == Qt::EditRole )
696  return mUserLabel.isEmpty() ? mLabel : mUserLabel;
697  else
698  return QVariant();
699 }
700 
701 
702 QSizeF QgsRasterSymbolLegendNode::drawSymbol( const QgsLegendSettings &settings, ItemContext *ctx, double itemHeight ) const
703 {
704  if ( ctx && ctx->painter )
705  {
706  QColor itemColor = mColor;
707  if ( QgsRasterLayer *rasterLayer = qobject_cast<QgsRasterLayer *>( layerNode()->layer() ) )
708  {
709  if ( QgsRasterRenderer *rasterRenderer = rasterLayer->renderer() )
710  itemColor.setAlpha( rasterRenderer->opacity() * 255.0 );
711  }
712  ctx->painter->setBrush( itemColor );
713 
714  if ( settings.drawRasterStroke() )
715  {
716  QPen pen;
717  pen.setColor( settings.rasterStrokeColor() );
718  pen.setWidthF( settings.rasterStrokeWidth() );
719  pen.setJoinStyle( Qt::MiterJoin );
720  ctx->painter->setPen( pen );
721  }
722  else
723  {
724  ctx->painter->setPen( Qt::NoPen );
725  }
726 
727  ctx->painter->drawRect( QRectF( ctx->point.x(), ctx->point.y() + ( itemHeight - settings.symbolSize().height() ) / 2,
728  settings.symbolSize().width(), settings.symbolSize().height() ) );
729  }
730  return settings.symbolSize();
731 }
732 
733 void QgsRasterSymbolLegendNode::exportSymbolToJson( const QgsLegendSettings &settings, const QgsRenderContext &, QJsonObject &json ) const
734 {
735  QImage img = QImage( settings.symbolSize().toSize(), QImage::Format_ARGB32 );
736  img.fill( Qt::transparent );
737 
738  QPainter painter( &img );
739  painter.setRenderHint( QPainter::Antialiasing );
740 
741  QColor itemColor = mColor;
742  if ( QgsRasterLayer *rasterLayer = qobject_cast<QgsRasterLayer *>( layerNode()->layer() ) )
743  {
744  if ( QgsRasterRenderer *rasterRenderer = rasterLayer->renderer() )
745  itemColor.setAlpha( rasterRenderer->opacity() * 255.0 );
746  }
747  painter.setBrush( itemColor );
748 
749  if ( settings.drawRasterStroke() )
750  {
751  QPen pen;
752  pen.setColor( settings.rasterStrokeColor() );
753  pen.setWidthF( settings.rasterStrokeWidth() );
754  pen.setJoinStyle( Qt::MiterJoin );
755  painter.setPen( pen );
756  }
757  else
758  {
759  painter.setPen( Qt::NoPen );
760  }
761 
762  painter.drawRect( QRectF( 0, 0, settings.symbolSize().width(), settings.symbolSize().height() ) );
763 
764  QByteArray byteArray;
765  QBuffer buffer( &byteArray );
766  img.save( &buffer, "PNG" );
767  const QString base64 = QString::fromLatin1( byteArray.toBase64().data() );
768  json[ "icon" ] = base64;
769 }
770 
771 // -------------------------------------------------------------------------
772 
774  : QgsLayerTreeModelLegendNode( nodeLayer, parent )
775  , mValid( false )
776 {
777 }
778 
779 QImage QgsWmsLegendNode::getLegendGraphic() const
780 {
781  if ( ! mValid && ! mFetcher )
782  {
783  // or maybe in presence of a downloader we should just delete it
784  // and start a new one ?
785 
786  QgsRasterLayer *layer = qobject_cast<QgsRasterLayer *>( mLayerNode->layer() );
787  const QgsLayerTreeModel *mod = model();
788  if ( ! mod )
789  return mImage;
790  const QgsMapSettings *ms = mod->legendFilterMapSettings();
791 
792  QgsRasterDataProvider *prov = layer->dataProvider();
793  if ( ! prov )
794  return mImage;
795 
796  Q_ASSERT( ! mFetcher );
797  mFetcher.reset( prov->getLegendGraphicFetcher( ms ) );
798  if ( mFetcher )
799  {
800  connect( mFetcher.get(), &QgsImageFetcher::finish, this, &QgsWmsLegendNode::getLegendGraphicFinished );
801  connect( mFetcher.get(), &QgsImageFetcher::error, this, &QgsWmsLegendNode::getLegendGraphicErrored );
802  connect( mFetcher.get(), &QgsImageFetcher::progress, this, &QgsWmsLegendNode::getLegendGraphicProgress );
803  mFetcher->start();
804  } // else QgsDebugMsg("XXX No legend supported?");
805 
806  }
807 
808  return mImage;
809 }
810 
811 QVariant QgsWmsLegendNode::data( int role ) const
812 {
813  //QgsDebugMsg( QStringLiteral("XXX data called with role %1 -- mImage size is %2x%3").arg(role).arg(mImage.width()).arg(mImage.height()) );
814 
815  if ( role == Qt::DecorationRole )
816  {
817  return QPixmap::fromImage( getLegendGraphic() );
818  }
819  else if ( role == Qt::SizeHintRole )
820  {
821  return getLegendGraphic().size();
822  }
823  return QVariant();
824 }
825 
826 QSizeF QgsWmsLegendNode::drawSymbol( const QgsLegendSettings &settings, ItemContext *ctx, double itemHeight ) const
827 {
828  Q_UNUSED( itemHeight )
829 
830  if ( ctx && ctx->painter )
831  {
832  ctx->painter->drawImage( QRectF( ctx->point, settings.wmsLegendSize() ),
833  mImage,
834  QRectF( QPointF( 0, 0 ), mImage.size() ) );
835  }
836  return settings.wmsLegendSize();
837 }
838 
840 {
841  QByteArray byteArray;
842  QBuffer buffer( &byteArray );
843  mImage.save( &buffer, "PNG" );
844  const QString base64 = QString::fromLatin1( byteArray.toBase64().data() );
845  json[ "icon" ] = base64;
846 }
847 
848 /* private */
849 QImage QgsWmsLegendNode::renderMessage( const QString &msg ) const
850 {
851  const int fontHeight = 10;
852  const int margin = fontHeight / 2;
853  const int nlines = 1;
854 
855  const int w = 512, h = fontHeight * nlines + margin * ( nlines + 1 );
856  QImage image( w, h, QImage::Format_ARGB32_Premultiplied );
857  QPainter painter;
858  painter.begin( &image );
859  painter.setPen( QColor( 255, 0, 0 ) );
860  painter.setFont( QFont( QStringLiteral( "Chicago" ), fontHeight ) );
861  painter.fillRect( 0, 0, w, h, QColor( 255, 255, 255 ) );
862  painter.drawText( 0, margin + fontHeight, msg );
863  //painter.drawText(0,2*(margin+fontHeight),tr("retrying in 5 seconds…"));
864  painter.end();
865 
866  return image;
867 }
868 
869 void QgsWmsLegendNode::getLegendGraphicProgress( qint64 cur, qint64 tot )
870 {
871  QString msg = QStringLiteral( "Downloading... %1/%2" ).arg( cur ).arg( tot );
872  //QgsDebugMsg ( QString("XXX %1").arg(msg) );
873  mImage = renderMessage( msg );
874  emit dataChanged();
875 }
876 
877 void QgsWmsLegendNode::getLegendGraphicErrored( const QString &msg )
878 {
879  if ( ! mFetcher ) return; // must be coming after finish
880 
881  mImage = renderMessage( msg );
882  //QgsDebugMsg( QStringLiteral("XXX emitting dataChanged after writing an image of %1x%2").arg(mImage.width()).arg(mImage.height()) );
883 
884  emit dataChanged();
885 
886  mFetcher.reset();
887 
888  mValid = true; // we consider it valid anyway
889  // ... but remove validity after 5 seconds
890  //QTimer::singleShot(5000, this, SLOT(invalidateMapBasedData()));
891 }
892 
893 void QgsWmsLegendNode::getLegendGraphicFinished( const QImage &image )
894 {
895  if ( ! mFetcher ) return; // must be coming after error
896 
897  //QgsDebugMsg( QStringLiteral("XXX legend graphic finished, image is %1x%2").arg(theImage.width()).arg(theImage.height()) );
898  if ( ! image.isNull() )
899  {
900  if ( image != mImage )
901  {
902  mImage = image;
903  //QgsDebugMsg( QStringLiteral("XXX emitting dataChanged") );
904  emit dataChanged();
905  }
906  mValid = true; // only if not null I guess
907  }
908  mFetcher.reset();
909 }
910 
912 {
913  //QgsDebugMsg( QStringLiteral("XXX invalidateMapBasedData called") );
914  // TODO: do this only if this extent != prev extent ?
915  mValid = false;
916  emit dataChanged();
917 }
918 
919 // -------------------------------------------------------------------------
920 
922  : QgsLayerTreeModelLegendNode( nodeLayer, parent )
923  , mSettings( new QgsDataDefinedSizeLegend( settings ) )
924 {
925 }
926 
928 {
929  delete mSettings;
930 }
931 
932 QVariant QgsDataDefinedSizeLegendNode::data( int role ) const
933 {
934  if ( role == Qt::DecorationRole )
935  {
936  cacheImage();
937  return QPixmap::fromImage( mImage );
938  }
939  else if ( role == Qt::SizeHintRole )
940  {
941  cacheImage();
942  return mImage.size();
943  }
944  return QVariant();
945 }
946 
948 {
949  // setup temporary render context
950  QgsRenderContext context;
951  context.setScaleFactor( settings.dpi() / 25.4 );
952  context.setRendererScale( settings.mapScale() );
953  context.setMapToPixel( QgsMapToPixel( 1 / ( settings.mmPerMapUnit() * context.scaleFactor() ) ) );
954  context.setForceVectorOutput( true );
955 
956  if ( ctx && ctx->painter )
957  {
958  context.setPainter( ctx->painter );
959  ctx->painter->save();
960  ctx->painter->setRenderHint( QPainter::Antialiasing );
961  ctx->painter->translate( ctx->point );
962  ctx->painter->scale( 1 / context.scaleFactor(), 1 / context.scaleFactor() );
963  }
964 
965  QgsDataDefinedSizeLegend ddsLegend( *mSettings );
966  ddsLegend.setFont( settings.style( QgsLegendStyle::SymbolLabel ).font() );
967  ddsLegend.setTextColor( settings.fontColor() );
968 
969  QSize contentSize;
970  int labelXOffset;
971  ddsLegend.drawCollapsedLegend( context, &contentSize, &labelXOffset );
972 
973  if ( ctx && ctx->painter )
974  ctx->painter->restore();
975 
976  ItemMetrics im;
977  im.symbolSize = QSizeF( ( contentSize.width() - labelXOffset ) / context.scaleFactor(), contentSize.height() / context.scaleFactor() );
978  im.labelSize = QSizeF( labelXOffset / context.scaleFactor(), contentSize.height() / context.scaleFactor() );
979  return im;
980 }
981 
982 
983 void QgsDataDefinedSizeLegendNode::cacheImage() const
984 {
985  if ( mImage.isNull() )
986  {
987  std::unique_ptr<QgsRenderContext> context( createTemporaryRenderContext() );
988  if ( !context )
989  {
990  context.reset( new QgsRenderContext );
991  context->setScaleFactor( 96 / 25.4 );
992  }
993  mImage = mSettings->collapsedLegendImage( *context );
994  }
995 }
void exportSymbolToJson(const QgsLegendSettings &settings, const QgsRenderContext &context, QJsonObject &json) const override
Adds a symbol in base64 string within a JSON object with the key "icon".
void setForceVectorOutput(bool force)
Sets whether rendering operations should use vector operations instead of any faster raster shortcuts...
void drawText(QPainter *p, double x, double y, const QString &text, const QFont &font) const
Draws Text.
virtual QgsLegendSymbolList legendSymbolItems() const
Returns a list of symbology items for the legend.
QgsRenderContext * context
Render context, if available.
QgsDataDefinedSizeLegendNode(QgsLayerTreeLayer *nodeLayer, const QgsDataDefinedSizeLegend &settings, QObject *parent=nullptr)
Construct the node using QgsDataDefinedSizeLegend as definition of the node&#39;s appearance.
virtual Qt::ItemFlags flags() const
Returns item flags associated with the item. Default implementation returns Qt::ItemIsEnabled.
double mapScale() const
Returns the legend map scale.
QgsRenderContext * createTemporaryRenderContext() const
Returns a temporary context or nullptr if legendMapViewData are not valid.
QList< QgsLegendSymbolItem > QgsLegendSymbolList
Text at point of origin draw mode.
QgsSymbol * symbol() const
Returns associated symbol. May be nullptr.
Abstract base class for all rendered symbols.
Definition: qgssymbol.h:61
QString ruleKey() const
Returns unique identifier of the rule for identification of the item within renderer.
bool useAdvancedEffects() const
QVariant data(int role) const override
Returns data associated with the item. Must be implemented in derived class.
virtual QSizeF drawSymbol(const QgsLegendSettings &settings, ItemContext *ctx, double itemHeight) const
Draws symbol on the left side of the item.
void setFont(const QFont &font)
Sets font used for rendering of labels - only valid for collapsed legend.
Use antialiasing while drawing.
QgsImageLegendNode(QgsLayerTreeLayer *nodeLayer, const QImage &img, QObject *parent=nullptr)
Constructor for QgsImageLegendNode.
virtual bool setData(const QVariant &value, int role)
Sets some data associated with the item. Default implementation does nothing and returns false...
QStringList evaluateItemText(const QString &text, const QgsExpressionContext &context) const
Splits a string using the wrap char taking into account handling empty wrap char which means no wrapp...
This class provides qgis with the ability to render raster datasets onto the mapcanvas.
QgsSymbolLegendNode(QgsLayerTreeLayer *nodeLayer, const QgsLegendSymbolItem &item, QObject *parent=nullptr)
Constructor for QgsSymbolLegendNode.
QVariant data(int role) const override
Returns data associated with the item. Must be implemented in derived class.
bool testFlag(Flag f) const
Check whether a flag is enabled.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:265
void emitStyleChanged()
Triggers an emission of the styleChanged() signal.
void setRendererScale(double scale)
Sets the renderer map scale.
QFont font() const
The font for this style.
virtual QgsImageFetcher * getLegendGraphicFetcher(const QgsMapSettings *mapSettings)
Returns a new image downloader for the raster legend.
void invalidateMapBasedData() override
Notification from model that information from associated map view has changed.
void invalidateMapBasedData() override
Notification from model that information from associated map view has changed.
QgsLayerTreeLayer * layerNode() const
Returns pointer to the parent layer node.
QVariant data(int role) const override
Returns data associated with the item. Must be implemented in derived class.
bool drawRasterStroke() const
Returns whether a stroke will be drawn around raster symbol items.
Line symbol.
Definition: qgssymbol.h:86
double textWidthMillimeters(const QFont &font, const QString &text) const
Returns the font width in millimeters (considers upscaling and downscaling with FONT_WORKAROUND_SCALE...
void exportSymbolToJson(const QgsLegendSettings &settings, const QgsRenderContext &context, QJsonObject &json) const override
Adds a symbol in base64 string within a JSON object with the key "icon".
QgsLayerTreeModelLegendNode(QgsLayerTreeLayer *nodeL, QObject *parent=nullptr)
Construct the node with pointer to its parent layer node.
QString label() const
Returns text label.
QgsWmsLegendNode(QgsLayerTreeLayer *nodeLayer, QObject *parent=nullptr)
Constructor for QgsWmsLegendNode.
QSizeF drawSymbol(const QgsLegendSettings &settings, ItemContext *ctx, double itemHeight) const override
Draws symbol on the left side of the item.
A marker symbol type, for rendering Point and MultiPoint geometries.
Definition: qgssymbol.h:766
QColor rasterStrokeColor() const
Returns the stroke color for the stroke drawn around raster symbol items.
void exportSymbolToJson(const QgsLegendSettings &settings, const QgsRenderContext &context, QJsonObject &json) const override
Adds a symbol in base64 string within a JSON object with the key "icon".
The QgsMapSettings class contains configuration for rendering of the map.
QgsUnitTypes::RenderUnit outputUnit() const
Returns the units to use for sizes and widths within the symbol.
Definition: qgssymbol.cpp:230
void toggleAllItems()
Toggle all items belonging to the same layer as this node.
QSize minimumIconSize() const
Calculates the minimum icon size to prevent cropping.
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:37
The QgsLayerTreeModel class is model implementation for Qt item views framework.
QSizeF wmsLegendSize() const
Rule key of the parent legend node - for legends with tree hierarchy (QString). Added in 2...
QgsLegendStyle style(QgsLegendStyle::Style s) const
Returns style.
QgsRasterDataProvider * dataProvider() override
Returns the layer&#39;s data provider, it may be nullptr.
QImage collapsedLegendImage(QgsRenderContext &context, const QColor &backgroundColor=Qt::transparent, double paddingMM=1) const
Returns output image that would be shown in the legend. Returns invalid image if legend is not config...
void exportSymbolToJson(const QgsLegendSettings &settings, const QgsRenderContext &context, QJsonObject &json) const override
Adds a symbol in base64 string within a JSON object with the key "icon".
QString name() const override
Returns the layer&#39;s name.
void setScaleFactor(double factor)
Sets the scaling factor for the render to convert painter units to physical sizes.
QSizeF drawSymbol(const QgsLegendSettings &settings, ItemContext *ctx, double itemHeight) const override
Draws symbol on the left side of the item.
void triggerRepaint(bool deferredUpdate=false)
Will advise the map canvas (and any other interested party) that this layer requires to be repainted...
static int scaleIconSize(int standardSize)
Scales an layer tree model icon size to compensate for display pixel density, making the icon size hi...
Qt::ItemFlags flags() const override
Returns item flags associated with the item. Default implementation returns Qt::ItemIsEnabled.
void setSymbol(QgsSymbol *s)
Sets the symbol of the item.
QgsRasterSymbolLegendNode(QgsLayerTreeLayer *nodeLayer, const QColor &color, const QString &label, QObject *parent=nullptr)
Constructor for QgsRasterSymbolLegendNode.
long featureCount(const QString &legendKey) const
Number of features rendered with specified legend key.
void checkAllItems()
Checks all items belonging to the same layer as this node.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void error(const QString &msg)
Emitted when an error occurs.
double rasterStrokeWidth() const
Returns the stroke width (in millimeters) for the stroke drawn around raster symbol items...
QgsLayerTreeModel * model() const
Returns pointer to model owning this legend node.
The QgsLegendSettings class stores the appearance and layout settings for legend drawing with QgsLege...
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...
ItemMetrics draw(const QgsLegendSettings &settings, ItemContext *ctx) override
Entry point called from QgsLegendRenderer to do the rendering.
void drawPreviewIcon(QPainter *painter, QSize size, QgsRenderContext *customContext=nullptr)
Draws an icon of the symbol that occupies an area given by size using the specified painter...
Definition: qgssymbol.cpp:491
void setPainter(QPainter *p)
Sets the destination QPainter for the render operation.
virtual bool legendSymbolItemChecked(const QString &key)
items of symbology items in legend is checked
QgsFeatureRenderer * renderer()
Returns renderer.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer&#39;s project and layer.
void dataChanged()
Emitted on internal data change so the layer tree model can forward the signal to views...
QSize iconSize(bool dockableToolbar)
Returns the user-preferred size of a window&#39;s toolbar icons.
void symbolFeatureCountMapChanged()
Emitted when the feature count for symbols on this layer has been recalculated.
virtual void checkLegendSymbolItem(const QString &key, bool state=true)
item in symbology was checked
virtual void setLegendSymbolItem(const QString &key, QgsSymbol *symbol)
Sets the symbol to be used for a legend symbol item.
nlohmann::json json
Definition: qgsjsonutils.h:27
bool isCheckable() const
Returns whether the item is user-checkable - whether renderer supports enabling/disabling it...
QSizeF drawSymbol(const QgsLegendSettings &settings, ItemContext *ctx, double itemHeight) const override
Draws symbol on the left side of the item.
QSizeF symbolSize() const
static void drawText(const QRectF &rect, double rotation, HAlignment alignment, const QStringList &textLines, QgsRenderContext &context, const QgsTextFormat &format, bool drawAsOutlines=true)
Draws text within a rectangle using the specified settings.
double fontHeightCharacterMM(const QFont &font, QChar c) const
Returns the font height of a character in millimeters.
virtual ItemMetrics draw(const QgsLegendSettings &settings, ItemContext *ctx)
Entry point called from QgsLegendRenderer to do the rendering.
QgsExpressionContext & expressionContext()
Gets the expression context.
void setEmbeddedInParent(bool embedded) override
QgsMapLayer * layer() const
Returns the map layer associated with this node.
void setSymbol(QgsSymbol *symbol)
Sets the symbol to be used by the legend node.
const QgsSymbol * symbol() const
Returns the symbol used by the legend node.
void exportToJson(const QgsLegendSettings &settings, const QgsRenderContext &context, QJsonObject &json)
Entry point called from QgsLegendRenderer to do the rendering in a JSON object.
Marker symbol.
Definition: qgssymbol.h:85
QgsSimpleLegendNode(QgsLayerTreeLayer *nodeLayer, const QString &label, const QIcon &icon=QIcon(), QObject *parent=nullptr, const QString &key=QString())
Constructor for QgsSimpleLegendNode.
virtual void setEmbeddedInParent(bool embedded)
QFont scaledFont(const QgsRenderContext &context) const
Returns a font with the size scaled to match the format&#39;s size settings (including units and map unit...
The class stores information about one class/rule of a vector layer renderer in a unified way that ca...
Contains information about the context of a rendering operation.
SymbolType type() const
Returns the symbol&#39;s type.
Definition: qgssymbol.h:120
QSizeF drawSymbol(const QgsLegendSettings &settings, ItemContext *ctx, double itemHeight) const override
Draws symbol on the left side of the item.
QPointF point
Top-left corner of the legend item.
bool setData(const QVariant &value, int role) override
Sets some data associated with the item. Default implementation does nothing and returns false...
virtual void exportSymbolToJson(const QgsLegendSettings &settings, const QgsRenderContext &context, QJsonObject &json) const
Adds a symbol in base64 string within a JSON object with the key "icon".
void setMapToPixel(const QgsMapToPixel &mtp)
Sets the context&#39;s map to pixel transform, which transforms between map coordinates and device coordi...
virtual QVariant data(int role) const =0
Returns data associated with the item. Must be implemented in derived class.
void legendMapViewData(double *mapUnitsPerPixel, int *dpi, double *scale) const
Gets hints about map view - to be used in legend nodes.
static QRect nonTransparentImageRect(const QImage &image, QSize minSize=QSize(), bool center=false)
Calculates the non-transparent region of an image.
The QgsLegendRendererItem class is abstract interface for legend items returned from QgsMapLayerLegen...
void setFlag(Flag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
QVariant data(int role) const override
Returns data associated with the item. Must be implemented in derived class.
void uncheckAllItems()
Unchecks all items belonging to the same layer as this node.
void appendScopes(const QList< QgsExpressionContextScope *> &scopes)
Appends a list of scopes to the end of the context.
void setTextColor(const QColor &color)
Sets text color for rendering of labels - only valid for collapsed legend.
virtual QSizeF drawSymbolText(const QgsLegendSettings &settings, ItemContext *ctx, QSizeF symbolSize) const
Draws label on the right side of the item.
QString parentRuleKey() const
Key of the parent legend node.
QVariant data(int role) const override
Returns data associated with the item. Must be implemented in derived class.
void drawCollapsedLegend(QgsRenderContext &context, QSize *outputSize SIP_OUT=nullptr, int *labelXOffset SIP_OUT=nullptr) const
Draw the legend if using LegendOneNodeForAll and optionally output size of the legend and x offset of...
double lineSpacing() const
For legends that support it, will show them in a tree instead of a list (needs also ShowLegend)...
QColor fontColor() const
static double textWidth(const QgsRenderContext &context, const QgsTextFormat &format, const QStringList &textLines, QFontMetricsF *fontMetrics=nullptr)
Returns the width of a text based on a given format.
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.
double labelXOffset
offset from the left side where label should start
void finish(const QImage &legend)
Emitted when the download completes.
Object that keeps configuration of appearance of marker symbol&#39;s data-defined size in legend...
QVariant data(int role) const override
Returns data associated with the item. Must be implemented in derived class.
int level() const
Indentation level that tells how deep the item is in a hierarchy of items. For flat lists level is 0...
double fontDescentMillimeters(const QFont &font) const
Returns the font descent in Millimeters (considers upscaling and downscaling with FONT_WORKAROUND_SCA...
double mmPerMapUnit() const
Raster renderer pipe that applies colors to a raster.
void exportSymbolTextToJson(const QgsLegendSettings &settings, QJsonObject &json) const
Adds a label in a JSON object with the key "title".
void progress(qint64 received, qint64 total)
Emitted to report progress.
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
Layer tree node points to a map layer.
Base class for raster data providers.
static double textHeight(const QgsRenderContext &context, const QgsTextFormat &format, const QStringList &textLines, DrawMode mode, QFontMetricsF *fontMetrics=nullptr)
Returns the height of a text based on a given format.
static QPixmap symbolPreviewPixmap(const QgsSymbol *symbol, QSize size, int padding=0, QgsRenderContext *customContext=nullptr)
Returns a pixmap preview for a color ramp.