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 ),
58 mPictureAnchor( UpperLeft ),
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;