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