Quantum GIS API Documentation
1.8
|
00001 /*************************************************************************** 00002 qgscomposerpicture.cpp 00003 ------------------- 00004 begin : September 2005 00005 copyright : (C) 2005 by Radim Blazek 00006 email : [email protected] 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 }