QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
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 
21 #include "qgslayertree.h"
22 #include "qgslayertreemodel.h"
23 #include "qgslegendsettings.h"
24 #include "qgsrasterlayer.h"
25 #include "qgsrendererv2.h"
26 #include "qgssymbollayerv2utils.h"
27 #include "qgsimageoperation.h"
28 #include "qgsvectorlayer.h"
29 
30 
31 
33  : QObject( parent )
34  , mLayerNode( nodeL )
35  , mEmbeddedInParent( false )
36 {
37 }
38 
40 {
41 }
42 
44 {
45  return qobject_cast<QgsLayerTreeModel*>( parent() );
46 }
47 
49 {
50  return Qt::ItemIsEnabled;
51 }
52 
53 bool QgsLayerTreeModelLegendNode::setData( const QVariant& value, int role )
54 {
55  Q_UNUSED( value );
56  Q_UNUSED( role );
57  return false;
58 }
59 
60 
62 {
63  QFont symbolLabelFont = settings.style( QgsComposerLegendStyle::SymbolLabel ).font();
64 
65  double textHeight = settings.fontHeightCharacterMM( symbolLabelFont, QChar( '0' ) );
66  // itemHeight here is not realy item height, it is only for symbol
67  // vertical alignment purpose, i.e. ok take single line height
68  // if there are more lines, thos run under the symbol
69  double itemHeight = qMax( static_cast< double >( settings.symbolSize().height() ), textHeight );
70 
71  ItemMetrics im;
72  im.symbolSize = drawSymbol( settings, ctx, itemHeight );
73  im.labelSize = drawSymbolText( settings, ctx, im.symbolSize );
74  return im;
75 }
76 
77 
78 QSizeF QgsLayerTreeModelLegendNode::drawSymbol( const QgsLegendSettings& settings, ItemContext* ctx, double itemHeight ) const
79 {
80  QIcon symbolIcon = data( Qt::DecorationRole ).value<QIcon>();
81  if ( symbolIcon.isNull() )
82  return QSizeF();
83 
84  if ( ctx )
85  symbolIcon.paint( ctx->painter, ctx->point.x(), ctx->point.y() + ( itemHeight - settings.symbolSize().height() ) / 2,
86  settings.symbolSize().width(), settings.symbolSize().height() );
87  return settings.symbolSize();
88 }
89 
90 
92 {
93  QSizeF labelSize( 0, 0 );
94 
95  QFont symbolLabelFont = settings.style( QgsComposerLegendStyle::SymbolLabel ).font();
96  double textHeight = settings.fontHeightCharacterMM( symbolLabelFont, QChar( '0' ) );
97 
98  QStringList lines = settings.splitStringForWrapping( data( Qt::DisplayRole ).toString() );
99 
100  labelSize.rheight() = lines.count() * textHeight + ( lines.count() - 1 ) * settings.lineSpacing();
101 
102  double labelX = 0.0, labelY = 0.0;
103  if ( ctx )
104  {
105  ctx->painter->setPen( settings.fontColor() );
106 
107  labelX = ctx->point.x() + qMax( static_cast< double >( symbolSize.width() ), ctx->labelXOffset );
108  labelY = ctx->point.y();
109 
110  // Vertical alignment of label with symbol
111  if ( labelSize.height() < symbolSize.height() )
112  labelY += symbolSize.height() / 2 - labelSize.height() / 2; // label centered with symbol
113 
114  labelY += textHeight;
115  }
116 
117  for ( QStringList::Iterator itemPart = lines.begin(); itemPart != lines.end(); ++itemPart )
118  {
119  labelSize.rwidth() = qMax( settings.textWidthMillimeters( symbolLabelFont, *itemPart ), double( labelSize.width() ) );
120 
121  if ( ctx )
122  {
123  settings.drawText( ctx->painter, labelX, labelY, *itemPart, symbolLabelFont );
124  if ( itemPart != lines.end() )
125  labelY += settings.lineSpacing() + textHeight;
126  }
127  }
128 
129  return labelSize;
130 }
131 
132 // -------------------------------------------------------------------------
133 
134 
136  : QgsLayerTreeModelLegendNode( nodeLayer, parent )
137  , mItem( item )
138  , mSymbolUsesMapUnits( false )
139  , mIconSize( 16, 16 )
140 {
141  updateLabel();
142 
143  if ( mItem.symbol() )
144  mSymbolUsesMapUnits = ( mItem.symbol()->outputUnit() != QgsSymbolV2::MM );
145 }
146 
148 {
149 }
150 
152 {
153  if ( mItem.isCheckable() )
154  return Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
155  else
156  return Qt::ItemIsEnabled;
157 }
158 
159 
161 {
162  QSize minSz( 16, 16 );
163  if ( mItem.symbol() && mItem.symbol()->type() == QgsSymbolV2::Marker )
164  {
165  QScopedPointer<QgsRenderContext> context( createTemporaryRenderContext() );
168  context.data() ).toImage(),
169  minSz,
170  true ).size();
171  }
172  else if ( mItem.symbol() && mItem.symbol()->type() == QgsSymbolV2::Line )
173  {
174  QScopedPointer<QgsRenderContext> context( createTemporaryRenderContext() );
177  context.data() ).toImage(),
178  minSz,
179  true ).size();
180  }
181 
182  if ( mItem.level() != 0 && !( model() && model()->testFlag( QgsLayerTreeModel::ShowLegendAsTree ) ) )
183  minSz.setWidth( mItem.level() * indentSize + minSz.width() );
184 
185  return minSz;
186 }
187 
189 {
190  return mItem.symbol();
191 }
192 
194 {
195  if ( !symbol )
196  return;
197 
198  QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer*>( mLayerNode->layer() );
199  if ( !vlayer || !vlayer->rendererV2() )
200  return;
201 
202  mItem.setSymbol( symbol );
203  vlayer->rendererV2()->setLegendSymbolItem( mItem.ruleKey(), symbol );
204 
205  mPixmap = QPixmap();
206 
207  emit dataChanged();
208  vlayer->triggerRepaint();
209 }
210 
212 {
213  checkAll( true );
214 }
215 
217 {
218  checkAll( false );
219 }
220 
221 inline
222 QgsRenderContext * QgsSymbolV2LegendNode::createTemporaryRenderContext() const
223 {
224  double scale = 0.0;
225  double mupp = 0.0;
226  int dpi = 0;
227  if ( model() )
228  model()->legendMapViewData( &mupp, &dpi, &scale );
229  bool validData = !qgsDoubleNear( mupp, 0.0 ) && dpi != 0 && !qgsDoubleNear( scale, 0.0 );
230 
231  // setup temporary render context
233  context->setScaleFactor( dpi / 25.4 );
234  context->setRendererScale( scale );
235  context->setMapToPixel( QgsMapToPixel( mupp ) );
236  return validData ? context.take() : nullptr;
237 }
238 
239 void QgsSymbolV2LegendNode::checkAll( bool state )
240 {
241  QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer*>( mLayerNode->layer() );
242  if ( !vlayer || !vlayer->rendererV2() )
243  return;
244 
245  QgsLegendSymbolListV2 symbolList = vlayer->rendererV2()->legendSymbolItemsV2();
246  Q_FOREACH ( const QgsLegendSymbolItemV2& item, symbolList )
247  {
248  vlayer->rendererV2()->checkLegendSymbolItem( item.ruleKey(), state );
249  }
250 
251  emit dataChanged();
252  vlayer->triggerRepaint();
253 }
254 
256 {
257  if ( role == Qt::DisplayRole )
258  {
259  return mLabel;
260  }
261  else if ( role == Qt::EditRole )
262  {
263  return mUserLabel.isEmpty() ? mItem.label() : mUserLabel;
264  }
265  else if ( role == Qt::DecorationRole )
266  {
267  if ( mPixmap.isNull() || mPixmap.size() != mIconSize )
268  {
269  QPixmap pix;
270  if ( mItem.symbol() )
271  {
272  QScopedPointer<QgsRenderContext> context( createTemporaryRenderContext() );
273  pix = QgsSymbolLayerV2Utils::symbolPreviewPixmap( mItem.symbol(), mIconSize, context.data() );
274  }
275  else
276  {
277  pix = QPixmap( mIconSize );
278  pix.fill( Qt::transparent );
279  }
280 
281  if ( mItem.level() == 0 || ( model() && model()->testFlag( QgsLayerTreeModel::ShowLegendAsTree ) ) )
282  mPixmap = pix;
283  else
284  {
285  // ident the symbol icon to make it look like a tree structure
286  QPixmap pix2( pix.width() + mItem.level() * indentSize, pix.height() );
287  pix2.fill( Qt::transparent );
288  QPainter p( &pix2 );
289  p.drawPixmap( mItem.level() * indentSize, 0, pix );
290  p.end();
291  mPixmap = pix2;
292  }
293  }
294  return mPixmap;
295  }
296  else if ( role == Qt::CheckStateRole )
297  {
298  if ( !mItem.isCheckable() )
299  return QVariant();
300 
301  QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer*>( mLayerNode->layer() );
302  if ( !vlayer || !vlayer->rendererV2() )
303  return QVariant();
304 
305  return vlayer->rendererV2()->legendSymbolItemChecked( mItem.ruleKey() ) ? Qt::Checked : Qt::Unchecked;
306  }
307  else if ( role == RuleKeyRole )
308  {
309  return mItem.ruleKey();
310  }
311  else if ( role == SymbolV2LegacyRuleKeyRole )
312  {
313  return QVariant::fromValue<void*>( mItem.legacyRuleKey() );
314  }
315  else if ( role == ParentRuleKeyRole )
316  {
317  return mItem.parentRuleKey();
318  }
319 
320  return QVariant();
321 }
322 
323 bool QgsSymbolV2LegendNode::setData( const QVariant& value, int role )
324 {
325  if ( role != Qt::CheckStateRole )
326  return false;
327 
328  if ( !mItem.isCheckable() )
329  return false;
330 
331  QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer*>( mLayerNode->layer() );
332  if ( !vlayer || !vlayer->rendererV2() )
333  return false;
334 
335  vlayer->rendererV2()->checkLegendSymbolItem( mItem.ruleKey(), value == Qt::Checked );
336 
337  emit dataChanged();
338 
339  vlayer->triggerRepaint();
340 
341  return true;
342 }
343 
344 
345 
346 QSizeF QgsSymbolV2LegendNode::drawSymbol( const QgsLegendSettings& settings, ItemContext* ctx, double itemHeight ) const
347 {
348  QgsSymbolV2* s = mItem.symbol();
349  if ( !s )
350  {
351  return QSizeF();
352  }
353 
354  // setup temporary render context
355  QgsRenderContext context;
356  context.setScaleFactor( settings.dpi() / 25.4 );
357  context.setRendererScale( settings.mapScale() );
358  context.setMapToPixel( QgsMapToPixel( 1 / ( settings.mmPerMapUnit() * context.scaleFactor() ) ) );
359  context.setForceVectorOutput( true );
360  context.setPainter( ctx ? ctx->painter : nullptr );
361 
362  //Consider symbol size for point markers
363  double height = settings.symbolSize().height();
364  double width = settings.symbolSize().width();
365 
366  //Center small marker symbols
367  double widthOffset = 0;
368  double heightOffset = 0;
369 
370  if ( QgsMarkerSymbolV2* markerSymbol = dynamic_cast<QgsMarkerSymbolV2*>( s ) )
371  {
372  // allow marker symbol to occupy bigger area if necessary
373  double size = QgsSymbolLayerV2Utils::convertToPainterUnits( context, markerSymbol->size(), markerSymbol->sizeUnit(), markerSymbol->sizeMapUnitScale() ) / context.scaleFactor();
374  height = size;
375  width = size;
376  if ( width < settings.symbolSize().width() )
377  {
378  widthOffset = ( settings.symbolSize().width() - width ) / 2.0;
379  }
380  if ( height < settings.symbolSize().height() )
381  {
382  heightOffset = ( settings.symbolSize().height() - height ) / 2.0;
383  }
384  }
385 
386  if ( ctx )
387  {
388  double currentXPosition = ctx->point.x();
389  double currentYCoord = ctx->point.y() + ( itemHeight - settings.symbolSize().height() ) / 2;
390  QPainter* p = ctx->painter;
391 
392  //setup painter scaling to dots so that raster symbology is drawn to scale
393  double dotsPerMM = context.scaleFactor();
394 
395  int opacity = 255;
396  if ( QgsVectorLayer* vectorLayer = dynamic_cast<QgsVectorLayer*>( layerNode()->layer() ) )
397  opacity = 255 - ( 255 * vectorLayer->layerTransparency() / 100 );
398 
399  p->save();
400  p->setRenderHint( QPainter::Antialiasing );
401  p->translate( currentXPosition + widthOffset, currentYCoord + heightOffset );
402  p->scale( 1.0 / dotsPerMM, 1.0 / dotsPerMM );
403  if ( opacity != 255 && settings.useAdvancedEffects() )
404  {
405  //semi transparent layer, so need to draw symbol to an image (to flatten it first)
406  //create image which is same size as legend rect, in case symbol bleeds outside its alloted space
407  QSize tempImageSize( width * dotsPerMM, height * dotsPerMM );
408  QImage tempImage = QImage( tempImageSize, QImage::Format_ARGB32 );
409  tempImage.fill( Qt::transparent );
410  QPainter imagePainter( &tempImage );
411  context.setPainter( &imagePainter );
412  s->drawPreviewIcon( &imagePainter, tempImageSize, &context );
413  context.setPainter( ctx->painter );
414  //reduce opacity of image
415  imagePainter.setCompositionMode( QPainter::CompositionMode_DestinationIn );
416  imagePainter.fillRect( tempImage.rect(), QColor( 0, 0, 0, opacity ) );
417  imagePainter.end();
418  //draw rendered symbol image
419  p->drawImage( 0, 0, tempImage );
420  }
421  else
422  {
423  s->drawPreviewIcon( p, QSize( width * dotsPerMM, height * dotsPerMM ), &context );
424  }
425  p->restore();
426  }
427 
428  return QSizeF( qMax( width + 2 * widthOffset, static_cast< double >( settings.symbolSize().width() ) ),
429  qMax( height + 2 * heightOffset, static_cast< double >( settings.symbolSize().height() ) ) );
430 }
431 
432 
434 {
436  updateLabel();
437 }
438 
439 
441 {
442  if ( mSymbolUsesMapUnits )
443  {
444  mPixmap = QPixmap();
445  emit dataChanged();
446  }
447 }
448 
449 
450 void QgsSymbolV2LegendNode::updateLabel()
451 {
452  bool showFeatureCount = mLayerNode->customProperty( "showFeatureCount", 0 ).toBool();
453  QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( mLayerNode->layer() );
454 
455  if ( mEmbeddedInParent )
456  {
457  QString layerName = mLayerNode->layerName();
458  if ( !mLayerNode->customProperty( "legend/title-label" ).isNull() )
459  layerName = mLayerNode->customProperty( "legend/title-label" ).toString();
460 
461  mLabel = mUserLabel.isEmpty() ? layerName : mUserLabel;
462  if ( showFeatureCount && vl && vl->featureCount() >= 0 )
463  mLabel += QString( " [%1]" ).arg( vl->featureCount() );
464  }
465  else
466  {
467  mLabel = mUserLabel.isEmpty() ? mItem.label() : mUserLabel;
468  if ( showFeatureCount && vl && mItem.legacyRuleKey() )
469  mLabel += QString( " [%1]" ).arg( vl->featureCount( mItem.legacyRuleKey() ) );
470  }
471 }
472 
473 
474 
475 // -------------------------------------------------------------------------
476 
477 
478 QgsSimpleLegendNode::QgsSimpleLegendNode( QgsLayerTreeLayer* nodeLayer, const QString& label, const QIcon& icon, QObject* parent, const QString& key )
479  : QgsLayerTreeModelLegendNode( nodeLayer, parent )
480  , mLabel( label )
481  , mIcon( icon )
482  , mKey( key )
483 {
484 }
485 
487 {
488  if ( role == Qt::DisplayRole || role == Qt::EditRole )
489  return mUserLabel.isEmpty() ? mLabel : mUserLabel;
490  else if ( role == Qt::DecorationRole )
491  return mIcon;
492  else if ( role == RuleKeyRole && !mKey.isEmpty() )
493  return mKey;
494  else
495  return QVariant();
496 }
497 
498 
499 // -------------------------------------------------------------------------
500 
502  : QgsLayerTreeModelLegendNode( nodeLayer, parent )
503  , mImage( img )
504 {
505 }
506 
508 {
509  if ( role == Qt::DecorationRole )
510  {
511  return QPixmap::fromImage( mImage );
512  }
513  else if ( role == Qt::SizeHintRole )
514  {
515  return mImage.size();
516  }
517  return QVariant();
518 }
519 
520 QSizeF QgsImageLegendNode::drawSymbol( const QgsLegendSettings& settings, ItemContext* ctx, double itemHeight ) const
521 {
522  Q_UNUSED( itemHeight );
523 
524  if ( ctx )
525  {
526  ctx->painter->drawImage( QRectF( ctx->point.x(), ctx->point.y(), settings.wmsLegendSize().width(), settings.wmsLegendSize().height() ),
527  mImage, QRectF( 0, 0, mImage.width(), mImage.height() ) );
528  }
529  return settings.wmsLegendSize();
530 }
531 
532 // -------------------------------------------------------------------------
533 
535  : QgsLayerTreeModelLegendNode( nodeLayer, parent )
536  , mColor( color )
537  , mLabel( label )
538 {
539 }
540 
542 {
543  if ( role == Qt::DecorationRole )
544  {
545  QSize iconSize( 16, 16 ); // TODO: configurable?
546  QPixmap pix( iconSize );
547  pix.fill( mColor );
548  return QIcon( pix );
549  }
550  else if ( role == Qt::DisplayRole || role == Qt::EditRole )
551  return mUserLabel.isEmpty() ? mLabel : mUserLabel;
552  else
553  return QVariant();
554 }
555 
556 
557 QSizeF QgsRasterSymbolLegendNode::drawSymbol( const QgsLegendSettings& settings, ItemContext* ctx, double itemHeight ) const
558 {
559  if ( ctx )
560  {
561  QColor itemColor = mColor;
562  if ( QgsRasterLayer* rasterLayer = dynamic_cast<QgsRasterLayer*>( layerNode()->layer() ) )
563  {
564  if ( QgsRasterRenderer* rasterRenderer = rasterLayer->renderer() )
565  itemColor.setAlpha( rasterRenderer->opacity() * 255.0 );
566  }
567  ctx->painter->setBrush( itemColor );
568 
569  if ( settings.drawRasterBorder() )
570  {
571  QPen pen;
572  pen.setColor( settings.rasterBorderColor() );
573  pen.setWidthF( settings.rasterBorderWidth() );
574  pen.setJoinStyle( Qt::MiterJoin );
575  ctx->painter->setPen( pen );
576  }
577  else
578  {
579  ctx->painter->setPen( Qt::NoPen );
580  }
581 
582  ctx->painter->drawRect( QRectF( ctx->point.x(), ctx->point.y() + ( itemHeight - settings.symbolSize().height() ) / 2,
583  settings.symbolSize().width(), settings.symbolSize().height() ) );
584  }
585  return settings.symbolSize();
586 }
587 
588 // -------------------------------------------------------------------------
589 
591  : QgsLayerTreeModelLegendNode( nodeLayer, parent )
592  , mValid( false )
593 {
594 }
595 
596 const QImage& QgsWMSLegendNode::getLegendGraphic() const
597 {
598  if ( ! mValid && ! mFetcher )
599  {
600  // or maybe in presence of a downloader we should just delete it
601  // and start a new one ?
602 
603  QgsRasterLayer* layer = qobject_cast<QgsRasterLayer*>( mLayerNode->layer() );
604  const QgsLayerTreeModel* mod = model();
605  if ( ! mod ) return mImage;
606  const QgsMapSettings* ms = mod->legendFilterMapSettings();
607 
608  QgsRasterDataProvider* prov = layer->dataProvider();
609 
610  Q_ASSERT( ! mFetcher );
611  mFetcher.reset( prov->getLegendGraphicFetcher( ms ) );
612  if ( mFetcher )
613  {
614  connect( mFetcher.data(), SIGNAL( finish( const QImage& ) ), this, SLOT( getLegendGraphicFinished( const QImage& ) ) );
615  connect( mFetcher.data(), SIGNAL( error( const QString& ) ), this, SLOT( getLegendGraphicErrored( const QString& ) ) );
616  connect( mFetcher.data(), SIGNAL( progress( qint64, qint64 ) ), this, SLOT( getLegendGraphicProgress( qint64, qint64 ) ) );
617  mFetcher->start();
618  } // else QgsDebugMsg("XXX No legend supported?");
619 
620  }
621 
622  return mImage;
623 }
624 
626 {
627  //QgsDebugMsg( QString("XXX data called with role %1 -- mImage size is %2x%3").arg(role).arg(mImage.width()).arg(mImage.height()) );
628 
629  if ( role == Qt::DecorationRole )
630  {
631  return QPixmap::fromImage( getLegendGraphic() );
632  }
633  else if ( role == Qt::SizeHintRole )
634  {
635  return getLegendGraphic().size();
636  }
637  return QVariant();
638 }
639 
640 QSizeF QgsWMSLegendNode::drawSymbol( const QgsLegendSettings& settings, ItemContext* ctx, double itemHeight ) const
641 {
642  Q_UNUSED( itemHeight );
643 
644  if ( ctx )
645  {
646  ctx->painter->drawImage( QRectF( ctx->point, settings.wmsLegendSize() ),
647  mImage,
648  QRectF( QPointF( 0, 0 ), mImage.size() ) );
649  }
650  return settings.wmsLegendSize();
651 }
652 
653 /* private */
654 QImage QgsWMSLegendNode::renderMessage( const QString& msg ) const
655 {
656  const int fontHeight = 10;
657  const int margin = fontHeight / 2;
658  const int nlines = 1;
659 
660  const int w = 512, h = fontHeight * nlines + margin * ( nlines + 1 );
661  QImage theImage( w, h, QImage::Format_ARGB32_Premultiplied );
662  QPainter painter;
663  painter.begin( &theImage );
664  painter.setPen( QColor( 255, 0, 0 ) );
665  painter.setFont( QFont( "Chicago", fontHeight ) );
666  painter.fillRect( 0, 0, w, h, QColor( 255, 255, 255 ) );
667  painter.drawText( 0, margin + fontHeight, msg );
668  //painter.drawText(0,2*(margin+fontHeight),QString("retrying in 5 seconds..."));
669  painter.end();
670 
671  return theImage;
672 }
673 
674 void QgsWMSLegendNode::getLegendGraphicProgress( qint64 cur, qint64 tot )
675 {
676  QString msg = QString( "Downloading... %1/%2" ).arg( cur ).arg( tot );
677  //QgsDebugMsg ( QString("XXX %1").arg(msg) );
678  mImage = renderMessage( msg );
679  emit dataChanged();
680 }
681 
682 void QgsWMSLegendNode::getLegendGraphicErrored( const QString& msg )
683 {
684  if ( ! mFetcher ) return; // must be coming after finish
685 
686  mImage = renderMessage( msg );
687  //QgsDebugMsg( QString("XXX emitting dataChanged after writing an image of %1x%2").arg(mImage.width()).arg(mImage.height()) );
688 
689  emit dataChanged();
690 
691  mFetcher.reset();
692 
693  mValid = true; // we consider it valid anyway
694  // ... but remove validity after 5 seconds
695  //QTimer::singleShot(5000, this, SLOT(invalidateMapBasedData()));
696 }
697 
698 void QgsWMSLegendNode::getLegendGraphicFinished( const QImage& theImage )
699 {
700  if ( ! mFetcher ) return; // must be coming after error
701 
702  //QgsDebugMsg( QString("XXX legend graphic finished, image is %1x%2").arg(theImage.width()).arg(theImage.height()) );
703  if ( ! theImage.isNull() )
704  {
705  if ( theImage != mImage )
706  {
707  mImage = theImage;
708  //QgsDebugMsg( QString("XXX emitting dataChanged") );
709  emit dataChanged();
710  }
711  mValid = true; // only if not null I guess
712  }
713  mFetcher.reset();
714 }
715 
717 {
718  //QgsDebugMsg( QString("XXX invalidateMapBasedData called") );
719  // TODO: do this only if this extent != prev extent ?
720  mValid = false;
721  emit dataChanged();
722 }
void setForceVectorOutput(bool force)
void drawText(QPainter *p, double x, double y, const QString &text, const QFont &font) const
Draws Text.
QSize size() const
void checkAllItems()
Checks all items belonging to the same layer as this node.
QgsWMSLegendNode(QgsLayerTreeLayer *nodeLayer, QObject *parent=nullptr)
virtual Qt::ItemFlags flags() const
Return item flags associated with the item.
double mapScale() const
int width() const
int width() const
bool end()
void fillRect(const QRectF &rectangle, const QBrush &brush)
void setCompositionMode(CompositionMode mode)
bool useAdvancedEffects() const
void setRenderHint(RenderHint hint, bool on)
virtual QSizeF drawSymbol(const QgsLegendSettings &settings, ItemContext *ctx, double itemHeight) const
Draws symbol on the left side of the item.
void fill(const QColor &color)
QgsImageLegendNode(QgsLayerTreeLayer *nodeLayer, const QImage &img, QObject *parent=nullptr)
virtual bool setData(const QVariant &value, int role)
Set some data associated with the item.
virtual QSizeF drawSymbol(const QgsLegendSettings &settings, ItemContext *ctx, double itemHeight) const override
Draws symbol on the left side of the item.
This class provides qgis with the ability to render raster datasets onto the mapcanvas.
virtual QVariant data(int role) const override
Return data associated with the item.
bool testFlag(Flag f) const
Check whether a flag is enabled.
qreal & rwidth()
void scale(qreal sx, qreal sy)
QStringList splitStringForWrapping(const QString &stringToSplt) const
Splits a string using the wrap char taking into account handling empty wrap char which means no wrapp...
QString ruleKey() const
Return unique identifier of the rule for identification of the item within renderer.
void setRendererScale(double scale)
double rasterBorderWidth() const
Returns the border width (in millimeters) for the border drawn around raster symbol items...
virtual QgsImageFetcher * getLegendGraphicFetcher(const QgsMapSettings *mapSettings)
Get an image downloader for the raster legend.
virtual void invalidateMapBasedData() override
Notification from model that information from associated map view has changed.
void save()
QgsLayerTreeLayer * layerNode() const
Return pointer to the parent layer node.
T value() const
QPixmap fromImage(const QImage &image, QFlags< Qt::ImageConversionFlag > flags)
void setJoinStyle(Qt::PenJoinStyle style)
void setAlpha(int alpha)
SymbolType type() const
Definition: qgssymbolv2.h:107
Line symbol.
Definition: qgssymbolv2.h:82
virtual QVariant data(int role) const override
Return data associated with the item.
virtual QgsLegendSymbolListV2 legendSymbolItemsV2() const
Return a list of symbology items for the legend.
virtual QVariant data(int role) const override
Return data associated with the item.
QSizeF drawSymbol(const QgsLegendSettings &settings, ItemContext *ctx, double itemHeight) const override
Draws symbol on the left side of the item.
bool isNull() const
double textWidthMillimeters(const QFont &font, const QString &text) const
Returns the font width in millimeters (considers upscaling and downscaling with FONT_WORKAROUND_SCALE...
virtual Qt::ItemFlags flags() const override
Return item flags associated with the item.
QgsLayerTreeModelLegendNode(QgsLayerTreeLayer *nodeL, QObject *parent=nullptr)
Construct the node with pointer to its parent layer node.
virtual bool legendSymbolItemChecked(const QString &key)
items of symbology items in legend is checked
void drawPreviewIcon(QPainter *painter, QSize size, QgsRenderContext *customContext=nullptr)
Draw icon of the symbol that occupyies area given by size using the painter.
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Compare two doubles (but allow some difference)
Definition: qgis.h:353
QSizeF drawSymbol(const QgsLegendSettings &settings, ItemContext *ctx, double itemHeight) const override
Draws symbol on the left side of the item.
virtual void checkLegendSymbolItem(const QString &key, bool state=true)
item in symbology was checked
Marker symbol.
Definition: qgssymbolv2.h:81
void reset(T *other)
The QgsMapSettings class contains configuration for rendering of the map.
long featureCount(QgsSymbolV2 *symbol)
Number of features rendered with specified symbol.
void drawRect(const QRectF &rectangle)
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:34
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...
void setFont(const QFont &font)
QgsFeatureRendererV2 * rendererV2()
Return renderer V2.
The output shall be in millimeters.
Definition: qgssymbolv2.h:67
QString parentRuleKey() const
Key of the parent legend node.
int count(const T &value) const
qreal x() const
qreal y() const
void setScaleFactor(double factor)
bool isNull() const
void fill(uint pixelValue)
static double convertToPainterUnits(const QgsRenderContext &c, double size, QgsSymbolV2::OutputUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale())
Converts a size from the specied units to painter units.
void setPen(const QColor &color)
int width() const
QgsRasterSymbolLegendNode(QgsLayerTreeLayer *nodeLayer, const QColor &color, const QString &label, QObject *parent=nullptr)
virtual QVariant data(int role) const override
Return data associated with the item.
void drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source)
void setWidth(int width)
virtual void setEmbeddedInParent(bool embedded) override
bool isEmpty() const
QRect rect() const
QgsLayerTreeModel * model() const
Return 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.
void legendMapViewData(double *mapUnitsPerPixel, int *dpi, double *scale)
Get hints about map view - to be used in legend nodes.
QgsComposerLegendStyle style(QgsComposerLegendStyle::Style s) const
Returns style.
void triggerRepaint()
Will advice the map canvas (and any other interested party) that this layer requires to be repainted...
bool isCheckable() const
Return whether the item is user-checkable - whether renderer supports enabling/disabling it...
void setWidthF(qreal width)
void setBrush(const QBrush &brush)
void setPainter(QPainter *p)
void drawText(const QPointF &position, const QString &text)
typedef Iterator
void setColor(const QColor &color)
QString label() const
Return text label.
void paint(QPainter *painter, const QRect &rect, QFlags< Qt::AlignmentFlag > alignment, Mode mode, State state) const
virtual void invalidateMapBasedData() override
Notification from model that information from associated map view has changed.
const QgsSymbolV2 * symbol() const
Returns the symbol used by the legend node.
void dataChanged()
Emitted on internal data change so the layer tree model can forward the signal to views...
T * data() const
iterator end()
bool isNull() const
int height() const
QSizeF symbolSize() const
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.
QgsSymbolV2 * symbol() const
Return associated symbol. May be null.
QgsMapLayer * layer() const
void restore()
virtual bool setData(const QVariant &value, int role) override
Set some data associated with the item.
QgsSymbolV2::OutputUnit outputUnit() const
QgsSimpleLegendNode(QgsLayerTreeLayer *nodeLayer, const QString &label, const QIcon &icon=QIcon(), QObject *parent=nullptr, const QString &key=QString())
virtual void setEmbeddedInParent(bool embedded)
Contains information about the context of a rendering operation.
void drawImage(const QRectF &target, const QImage &image, const QRectF &source, QFlags< Qt::ImageConversionFlag > flags)
QSize minimumIconSize() const
Get the minimum icon size to prevent cropping.
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.
static QPixmap symbolPreviewPixmap(QgsSymbolV2 *symbol, QSize size, QgsRenderContext *customContext=nullptr)
bool isNull() const
void setMapToPixel(const QgsMapToPixel &mtp)
virtual QVariant data(int role) const =0
Return data associated with the item.
QSize size() const
static QRect nonTransparentImageRect(const QImage &image, QSize minSize=QSize(), bool center=false)
Calculates the non-transparent region of an image.
bool toBool() const
The QgsLegendRendererItem class is abstract interface for legend items returned from QgsMapLayerLegen...
void translate(const QPointF &offset)
QgsSymbolV2 * legacyRuleKey() const
Used for older code that identifies legend entries from symbol pointer within renderer.
for QgsSymbolV2LegendNode only - legacy rule key (void ptr, to be cast to QgsSymbolV2 ptr) ...
QString layerName() const
void setSymbol(QgsSymbolV2 *symbol)
Sets the symbol to be used by the legend node.
int height() const
QgsRasterDataProvider * dataProvider()
Returns the data provider.
void uncheckAllItems()
Unchecks all items belonging to the same layer as this node.
virtual QSizeF drawSymbolText(const QgsLegendSettings &settings, ItemContext *ctx, QSizeF symbolSize) const
Draws label on the right side of the item.
int level() const
Identation level that tells how deep the item is in a hierarchy of items. For flat lists level is 0...
QColor rasterBorderColor() const
Returns the border color for the border drawn around raster symbol items.
qreal & rheight()
virtual QVariant data(int role) const override
Return data associated with the item.
double lineSpacing() const
qreal height() const
For legends that support it, will show them in a tree instead of a list (needs also ShowLegend)...
QColor fontColor() const
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
void setSymbol(QgsSymbolV2 *s)
Set symbol of the item. Takes ownership of symbol.
QObject * parent() const
double scaleFactor() const
Represents a vector layer which manages a vector based data sets.
double labelXOffset
offset from the left side where label should start
bool begin(QPaintDevice *device)
bool drawRasterBorder() const
Returns whether a border will be drawn around raster symbol items.
The class stores information about one class/rule of a vector layer renderer in a unified way that ca...
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QString toString() const
double mmPerMapUnit() const
iterator begin()
Raster renderer pipe that applies colors to a raster.
virtual void setLegendSymbolItem(const QString &key, QgsSymbolV2 *symbol)
Sets the symbol to be used for a legend symbol item.
qreal width() const
QgsSymbolV2LegendNode(QgsLayerTreeLayer *nodeLayer, const QgsLegendSymbolItemV2 &item, QObject *parent=nullptr)
Layer tree node points to a map layer.
Base class for raster data providers.
typedef ItemFlags