QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
qgslayoutitempicture.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgslayoutitempicture.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 
18 #include "qgslayoutitempicture.h"
19 #include "qgslayoutitemregistry.h"
20 #include "qgslayout.h"
21 #include "qgslayoutrendercontext.h"
22 #include "qgslayoutreportcontext.h"
23 #include "qgslayoutitemmap.h"
24 #include "qgslayoututils.h"
25 #include "qgsproject.h"
26 #include "qgsexpression.h"
27 #include "qgsvectorlayer.h"
28 #include "qgsmessagelog.h"
29 #include "qgspathresolver.h"
30 #include "qgsproperty.h"
32 #include "qgssymbollayerutils.h"
33 #include "qgssvgcache.h"
34 #include "qgslogger.h"
35 #include "qgsbearingutils.h"
36 #include "qgsmapsettings.h"
37 #include "qgsreadwritecontext.h"
38 #include "qgsimagecache.h"
40 
41 #include <QDomDocument>
42 #include <QDomElement>
43 #include <QFileInfo>
44 #include <QImageReader>
45 #include <QPainter>
46 #include <QSvgRenderer>
47 #include <QNetworkRequest>
48 #include <QNetworkReply>
49 #include <QEventLoop>
50 #include <QCoreApplication>
51 #include <QUrl>
52 
54  : QgsLayoutItem( layout )
55  , mNorthArrowHandler( new QgsLayoutNorthArrowHandler( this ) )
56 {
57  //default to no background
58  setBackgroundEnabled( false );
59 
60  //connect some signals
61 
62  //connect to atlas feature changing
63  //to update the picture source expression
64  connect( &layout->reportContext(), &QgsLayoutReportContext::changed, this, [ = ] { refreshPicture(); } );
65 
66  //connect to layout print resolution changing
68 
69  connect( this, &QgsLayoutItem::sizePositionChanged, this, &QgsLayoutItemPicture::shapeChanged );
70  connect( mNorthArrowHandler, &QgsLayoutNorthArrowHandler::arrowRotationChanged, this, &QgsLayoutItemPicture::updateNorthArrowRotation );
71 }
72 
74 {
76 }
77 
79 {
80  return QgsApplication::getThemeIcon( QStringLiteral( "/mLayoutItemPicture.svg" ) );
81 }
82 
84 {
85  return new QgsLayoutItemPicture( layout );
86 }
87 
89 {
90  QPainter *painter = context.renderContext().painter();
91  const QgsScopedQPainterState painterState( painter );
92  // painter is scaled to dots, so scale back to layout units
93  painter->scale( context.renderContext().scaleFactor(), context.renderContext().scaleFactor() );
94 
95  const bool prevSmoothTransform = painter->testRenderHint( QPainter::RenderHint::SmoothPixmapTransform );
96  if ( mLayout->renderContext().testFlag( QgsLayoutRenderContext::FlagAntialiasing ) )
97  painter->setRenderHint( QPainter::RenderHint::SmoothPixmapTransform, true );
98 
99  //picture resizing
100  if ( mMode != FormatUnknown )
101  {
102  double boundRectWidthMM;
103  double boundRectHeightMM;
104  QRect imageRect;
105  if ( mResizeMode == QgsLayoutItemPicture::Zoom || mResizeMode == QgsLayoutItemPicture::ZoomResizeFrame )
106  {
107  boundRectWidthMM = mPictureWidth;
108  boundRectHeightMM = mPictureHeight;
109  imageRect = QRect( 0, 0, mImage.width(), mImage.height() );
110  }
111  else if ( mResizeMode == QgsLayoutItemPicture::Stretch )
112  {
113  boundRectWidthMM = rect().width();
114  boundRectHeightMM = rect().height();
115  imageRect = QRect( 0, 0, mImage.width(), mImage.height() );
116  }
117  else if ( mResizeMode == QgsLayoutItemPicture::Clip )
118  {
119  boundRectWidthMM = rect().width();
120  boundRectHeightMM = rect().height();
121  const int imageRectWidthPixels = mImage.width();
122  const int imageRectHeightPixels = mImage.height();
123  imageRect = clippedImageRect( boundRectWidthMM, boundRectHeightMM,
124  QSize( imageRectWidthPixels, imageRectHeightPixels ) );
125  }
126  else
127  {
128  boundRectWidthMM = rect().width();
129  boundRectHeightMM = rect().height();
130  imageRect = QRect( 0, 0, mLayout->convertFromLayoutUnits( rect().width(), QgsUnitTypes::LayoutMillimeters ).length() * mLayout->renderContext().dpi() / 25.4,
131  mLayout->convertFromLayoutUnits( rect().height(), QgsUnitTypes::LayoutMillimeters ).length() * mLayout->renderContext().dpi() / 25.4 );
132  }
133 
134  //zoom mode - calculate anchor point and rotation
135  if ( mResizeMode == Zoom )
136  {
137  //TODO - allow placement modes with rotation set. for now, setting a rotation
138  //always places picture in center of frame
139  if ( !qgsDoubleNear( mPictureRotation, 0.0 ) )
140  {
141  painter->translate( rect().width() / 2.0, rect().height() / 2.0 );
142  painter->rotate( mPictureRotation );
143  painter->translate( -boundRectWidthMM / 2.0, -boundRectHeightMM / 2.0 );
144  }
145  else
146  {
147  //shift painter to edge/middle of frame depending on placement
148  const double diffX = rect().width() - boundRectWidthMM;
149  const double diffY = rect().height() - boundRectHeightMM;
150 
151  double dX = 0;
152  double dY = 0;
153  switch ( mPictureAnchor )
154  {
155  case UpperLeft:
156  case MiddleLeft:
157  case LowerLeft:
158  //nothing to do
159  break;
160  case UpperMiddle:
161  case Middle:
162  case LowerMiddle:
163  dX = diffX / 2.0;
164  break;
165  case UpperRight:
166  case MiddleRight:
167  case LowerRight:
168  dX = diffX;
169  break;
170  }
171  switch ( mPictureAnchor )
172  {
173  case UpperLeft:
174  case UpperMiddle:
175  case UpperRight:
176  //nothing to do
177  break;
178  case MiddleLeft:
179  case Middle:
180  case MiddleRight:
181  dY = diffY / 2.0;
182  break;
183  case LowerLeft:
184  case LowerMiddle:
185  case LowerRight:
186  dY = diffY;
187  break;
188  }
189  painter->translate( dX, dY );
190  }
191  }
192  else if ( mResizeMode == ZoomResizeFrame )
193  {
194  if ( !qgsDoubleNear( mPictureRotation, 0.0 ) )
195  {
196  painter->translate( rect().width() / 2.0, rect().height() / 2.0 );
197  painter->rotate( mPictureRotation );
198  painter->translate( -boundRectWidthMM / 2.0, -boundRectHeightMM / 2.0 );
199  }
200  }
201 
202  if ( mMode == FormatSVG )
203  {
204  mSVG.render( painter, QRectF( 0, 0, boundRectWidthMM, boundRectHeightMM ) );
205  }
206  else if ( mMode == FormatRaster )
207  {
208  painter->drawImage( QRectF( 0, 0, boundRectWidthMM, boundRectHeightMM ), mImage, imageRect );
209  }
210  }
211  painter->setRenderHint( QPainter::RenderHint::SmoothPixmapTransform, prevSmoothTransform );
212 }
213 
214 QSizeF QgsLayoutItemPicture::applyItemSizeConstraint( const QSizeF targetSize )
215 {
216  const QSizeF currentPictureSize = pictureSize();
217  QSizeF newSize = targetSize;
218  if ( mResizeMode == QgsLayoutItemPicture::Clip )
219  {
220  mPictureWidth = targetSize.width();
221  mPictureHeight = targetSize.height();
222  }
223  else
224  {
225  if ( mResizeMode == ZoomResizeFrame && !rect().isEmpty() && !( currentPictureSize.isEmpty() ) )
226  {
227  QSizeF targetImageSize;
228  if ( qgsDoubleNear( mPictureRotation, 0.0 ) )
229  {
230  targetImageSize = currentPictureSize;
231  }
232  else
233  {
234  //calculate aspect ratio of bounds of rotated image
235  QTransform tr;
236  tr.rotate( mPictureRotation );
237  const QRectF rotatedBounds = tr.mapRect( QRectF( 0, 0, currentPictureSize.width(), currentPictureSize.height() ) );
238  targetImageSize = QSizeF( rotatedBounds.width(), rotatedBounds.height() );
239  }
240 
241  //if height has changed more than width, then fix width and set height correspondingly
242  //else, do the opposite
243  if ( std::fabs( rect().width() - targetSize.width() ) <
244  std::fabs( rect().height() - targetSize.height() ) )
245  {
246  newSize.setHeight( targetImageSize.height() * newSize.width() / targetImageSize.width() );
247  }
248  else
249  {
250  newSize.setWidth( targetImageSize.width() * newSize.height() / targetImageSize.height() );
251  }
252  }
253  else if ( mResizeMode == FrameToImageSize )
254  {
255  if ( !( currentPictureSize.isEmpty() ) )
256  {
257  const QgsLayoutSize sizeMM = mLayout->convertFromLayoutUnits( currentPictureSize, QgsUnitTypes::LayoutMillimeters );
258  newSize.setWidth( sizeMM.width() * 25.4 / mLayout->renderContext().dpi() );
259  newSize.setHeight( sizeMM.height() * 25.4 / mLayout->renderContext().dpi() );
260  }
261  }
262 
263  //find largest scaling of picture with this rotation which fits in item
264  if ( mResizeMode == Zoom || mResizeMode == ZoomResizeFrame )
265  {
266  const QRectF rotatedImageRect = QgsLayoutUtils::largestRotatedRectWithinBounds( QRectF( 0, 0, currentPictureSize.width(), currentPictureSize.height() ),
267  QRectF( 0, 0, newSize.width(), newSize.height() ), mPictureRotation );
268  mPictureWidth = rotatedImageRect.width();
269  mPictureHeight = rotatedImageRect.height();
270  }
271  else
272  {
273  mPictureWidth = newSize.width();
274  mPictureHeight = newSize.height();
275  }
276 
277  if ( newSize != targetSize )
278  {
279  emit changed();
280  }
281  }
282 
283  return newSize;
284 }
285 
286 QRect QgsLayoutItemPicture::clippedImageRect( double &boundRectWidthMM, double &boundRectHeightMM, QSize imageRectPixels )
287 {
288  const int boundRectWidthPixels = boundRectWidthMM * mLayout->renderContext().dpi() / 25.4;
289  const int boundRectHeightPixels = boundRectHeightMM * mLayout->renderContext().dpi() / 25.4;
290 
291  //update boundRectWidth/Height so that they exactly match pixel bounds
292  boundRectWidthMM = boundRectWidthPixels * 25.4 / mLayout->renderContext().dpi();
293  boundRectHeightMM = boundRectHeightPixels * 25.4 / mLayout->renderContext().dpi();
294 
295  //calculate part of image which fits in bounds
296  int leftClip = 0;
297  int topClip = 0;
298 
299  //calculate left crop
300  switch ( mPictureAnchor )
301  {
302  case UpperLeft:
303  case MiddleLeft:
304  case LowerLeft:
305  leftClip = 0;
306  break;
307  case UpperMiddle:
308  case Middle:
309  case LowerMiddle:
310  leftClip = ( imageRectPixels.width() - boundRectWidthPixels ) / 2;
311  break;
312  case UpperRight:
313  case MiddleRight:
314  case LowerRight:
315  leftClip = imageRectPixels.width() - boundRectWidthPixels;
316  break;
317  }
318 
319  //calculate top crop
320  switch ( mPictureAnchor )
321  {
322  case UpperLeft:
323  case UpperMiddle:
324  case UpperRight:
325  topClip = 0;
326  break;
327  case MiddleLeft:
328  case Middle:
329  case MiddleRight:
330  topClip = ( imageRectPixels.height() - boundRectHeightPixels ) / 2;
331  break;
332  case LowerLeft:
333  case LowerMiddle:
334  case LowerRight:
335  topClip = imageRectPixels.height() - boundRectHeightPixels;
336  break;
337  }
338 
339  return QRect( leftClip, topClip, boundRectWidthPixels, boundRectHeightPixels );
340 }
341 
343 {
344  const QgsExpressionContext scopedContext = createExpressionContext();
345  const QgsExpressionContext *evalContext = context ? context : &scopedContext;
346 
347  mDataDefinedProperties.prepare( *evalContext );
348 
349  QVariant source( mSourcePath );
350 
351  //data defined source set?
352  mHasExpressionError = false;
354  {
355  mMode = FormatUnknown;
356  bool ok = false;
358  source = sourceProperty.value( *evalContext, source, &ok );
359  if ( !ok || !source.canConvert( QMetaType::QString ) )
360  {
361  mHasExpressionError = true;
362  source = QString();
363  QgsMessageLog::logMessage( tr( "Picture expression eval error" ) );
364  }
365  else if ( source.type() != QVariant::ByteArray )
366  {
367  source = source.toString().trimmed();
368  QgsDebugMsgLevel( QStringLiteral( "exprVal PictureSource:%1" ).arg( source.toString() ), 2 );
369  }
370  }
371 
372  loadPicture( source );
373 }
374 
375 void QgsLayoutItemPicture::loadRemotePicture( const QString &url )
376 {
377  //remote location
378 
379  QgsNetworkContentFetcher fetcher;
380  QEventLoop loop;
381  connect( &fetcher, &QgsNetworkContentFetcher::finished, &loop, &QEventLoop::quit );
382  fetcher.fetchContent( QUrl( url ) );
383 
384  //wait until picture fetched
385  loop.exec( QEventLoop::ExcludeUserInputEvents );
386 
387  QNetworkReply *reply = fetcher.reply();
388  if ( reply )
389  {
390  QImageReader imageReader( reply );
391  imageReader.setAutoTransform( true );
392 
393  if ( imageReader.format() == "pdf" )
394  {
395  // special handling for this format -- we need to pass the desired target size onto the image reader
396  // so that it can correctly render the (vector) pdf content at the desired dpi. Otherwise it returns
397  // a very low resolution image (the driver assumes points == pixels!)
398  // For other image formats, we read the original image size only and defer resampling to later in this
399  // function. That gives us more control over the resampling method used.
400 
401  // driver assumes points == pixels, so driver image size is reported assuming 72 dpi.
402  const QSize sizeAt72Dpi = imageReader.size();
403  const QSize sizeAtTargetDpi = sizeAt72Dpi * mLayout->renderContext().dpi() / 72;
404  imageReader.setScaledSize( sizeAtTargetDpi );
405  }
406 
407  mImage = imageReader.read();
408  mMode = FormatRaster;
409  }
410  else
411  {
412  mMode = FormatUnknown;
413  }
414 }
415 
416 void QgsLayoutItemPicture::loadLocalPicture( const QString &path )
417 {
418  QFile pic;
419  pic.setFileName( path );
420 
421  if ( !pic.exists() )
422  {
423  mMode = FormatUnknown;
424  }
425  else
426  {
427  const QFileInfo sourceFileInfo( pic );
428  const QString sourceFileSuffix = sourceFileInfo.suffix();
429  if ( sourceFileSuffix.compare( QLatin1String( "svg" ), Qt::CaseInsensitive ) == 0 )
430  {
431  //try to open svg
433  const QColor fillColor = mDataDefinedProperties.valueAsColor( QgsLayoutObject::PictureSvgBackgroundColor, context, mSvgFillColor );
434  const QColor strokeColor = mDataDefinedProperties.valueAsColor( QgsLayoutObject::PictureSvgStrokeColor, context, mSvgStrokeColor );
435  const double strokeWidth = mDataDefinedProperties.valueAsDouble( QgsLayoutObject::PictureSvgStrokeWidth, context, mSvgStrokeWidth );
436  const QgsStringMap evaluatedParameters = QgsSymbolLayerUtils::evaluatePropertiesMap( svgDynamicParameters(), context );
437 
438  const QByteArray &svgContent = QgsApplication::svgCache()->svgContent( path, rect().width(), fillColor, strokeColor, strokeWidth,
439  1.0, 0, false, evaluatedParameters );
440  mSVG.load( svgContent );
441  if ( mSVG.isValid() )
442  {
443  mMode = FormatSVG;
444  const QRect viewBox = mSVG.viewBox(); //take width/height ratio from view box instead of default size
445  mDefaultSvgSize.setWidth( viewBox.width() );
446  mDefaultSvgSize.setHeight( viewBox.height() );
447  }
448  else
449  {
450  mMode = FormatUnknown;
451  }
452  }
453  else
454  {
455  //try to open raster with QImageReader
456  QImageReader imageReader( pic.fileName() );
457  imageReader.setAutoTransform( true );
458 
459  if ( imageReader.format() == "pdf" )
460  {
461  // special handling for this format -- we need to pass the desired target size onto the image reader
462  // so that it can correctly render the (vector) pdf content at the desired dpi. Otherwise it returns
463  // a very low resolution image (the driver assumes points == pixels!)
464  // For other image formats, we read the original image size only and defer resampling to later in this
465  // function. That gives us more control over the resampling method used.
466 
467  // driver assumes points == pixels, so driver image size is reported assuming 72 dpi.
468  const QSize sizeAt72Dpi = imageReader.size();
469  const QSize sizeAtTargetDpi = sizeAt72Dpi * mLayout->renderContext().dpi() / 72;
470  imageReader.setScaledSize( sizeAtTargetDpi );
471  }
472 
473  if ( imageReader.read( &mImage ) )
474  {
475  mMode = FormatRaster;
476  }
477  else
478  {
479  mMode = FormatUnknown;
480  }
481  }
482  }
483 }
484 
485 void QgsLayoutItemPicture::loadPictureUsingCache( const QString &path )
486 {
487  if ( path.isEmpty() )
488  {
489  mImage = QImage();
490  return;
491  }
492 
493  switch ( mMode )
494  {
495  case FormatUnknown:
496  break;
497 
498  case FormatRaster:
499  {
500  bool fitsInCache = false;
501  bool isMissing = false;
502  mImage = QgsApplication::imageCache()->pathAsImage( path, QSize(), true, 1, fitsInCache, true, mLayout->renderContext().dpi(), -1, &isMissing );
503  if ( mImage.isNull() || isMissing )
504  mMode = FormatUnknown;
505  break;
506  }
507 
508  case FormatSVG:
509  {
511  const QColor fillColor = mDataDefinedProperties.valueAsColor( QgsLayoutObject::PictureSvgBackgroundColor, context, mSvgFillColor );
512  const QColor strokeColor = mDataDefinedProperties.valueAsColor( QgsLayoutObject::PictureSvgStrokeColor, context, mSvgStrokeColor );
513  const double strokeWidth = mDataDefinedProperties.valueAsDouble( QgsLayoutObject::PictureSvgStrokeWidth, context, mSvgStrokeWidth );
514 
515  const QgsStringMap evaluatedParameters = QgsSymbolLayerUtils::evaluatePropertiesMap( svgDynamicParameters(), context );
516 
517  bool isMissingImage = false;
518  const QByteArray &svgContent = QgsApplication::svgCache()->svgContent( path, rect().width(), fillColor, strokeColor, strokeWidth,
519  1.0, 0, false, evaluatedParameters, &isMissingImage );
520  mSVG.load( svgContent );
521  if ( mSVG.isValid() && !isMissingImage )
522  {
523  mMode = FormatSVG;
524  const QRect viewBox = mSVG.viewBox(); //take width/height ratio from view box instead of default size
525  mDefaultSvgSize.setWidth( viewBox.width() );
526  mDefaultSvgSize.setHeight( viewBox.height() );
527  }
528  else
529  {
530  mMode = FormatUnknown;
531  }
532  break;
533  }
534  }
535 }
536 
537 void QgsLayoutItemPicture::updateNorthArrowRotation( double rotation )
538 {
539  setPictureRotation( rotation );
540  emit pictureRotationChanged( rotation );
541 }
542 
543 void QgsLayoutItemPicture::loadPicture( const QVariant &data )
544 {
545  const Format origFormat = mMode;
546  mIsMissingImage = false;
547  QVariant imageData( data );
548  mEvaluatedPath = data.toString();
549 
550  if ( mEvaluatedPath.startsWith( QLatin1String( "base64:" ), Qt::CaseInsensitive ) && mMode == FormatUnknown )
551  {
552  const QByteArray base64 = mEvaluatedPath.mid( 7 ).toLocal8Bit(); // strip 'base64:' prefix
553  imageData = QByteArray::fromBase64( base64, QByteArray::OmitTrailingEquals );
554  }
555 
556  if ( imageData.type() == QVariant::ByteArray )
557  {
558  if ( mImage.loadFromData( imageData.toByteArray() ) )
559  {
560  mMode = FormatRaster;
561  }
562  }
563  else if ( mMode == FormatUnknown && mEvaluatedPath.startsWith( QLatin1String( "http" ) ) )
564  {
565  //remote location (unsafe way, uses QEventLoop) - for old API/project compatibility only!!
566  loadRemotePicture( mEvaluatedPath );
567  }
568  else if ( mMode == FormatUnknown )
569  {
570  //local location - for old API/project compatibility only!!
571  loadLocalPicture( mEvaluatedPath );
572  }
573  else
574  {
575  loadPictureUsingCache( mEvaluatedPath );
576  }
577 
578  if ( mMode != FormatUnknown ) //make sure we start with a new QImage
579  {
580  recalculateSize();
581  }
582  else if ( mHasExpressionError || !mEvaluatedPath.isEmpty() )
583  {
584  //trying to load an invalid file or bad expression, show cross picture
585  mIsMissingImage = true;
586  if ( origFormat == FormatRaster )
587  {
588  const QString badFile( QStringLiteral( ":/images/composer/missing_image.png" ) );
589  QImageReader imageReader( badFile );
590  if ( imageReader.read( &mImage ) )
591  mMode = FormatRaster;
592  }
593  else
594  {
595  const QString badFile( QStringLiteral( ":/images/composer/missing_image.svg" ) );
596  mSVG.load( badFile );
597  if ( mSVG.isValid() )
598  {
599  mMode = FormatSVG;
600  const QRect viewBox = mSVG.viewBox(); //take width/height ratio from view box instead of default size
601  mDefaultSvgSize.setWidth( viewBox.width() );
602  mDefaultSvgSize.setHeight( viewBox.height() );
603  }
604  }
605  recalculateSize();
606  }
607 
608  update();
609  emit changed();
610 }
611 
612 QRectF QgsLayoutItemPicture::boundedImageRect( double deviceWidth, double deviceHeight )
613 {
614  double imageToDeviceRatio;
615  if ( mImage.width() / deviceWidth > mImage.height() / deviceHeight )
616  {
617  imageToDeviceRatio = deviceWidth / mImage.width();
618  const double height = imageToDeviceRatio * mImage.height();
619  return QRectF( 0, 0, deviceWidth, height );
620  }
621  else
622  {
623  imageToDeviceRatio = deviceHeight / mImage.height();
624  const double width = imageToDeviceRatio * mImage.width();
625  return QRectF( 0, 0, width, deviceHeight );
626  }
627 }
628 
629 QRectF QgsLayoutItemPicture::boundedSVGRect( double deviceWidth, double deviceHeight )
630 {
631  double imageToSvgRatio;
632  if ( deviceWidth / mDefaultSvgSize.width() > deviceHeight / mDefaultSvgSize.height() )
633  {
634  imageToSvgRatio = deviceHeight / mDefaultSvgSize.height();
635  const double width = mDefaultSvgSize.width() * imageToSvgRatio;
636  return QRectF( 0, 0, width, deviceHeight );
637  }
638  else
639  {
640  imageToSvgRatio = deviceWidth / mDefaultSvgSize.width();
641  const double height = mDefaultSvgSize.height() * imageToSvgRatio;
642  return QRectF( 0, 0, deviceWidth, height );
643  }
644 }
645 
646 QSizeF QgsLayoutItemPicture::pictureSize()
647 {
648  if ( mMode == FormatSVG )
649  {
650  return mDefaultSvgSize;
651  }
652  else if ( mMode == FormatRaster )
653  {
654  return QSizeF( mImage.width(), mImage.height() );
655  }
656  else
657  {
658  return QSizeF( 0, 0 );
659  }
660 }
661 
663 {
664  return mIsMissingImage;
665 }
666 
668 {
669  return mEvaluatedPath;
670 }
671 
672 QMap<QString, QgsProperty> QgsLayoutItemPicture::svgDynamicParameters() const
673 {
674  const QVariantMap parameters = mCustomProperties.value( QStringLiteral( "svg-dynamic-parameters" ), QVariantMap() ).toMap();
675  return QgsProperty::variantMapToPropertyMap( parameters );
676 }
677 
678 void QgsLayoutItemPicture::setSvgDynamicParameters( const QMap<QString, QgsProperty> &parameters )
679 {
680  const QVariantMap variantMap = QgsProperty::propertyMapToVariantMap( parameters );
681  mCustomProperties.setValue( QStringLiteral( "svg-dynamic-parameters" ), variantMap );
682  refreshPicture();
683 }
684 
685 void QgsLayoutItemPicture::shapeChanged()
686 {
687  if ( mMode == FormatSVG && !mLoadingSvg )
688  {
689  mLoadingSvg = true;
690  refreshPicture();
691  mLoadingSvg = false;
692  }
693 }
694 
696 {
697  const double oldRotation = mPictureRotation;
698  mPictureRotation = rotation;
699 
700  if ( mResizeMode == Zoom )
701  {
702  //find largest scaling of picture with this rotation which fits in item
703  const QSizeF currentPictureSize = pictureSize();
704  const QRectF rotatedImageRect = QgsLayoutUtils::largestRotatedRectWithinBounds( QRectF( 0, 0, currentPictureSize.width(), currentPictureSize.height() ), rect(), mPictureRotation );
705  mPictureWidth = rotatedImageRect.width();
706  mPictureHeight = rotatedImageRect.height();
707  update();
708  }
709  else if ( mResizeMode == ZoomResizeFrame )
710  {
711  const QSizeF currentPictureSize = pictureSize();
712  const QRectF oldRect = QRectF( pos().x(), pos().y(), rect().width(), rect().height() );
713 
714  //calculate actual size of image inside frame
715  const QRectF rotatedImageRect = QgsLayoutUtils::largestRotatedRectWithinBounds( QRectF( 0, 0, currentPictureSize.width(), currentPictureSize.height() ), rect(), oldRotation );
716 
717  //rotate image rect by new rotation and get bounding box
718  QTransform tr;
719  tr.rotate( mPictureRotation );
720  QRectF newRect = tr.mapRect( QRectF( 0, 0, rotatedImageRect.width(), rotatedImageRect.height() ) );
721 
722  //keep the center in the same location
723  newRect.moveCenter( oldRect.center() );
724  attemptSetSceneRect( newRect );
725  emit changed();
726  }
727 
728  emit pictureRotationChanged( mPictureRotation );
729 }
730 
732 {
733  mNorthArrowHandler->setLinkedMap( map );
734 }
735 
737 {
738  mResizeMode = mode;
740  || ( mode == QgsLayoutItemPicture::Zoom && !qgsDoubleNear( mPictureRotation, 0.0 ) ) )
741  {
742  //call set scene rect to force item to resize to fit picture
743  recalculateSize();
744  }
745  update();
746 }
747 
749 {
750  //call set scene rect with current position/size, as this will trigger the
751  //picture item to recalculate its frame and image size
752  attemptSetSceneRect( QRectF( pos().x(), pos().y(), rect().width(), rect().height() ) );
753 }
754 
756 {
759  || property == QgsLayoutObject::AllProperties )
760  {
762  refreshPicture( &context );
763  }
764 
766 }
767 
768 void QgsLayoutItemPicture::setPicturePath( const QString &path, Format format )
769 {
770  mMode = format;
771  mSourcePath = path;
772  refreshPicture();
773 }
774 
776 {
777  return mSourcePath;
778 }
779 
780 bool QgsLayoutItemPicture::writePropertiesToElement( QDomElement &elem, QDomDocument &, const QgsReadWriteContext &context ) const
781 {
782  QString imagePath = mSourcePath;
783 
784  // convert from absolute path to relative. For SVG we also need to consider system SVG paths
785  const QgsPathResolver pathResolver = context.pathResolver();
786  if ( imagePath.endsWith( QLatin1String( ".svg" ), Qt::CaseInsensitive ) )
787  imagePath = QgsSymbolLayerUtils::svgSymbolPathToName( imagePath, pathResolver );
788  else
789  imagePath = pathResolver.writePath( imagePath );
790 
791  elem.setAttribute( QStringLiteral( "file" ), imagePath );
792  elem.setAttribute( QStringLiteral( "pictureWidth" ), QString::number( mPictureWidth ) );
793  elem.setAttribute( QStringLiteral( "pictureHeight" ), QString::number( mPictureHeight ) );
794  elem.setAttribute( QStringLiteral( "resizeMode" ), QString::number( static_cast< int >( mResizeMode ) ) );
795  elem.setAttribute( QStringLiteral( "anchorPoint" ), QString::number( static_cast< int >( mPictureAnchor ) ) );
796  elem.setAttribute( QStringLiteral( "svgFillColor" ), QgsSymbolLayerUtils::encodeColor( mSvgFillColor ) );
797  elem.setAttribute( QStringLiteral( "svgBorderColor" ), QgsSymbolLayerUtils::encodeColor( mSvgStrokeColor ) );
798  elem.setAttribute( QStringLiteral( "svgBorderWidth" ), QString::number( mSvgStrokeWidth ) );
799  elem.setAttribute( QStringLiteral( "mode" ), mMode );
800 
801  //rotation
802  elem.setAttribute( QStringLiteral( "pictureRotation" ), QString::number( mPictureRotation ) );
803  if ( !mNorthArrowHandler->linkedMap() )
804  {
805  elem.setAttribute( QStringLiteral( "mapUuid" ), QString() );
806  }
807  else
808  {
809  elem.setAttribute( QStringLiteral( "mapUuid" ), mNorthArrowHandler->linkedMap()->uuid() );
810  }
811  elem.setAttribute( QStringLiteral( "northMode" ), mNorthArrowHandler->northMode() );
812  elem.setAttribute( QStringLiteral( "northOffset" ), mNorthArrowHandler->northOffset() );
813  return true;
814 }
815 
816 bool QgsLayoutItemPicture::readPropertiesFromElement( const QDomElement &itemElem, const QDomDocument &, const QgsReadWriteContext &context )
817 {
818  mPictureWidth = itemElem.attribute( QStringLiteral( "pictureWidth" ), QStringLiteral( "10" ) ).toDouble();
819  mPictureHeight = itemElem.attribute( QStringLiteral( "pictureHeight" ), QStringLiteral( "10" ) ).toDouble();
820  mResizeMode = QgsLayoutItemPicture::ResizeMode( itemElem.attribute( QStringLiteral( "resizeMode" ), QStringLiteral( "0" ) ).toInt() );
821  //when loading from xml, default to anchor point of middle to match pre 2.4 behavior
822  mPictureAnchor = static_cast< QgsLayoutItem::ReferencePoint >( itemElem.attribute( QStringLiteral( "anchorPoint" ), QString::number( QgsLayoutItem::Middle ) ).toInt() );
823 
824  mSvgFillColor = QgsSymbolLayerUtils::decodeColor( itemElem.attribute( QStringLiteral( "svgFillColor" ), QgsSymbolLayerUtils::encodeColor( QColor( 255, 255, 255 ) ) ) );
825  mSvgStrokeColor = QgsSymbolLayerUtils::decodeColor( itemElem.attribute( QStringLiteral( "svgBorderColor" ), QgsSymbolLayerUtils::encodeColor( QColor( 0, 0, 0 ) ) ) );
826  mSvgStrokeWidth = itemElem.attribute( QStringLiteral( "svgBorderWidth" ), QStringLiteral( "0.2" ) ).toDouble();
827  mMode = static_cast< Format >( itemElem.attribute( QStringLiteral( "mode" ), QString::number( FormatUnknown ) ).toInt() );
828 
829  const QDomNodeList composerItemList = itemElem.elementsByTagName( QStringLiteral( "ComposerItem" ) );
830  if ( !composerItemList.isEmpty() )
831  {
832  const QDomElement composerItemElem = composerItemList.at( 0 ).toElement();
833 
834  if ( !qgsDoubleNear( composerItemElem.attribute( QStringLiteral( "rotation" ), QStringLiteral( "0" ) ).toDouble(), 0.0 ) )
835  {
836  //in versions prior to 2.1 picture rotation was stored in the rotation attribute
837  mPictureRotation = composerItemElem.attribute( QStringLiteral( "rotation" ), QStringLiteral( "0" ) ).toDouble();
838  }
839  }
840 
841  mDefaultSvgSize = QSize( 0, 0 );
842 
843  if ( itemElem.hasAttribute( QStringLiteral( "sourceExpression" ) ) )
844  {
845  //update pre 2.5 picture expression to use data defined expression
846  const QString sourceExpression = itemElem.attribute( QStringLiteral( "sourceExpression" ), QString() );
847  const QString useExpression = itemElem.attribute( QStringLiteral( "useExpression" ) );
848  bool expressionActive;
849  expressionActive = ( useExpression.compare( QLatin1String( "true" ), Qt::CaseInsensitive ) == 0 );
850 
852  }
853 
854  QString imagePath = itemElem.attribute( QStringLiteral( "file" ) );
855 
856  // convert from relative path to absolute. For SVG we also need to consider system SVG paths
857  const QgsPathResolver pathResolver = context.pathResolver();
858  if ( imagePath.endsWith( QLatin1String( ".svg" ), Qt::CaseInsensitive ) )
859  imagePath = QgsSymbolLayerUtils::svgSymbolNameToPath( imagePath, pathResolver );
860  else
861  imagePath = pathResolver.readPath( imagePath );
862 
863  mSourcePath = imagePath;
864 
865  //picture rotation
866  if ( !qgsDoubleNear( itemElem.attribute( QStringLiteral( "pictureRotation" ), QStringLiteral( "0" ) ).toDouble(), 0.0 ) )
867  {
868  mPictureRotation = itemElem.attribute( QStringLiteral( "pictureRotation" ), QStringLiteral( "0" ) ).toDouble();
869  }
870 
871  //rotation map
872  mNorthArrowHandler->setNorthMode( static_cast< QgsLayoutNorthArrowHandler::NorthMode >( itemElem.attribute( QStringLiteral( "northMode" ), QStringLiteral( "0" ) ).toInt() ) );
873  mNorthArrowHandler->setNorthOffset( itemElem.attribute( QStringLiteral( "northOffset" ), QStringLiteral( "0" ) ).toDouble() );
874 
875  mNorthArrowHandler->setLinkedMap( nullptr );
876  mRotationMapUuid = itemElem.attribute( QStringLiteral( "mapUuid" ) );
877 
878  return true;
879 }
880 
882 {
883  return mNorthArrowHandler->linkedMap();
884 }
885 
887 {
888  return static_cast< QgsLayoutItemPicture::NorthMode >( mNorthArrowHandler->northMode() );
889 }
890 
892 {
893  mNorthArrowHandler->setNorthMode( static_cast< QgsLayoutNorthArrowHandler::NorthMode >( mode ) );
894 }
895 
897 {
898  return mNorthArrowHandler->northOffset();
899 }
900 
902 {
903  mNorthArrowHandler->setNorthOffset( offset );
904 }
905 
907 {
908  mPictureAnchor = anchor;
909  update();
910 }
911 
912 void QgsLayoutItemPicture::setSvgFillColor( const QColor &color )
913 {
914  mSvgFillColor = color;
915  refreshPicture();
916 }
917 
918 void QgsLayoutItemPicture::setSvgStrokeColor( const QColor &color )
919 {
920  mSvgStrokeColor = color;
921  refreshPicture();
922 }
923 
925 {
926  mSvgStrokeWidth = width;
927  refreshPicture();
928 }
929 
931 {
932  if ( mMode == mode )
933  return;
934 
935  mMode = mode;
936  refreshPicture();
937 }
938 
940 {
941  if ( !mLayout || mRotationMapUuid.isEmpty() )
942  {
943  mNorthArrowHandler->setLinkedMap( nullptr );
944  }
945  else
946  {
947  mNorthArrowHandler->setLinkedMap( qobject_cast< QgsLayoutItemMap * >( mLayout->itemByUuid( mRotationMapUuid, true ) ) );
948  }
949 
950  refreshPicture();
951 }
QgsExpressionContext
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Definition: qgsexpressioncontext.h:406
QgsLayoutItemPicture::setLinkedMap
void setLinkedMap(QgsLayoutItemMap *map)
Sets the map object for rotation.
Definition: qgslayoutitempicture.cpp:731
QgsLayoutObject::layout
const QgsLayout * layout() const
Returns the layout the object is attached to.
Definition: qgslayoutobject.cpp:216
QgsLayoutItemPicture::FrameToImageSize
@ FrameToImageSize
Sets size of frame to match original size of image without scaling.
Definition: qgslayoutitempicture.h:49
QgsLayoutItemPicture::draw
void draw(QgsLayoutItemRenderContext &context) override
Draws the item's contents using the specified item render context.
Definition: qgslayoutitempicture.cpp:88
qgssvgcache.h
QgsPropertyCollection::prepare
bool prepare(const QgsExpressionContext &context=QgsExpressionContext()) const override
Prepares the collection against a specified expression context.
Definition: qgspropertycollection.cpp:240
QgsLayoutItemPicture::setSvgStrokeColor
void setSvgStrokeColor(const QColor &color)
Sets the stroke color used for parametrized SVG files.
Definition: qgslayoutitempicture.cpp:918
QgsAbstractPropertyCollection::valueAsDouble
double valueAsDouble(int key, const QgsExpressionContext &context, double defaultValue=0.0, bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a double.
Definition: qgspropertycollection.cpp:66
QgsProperty::variantMapToPropertyMap
static QMap< QString, QgsProperty > variantMapToPropertyMap(const QVariantMap &variantMap)
Convert a map of QVariant to a map of QgsProperty This is useful to restore a map of properties.
Definition: qgsproperty.cpp:217
QgsSymbolLayerUtils::encodeColor
static QString encodeColor(const QColor &color)
Definition: qgssymbollayerutils.cpp:64
QgsLayoutItemPicture::svgDynamicParameters
QMap< QString, QgsProperty > svgDynamicParameters() const
Returns the SVG dynamic parameters.
Definition: qgslayoutitempicture.cpp:672
QgsLayoutItemPicture::pictureRotationChanged
void pictureRotationChanged(double newRotation)
Emitted on picture rotation change.
QgsProperty
A store for object properties.
Definition: qgsproperty.h:230
QgsLayoutItem::sizePositionChanged
void sizePositionChanged()
Emitted when the item's size or position changes.
QgsLayoutSize::width
double width() const
Returns the width of the size.
Definition: qgslayoutsize.h:76
QgsImageCache::pathAsImage
QImage pathAsImage(const QString &path, const QSize size, const bool keepAspectRatio, const double opacity, bool &fitsInCache, bool blocking=false, double targetDpi=96, int frameNumber=-1, bool *isMissing=nullptr)
Returns the specified path rendered as an image.
Definition: qgsimagecache.cpp:137
QgsReadWriteContext
The class is used as a container of context for various read/write operations on other objects.
Definition: qgsreadwritecontext.h:34
QgsLayoutItemPicture::icon
QIcon icon() const override
Returns the item's icon.
Definition: qgslayoutitempicture.cpp:78
QgsLayoutItem::Middle
@ Middle
Center of item.
Definition: qgslayoutitem.h:207
QgsDebugMsgLevel
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
QgsLayoutItem::MiddleRight
@ MiddleRight
Middle right of item.
Definition: qgslayoutitem.h:208
qgsexpression.h
QgsLayout::renderContext
QgsLayoutRenderContext & renderContext()
Returns a reference to the layout's render context, which stores information relating to the current ...
Definition: qgslayout.cpp:359
QgsLayoutItemPicture::setSvgDynamicParameters
void setSvgDynamicParameters(const QMap< QString, QgsProperty > &parameters)
Sets the SVG dynamic parameters.
Definition: qgslayoutitempicture.cpp:678
qgsreadwritecontext.h
QgsLayoutObject::mCustomProperties
QgsObjectCustomProperties mCustomProperties
Custom properties for object.
Definition: qgslayoutobject.h:368
QgsSvgCache::svgContent
QByteArray svgContent(const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth, double widthScaleFactor, double fixedAspectRatio=0, bool blocking=false, const QMap< QString, QString > &parameters=QMap< QString, QString >(), bool *isMissingImage=nullptr)
Gets the SVG content corresponding to the given path.
Definition: qgssvgcache.cpp:209
qgslayoutnortharrowhandler.h
QgsLayoutNorthArrowHandler::linkedMap
QgsLayoutItemMap * linkedMap() const
Returns the linked rotation map, if set.
Definition: qgslayoutnortharrowhandler.cpp:107
qgssymbollayerutils.h
QgsLayoutItem::MiddleLeft
@ MiddleLeft
Middle left of item.
Definition: qgslayoutitem.h:206
QgsLayoutItemRenderContext
Contains settings and helpers relating to a render of a QgsLayoutItem.
Definition: qgslayoutitem.h:44
QgsLayoutItem::attemptSetSceneRect
void attemptSetSceneRect(const QRectF &rect, bool includesFrame=false)
Attempts to update the item's position and size to match the passed rect in layout coordinates.
Definition: qgslayoutitem.cpp:511
qgspathresolver.h
QgsLayoutItemPicture::NorthMode
NorthMode
Method for syncing rotation to a map's North direction.
Definition: qgslayoutitempicture.h:63
QgsLayoutItemPicture::evaluatedPath
QString evaluatedPath() const
Returns the current evaluated picture path, which includes the result of data defined path overrides.
Definition: qgslayoutitempicture.cpp:667
QgsLayoutObject::mDataDefinedProperties
QgsPropertyCollection mDataDefinedProperties
Definition: qgslayoutobject.h:365
QgsLayoutItem::refreshDataDefinedProperty
virtual void refreshDataDefinedProperty(QgsLayoutObject::DataDefinedProperty property=QgsLayoutObject::AllProperties)
Refreshes a data defined property for the item by reevaluating the property's value and redrawing the...
Definition: qgslayoutitem.cpp:1082
QgsLayoutItemPicture::isMissingImage
bool isMissingImage() const
Returns true if the source image is missing and the picture cannot be rendered.
Definition: qgslayoutitempicture.cpp:662
QgsProperty::fromExpression
static QgsProperty fromExpression(const QString &expression, bool isActive=true)
Returns a new ExpressionBasedProperty created from the specified expression.
Definition: qgsproperty.cpp:237
QgsSymbolLayerUtils::svgSymbolPathToName
static QString svgSymbolPathToName(const QString &path, const QgsPathResolver &pathResolver)
Determines an SVG symbol's name from its path.
Definition: qgssymbollayerutils.cpp:4303
qgsmapsettings.h
QgsRenderContext::scaleFactor
double scaleFactor() const
Returns the scaling factor for the render to convert painter units to physical sizes.
Definition: qgsrendercontext.h:266
QgsLayoutItemPicture::northOffset
double northOffset() const
Returns the offset added to the picture's rotation from a map's North.
Definition: qgslayoutitempicture.cpp:896
QgsLayoutObject::changed
void changed()
Emitted when the object's properties change.
QgsSymbolLayerUtils::decodeColor
static QColor decodeColor(const QString &str)
Definition: qgssymbollayerutils.cpp:69
QgsLayoutObject::PictureSvgStrokeColor
@ PictureSvgStrokeColor
SVG stroke color.
Definition: qgslayoutobject.h:188
QgsLayoutItem::ReferencePoint
ReferencePoint
Fixed position reference point.
Definition: qgslayoutitem.h:201
QgsLayoutItemPicture::linkedMap
QgsLayoutItemMap * linkedMap() const
Returns the linked rotation map, if set.
Definition: qgslayoutitempicture.cpp:881
QgsProperty::value
QVariant value(const QgsExpressionContext &context, const QVariant &defaultValue=QVariant(), bool *ok=nullptr) const
Calculates the current value of the property, including any transforms which are set for the property...
Definition: qgsproperty.cpp:585
QgsLayoutObject::PictureSvgStrokeWidth
@ PictureSvgStrokeWidth
SVG stroke width.
Definition: qgslayoutobject.h:189
QgsPropertyCollection::property
QgsProperty property(int key) const override
Returns a matching property from the collection, if one exists.
Definition: qgspropertycollection.cpp:214
QgsLayoutItemPicture::applyItemSizeConstraint
QSizeF applyItemSizeConstraint(QSizeF targetSize) override
Applies any item-specific size constraint handling to a given targetSize in layout units.
Definition: qgslayoutitempicture.cpp:214
QgsLayoutItemPicture::readPropertiesFromElement
bool readPropertiesFromElement(const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context) override
Sets item state from a DOM element.
Definition: qgslayoutitempicture.cpp:816
QgsSymbolLayerUtils::evaluatePropertiesMap
static QgsStringMap evaluatePropertiesMap(const QMap< QString, QgsProperty > &propertiesMap, const QgsExpressionContext &context)
Evaluates a map of properties using the given context and returns a variant map with evaluated expres...
Definition: qgssymbollayerutils.cpp:5078
qgslayoututils.h
QgsLayoutNorthArrowHandler::northMode
NorthMode northMode() const
Returns the mode used to calculate the arrow rotation.
Definition: qgslayoutnortharrowhandler.h:74
QgsLayoutObject::AllProperties
@ AllProperties
All properties for item.
Definition: qgslayoutobject.h:135
QgsPathResolver::writePath
QString writePath(const QString &filename) const
Prepare a filename to save it to the project file.
Definition: qgspathresolver.cpp:225
QgsProperty::propertyMapToVariantMap
static QVariantMap propertyMapToVariantMap(const QMap< QString, QgsProperty > &propertyMap)
Convert a map of QgsProperty to a map of QVariant This is useful to save a map of properties.
Definition: qgsproperty.cpp:208
QgsNetworkContentFetcher
HTTP network content fetcher. A simple method for fetching remote HTTP content and converting the con...
Definition: qgsnetworkcontentfetcher.h:39
QgsLayoutItemPicture::Stretch
@ Stretch
Stretches image to fit frame, ignores aspect ratio.
Definition: qgslayoutitempicture.h:46
QgsLayoutItemPicture::finalizeRestoreFromXml
void finalizeRestoreFromXml() override
Called after all pending items have been restored from XML.
Definition: qgslayoutitempicture.cpp:939
QgsLayoutItemPicture::refreshDataDefinedProperty
void refreshDataDefinedProperty(QgsLayoutObject::DataDefinedProperty property=QgsLayoutObject::AllProperties) override
Definition: qgslayoutitempicture.cpp:755
QgsLayoutItemPicture::setNorthMode
void setNorthMode(NorthMode mode)
Sets the mode used to align the picture to a map's North.
Definition: qgslayoutitempicture.cpp:891
QgsNetworkContentFetcher::fetchContent
void fetchContent(const QUrl &url, const QString &authcfg=QString())
Fetches content from a remote URL and handles redirects.
Definition: qgsnetworkcontentfetcher.cpp:37
qgsDoubleNear
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:2265
QgsLayoutItemPicture::setNorthOffset
void setNorthOffset(double offset)
Sets the offset added to the picture's rotation from a map's North.
Definition: qgslayoutitempicture.cpp:901
QgsLayoutNorthArrowHandler::setNorthOffset
void setNorthOffset(double offset)
Sets the offset added to the arrows's rotation from a map's North.
Definition: qgslayoutnortharrowhandler.cpp:118
QgsNetworkContentFetcher::reply
QNetworkReply * reply()
Returns a reference to the network reply.
Definition: qgsnetworkcontentfetcher.cpp:89
QgsLayoutItemPicture::ZoomResizeFrame
@ ZoomResizeFrame
Enlarges image to fit frame, then resizes frame to fit resultant image.
Definition: qgslayoutitempicture.h:48
QgsLayoutItem::setBackgroundEnabled
void setBackgroundEnabled(bool drawBackground)
Sets whether this item has a background drawn under it or not.
Definition: qgslayoutitem.cpp:887
QgsLayoutItemPicture::create
static QgsLayoutItemPicture * create(QgsLayout *layout)
Returns a new picture item for the specified layout.
Definition: qgslayoutitempicture.cpp:83
QgsObjectCustomProperties::setValue
void setValue(const QString &key, const QVariant &value)
Add an entry to the store with the specified key.
Definition: qgsobjectcustomproperties.cpp:31
QgsLayout::reportContext
QgsLayoutReportContext & reportContext()
Returns a reference to the layout's report context, which stores information relating to the current ...
Definition: qgslayout.cpp:369
QgsApplication::imageCache
static QgsImageCache * imageCache()
Returns the application's image cache, used for caching resampled versions of raster images.
Definition: qgsapplication.cpp:2365
QgsLayoutItemPicture::Format
Format
Format of source image.
Definition: qgslayoutitempicture.h:55
QgsLayoutItemPicture::FormatUnknown
@ FormatUnknown
Invalid or unknown image type.
Definition: qgslayoutitempicture.h:59
QgsMessageLog::logMessage
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
Definition: qgsmessagelog.cpp:27
QgsLayoutItemPicture::refreshPicture
void refreshPicture(const QgsExpressionContext *context=nullptr)
Recalculates the source image (if using an expression for picture's source) and reloads and redraws t...
Definition: qgslayoutitempicture.cpp:342
QgsLayoutItemPicture::Clip
@ Clip
Draws image at original size and clips any portion which falls outside frame.
Definition: qgslayoutitempicture.h:47
QgsLayoutItemPicture::setPicturePath
void setPicturePath(const QString &path, Format format=FormatUnknown)
Sets the source path of the image (may be svg or a raster format).
Definition: qgslayoutitempicture.cpp:768
QgsLayoutItemPicture::ResizeMode
ResizeMode
Controls how pictures are scaled within the item's frame.
Definition: qgslayoutitempicture.h:43
QgsLayoutNorthArrowHandler::setLinkedMap
void setLinkedMap(QgsLayoutItemMap *map)
Sets the linked map item.
Definition: qgslayoutnortharrowhandler.cpp:81
QgsLayoutNorthArrowHandler::arrowRotationChanged
void arrowRotationChanged(double newRotation)
Emitted on arrow rotation change.
QgsLayoutItem
Base class for graphical items within a QgsLayout.
Definition: qgslayoutitem.h:112
QgsLayoutNorthArrowHandler::setNorthMode
void setNorthMode(NorthMode mode)
Sets the mode used to calculate the arrow rotation.
Definition: qgslayoutnortharrowhandler.cpp:112
QgsLayoutItemPicture::mode
Format mode() const
Returns the current picture mode (image format).
Definition: qgslayoutitempicture.h:235
QgsScopedQPainterState
Scoped object for saving and restoring a QPainter object's state.
Definition: qgsrendercontext.h:1336
QgsLayoutItemPicture::FormatSVG
@ FormatSVG
SVG image.
Definition: qgslayoutitempicture.h:57
QgsLayoutReportContext::changed
void changed()
Emitted certain settings in the context is changed, e.g.
qgslayout.h
QgsLayoutNorthArrowHandler
An object which handles north-arrow type behavior for layout items.
Definition: qgslayoutnortharrowhandler.h:32
QgsApplication::svgCache
static QgsSvgCache * svgCache()
Returns the application's SVG cache, used for caching SVG images and handling parameter replacement w...
Definition: qgsapplication.cpp:2360
QgsLayoutItem::LowerRight
@ LowerRight
Lower right corner of item.
Definition: qgslayoutitem.h:211
QgsLayoutItemPicture::setMode
void setMode(Format mode)
Sets the current picture mode (image format).
Definition: qgslayoutitempicture.cpp:930
QgsLayoutSize::height
double height() const
Returns the height of the size.
Definition: qgslayoutsize.h:90
QgsLayoutItem::LowerLeft
@ LowerLeft
Lower left corner of item.
Definition: qgslayoutitem.h:209
QgsLayoutItemPicture
A layout item subclass that displays SVG files or raster format images (jpg, png, ....
Definition: qgslayoutitempicture.h:35
qgsvectorlayer.h
QgsLayoutNorthArrowHandler::NorthMode
NorthMode
Method for syncing rotation to a map's North direction.
Definition: qgslayoutnortharrowhandler.h:38
QgsLayoutItemMap
Layout graphical items for displaying a map.
Definition: qgslayoutitemmap.h:317
QgsPathResolver::readPath
QString readPath(const QString &filename) const
Turn filename read from the project file to an absolute path.
Definition: qgspathresolver.cpp:37
QgsLayoutItemPicture::northMode
NorthMode northMode() const
Returns the mode used to align the picture to a map's North.
Definition: qgslayoutitempicture.cpp:886
QgsLayoutItemPicture::setSvgStrokeWidth
void setSvgStrokeWidth(double width)
Sets the stroke width (in layout units) used for parametrized SVG files.
Definition: qgslayoutitempicture.cpp:924
QgsLayoutItemRenderContext::renderContext
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
Definition: qgslayoutitem.h:72
QgsLayoutItem::uuid
virtual QString uuid() const
Returns the item identification string.
Definition: qgslayoutitem.h:345
QgsStringMap
QMap< QString, QString > QgsStringMap
Definition: qgis.h:2781
qgslayoutrendercontext.h
QgsLayoutItemPicture::setResizeMode
void setResizeMode(QgsLayoutItemPicture::ResizeMode mode)
Sets the resize mode used for drawing the picture within the item bounds.
Definition: qgslayoutitempicture.cpp:736
QgsLayoutObject::mLayout
QPointer< QgsLayout > mLayout
Definition: qgslayoutobject.h:363
qgslayoutreportcontext.h
QgsLayoutItemPicture::Zoom
@ Zoom
Enlarges image to fit frame while maintaining aspect ratio of picture.
Definition: qgslayoutitempicture.h:45
QgsLayout
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
Definition: qgslayout.h:50
qgsimagecache.h
QgsLayoutItemRegistry::LayoutPicture
@ LayoutPicture
Picture item.
Definition: qgslayoutitemregistry.h:348
QgsSymbolLayerUtils::svgSymbolNameToPath
static QString svgSymbolNameToPath(const QString &name, const QgsPathResolver &pathResolver)
Determines an SVG symbol's path from its name.
Definition: qgssymbollayerutils.cpp:4237
QgsObjectCustomProperties::value
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
Returns the value for the given key.
Definition: qgsobjectcustomproperties.cpp:36
QgsLayoutItemPicture::setPictureAnchor
void setPictureAnchor(QgsLayoutItem::ReferencePoint anchor)
Sets the picture's anchor point, which controls how it is placed within the picture item's frame.
Definition: qgslayoutitempicture.cpp:906
QgsLayoutItemPicture::writePropertiesToElement
bool writePropertiesToElement(QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context) const override
Stores item state within an XML DOM element.
Definition: qgslayoutitempicture.cpp:780
QgsLayoutItemPicture::picturePath
QString picturePath() const
Returns the path of the source image.
Definition: qgslayoutitempicture.cpp:775
QgsLayoutUtils::largestRotatedRectWithinBounds
static QRectF largestRotatedRectWithinBounds(const QRectF &originalRect, const QRectF &boundsRect, double rotation)
Calculates the largest scaled version of originalRect which fits within boundsRect,...
Definition: qgslayoututils.cpp:302
qgsbearingutils.h
QgsLayoutItem::UpperRight
@ UpperRight
Upper right corner of item.
Definition: qgslayoutitem.h:205
QgsNetworkContentFetcher::finished
void finished()
Emitted when content has loaded.
qgslayoutitempicture.h
qgsproperty.h
QgsLayoutItemPicture::QgsLayoutItemPicture
QgsLayoutItemPicture(QgsLayout *layout)
Constructor for QgsLayoutItemPicture, with the specified parent layout.
Definition: qgslayoutitempicture.cpp:53
QgsLayoutNorthArrowHandler::northOffset
double northOffset() const
Returns the offset added to the arrows's rotation from a map's North.
Definition: qgslayoutnortharrowhandler.h:88
QgsLayoutSize
This class provides a method of storing sizes, consisting of a width and height, for use in QGIS layo...
Definition: qgslayoutsize.h:40
qgsnetworkcontentfetcher.h
QgsPropertyCollection::setProperty
void setProperty(int key, const QgsProperty &property)
Adds a property to the collection and takes ownership of it.
Definition: qgspropertycollection.cpp:187
QgsApplication::getThemeIcon
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
Definition: qgsapplication.cpp:693
QgsLayoutItem::UpperMiddle
@ UpperMiddle
Upper center of item.
Definition: qgslayoutitem.h:204
QgsUnitTypes::LayoutMillimeters
@ LayoutMillimeters
Millimeters.
Definition: qgsunittypes.h:183
qgslogger.h
QgsLayoutItemPicture::FormatRaster
@ FormatRaster
Raster image.
Definition: qgslayoutitempicture.h:58
QgsRenderContext::painter
QPainter * painter()
Returns the destination QPainter for the render operation.
Definition: qgsrendercontext.h:112
QgsLayoutItemPicture::type
int type() const override
Definition: qgslayoutitempicture.cpp:73
QgsLayoutRenderContext::FlagAntialiasing
@ FlagAntialiasing
Use antialiasing when drawing items.
Definition: qgslayoutrendercontext.h:48
QgsPropertyCollection::isActive
bool isActive(int key) const override
Returns true if the collection contains an active property with the specified key.
Definition: qgspropertycollection.cpp:268
qgslayoutitemregistry.h
QgsLayoutItem::createExpressionContext
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
Definition: qgslayoutitem.cpp:1159
QgsLayoutItem::UpperLeft
@ UpperLeft
Upper left corner of item.
Definition: qgslayoutitem.h:203
QgsPathResolver
Resolves relative paths into absolute paths and vice versa. Used for writing.
Definition: qgspathresolver.h:31
QgsLayoutObject::PictureSvgBackgroundColor
@ PictureSvgBackgroundColor
SVG background color.
Definition: qgslayoutobject.h:187
qgsproject.h
QgsLayoutItemPicture::setPictureRotation
void setPictureRotation(double rotation)
Sets the picture rotation within the item bounds, in degrees clockwise.
Definition: qgslayoutitempicture.cpp:695
QgsLayoutObject::DataDefinedProperty
DataDefinedProperty
Data defined properties for different item types.
Definition: qgslayoutobject.h:132
QgsLayoutItemPicture::recalculateSize
void recalculateSize()
Forces a recalculation of the picture's frame size.
Definition: qgslayoutitempicture.cpp:748
QgsAbstractPropertyCollection::valueAsColor
QColor valueAsColor(int key, const QgsExpressionContext &context, const QColor &defaultColor=QColor(), bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a color.
Definition: qgspropertycollection.cpp:54
QgsLayoutObject::PictureSource
@ PictureSource
Picture source url.
Definition: qgslayoutobject.h:186
QgsReadWriteContext::pathResolver
const QgsPathResolver & pathResolver() const
Returns path resolver for conversion between relative and absolute paths.
Definition: qgsreadwritecontext.cpp:47
qgslayoutitemmap.h
QgsLayoutItem::LowerMiddle
@ LowerMiddle
Lower center of item.
Definition: qgslayoutitem.h:210
qgsmessagelog.h
QgsLayoutItemPicture::setSvgFillColor
void setSvgFillColor(const QColor &color)
Sets the fill color used for parametrized SVG files.
Definition: qgslayoutitempicture.cpp:912
QgsLayoutRenderContext::dpiChanged
void dpiChanged()
Emitted when the context's DPI is changed.