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