Quantum GIS API Documentation  master-693a1fe
src/core/composer/qgscomposerpicture.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002                            qgscomposerpicture.cpp
00003                              -------------------
00004     begin                : September 2005
00005     copyright            : (C) 2005 by Radim Blazek
00006     email                : radim.blazek@gmail.com
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00018 #include "qgscomposerpicture.h"
00019 #include "qgscomposermap.h"
00020 #include "qgscomposition.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 )
00031     : QgsComposerItem( composition ), mMode( Unknown ), mRotationMap( 0 )
00032 {
00033   mPictureWidth = rect().width();
00034 }
00035 
00036 QgsComposerPicture::QgsComposerPicture(): QgsComposerItem( 0 ), mMode( Unknown ), mRotationMap( 0 )
00037 {
00038   mPictureHeight = rect().height();
00039 }
00040 
00041 
00042 QgsComposerPicture::~QgsComposerPicture()
00043 {
00044 
00045 }
00046 
00047 void QgsComposerPicture::paint( QPainter* painter, const QStyleOptionGraphicsItem* itemStyle, QWidget* pWidget )
00048 {
00049   Q_UNUSED( itemStyle );
00050   Q_UNUSED( pWidget );
00051   if ( !painter )
00052   {
00053     return;
00054   }
00055 
00056   drawBackground( painter );
00057 
00058   int newDpi = ( painter->device()->logicalDpiX() + painter->device()->logicalDpiY() ) / 2;
00059 
00060   if ( mMode != Unknown )
00061   {
00062     double rectPixelWidth = /*rect().width()*/mPictureWidth * newDpi / 25.4;
00063     double rectPixelHeight = /*rect().height()*/ mPictureHeight * newDpi / 25.4;
00064     QRectF boundRect;
00065     if ( mMode == SVG )
00066     {
00067       boundRect = boundedSVGRect( rectPixelWidth, rectPixelHeight );
00068     }
00069     else if ( mMode == RASTER )
00070     {
00071       boundRect = boundedImageRect( rectPixelWidth, rectPixelHeight );
00072     }
00073 
00074     double boundRectWidthMM = boundRect.width() / newDpi * 25.4;
00075     double boundRectHeightMM = boundRect.height() / newDpi * 25.4;
00076 
00077     painter->save();
00078     painter->translate( rect().width() / 2.0, rect().height() / 2.0 );
00079     painter->rotate( mRotation );
00080     painter->translate( -boundRectWidthMM / 2.0, -boundRectHeightMM / 2.0 );
00081 
00082     if ( mMode == SVG )
00083     {
00084       mSVG.render( painter, QRectF( 0, 0, boundRectWidthMM,  boundRectHeightMM ) );
00085     }
00086     else if ( mMode == RASTER )
00087     {
00088       painter->drawImage( QRectF( 0, 0, boundRectWidthMM,  boundRectHeightMM ), mImage, QRectF( 0, 0, mImage.width(), mImage.height() ) );
00089     }
00090 
00091     painter->restore();
00092   }
00093 
00094   //frame and selection boxes
00095   drawFrame( painter );
00096   if ( isSelected() )
00097   {
00098     drawSelectionBoxes( painter );
00099   }
00100 }
00101 
00102 void QgsComposerPicture::setPictureFile( const QString& path )
00103 {
00104   mSourceFile.setFileName( path );
00105   if ( !mSourceFile.exists() )
00106   {
00107     mMode = Unknown;
00108   }
00109 
00110   QFileInfo sourceFileInfo( mSourceFile );
00111   QString sourceFileSuffix = sourceFileInfo.suffix();
00112   if ( sourceFileSuffix.compare( "svg", Qt::CaseInsensitive ) == 0 )
00113   {
00114     //try to open svg
00115     mSVG.load( mSourceFile.fileName() );
00116     if ( mSVG.isValid() )
00117     {
00118       mMode = SVG;
00119       QRect viewBox = mSVG.viewBox(); //take width/height ratio from view box instead of default size
00120       mDefaultSvgSize.setWidth( viewBox.width() );
00121       mDefaultSvgSize.setHeight( viewBox.height() );
00122     }
00123     else
00124     {
00125       mMode = Unknown;
00126     }
00127   }
00128   else
00129   {
00130     //try to open raster with QImageReader
00131     QImageReader imageReader( mSourceFile.fileName() );
00132     if ( imageReader.read( &mImage ) )
00133     {
00134       mMode = RASTER;
00135     }
00136     else
00137     {
00138       mMode = Unknown;
00139     }
00140   }
00141 
00142   if ( mMode != Unknown ) //make sure we start with a new QImage
00143   {
00144     setSceneRect( QRectF( transform().dx(), transform().dy(), rect().width(), rect().height() ) );
00145   }
00146   emit itemChanged();
00147 }
00148 
00149 QRectF QgsComposerPicture::boundedImageRect( double deviceWidth, double deviceHeight )
00150 {
00151   double imageToDeviceRatio;
00152   if ( mImage.width() / deviceWidth > mImage.height() / deviceHeight )
00153   {
00154     imageToDeviceRatio =  deviceWidth / mImage.width();
00155     double height = imageToDeviceRatio * mImage.height();
00156     return QRectF( 0, 0, deviceWidth, height );
00157   }
00158   else
00159   {
00160     imageToDeviceRatio = deviceHeight / mImage.height();
00161     double width = imageToDeviceRatio * mImage.width();
00162     return QRectF( 0, 0, width, deviceHeight );
00163   }
00164 }
00165 
00166 QRectF QgsComposerPicture::boundedSVGRect( double deviceWidth, double deviceHeight )
00167 {
00168   double imageToSvgRatio;
00169   if ( deviceWidth / mDefaultSvgSize.width() > deviceHeight / mDefaultSvgSize.height() )
00170   {
00171     imageToSvgRatio = deviceHeight / mDefaultSvgSize.height();
00172     double width = mDefaultSvgSize.width() * imageToSvgRatio;
00173     return QRectF( 0, 0, width, deviceHeight );
00174   }
00175   else
00176   {
00177     imageToSvgRatio = deviceWidth / mDefaultSvgSize.width();
00178     double height = mDefaultSvgSize.height() * imageToSvgRatio;
00179     return QRectF( 0, 0, deviceWidth, height );
00180   }
00181 }
00182 
00183 #if 0
00184 QRectF QgsComposerPicture::boundedSVGRect( double deviceWidth, double deviceHeight )
00185 {
00186   double imageToSvgRatio;
00187   if ( deviceWidth / mDefaultSvgSize.width() < deviceHeight / mDefaultSvgSize.height() )
00188   {
00189     imageToSvgRatio = deviceWidth / mDefaultSvgSize.width();
00190     double height = mDefaultSvgSize.height() * imageToSvgRatio;
00191     return QRectF( 0, 0, deviceWidth, height );
00192   }
00193   else
00194   {
00195     imageToSvgRatio = deviceHeight / mDefaultSvgSize.height();
00196     double width = mDefaultSvgSize.width() * imageToSvgRatio;
00197     return QRectF( 0, 0, width, deviceHeight );
00198   }
00199 }
00200 #endif //0
00201 
00202 void QgsComposerPicture::setSceneRect( const QRectF& rectangle )
00203 {
00204   QgsComposerItem::setSceneRect( rectangle );
00205 
00206   //consider to change size of the shape if the rectangle changes width and/or height
00207   double newPictureWidth = rectangle.width();
00208   double newPictureHeight = rectangle.height();
00209   imageSizeConsideringRotation( newPictureWidth, newPictureHeight );
00210   mPictureWidth = newPictureWidth;
00211   mPictureHeight = newPictureHeight;
00212 
00213   emit itemChanged();
00214 }
00215 
00216 void QgsComposerPicture::setRotation( double r )
00217 {
00218   //adapt rectangle size
00219   double width = mPictureWidth;
00220   double height = mPictureHeight;
00221   sizeChangedByRotation( width, height );
00222 
00223   //adapt scene rect to have the same center and the new width / height
00224   double x = transform().dx() + rect().width() / 2.0 - width / 2.0;
00225   double y = transform().dy() + rect().height() / 2.0 - height / 2.0;
00226   QgsComposerItem::setSceneRect( QRectF( x, y, width, height ) );
00227 
00228   QgsComposerItem::setRotation( r );
00229 }
00230 
00231 void QgsComposerPicture::setRotationMap( int composerMapId )
00232 {
00233   if ( !mComposition )
00234   {
00235     return;
00236   }
00237 
00238   if ( composerMapId == -1 ) //disable rotation from map
00239   {
00240     QObject::disconnect( mRotationMap, SIGNAL( rotationChanged( double ) ), this, SLOT( setRotation( double ) ) );
00241     mRotationMap = 0;
00242   }
00243 
00244   const QgsComposerMap* map = mComposition->getComposerMapById( composerMapId );
00245   if ( !map )
00246   {
00247     return;
00248   }
00249   if ( mRotationMap )
00250   {
00251     QObject::disconnect( mRotationMap, SIGNAL( rotationChanged( double ) ), this, SLOT( setRotation( double ) ) );
00252   }
00253   mRotation = map->rotation();
00254   QObject::connect( map, SIGNAL( rotationChanged( double ) ), this, SLOT( setRotation( double ) ) );
00255   mRotationMap = map;
00256   setRotation( map->rotation() );
00257 }
00258 
00259 QString QgsComposerPicture::pictureFile() const
00260 {
00261   return mSourceFile.fileName();
00262 }
00263 
00264 bool QgsComposerPicture::writeXML( QDomElement& elem, QDomDocument & doc ) const
00265 {
00266   if ( elem.isNull() )
00267   {
00268     return false;
00269   }
00270   QDomElement composerPictureElem = doc.createElement( "ComposerPicture" );
00271   composerPictureElem.setAttribute( "file", QgsProject::instance()->writePath( mSourceFile.fileName() ) );
00272   composerPictureElem.setAttribute( "pictureWidth", QString::number( mPictureWidth ) );
00273   composerPictureElem.setAttribute( "pictureHeight", QString::number( mPictureHeight ) );
00274   if ( !mRotationMap )
00275   {
00276     composerPictureElem.setAttribute( "mapId", -1 );
00277   }
00278   else
00279   {
00280     composerPictureElem.setAttribute( "mapId", mRotationMap->id() );
00281   }
00282 
00283   _writeXML( composerPictureElem, doc );
00284   elem.appendChild( composerPictureElem );
00285   return true;
00286 }
00287 
00288 bool QgsComposerPicture::readXML( const QDomElement& itemElem, const QDomDocument& doc )
00289 {
00290   if ( itemElem.isNull() )
00291   {
00292     return false;
00293   }
00294 
00295   mPictureWidth = itemElem.attribute( "pictureWidth", "10" ).toDouble();
00296   mPictureHeight = itemElem.attribute( "pictureHeight", "10" ).toDouble();
00297 
00298   QDomNodeList composerItemList = itemElem.elementsByTagName( "ComposerItem" );
00299   if ( composerItemList.size() > 0 )
00300   {
00301     _readXML( composerItemList.at( 0 ).toElement(), doc );
00302   }
00303 
00304 
00305   mDefaultSvgSize = QSize( 0, 0 );
00306 
00307   QString fileName = QgsProject::instance()->readPath( itemElem.attribute( "file" ) );
00308   setPictureFile( fileName );
00309 
00310   //rotation map
00311   int rotationMapId = itemElem.attribute( "mapId", "-1" ).toInt();
00312   if ( rotationMapId == -1 )
00313   {
00314     mRotationMap = 0;
00315   }
00316   else if ( mComposition )
00317   {
00318 
00319     if ( mRotationMap )
00320     {
00321       QObject::disconnect( mRotationMap, SIGNAL( rotationChanged( double ) ), this, SLOT( setRotation( double ) ) );
00322     }
00323     mRotationMap = mComposition->getComposerMapById( rotationMapId );
00324     QObject::connect( mRotationMap, SIGNAL( rotationChanged( double ) ), this, SLOT( setRotation( double ) ) );
00325   }
00326 
00327   emit itemChanged();
00328   return true;
00329 }
00330 
00331 int QgsComposerPicture::rotationMap() const
00332 {
00333   if ( !mRotationMap )
00334   {
00335     return -1;
00336   }
00337   else
00338   {
00339     return mRotationMap->id();
00340   }
00341 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines