|
QGIS API Documentation
master-59fd5e0
|
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 }