00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "qgscomposerpicture.h"
00020 #include "qgscomposermap.h"
00021 #include "qgsproject.h"
00022 #include <QDomDocument>
00023 #include <QDomElement>
00024 #include <QFileInfo>
00025 #include <QImageReader>
00026 #include <QPainter>
00027 #include <QSvgRenderer>
00028
00029
00030 QgsComposerPicture::QgsComposerPicture( QgsComposition *composition ): QgsComposerItem( composition ), mMode( Unknown ), \
00031 mSvgCacheUpToDate( false ), mCachedDpi( 0 ), mCachedRotation( 0 ), mCachedViewScaleFactor( -1 ), mRotationMap( 0 )
00032 {
00033 mPictureWidth = rect().width();
00034 }
00035
00036 QgsComposerPicture::QgsComposerPicture(): QgsComposerItem( 0 ), mMode( Unknown ), mSvgCacheUpToDate( false ), mCachedRotation( 0 ), mCachedViewScaleFactor( -1 ), mRotationMap( 0 )
00037 {
00038 mPictureHeight = rect().height();
00039 }
00040
00041 QgsComposerPicture::~QgsComposerPicture()
00042 {
00043
00044 }
00045
00046 void QgsComposerPicture::paint( QPainter* painter, const QStyleOptionGraphicsItem* itemStyle, QWidget* pWidget )
00047 {
00048 if ( !painter )
00049 {
00050 return;
00051 }
00052
00053 drawBackground( painter );
00054
00055 int newDpi = ( painter->device()->logicalDpiX() + painter->device()->logicalDpiY() ) / 2;
00056 double viewScaleFactor = horizontalViewScaleFactor();
00057
00058 if ( newDpi != mCachedDpi || mCachedRotation != mRotation || mCachedViewScaleFactor != viewScaleFactor )
00059 {
00060 mSvgCacheUpToDate = false;
00061 }
00062
00063 if ( mMode != Unknown )
00064 {
00065 double rectPixelWidth = mPictureWidth * newDpi / 25.4;
00066 double rectPixelHeight = mPictureHeight * newDpi / 25.4;
00067 QRectF boundRect;
00068 if ( mMode == SVG )
00069 {
00070 boundRect = boundedSVGRect( rectPixelWidth, rectPixelHeight );
00071 }
00072 else if ( mMode == RASTER )
00073 {
00074 boundRect = boundedImageRect( rectPixelWidth, rectPixelHeight );
00075 }
00076
00077 double boundRectWidthMM = boundRect.width() / newDpi * 25.4;
00078 double boundRectHeightMM = boundRect.height() / newDpi * 25.4;
00079 double boundImageWidth = boundRect.width();
00080 double boundImageHeight = boundRect.height();
00081
00082 if ( mMode == SVG )
00083 {
00084 if ( !mSvgCacheUpToDate )
00085 {
00086
00087 if ( mComposition && mComposition->plotStyle() == QgsComposition::Preview )
00088 {
00089 boundImageWidth *= std::min( viewScaleFactor, 10.0 );
00090 boundImageHeight *= std::min( viewScaleFactor, 10.0 );
00091 }
00092 mImage = QImage( boundImageWidth, boundImageHeight, QImage::Format_ARGB32 );
00093 updateImageFromSvg();
00094 }
00095 }
00096
00097 painter->save();
00098 painter->translate( rect().width() / 2.0, rect().height() / 2.0 );
00099 painter->rotate( mRotation );
00100 painter->translate( -boundRectWidthMM / 2.0, -boundRectHeightMM / 2.0 );
00101
00102 painter->drawImage( QRectF( 0, 0, boundRectWidthMM, boundRectHeightMM ), mImage, QRectF( 0, 0, mImage.width(), mImage.height() ) );
00103
00104 painter->restore();
00105 }
00106
00107 mCachedDpi = newDpi;
00108 mCachedRotation = mRotation;
00109 mCachedViewScaleFactor = viewScaleFactor;
00110
00111
00112 drawFrame( painter );
00113 if ( isSelected() )
00114 {
00115 drawSelectionBoxes( painter );
00116 }
00117 }
00118
00119 void QgsComposerPicture::setPictureFile( const QString& path )
00120 {
00121 mSourceFile.setFileName( path );
00122 if ( !mSourceFile.exists() )
00123 {
00124 mMode = Unknown;
00125 }
00126
00127 QFileInfo sourceFileInfo( mSourceFile );
00128 QString sourceFileSuffix = sourceFileInfo.suffix();
00129 if ( sourceFileSuffix.compare( "svg", Qt::CaseInsensitive ) == 0 )
00130 {
00131
00132 QSvgRenderer validTestRenderer( mSourceFile.fileName() );
00133 if ( validTestRenderer.isValid() )
00134 {
00135 mMode = SVG;
00136 QRect viewBox = validTestRenderer.viewBox();
00137 mDefaultSvgSize.setWidth( viewBox.width() );
00138 mDefaultSvgSize.setHeight( viewBox.height() );
00139 mSvgCacheUpToDate = false;
00140 }
00141 else
00142 {
00143 mMode = Unknown;
00144 }
00145 }
00146 else
00147 {
00148
00149 QImageReader imageReader( mSourceFile.fileName() );
00150 if ( imageReader.read( &mImage ) )
00151 {
00152 mMode = RASTER;
00153 }
00154 else
00155 {
00156 mMode = Unknown;
00157 }
00158 }
00159
00160 if ( mMode != Unknown )
00161 {
00162 setSceneRect( QRectF( transform().dx(), transform().dy(), rect().width(), rect().height() ) );
00163 }
00164 emit settingsChanged();
00165 }
00166
00167 QRectF QgsComposerPicture::boundedImageRect( double deviceWidth, double deviceHeight )
00168 {
00169 double imageToDeviceRatio;
00170 if ( mImage.width() / deviceWidth > mImage.height() / deviceHeight )
00171 {
00172 imageToDeviceRatio = deviceWidth / mImage.width();
00173 double height = imageToDeviceRatio * mImage.height();
00174 return QRectF( 0, 0, deviceWidth, height );
00175 }
00176 else
00177 {
00178 imageToDeviceRatio = deviceHeight / mImage.height();
00179 double width = imageToDeviceRatio * mImage.width();
00180 return QRectF( 0, 0, width, deviceHeight );
00181 }
00182 }
00183
00184 QRectF QgsComposerPicture::boundedSVGRect( double deviceWidth, double deviceHeight )
00185 {
00186 double imageToSvgRatio;
00187 if ( deviceWidth / mDefaultSvgSize.width() > deviceHeight / mDefaultSvgSize.height() )
00188 {
00189 imageToSvgRatio = deviceHeight / mDefaultSvgSize.height();
00190 double width = mDefaultSvgSize.width() * imageToSvgRatio;
00191 return QRectF( 0, 0, width, deviceHeight );
00192 }
00193 else
00194 {
00195 imageToSvgRatio = deviceWidth / mDefaultSvgSize.width();
00196 double height = mDefaultSvgSize.height() * imageToSvgRatio;
00197 return QRectF( 0, 0, deviceWidth, height );
00198 }
00199 }
00200
00201 #if 0
00202 QRectF QgsComposerPicture::boundedSVGRect( double deviceWidth, double deviceHeight )
00203 {
00204 double imageToSvgRatio;
00205 if ( deviceWidth / mDefaultSvgSize.width() < deviceHeight / mDefaultSvgSize.height() )
00206 {
00207 imageToSvgRatio = deviceWidth / mDefaultSvgSize.width();
00208 double height = mDefaultSvgSize.height() * imageToSvgRatio;
00209 return QRectF( 0, 0, deviceWidth, height );
00210 }
00211 else
00212 {
00213 imageToSvgRatio = deviceHeight / mDefaultSvgSize.height();
00214 double width = mDefaultSvgSize.width() * imageToSvgRatio;
00215 return QRectF( 0, 0, width, deviceHeight );
00216 }
00217 }
00218 #endif //0
00219
00220 void QgsComposerPicture::updateImageFromSvg()
00221 {
00222 mImage.fill( 0 );
00223 QPainter p( &mImage );
00224 p.setRenderHints( QPainter::Antialiasing | QPainter::TextAntialiasing, true );
00225 QSvgRenderer theRenderer( mSourceFile.fileName() );
00226 theRenderer.render( &p );
00227 mSvgCacheUpToDate = true;
00228 }
00229
00230
00231
00232 void QgsComposerPicture::setSceneRect( const QRectF& rectangle )
00233 {
00234 mSvgCacheUpToDate = false;
00235 QgsComposerItem::setSceneRect( rectangle );
00236
00237
00238 double newPictureWidth = rectangle.width();
00239 double newPictureHeight = rectangle.height();
00240 imageSizeConsideringRotation( newPictureWidth, newPictureHeight );
00241 mPictureWidth = newPictureWidth;
00242 mPictureHeight = newPictureHeight;
00243
00244 emit settingsChanged();
00245 }
00246
00247 void QgsComposerPicture::setRotation( double r )
00248 {
00249
00250 double width = mPictureWidth;
00251 double height = mPictureHeight;
00252 sizeChangedByRotation( width, height );
00253
00254
00255 double x = transform().dx() + rect().width() / 2.0 - width / 2.0;
00256 double y = transform().dy() + rect().height() / 2.0 - height / 2.0;
00257 QgsComposerItem::setSceneRect( QRectF( x, y, width, height ) );
00258
00259 QgsComposerItem::setRotation( r );
00260 }
00261
00262 void QgsComposerPicture::setRotationMap( int composerMapId )
00263 {
00264 if ( !mComposition )
00265 {
00266 return;
00267 }
00268
00269 if ( composerMapId == -1 )
00270 {
00271 QObject::disconnect( mRotationMap, SIGNAL( rotationChanged( double ) ), this, SLOT( setRotation( double ) ) );
00272 mRotationMap = 0;
00273 }
00274
00275 const QgsComposerMap* map = mComposition->getComposerMapById( composerMapId );
00276 if ( !map )
00277 {
00278 return;
00279 }
00280 if ( mRotationMap )
00281 {
00282 QObject::disconnect( mRotationMap, SIGNAL( rotationChanged( double ) ), this, SLOT( setRotation( double ) ) );
00283 }
00284 mRotation = map->rotation();
00285 QObject::connect( map, SIGNAL( rotationChanged( double ) ), this, SLOT( setRotation( double ) ) );
00286 mRotationMap = map;
00287 setRotation( map->rotation() );
00288 }
00289
00290 QString QgsComposerPicture::pictureFile() const
00291 {
00292 return mSourceFile.fileName();
00293 }
00294
00295 bool QgsComposerPicture::writeXML( QDomElement& elem, QDomDocument & doc ) const
00296 {
00297 if ( elem.isNull() )
00298 {
00299 return false;
00300 }
00301 QDomElement composerPictureElem = doc.createElement( "ComposerPicture" );
00302 composerPictureElem.setAttribute( "file", QgsProject::instance()->writePath( mSourceFile.fileName() ) );
00303 composerPictureElem.setAttribute( "pictureWidth", mPictureWidth );
00304 composerPictureElem.setAttribute( "pictureHeight", mPictureHeight );
00305 if ( !mRotationMap )
00306 {
00307 composerPictureElem.setAttribute( "mapId", -1 );
00308 }
00309 else
00310 {
00311 composerPictureElem.setAttribute( "mapId", mRotationMap->id() );
00312 }
00313
00314 _writeXML( composerPictureElem, doc );
00315 elem.appendChild( composerPictureElem );
00316 return true;
00317 }
00318
00319 bool QgsComposerPicture::readXML( const QDomElement& itemElem, const QDomDocument& doc )
00320 {
00321 if ( itemElem.isNull() )
00322 {
00323 return false;
00324 }
00325
00326 mPictureWidth = itemElem.attribute( "pictureWidth", "10" ).toDouble();
00327 mPictureHeight = itemElem.attribute( "pictureHeight", "10" ).toDouble();
00328
00329 QDomNodeList composerItemList = itemElem.elementsByTagName( "ComposerItem" );
00330 if ( composerItemList.size() > 0 )
00331 {
00332 _readXML( composerItemList.at( 0 ).toElement(), doc );
00333 }
00334
00335
00336 mSvgCacheUpToDate = false;
00337 mDefaultSvgSize = QSize( 0, 0 );
00338 mCachedDpi = 0;
00339
00340 QString fileName = QgsProject::instance()->readPath( itemElem.attribute( "file" ) );
00341 setPictureFile( fileName );
00342
00343
00344 int rotationMapId = itemElem.attribute( "mapId", "-1" ).toInt();
00345 if ( rotationMapId == -1 )
00346 {
00347 mRotationMap = 0;
00348 }
00349 else if ( mComposition )
00350 {
00351
00352 if ( mRotationMap )
00353 {
00354 QObject::disconnect( mRotationMap, SIGNAL( rotationChanged( double ) ), this, SLOT( setRotation( double ) ) );
00355 }
00356 mRotationMap = mComposition->getComposerMapById( rotationMapId );
00357 QObject::connect( mRotationMap, SIGNAL( rotationChanged( double ) ), this, SLOT( setRotation( double ) ) );
00358 }
00359
00360 return true;
00361 }
00362
00363 int QgsComposerPicture::rotationMap() const
00364 {
00365 if ( !mRotationMap )
00366 {
00367 return -1;
00368 }
00369 else
00370 {
00371 return mRotationMap->id();
00372 }
00373 }