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