QGIS API Documentation  3.14.0-Pi (9f7028fd23)
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  painter->save();
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  painter->restore();
208 }
209 
210 QSizeF QgsLayoutItemPicture::applyItemSizeConstraint( const QSizeF targetSize )
211 {
212  QSizeF currentPictureSize = pictureSize();
213  QSizeF newSize = targetSize;
214  if ( mResizeMode == QgsLayoutItemPicture::Clip )
215  {
216  mPictureWidth = targetSize.width();
217  mPictureHeight = targetSize.height();
218  }
219  else
220  {
221  if ( mResizeMode == ZoomResizeFrame && !rect().isEmpty() && !( currentPictureSize.isEmpty() ) )
222  {
223  QSizeF targetImageSize;
224  if ( qgsDoubleNear( mPictureRotation, 0.0 ) )
225  {
226  targetImageSize = currentPictureSize;
227  }
228  else
229  {
230  //calculate aspect ratio of bounds of rotated image
231  QTransform tr;
232  tr.rotate( mPictureRotation );
233  QRectF rotatedBounds = tr.mapRect( QRectF( 0, 0, currentPictureSize.width(), currentPictureSize.height() ) );
234  targetImageSize = QSizeF( rotatedBounds.width(), rotatedBounds.height() );
235  }
236 
237  //if height has changed more than width, then fix width and set height correspondingly
238  //else, do the opposite
239  if ( std::fabs( rect().width() - targetSize.width() ) <
240  std::fabs( rect().height() - targetSize.height() ) )
241  {
242  newSize.setHeight( targetImageSize.height() * newSize.width() / targetImageSize.width() );
243  }
244  else
245  {
246  newSize.setWidth( targetImageSize.width() * newSize.height() / targetImageSize.height() );
247  }
248  }
249  else if ( mResizeMode == FrameToImageSize )
250  {
251  if ( !( currentPictureSize.isEmpty() ) )
252  {
253  QgsLayoutSize sizeMM = mLayout->convertFromLayoutUnits( currentPictureSize, QgsUnitTypes::LayoutMillimeters );
254  newSize.setWidth( sizeMM.width() * 25.4 / mLayout->renderContext().dpi() );
255  newSize.setHeight( sizeMM.height() * 25.4 / mLayout->renderContext().dpi() );
256  }
257  }
258 
259  //find largest scaling of picture with this rotation which fits in item
260  if ( mResizeMode == Zoom || mResizeMode == ZoomResizeFrame )
261  {
262  QRectF rotatedImageRect = QgsLayoutUtils::largestRotatedRectWithinBounds( QRectF( 0, 0, currentPictureSize.width(), currentPictureSize.height() ),
263  QRectF( 0, 0, newSize.width(), newSize.height() ), mPictureRotation );
264  mPictureWidth = rotatedImageRect.width();
265  mPictureHeight = rotatedImageRect.height();
266  }
267  else
268  {
269  mPictureWidth = newSize.width();
270  mPictureHeight = newSize.height();
271  }
272 
273  if ( newSize != targetSize )
274  {
275  emit changed();
276  }
277  }
278 
279  return newSize;
280 }
281 
282 QRect QgsLayoutItemPicture::clippedImageRect( double &boundRectWidthMM, double &boundRectHeightMM, QSize imageRectPixels )
283 {
284  int boundRectWidthPixels = boundRectWidthMM * mLayout->renderContext().dpi() / 25.4;
285  int boundRectHeightPixels = boundRectHeightMM * mLayout->renderContext().dpi() / 25.4;
286 
287  //update boundRectWidth/Height so that they exactly match pixel bounds
288  boundRectWidthMM = boundRectWidthPixels * 25.4 / mLayout->renderContext().dpi();
289  boundRectHeightMM = boundRectHeightPixels * 25.4 / mLayout->renderContext().dpi();
290 
291  //calculate part of image which fits in bounds
292  int leftClip = 0;
293  int topClip = 0;
294 
295  //calculate left crop
296  switch ( mPictureAnchor )
297  {
298  case UpperLeft:
299  case MiddleLeft:
300  case LowerLeft:
301  leftClip = 0;
302  break;
303  case UpperMiddle:
304  case Middle:
305  case LowerMiddle:
306  leftClip = ( imageRectPixels.width() - boundRectWidthPixels ) / 2;
307  break;
308  case UpperRight:
309  case MiddleRight:
310  case LowerRight:
311  leftClip = imageRectPixels.width() - boundRectWidthPixels;
312  break;
313  }
314 
315  //calculate top crop
316  switch ( mPictureAnchor )
317  {
318  case UpperLeft:
319  case UpperMiddle:
320  case UpperRight:
321  topClip = 0;
322  break;
323  case MiddleLeft:
324  case Middle:
325  case MiddleRight:
326  topClip = ( imageRectPixels.height() - boundRectHeightPixels ) / 2;
327  break;
328  case LowerLeft:
329  case LowerMiddle:
330  case LowerRight:
331  topClip = imageRectPixels.height() - boundRectHeightPixels;
332  break;
333  }
334 
335  return QRect( leftClip, topClip, boundRectWidthPixels, boundRectHeightPixels );
336 }
337 
339 {
341  const QgsExpressionContext *evalContext = context ? context : &scopedContext;
342 
343  mDataDefinedProperties.prepare( *evalContext );
344 
345  QVariant source( mSourcePath );
346 
347  //data defined source set?
348  mHasExpressionError = false;
350  {
351  mMode = FormatUnknown;
352  bool ok = false;
354  source = sourceProperty.value( *evalContext, source, &ok );
355  if ( !ok || !source.canConvert( QMetaType::QString ) )
356  {
357  mHasExpressionError = true;
358  source = QString();
359  QgsMessageLog::logMessage( tr( "Picture expression eval error" ) );
360  }
361  else if ( source.type() != QVariant::ByteArray )
362  {
363  source = source.toString().trimmed();
364  QgsDebugMsgLevel( QStringLiteral( "exprVal PictureSource:%1" ).arg( source.toString() ), 2 );
365  }
366  }
367 
368  loadPicture( source );
369 }
370 
371 void QgsLayoutItemPicture::loadRemotePicture( const QString &url )
372 {
373  //remote location
374 
375  QgsNetworkContentFetcher fetcher;
376  QEventLoop loop;
377  connect( &fetcher, &QgsNetworkContentFetcher::finished, &loop, &QEventLoop::quit );
378  fetcher.fetchContent( QUrl( url ) );
379 
380  //wait until picture fetched
381  loop.exec( QEventLoop::ExcludeUserInputEvents );
382 
383  QNetworkReply *reply = fetcher.reply();
384  if ( reply )
385  {
386  QImageReader imageReader( reply );
387  mImage = imageReader.read();
388  mMode = FormatRaster;
389  }
390  else
391  {
392  mMode = FormatUnknown;
393  }
394 }
395 
396 void QgsLayoutItemPicture::loadLocalPicture( const QString &path )
397 {
398  QFile pic;
399  pic.setFileName( path );
400 
401  if ( !pic.exists() )
402  {
403  mMode = FormatUnknown;
404  }
405  else
406  {
407  QFileInfo sourceFileInfo( pic );
408  QString sourceFileSuffix = sourceFileInfo.suffix();
409  if ( sourceFileSuffix.compare( QLatin1String( "svg" ), Qt::CaseInsensitive ) == 0 )
410  {
411  //try to open svg
413  QColor fillColor = mDataDefinedProperties.valueAsColor( QgsLayoutObject::PictureSvgBackgroundColor, context, mSvgFillColor );
414  QColor strokeColor = mDataDefinedProperties.valueAsColor( QgsLayoutObject::PictureSvgStrokeColor, context, mSvgStrokeColor );
415  double strokeWidth = mDataDefinedProperties.valueAsDouble( QgsLayoutObject::PictureSvgStrokeWidth, context, mSvgStrokeWidth );
416  const QByteArray &svgContent = QgsApplication::svgCache()->svgContent( path, rect().width(), fillColor, strokeColor, strokeWidth,
417  1.0 );
418  mSVG.load( svgContent );
419  if ( mSVG.isValid() )
420  {
421  mMode = FormatSVG;
422  QRect viewBox = mSVG.viewBox(); //take width/height ratio from view box instead of default size
423  mDefaultSvgSize.setWidth( viewBox.width() );
424  mDefaultSvgSize.setHeight( viewBox.height() );
425  }
426  else
427  {
428  mMode = FormatUnknown;
429  }
430  }
431  else
432  {
433  //try to open raster with QImageReader
434  QImageReader imageReader( pic.fileName() );
435  if ( imageReader.read( &mImage ) )
436  {
437  mMode = FormatRaster;
438  }
439  else
440  {
441  mMode = FormatUnknown;
442  }
443  }
444  }
445 }
446 
447 void QgsLayoutItemPicture::loadPictureUsingCache( const QString &path )
448 {
449  if ( path.isEmpty() )
450  {
451  mImage = QImage();
452  return;
453  }
454 
455  switch ( mMode )
456  {
457  case FormatUnknown:
458  break;
459 
460  case FormatRaster:
461  {
462  bool fitsInCache = false;
463  bool isMissing = false;
464  mImage = QgsApplication::imageCache()->pathAsImage( path, QSize(), true, 1, fitsInCache, true, &isMissing );
465  if ( mImage.isNull() || isMissing )
466  mMode = FormatUnknown;
467  break;
468  }
469 
470  case FormatSVG:
471  {
473  QColor fillColor = mDataDefinedProperties.valueAsColor( QgsLayoutObject::PictureSvgBackgroundColor, context, mSvgFillColor );
474  QColor strokeColor = mDataDefinedProperties.valueAsColor( QgsLayoutObject::PictureSvgStrokeColor, context, mSvgStrokeColor );
475  double strokeWidth = mDataDefinedProperties.valueAsDouble( QgsLayoutObject::PictureSvgStrokeWidth, context, mSvgStrokeWidth );
476  bool isMissingImage = false;
477  const QByteArray &svgContent = QgsApplication::svgCache()->svgContent( path, rect().width(), fillColor, strokeColor, strokeWidth,
478  1.0, 0, false, &isMissingImage );
479  mSVG.load( svgContent );
480  if ( mSVG.isValid() && !isMissingImage )
481  {
482  mMode = FormatSVG;
483  QRect viewBox = mSVG.viewBox(); //take width/height ratio from view box instead of default size
484  mDefaultSvgSize.setWidth( viewBox.width() );
485  mDefaultSvgSize.setHeight( viewBox.height() );
486  }
487  else
488  {
489  mMode = FormatUnknown;
490  }
491  break;
492  }
493  }
494 }
495 
496 void QgsLayoutItemPicture::updateNorthArrowRotation( double rotation )
497 {
498  setPictureRotation( rotation );
499  emit pictureRotationChanged( rotation );
500 }
501 
502 void QgsLayoutItemPicture::loadPicture( const QVariant &data )
503 {
504  mIsMissingImage = false;
505  QVariant imageData( data );
506  mEvaluatedPath = data.toString();
507 
508  if ( mEvaluatedPath.startsWith( QLatin1String( "base64:" ), Qt::CaseInsensitive ) && mMode == FormatUnknown )
509  {
510  QByteArray base64 = mEvaluatedPath.mid( 7 ).toLocal8Bit(); // strip 'base64:' prefix
511  imageData = QByteArray::fromBase64( base64, QByteArray::OmitTrailingEquals );
512  }
513 
514  if ( imageData.type() == QVariant::ByteArray )
515  {
516  if ( mImage.loadFromData( imageData.toByteArray() ) )
517  {
518  mMode = FormatRaster;
519  }
520  }
521  else if ( mMode == FormatUnknown && mEvaluatedPath.startsWith( QLatin1String( "http" ) ) )
522  {
523  //remote location (unsafe way, uses QEventLoop) - for old API/project compatibility only!!
524  loadRemotePicture( mEvaluatedPath );
525  }
526  else if ( mMode == FormatUnknown )
527  {
528  //local location - for old API/project compatibility only!!
529  loadLocalPicture( mEvaluatedPath );
530  }
531  else
532  {
533  loadPictureUsingCache( mEvaluatedPath );
534  }
535 
536  if ( mMode != FormatUnknown ) //make sure we start with a new QImage
537  {
538  recalculateSize();
539  }
540  else if ( mHasExpressionError || !mEvaluatedPath.isEmpty() )
541  {
542  //trying to load an invalid file or bad expression, show cross picture
543  mMode = FormatSVG;
544  mIsMissingImage = true;
545  QString badFile( QStringLiteral( ":/images/composer/missing_image.svg" ) );
546  mSVG.load( badFile );
547  if ( mSVG.isValid() )
548  {
549  mMode = FormatSVG;
550  QRect viewBox = mSVG.viewBox(); //take width/height ratio from view box instead of default size
551  mDefaultSvgSize.setWidth( viewBox.width() );
552  mDefaultSvgSize.setHeight( viewBox.height() );
553  recalculateSize();
554  }
555  }
556 
557  update();
558  emit changed();
559 }
560 
561 QRectF QgsLayoutItemPicture::boundedImageRect( double deviceWidth, double deviceHeight )
562 {
563  double imageToDeviceRatio;
564  if ( mImage.width() / deviceWidth > mImage.height() / deviceHeight )
565  {
566  imageToDeviceRatio = deviceWidth / mImage.width();
567  double height = imageToDeviceRatio * mImage.height();
568  return QRectF( 0, 0, deviceWidth, height );
569  }
570  else
571  {
572  imageToDeviceRatio = deviceHeight / mImage.height();
573  double width = imageToDeviceRatio * mImage.width();
574  return QRectF( 0, 0, width, deviceHeight );
575  }
576 }
577 
578 QRectF QgsLayoutItemPicture::boundedSVGRect( double deviceWidth, double deviceHeight )
579 {
580  double imageToSvgRatio;
581  if ( deviceWidth / mDefaultSvgSize.width() > deviceHeight / mDefaultSvgSize.height() )
582  {
583  imageToSvgRatio = deviceHeight / mDefaultSvgSize.height();
584  double width = mDefaultSvgSize.width() * imageToSvgRatio;
585  return QRectF( 0, 0, width, deviceHeight );
586  }
587  else
588  {
589  imageToSvgRatio = deviceWidth / mDefaultSvgSize.width();
590  double height = mDefaultSvgSize.height() * imageToSvgRatio;
591  return QRectF( 0, 0, deviceWidth, height );
592  }
593 }
594 
595 QSizeF QgsLayoutItemPicture::pictureSize()
596 {
597  if ( mMode == FormatSVG )
598  {
599  return mDefaultSvgSize;
600  }
601  else if ( mMode == FormatRaster )
602  {
603  return QSizeF( mImage.width(), mImage.height() );
604  }
605  else
606  {
607  return QSizeF( 0, 0 );
608  }
609 }
610 
612 {
613  return mIsMissingImage;
614 }
615 
617 {
618  return mEvaluatedPath;
619 }
620 
621 void QgsLayoutItemPicture::shapeChanged()
622 {
623  if ( mMode == FormatSVG && !mLoadingSvg )
624  {
625  mLoadingSvg = true;
626  refreshPicture();
627  mLoadingSvg = false;
628  }
629 }
630 
632 {
633  double oldRotation = mPictureRotation;
634  mPictureRotation = rotation;
635 
636  if ( mResizeMode == Zoom )
637  {
638  //find largest scaling of picture with this rotation which fits in item
639  QSizeF currentPictureSize = pictureSize();
640  QRectF rotatedImageRect = QgsLayoutUtils::largestRotatedRectWithinBounds( QRectF( 0, 0, currentPictureSize.width(), currentPictureSize.height() ), rect(), mPictureRotation );
641  mPictureWidth = rotatedImageRect.width();
642  mPictureHeight = rotatedImageRect.height();
643  update();
644  }
645  else if ( mResizeMode == ZoomResizeFrame )
646  {
647  QSizeF currentPictureSize = pictureSize();
648  QRectF oldRect = QRectF( pos().x(), pos().y(), rect().width(), rect().height() );
649 
650  //calculate actual size of image inside frame
651  QRectF rotatedImageRect = QgsLayoutUtils::largestRotatedRectWithinBounds( QRectF( 0, 0, currentPictureSize.width(), currentPictureSize.height() ), rect(), oldRotation );
652 
653  //rotate image rect by new rotation and get bounding box
654  QTransform tr;
655  tr.rotate( mPictureRotation );
656  QRectF newRect = tr.mapRect( QRectF( 0, 0, rotatedImageRect.width(), rotatedImageRect.height() ) );
657 
658  //keep the center in the same location
659  newRect.moveCenter( oldRect.center() );
660  attemptSetSceneRect( newRect );
661  emit changed();
662  }
663 
664  emit pictureRotationChanged( mPictureRotation );
665 }
666 
668 {
669  mNorthArrowHandler->setLinkedMap( map );
670 }
671 
673 {
674  mResizeMode = mode;
676  || ( mode == QgsLayoutItemPicture::Zoom && !qgsDoubleNear( mPictureRotation, 0.0 ) ) )
677  {
678  //call set scene rect to force item to resize to fit picture
679  recalculateSize();
680  }
681  update();
682 }
683 
685 {
686  //call set scene rect with current position/size, as this will trigger the
687  //picture item to recalculate its frame and image size
688  attemptSetSceneRect( QRectF( pos().x(), pos().y(), rect().width(), rect().height() ) );
689 }
690 
692 {
695  || property == QgsLayoutObject::AllProperties )
696  {
698  refreshPicture( &context );
699  }
700 
702 }
703 
704 void QgsLayoutItemPicture::setPicturePath( const QString &path, Format format )
705 {
706  mMode = format;
707  mSourcePath = path;
708  refreshPicture();
709 }
710 
712 {
713  return mSourcePath;
714 }
715 
716 bool QgsLayoutItemPicture::writePropertiesToElement( QDomElement &elem, QDomDocument &, const QgsReadWriteContext &context ) const
717 {
718  QString imagePath = mSourcePath;
719 
720  // convert from absolute path to relative. For SVG we also need to consider system SVG paths
721  QgsPathResolver pathResolver = context.pathResolver();
722  if ( imagePath.endsWith( QLatin1String( ".svg" ), Qt::CaseInsensitive ) )
723  imagePath = QgsSymbolLayerUtils::svgSymbolPathToName( imagePath, pathResolver );
724  else
725  imagePath = pathResolver.writePath( imagePath );
726 
727  elem.setAttribute( QStringLiteral( "file" ), imagePath );
728  elem.setAttribute( QStringLiteral( "pictureWidth" ), QString::number( mPictureWidth ) );
729  elem.setAttribute( QStringLiteral( "pictureHeight" ), QString::number( mPictureHeight ) );
730  elem.setAttribute( QStringLiteral( "resizeMode" ), QString::number( static_cast< int >( mResizeMode ) ) );
731  elem.setAttribute( QStringLiteral( "anchorPoint" ), QString::number( static_cast< int >( mPictureAnchor ) ) );
732  elem.setAttribute( QStringLiteral( "svgFillColor" ), QgsSymbolLayerUtils::encodeColor( mSvgFillColor ) );
733  elem.setAttribute( QStringLiteral( "svgBorderColor" ), QgsSymbolLayerUtils::encodeColor( mSvgStrokeColor ) );
734  elem.setAttribute( QStringLiteral( "svgBorderWidth" ), QString::number( mSvgStrokeWidth ) );
735  elem.setAttribute( QStringLiteral( "mode" ), mMode );
736 
737  //rotation
738  elem.setAttribute( QStringLiteral( "pictureRotation" ), QString::number( mPictureRotation ) );
739  if ( !mNorthArrowHandler->linkedMap() )
740  {
741  elem.setAttribute( QStringLiteral( "mapUuid" ), QString() );
742  }
743  else
744  {
745  elem.setAttribute( QStringLiteral( "mapUuid" ), mNorthArrowHandler->linkedMap()->uuid() );
746  }
747  elem.setAttribute( QStringLiteral( "northMode" ), mNorthArrowHandler->northMode() );
748  elem.setAttribute( QStringLiteral( "northOffset" ), mNorthArrowHandler->northOffset() );
749  return true;
750 }
751 
752 bool QgsLayoutItemPicture::readPropertiesFromElement( const QDomElement &itemElem, const QDomDocument &, const QgsReadWriteContext &context )
753 {
754  mPictureWidth = itemElem.attribute( QStringLiteral( "pictureWidth" ), QStringLiteral( "10" ) ).toDouble();
755  mPictureHeight = itemElem.attribute( QStringLiteral( "pictureHeight" ), QStringLiteral( "10" ) ).toDouble();
756  mResizeMode = QgsLayoutItemPicture::ResizeMode( itemElem.attribute( QStringLiteral( "resizeMode" ), QStringLiteral( "0" ) ).toInt() );
757  //when loading from xml, default to anchor point of middle to match pre 2.4 behavior
758  mPictureAnchor = static_cast< QgsLayoutItem::ReferencePoint >( itemElem.attribute( QStringLiteral( "anchorPoint" ), QString::number( QgsLayoutItem::Middle ) ).toInt() );
759 
760  mSvgFillColor = QgsSymbolLayerUtils::decodeColor( itemElem.attribute( QStringLiteral( "svgFillColor" ), QgsSymbolLayerUtils::encodeColor( QColor( 255, 255, 255 ) ) ) );
761  mSvgStrokeColor = QgsSymbolLayerUtils::decodeColor( itemElem.attribute( QStringLiteral( "svgBorderColor" ), QgsSymbolLayerUtils::encodeColor( QColor( 0, 0, 0 ) ) ) );
762  mSvgStrokeWidth = itemElem.attribute( QStringLiteral( "svgBorderWidth" ), QStringLiteral( "0.2" ) ).toDouble();
763  mMode = static_cast< Format >( itemElem.attribute( QStringLiteral( "mode" ), QString::number( FormatUnknown ) ).toInt() );
764 
765  QDomNodeList composerItemList = itemElem.elementsByTagName( QStringLiteral( "ComposerItem" ) );
766  if ( !composerItemList.isEmpty() )
767  {
768  QDomElement composerItemElem = composerItemList.at( 0 ).toElement();
769 
770  if ( !qgsDoubleNear( composerItemElem.attribute( QStringLiteral( "rotation" ), QStringLiteral( "0" ) ).toDouble(), 0.0 ) )
771  {
772  //in versions prior to 2.1 picture rotation was stored in the rotation attribute
773  mPictureRotation = composerItemElem.attribute( QStringLiteral( "rotation" ), QStringLiteral( "0" ) ).toDouble();
774  }
775  }
776 
777  mDefaultSvgSize = QSize( 0, 0 );
778 
779  if ( itemElem.hasAttribute( QStringLiteral( "sourceExpression" ) ) )
780  {
781  //update pre 2.5 picture expression to use data defined expression
782  QString sourceExpression = itemElem.attribute( QStringLiteral( "sourceExpression" ), QString() );
783  QString useExpression = itemElem.attribute( QStringLiteral( "useExpression" ) );
784  bool expressionActive;
785  expressionActive = ( useExpression.compare( QLatin1String( "true" ), Qt::CaseInsensitive ) == 0 );
786 
788  }
789 
790  QString imagePath = itemElem.attribute( QStringLiteral( "file" ) );
791 
792  // convert from relative path to absolute. For SVG we also need to consider system SVG paths
793  QgsPathResolver pathResolver = context.pathResolver();
794  if ( imagePath.endsWith( QLatin1String( ".svg" ), Qt::CaseInsensitive ) )
795  imagePath = QgsSymbolLayerUtils::svgSymbolNameToPath( imagePath, pathResolver );
796  else
797  imagePath = pathResolver.readPath( imagePath );
798 
799  mSourcePath = imagePath;
800 
801  //picture rotation
802  if ( !qgsDoubleNear( itemElem.attribute( QStringLiteral( "pictureRotation" ), QStringLiteral( "0" ) ).toDouble(), 0.0 ) )
803  {
804  mPictureRotation = itemElem.attribute( QStringLiteral( "pictureRotation" ), QStringLiteral( "0" ) ).toDouble();
805  }
806 
807  //rotation map
808  mNorthArrowHandler->setNorthMode( static_cast< QgsLayoutNorthArrowHandler::NorthMode >( itemElem.attribute( QStringLiteral( "northMode" ), QStringLiteral( "0" ) ).toInt() ) );
809  mNorthArrowHandler->setNorthOffset( itemElem.attribute( QStringLiteral( "northOffset" ), QStringLiteral( "0" ) ).toDouble() );
810 
811  mNorthArrowHandler->setLinkedMap( nullptr );
812  mRotationMapUuid = itemElem.attribute( QStringLiteral( "mapUuid" ) );
813 
814  return true;
815 }
816 
818 {
819  return mNorthArrowHandler->linkedMap();
820 }
821 
823 {
824  return static_cast< QgsLayoutItemPicture::NorthMode >( mNorthArrowHandler->northMode() );
825 }
826 
828 {
829  mNorthArrowHandler->setNorthMode( static_cast< QgsLayoutNorthArrowHandler::NorthMode >( mode ) );
830 }
831 
833 {
834  return mNorthArrowHandler->northOffset();
835 }
836 
838 {
839  mNorthArrowHandler->setNorthOffset( offset );
840 }
841 
843 {
844  mPictureAnchor = anchor;
845  update();
846 }
847 
848 void QgsLayoutItemPicture::setSvgFillColor( const QColor &color )
849 {
850  mSvgFillColor = color;
851  refreshPicture();
852 }
853 
854 void QgsLayoutItemPicture::setSvgStrokeColor( const QColor &color )
855 {
856  mSvgStrokeColor = color;
857  refreshPicture();
858 }
859 
861 {
862  mSvgStrokeWidth = width;
863  refreshPicture();
864 }
865 
867 {
868  if ( mMode == mode )
869  return;
870 
871  mMode = mode;
872  refreshPicture();
873 }
874 
876 {
877  if ( !mLayout || mRotationMapUuid.isEmpty() )
878  {
879  mNorthArrowHandler->setLinkedMap( nullptr );
880  }
881  else
882  {
883  mNorthArrowHandler->setLinkedMap( qobject_cast< QgsLayoutItemMap * >( mLayout->itemByUuid( mRotationMapUuid, true ) ) );
884  }
885 
886  refreshPicture();
887 }
QgsExpressionContext
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Definition: qgsexpressioncontext.h:369
QgsLayoutItemPicture::setLinkedMap
void setLinkedMap(QgsLayoutItemMap *map)
Sets the map object for rotation.
Definition: qgslayoutitempicture.cpp:667
QgsLayoutObject::layout
const QgsLayout * layout() const
Returns the layout the object is attached to.
Definition: qgslayoutobject.cpp:118
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:230
QgsLayoutItemPicture::setSvgStrokeColor
void setSvgStrokeColor(const QColor &color)
Sets the stroke color used for parametrized SVG files.
Definition: qgslayoutitempicture.cpp:854
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:231
QgsApplication::getThemeIcon
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
Definition: qgsapplication.cpp:605
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
Definition: qgsreadwritecontext.h:34
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
QgsLayout::renderContext
QgsLayoutRenderContext & renderContext()
Returns a reference to the layout's render context, which stores information relating to the current ...
Definition: qgslayout.cpp:358
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
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:514
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:616
QgsLayoutObject::mDataDefinedProperties
QgsPropertyCollection mDataDefinedProperties
Definition: qgslayoutobject.h:337
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:611
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:3945
qgsmapsettings.h
QgsRenderContext::scaleFactor
double scaleFactor() const
Returns the scaling factor for the render to convert painter units to physical sizes.
Definition: qgsrendercontext.h:317
QgsLayoutItemPicture::northOffset
double northOffset() const
Returns the offset added to the picture's rotation from a map's North.
Definition: qgslayoutitempicture.cpp:832
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:180
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:817
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:181
QgsPropertyCollection::property
QgsProperty property(int key) const override
Returns a matching property from the collection, if one exists.
Definition: qgspropertycollection.cpp:204
QgsLayoutItemPicture::applyItemSizeConstraint
QSizeF applyItemSizeConstraint(QSizeF targetSize) override
Applies any item-specific size constraint handling to a given targetSize in layout units.
Definition: qgslayoutitempicture.cpp:210
QgsLayoutItemPicture::readPropertiesFromElement
bool readPropertiesFromElement(const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context) override
Sets item state from a DOM element.
Definition: qgslayoutitempicture.cpp:752
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:187
QgsNetworkContentFetcher
HTTP network content fetcher. A simple method for fetching remote HTTP content and converting the con...
Definition: qgsnetworkcontentfetcher.h:37
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:875
QgsLayoutItemPicture::refreshDataDefinedProperty
void refreshDataDefinedProperty(QgsLayoutObject::DataDefinedProperty property=QgsLayoutObject::AllProperties) override
Definition: qgslayoutitempicture.cpp:691
QgsLayoutItemPicture::setNorthMode
void setNorthMode(NorthMode mode)
Sets the mode used to align the picture to a map's North.
Definition: qgslayoutitempicture.cpp:827
QgsNetworkContentFetcher::fetchContent
void fetchContent(const QUrl &url, const QString &authcfg=QString())
Fetches content from a remote URL and handles redirects.
Definition: qgsnetworkcontentfetcher.cpp:40
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:837
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:79
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:82
QgsLayout::reportContext
QgsLayoutReportContext & reportContext()
Returns a reference to the layout's report context, which stores information relating to the current ...
Definition: qgslayout.cpp:368
QgsApplication::imageCache
static QgsImageCache * imageCache()
Returns the application's image cache, used for caching resampled versions of raster images.
Definition: qgsapplication.cpp:2134
QgsLayoutItemPicture::Format
Format
Format of source image.
Definition: qgslayoutitempicture.h:55
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:338
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:704
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
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
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:2129
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:866
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
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:39
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:822
QgsLayoutItemPicture::setSvgStrokeWidth
void setSvgStrokeWidth(double width)
Sets the stroke width (in layout units) used for parametrized SVG files.
Definition: qgslayoutitempicture.cpp:860
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:340
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:672
QgsLayoutObject::mLayout
QPointer< QgsLayout > mLayout
Definition: qgslayoutobject.h:335
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:49
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:3879
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:842
QgsLayoutItemPicture::writePropertiesToElement
bool writePropertiesToElement(QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context) const override
Stores item state within an XML DOM element.
Definition: qgslayoutitempicture.cpp:716
QgsLayoutItemPicture::picturePath
QString picturePath() const
Returns the path of the source image.
Definition: qgslayoutitempicture.cpp:711
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:293
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: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:177
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:174
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:258
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
Definition: qgspathresolver.h:31
QgsLayoutObject::PictureSvgBackgroundColor
@ PictureSvgBackgroundColor
SVG background color.
Definition: qgslayoutobject.h:179
qgsproject.h
QgsLayoutItemPicture::setPictureRotation
void setPictureRotation(double rotation)
Sets the picture rotation within the item bounds, in degrees clockwise.
Definition: qgslayoutitempicture.cpp:631
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:684
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:178
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:848
QgsLayoutRenderContext::dpiChanged
void dpiChanged()
Emitted when the context's DPI is changed.