29 #include <QDomDocument> 30 #include <QDomElement> 32 #include <QImageReader> 34 #include <QSvgRenderer> 35 #include <QNetworkRequest> 36 #include <QNetworkReply> 38 #include <QCoreApplication> 43 , mPictureRotation( 0 )
46 , mPictureAnchor( UpperLeft )
47 , mHasExpressionError( false )
49 mPictureWidth = rect().width();
55 mPictureRotation( 0 ),
59 mHasExpressionError(
false )
61 mPictureHeight = rect().height();
65 void QgsComposerPicture::init()
94 Q_UNUSED( itemStyle );
112 double boundRectWidthMM;
113 double boundRectHeightMM;
117 boundRectWidthMM = mPictureWidth;
118 boundRectHeightMM = mPictureHeight;
119 imageRect = QRect( 0, 0, mImage.width(), mImage.height() );
123 boundRectWidthMM = rect().width();
124 boundRectHeightMM = rect().height();
125 imageRect = QRect( 0, 0, mImage.width(), mImage.height() );
129 boundRectWidthMM = rect().width();
130 boundRectHeightMM = rect().height();
131 int imageRectWidthPixels = mImage.width();
132 int imageRectHeightPixels = mImage.height();
133 imageRect = clippedImageRect( boundRectWidthMM, boundRectHeightMM,
134 QSize( imageRectWidthPixels, imageRectHeightPixels ) );
138 boundRectWidthMM = rect().width();
139 boundRectHeightMM = rect().height();
145 painter->setRenderHint( QPainter::Antialiasing,
true );
148 if ( mResizeMode ==
Zoom )
152 if ( mPictureRotation != 0 )
154 painter->translate( rect().width() / 2.0, rect().height() / 2.0 );
155 painter->rotate( mPictureRotation );
156 painter->translate( -boundRectWidthMM / 2.0, -boundRectHeightMM / 2.0 );
161 double diffX = rect().width() - boundRectWidthMM;
162 double diffY = rect().height() - boundRectHeightMM;
166 switch ( mPictureAnchor )
184 switch ( mPictureAnchor )
202 painter->translate( dX, dY );
207 if ( mPictureRotation != 0 )
209 painter->translate( rect().width() / 2.0, rect().height() / 2.0 );
210 painter->rotate( mPictureRotation );
211 painter->translate( -boundRectWidthMM / 2.0, -boundRectHeightMM / 2.0 );
217 mSVG.render( painter, QRectF( 0, 0, boundRectWidthMM, boundRectHeightMM ) );
219 else if ( mMode ==
RASTER )
221 painter->drawImage( QRectF( 0, 0, boundRectWidthMM, boundRectHeightMM ), mImage, imageRect );
235 QRect QgsComposerPicture::clippedImageRect(
double &boundRectWidthMM,
double &boundRectHeightMM, QSize imageRectPixels )
249 switch ( mPictureAnchor )
259 leftClip = ( imageRectPixels.width() - boundRectWidthPixels ) / 2;
264 leftClip = imageRectPixels.width() - boundRectWidthPixels;
269 switch ( mPictureAnchor )
279 topClip = ( imageRectPixels.height() - boundRectHeightPixels ) / 2;
284 topClip = imageRectPixels.height() - boundRectHeightPixels;
288 return QRect( leftClip, topClip, boundRectWidthPixels, boundRectHeightPixels );
298 QString source = mSourcePath;
301 mHasExpressionError =
false;
307 source = exprVal.toString().trimmed();
308 QgsDebugMsg( QString(
"exprVal PictureSource:%1" ).arg( source ) );
312 mHasExpressionError =
true;
318 loadPicture( source );
321 void QgsComposerPicture::loadRemotePicture(
const QString &url )
329 connect( &fetcher, SIGNAL( finished() ),
this, SLOT( remotePictureLoaded() ) );
333 qApp->processEvents();
336 QNetworkReply* reply = fetcher.
reply();
339 QImageReader imageReader( reply );
340 mImage = imageReader.read();
342 reply->deleteLater();
350 void QgsComposerPicture::loadLocalPicture(
const QString &path )
353 pic.setFileName( path );
361 QFileInfo sourceFileInfo( pic );
362 QString sourceFileSuffix = sourceFileInfo.suffix();
363 if ( sourceFileSuffix.compare(
"svg", Qt::CaseInsensitive ) == 0 )
366 mSVG.load( pic.fileName() );
367 if ( mSVG.isValid() )
370 QRect viewBox = mSVG.viewBox();
371 mDefaultSvgSize.setWidth( viewBox.width() );
372 mDefaultSvgSize.setHeight( viewBox.height() );
382 QImageReader imageReader( pic.fileName() );
383 if ( imageReader.read( &mImage ) )
396 void QgsComposerPicture::remotePictureLoaded()
401 void QgsComposerPicture::loadPicture(
const QString &path )
403 if ( path.startsWith(
"http" ) )
406 loadRemotePicture( path );
411 loadLocalPicture( path );
417 else if ( mHasExpressionError || !( path.isEmpty() ) )
421 QString badFile = QString(
":/images/composer/missing_image.svg" );
422 mSVG.load( badFile );
423 if ( mSVG.isValid() )
426 QRect viewBox = mSVG.viewBox();
427 mDefaultSvgSize.setWidth( viewBox.width() );
428 mDefaultSvgSize.setHeight( viewBox.height() );
436 QRectF QgsComposerPicture::boundedImageRect(
double deviceWidth,
double deviceHeight )
438 double imageToDeviceRatio;
439 if ( mImage.width() / deviceWidth > mImage.height() / deviceHeight )
441 imageToDeviceRatio = deviceWidth / mImage.width();
442 double height = imageToDeviceRatio * mImage.height();
443 return QRectF( 0, 0, deviceWidth, height );
447 imageToDeviceRatio = deviceHeight / mImage.height();
448 double width = imageToDeviceRatio * mImage.width();
449 return QRectF( 0, 0, width, deviceHeight );
453 QRectF QgsComposerPicture::boundedSVGRect(
double deviceWidth,
double deviceHeight )
455 double imageToSvgRatio;
456 if ( deviceWidth / mDefaultSvgSize.width() > deviceHeight / mDefaultSvgSize.height() )
458 imageToSvgRatio = deviceHeight / mDefaultSvgSize.height();
459 double width = mDefaultSvgSize.width() * imageToSvgRatio;
460 return QRectF( 0, 0, width, deviceHeight );
464 imageToSvgRatio = deviceWidth / mDefaultSvgSize.width();
465 double height = mDefaultSvgSize.height() * imageToSvgRatio;
466 return QRectF( 0, 0, deviceWidth, height );
470 QSizeF QgsComposerPicture::pictureSize()
474 return mDefaultSvgSize;
476 else if ( mMode ==
RASTER )
478 return QSizeF( mImage.width(), mImage.height() );
482 return QSizeF( 0, 0 );
487 QRectF QgsComposerPicture::boundedSVGRect(
double deviceWidth,
double deviceHeight )
489 double imageToSvgRatio;
490 if ( deviceWidth / mDefaultSvgSize.width() < deviceHeight / mDefaultSvgSize.height() )
492 imageToSvgRatio = deviceWidth / mDefaultSvgSize.width();
493 double height = mDefaultSvgSize.height() * imageToSvgRatio;
494 return QRectF( 0, 0, deviceWidth, height );
498 imageToSvgRatio = deviceHeight / mDefaultSvgSize.height();
499 double width = mDefaultSvgSize.width() * imageToSvgRatio;
500 return QRectF( 0, 0, width, deviceHeight );
508 QSizeF currentPictureSize = pictureSize();
513 mPictureWidth = rectangle.width();
514 mPictureHeight = rectangle.height();
518 QRectF newRect = rectangle;
520 if ( mResizeMode ==
ZoomResizeFrame && !rect().isEmpty() && !( currentPictureSize.isEmpty() ) )
522 QSizeF targetImageSize;
523 if ( mPictureRotation == 0 )
525 targetImageSize = currentPictureSize;
531 tr.rotate( mPictureRotation );
532 QRectF rotatedBounds = tr.mapRect( QRectF( 0, 0, currentPictureSize.width(), currentPictureSize.height() ) );
533 targetImageSize = QSizeF( rotatedBounds.width(), rotatedBounds.height() );
538 if ( qAbs( rect().width() - rectangle.width() ) <
539 qAbs( rect().height() - rectangle.height() ) )
541 newRect.setHeight( targetImageSize.height() * newRect.width() / targetImageSize.width() );
545 newRect.setWidth( targetImageSize.width() * newRect.height() / targetImageSize.height() );
550 if ( !( currentPictureSize.isEmpty() ) )
561 mPictureWidth = rotatedImageRect.width();
562 mPictureHeight = rotatedImageRect.height();
566 mPictureWidth = newRect.width();
567 mPictureHeight = newRect.height();
582 double oldRotation = mPictureRotation;
583 mPictureRotation = r;
585 if ( mResizeMode ==
Zoom )
588 QSizeF currentPictureSize = pictureSize();
590 mPictureWidth = rotatedImageRect.width();
591 mPictureHeight = rotatedImageRect.height();
596 QSizeF currentPictureSize = pictureSize();
597 QRectF oldRect = QRectF( pos().x(), pos().y(), rect().width(), rect().height() );
604 tr.rotate( mPictureRotation );
605 QRectF newRect = tr.mapRect( QRectF( 0, 0, rotatedImageRect.width(), rotatedImageRect.height() ) );
608 newRect.moveCenter( oldRect.center() );
623 if ( composerMapId == -1 )
625 QObject::disconnect( mRotationMap, SIGNAL( mapRotationChanged(
double ) ),
this, SLOT(
setPictureRotation(
double ) ) );
636 QObject::disconnect( mRotationMap, SIGNAL( mapRotationChanged(
double ) ),
this, SLOT(
setPictureRotation(
double ) ) );
639 QObject::connect( map, SIGNAL( mapRotationChanged(
double ) ),
this, SLOT(
setPictureRotation(
double ) ) );
661 setSceneRect( QRectF( pos().x(), pos().y(), rect().width(), rect().height() ) );
708 QDomElement composerPictureElem = doc.createElement(
"ComposerPicture" );
710 composerPictureElem.setAttribute(
"pictureWidth", QString::number( mPictureWidth ) );
711 composerPictureElem.setAttribute(
"pictureHeight", QString::number( mPictureHeight ) );
712 composerPictureElem.setAttribute(
"resizeMode", QString::number((
int )mResizeMode ) );
713 composerPictureElem.setAttribute(
"anchorPoint", QString::number((
int )mPictureAnchor ) );
716 composerPictureElem.setAttribute(
"pictureRotation", QString::number( mPictureRotation ) );
719 composerPictureElem.setAttribute(
"mapId", -1 );
723 composerPictureElem.setAttribute(
"mapId", mRotationMap->
id() );
727 elem.appendChild( composerPictureElem );
733 if ( itemElem.isNull() )
738 mPictureWidth = itemElem.attribute(
"pictureWidth",
"10" ).toDouble();
739 mPictureHeight = itemElem.attribute(
"pictureHeight",
"10" ).toDouble();
744 QDomNodeList composerItemList = itemElem.elementsByTagName(
"ComposerItem" );
745 if ( composerItemList.size() > 0 )
747 QDomElement composerItemElem = composerItemList.at( 0 ).toElement();
749 if ( composerItemElem.attribute(
"rotation",
"0" ).toDouble() != 0 )
752 mPictureRotation = composerItemElem.attribute(
"rotation",
"0" ).toDouble();
758 mDefaultSvgSize = QSize( 0, 0 );
760 if ( itemElem.hasAttribute(
"sourceExpression" ) )
763 QString sourceExpression = itemElem.attribute(
"sourceExpression",
"" );
764 QString useExpression = itemElem.attribute(
"useExpression" );
765 bool expressionActive;
766 if ( useExpression.compare(
"true", Qt::CaseInsensitive ) == 0 )
768 expressionActive =
true;
772 expressionActive =
false;
781 if ( itemElem.attribute(
"pictureRotation",
"0" ).toDouble() != 0 )
783 mPictureRotation = itemElem.attribute(
"pictureRotation",
"0" ).toDouble();
787 int rotationMapId = itemElem.attribute(
"mapId",
"-1" ).toInt();
788 if ( rotationMapId == -1 )
797 QObject::disconnect( mRotationMap, SIGNAL( mapRotationChanged(
double ) ),
this, SLOT(
setRotation(
double ) ) );
800 QObject::connect( mRotationMap, SIGNAL( mapRotationChanged(
double ) ),
this, SLOT(
setRotation(
double ) ) );
817 return mRotationMap->
id();
823 mPictureAnchor = anchor;
void setActive(bool active)
bool readXML(const QDomElement &itemElem, const QDomDocument &doc) override
Sets state from Dom document.
Q_DECL_DEPRECATED bool imageSizeConsideringRotation(double &width, double &height, double rotation) const
Calculates width and hight of the picture (in mm) such that it fits into the item frame with the give...
virtual void refreshDataDefinedProperty(const QgsComposerObject::DataDefinedProperty property=QgsComposerObject::AllProperties) override
Refreshes a data defined property for the item by reevaluating the property's value and redrawing the...
void itemChanged()
Emitted when the item changes.
bool writeXML(QDomElement &elem, QDomDocument &doc) const override
Stores state in Dom element.
QgsComposerPicture(QgsComposition *composition)
Q_DECL_DEPRECATED bool imageSizeConsideringRotation(double &width, double &height) const
Calculates width and hight of the picture (in mm) such that it fits into the item frame with the give...
Mode mode() const
Returns the current picture mode (image format).
QMap< QgsComposerObject::DataDefinedProperty, QString > mDataDefinedNames
Map of data defined properties for the item to string name to use when exporting item to xml...
A item that forms part of a map composition.
#define Q_NOWARN_DEPRECATED_PUSH
static QRectF largestRotatedRectWithinBounds(const QRectF originalRect, const QRectF boundsRect, const double rotation)
Calculates the largest scaled version of originalRect which fits within boundsRect, when it is rotated by a specified amount.
void fetchContent(const QUrl url)
Fetches content from a remote URL and handles redirects.
QString expressionString() const
virtual void drawFrame(QPainter *p)
Draw black frame around item.
QString picturePath() const
Returns the path of the source image.
QNetworkReply * reply()
Returns a reference to the network reply.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
QString readPath(QString filename) const
turn filename read from the project file to an absolute path
DataDefinedProperty
Data defined properties for different item types.
bool dataDefinedEvaluate(const QgsComposerObject::DataDefinedProperty property, QVariant &expressionValue)
Evaluate a data defined property and return the calculated value.
A composer class that displays svg files or raster format (jpg, png, ...)
static void logMessage(QString message, QString tag=QString::null, MessageLevel level=WARNING)
add a message to the instance (and create it if necessary)
void recalculateSize()
Forces a recalculation of the picture's frame size.
bool _readXML(const QDomElement &itemElem, const QDomDocument &doc)
Reads parameter that are not subclass specific in document.
QgsDataDefined * dataDefinedProperty(const DataDefinedProperty property) const
Returns a reference to the data defined settings for one of the item's data defined properties...
void setPictureAnchor(QgsComposerItem::ItemPositionMode anchor)
Sets the picture's anchor point, which controls how it is placed within the picture item's frame...
void paint(QPainter *painter, const QStyleOptionGraphicsItem *itemStyle, QWidget *pWidget) override
Reimplementation of QCanvasItem::paint.
HTTP network content fetcher.
virtual void drawSelectionBoxes(QPainter *p)
Draws additional graphics on selected items.
int printResolution() const
virtual void setResizeMode(ResizeMode mode)
Sets the resize mode used for drawing the picture within the item bounds.
virtual void setUsePictureExpression(bool useExpression)
Sets whether the picture should use an expression based image source path.
bool shouldDrawItem() const
Returns whether the item should be drawn in the current context.
double mapRotation(QgsComposerObject::PropertyValueType valueType=QgsComposerObject::EvaluatedValue) const
Returns the rotation used for drawing the map within the composer item.
void setBackgroundEnabled(const bool drawBackground)
Set whether this item has a Background drawn around it or not.
Graphics scene for map printing.
Object representing map window.
Q_DECL_DEPRECATED QString pictureFile() const
Returns the path of the source image file.
Q_DECL_DEPRECATED bool cornerPointOnRotatedAndScaledRect(double &x, double &y, double width, double height) const
Calculates corner point after rotation and scaling.
void pictureRotationChanged(double newRotation)
Is emitted on picture rotation change.
#define Q_NOWARN_DEPRECATED_POP
int id() const
Get identification number.
Q_DECL_DEPRECATED void setPictureFile(const QString &path)
Sets the source file of the image (may be svg or a raster format).
QgsComposition * mComposition
void refreshPicture()
Recalculates the source image (if using an expression for picture's source) and reloads and redraws t...
Q_DECL_DEPRECATED bool cornerPointOnRotatedAndScaledRect(double &x, double &y, double width, double height, double rotation) const
Calculates corner point after rotation and scaling.
bool _writeXML(QDomElement &itemElem, QDomDocument &doc) const
Writes parameter that are not subclass specific in document.
virtual void refreshDataDefinedProperty(const QgsComposerObject::DataDefinedProperty property=QgsComposerObject::AllProperties) override
Refreshes a data defined property for the item by reevaluating the property's value and redrawing the...
virtual void drawBackground(QPainter *p)
Draw background.
Q_DECL_DEPRECATED QString pictureExpression() const
Returns the expression the item is using for the picture source.
static QgsProject * instance()
access to canonical QgsProject instance
virtual void setSceneRect(const QRectF &rectangle)
Sets this items bound in scene coordinates such that 1 item size units corresponds to 1 scene size un...
void setDataDefinedProperty(const DataDefinedProperty property, const bool active, const bool useExpression, const QString &expression, const QString &field)
Sets parameters for a data defined property for the item.
void setSceneRect(const QRectF &rectangle) override
Sets this items bound in scene coordinates such that 1 item size units corresponds to 1 scene size un...
QgsAtlasComposition & atlasComposition()
virtual void setRotation(double r) override
Sets the picture rotation within the item bounds.
void setRotationMap(int composerMapId)
Sets the map object for rotation (by id).
void setPicturePath(const QString &path)
Sets the source path of the image (may be svg or a raster format).
QgsComposerItem(QgsComposition *composition, bool manageZValue=true)
Constructor.
virtual void setPictureRotation(double r)
Sets the picture rotation within the item bounds.
const QgsComposerMap * getComposerMapById(const int id) const
Returns the composer map with specified id.
int rotationMap() const
Returns the id of the rotation map.
void setExpressionString(const QString &expr)
virtual void setPictureExpression(QString expression)
Sets an expression to use for the picture source.
Q_DECL_DEPRECATED void sizeChangedByRotation(double &width, double &height, double rotation)
Calculates width / height of the bounding box of a rotated rectangle.
Q_DECL_DEPRECATED bool usePictureExpression() const
Returns whether the picture item is using an expression for the image source.
Q_DECL_DEPRECATED void sizeChangedByRotation(double &width, double &height)
Calculates width / height of the bounding box of a rotated rectangle.