QGIS API Documentation  2.0.1-Dufour
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
qgscomposerpicture.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgscomposerpicture.cpp
3  -------------------
4  begin : September 2005
5  copyright : (C) 2005 by Radim Blazek
6  email : [email protected]
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "qgscomposerpicture.h"
19 #include "qgscomposermap.h"
20 #include "qgscomposition.h"
21 #include "qgsproject.h"
22 #include <QDomDocument>
23 #include <QDomElement>
24 #include <QFileInfo>
25 #include <QImageReader>
26 #include <QPainter>
27 #include <QSvgRenderer>
28 
29 
31  : QgsComposerItem( composition ), mMode( Unknown ), mRotationMap( 0 )
32 {
33  mPictureWidth = rect().width();
34 }
35 
37 {
38  mPictureHeight = rect().height();
39 }
40 
41 
43 {
44 
45 }
46 
47 void QgsComposerPicture::paint( QPainter* painter, const QStyleOptionGraphicsItem* itemStyle, QWidget* pWidget )
48 {
49  Q_UNUSED( itemStyle );
50  Q_UNUSED( pWidget );
51  if ( !painter )
52  {
53  return;
54  }
55 
56  drawBackground( painter );
57 
58  int newDpi = ( painter->device()->logicalDpiX() + painter->device()->logicalDpiY() ) / 2;
59 
60  if ( mMode != Unknown )
61  {
62  double rectPixelWidth = /*rect().width()*/mPictureWidth * newDpi / 25.4;
63  double rectPixelHeight = /*rect().height()*/ mPictureHeight * newDpi / 25.4;
64  QRectF boundRect;
65  if ( mMode == SVG )
66  {
67  boundRect = boundedSVGRect( rectPixelWidth, rectPixelHeight );
68  }
69  else if ( mMode == RASTER )
70  {
71  boundRect = boundedImageRect( rectPixelWidth, rectPixelHeight );
72  }
73 
74  double boundRectWidthMM = boundRect.width() / newDpi * 25.4;
75  double boundRectHeightMM = boundRect.height() / newDpi * 25.4;
76 
77  painter->save();
78  painter->translate( rect().width() / 2.0, rect().height() / 2.0 );
79  painter->rotate( mRotation );
80  painter->translate( -boundRectWidthMM / 2.0, -boundRectHeightMM / 2.0 );
81 
82  if ( mMode == SVG )
83  {
84  mSVG.render( painter, QRectF( 0, 0, boundRectWidthMM, boundRectHeightMM ) );
85  }
86  else if ( mMode == RASTER )
87  {
88  painter->drawImage( QRectF( 0, 0, boundRectWidthMM, boundRectHeightMM ), mImage, QRectF( 0, 0, mImage.width(), mImage.height() ) );
89  }
90 
91  painter->restore();
92  }
93 
94  //frame and selection boxes
95  drawFrame( painter );
96  if ( isSelected() )
97  {
98  drawSelectionBoxes( painter );
99  }
100 }
101 
102 void QgsComposerPicture::setPictureFile( const QString& path )
103 {
104  mSourceFile.setFileName( path );
105  if ( !mSourceFile.exists() )
106  {
107  mMode = Unknown;
108  }
109 
110  QFileInfo sourceFileInfo( mSourceFile );
111  QString sourceFileSuffix = sourceFileInfo.suffix();
112  if ( sourceFileSuffix.compare( "svg", Qt::CaseInsensitive ) == 0 )
113  {
114  //try to open svg
115  mSVG.load( mSourceFile.fileName() );
116  if ( mSVG.isValid() )
117  {
118  mMode = SVG;
119  QRect viewBox = mSVG.viewBox(); //take width/height ratio from view box instead of default size
120  mDefaultSvgSize.setWidth( viewBox.width() );
121  mDefaultSvgSize.setHeight( viewBox.height() );
122  }
123  else
124  {
125  mMode = Unknown;
126  }
127  }
128  else
129  {
130  //try to open raster with QImageReader
131  QImageReader imageReader( mSourceFile.fileName() );
132  if ( imageReader.read( &mImage ) )
133  {
134  mMode = RASTER;
135  }
136  else
137  {
138  mMode = Unknown;
139  }
140  }
141 
142  if ( mMode != Unknown ) //make sure we start with a new QImage
143  {
144  setSceneRect( QRectF( transform().dx(), transform().dy(), rect().width(), rect().height() ) );
145  }
146  emit itemChanged();
147 }
148 
149 QRectF QgsComposerPicture::boundedImageRect( double deviceWidth, double deviceHeight )
150 {
151  double imageToDeviceRatio;
152  if ( mImage.width() / deviceWidth > mImage.height() / deviceHeight )
153  {
154  imageToDeviceRatio = deviceWidth / mImage.width();
155  double height = imageToDeviceRatio * mImage.height();
156  return QRectF( 0, 0, deviceWidth, height );
157  }
158  else
159  {
160  imageToDeviceRatio = deviceHeight / mImage.height();
161  double width = imageToDeviceRatio * mImage.width();
162  return QRectF( 0, 0, width, deviceHeight );
163  }
164 }
165 
166 QRectF QgsComposerPicture::boundedSVGRect( double deviceWidth, double deviceHeight )
167 {
168  double imageToSvgRatio;
169  if ( deviceWidth / mDefaultSvgSize.width() > deviceHeight / mDefaultSvgSize.height() )
170  {
171  imageToSvgRatio = deviceHeight / mDefaultSvgSize.height();
172  double width = mDefaultSvgSize.width() * imageToSvgRatio;
173  return QRectF( 0, 0, width, deviceHeight );
174  }
175  else
176  {
177  imageToSvgRatio = deviceWidth / mDefaultSvgSize.width();
178  double height = mDefaultSvgSize.height() * imageToSvgRatio;
179  return QRectF( 0, 0, deviceWidth, height );
180  }
181 }
182 
183 #if 0
184 QRectF QgsComposerPicture::boundedSVGRect( double deviceWidth, double deviceHeight )
185 {
186  double imageToSvgRatio;
187  if ( deviceWidth / mDefaultSvgSize.width() < deviceHeight / mDefaultSvgSize.height() )
188  {
189  imageToSvgRatio = deviceWidth / mDefaultSvgSize.width();
190  double height = mDefaultSvgSize.height() * imageToSvgRatio;
191  return QRectF( 0, 0, deviceWidth, height );
192  }
193  else
194  {
195  imageToSvgRatio = deviceHeight / mDefaultSvgSize.height();
196  double width = mDefaultSvgSize.width() * imageToSvgRatio;
197  return QRectF( 0, 0, width, deviceHeight );
198  }
199 }
200 #endif //0
201 
202 void QgsComposerPicture::setSceneRect( const QRectF& rectangle )
203 {
204  QgsComposerItem::setSceneRect( rectangle );
205 
206  //consider to change size of the shape if the rectangle changes width and/or height
207  double newPictureWidth = rectangle.width();
208  double newPictureHeight = rectangle.height();
209  imageSizeConsideringRotation( newPictureWidth, newPictureHeight );
210  mPictureWidth = newPictureWidth;
211  mPictureHeight = newPictureHeight;
212 
213  emit itemChanged();
214 }
215 
217 {
218  //adapt rectangle size
219  double width = mPictureWidth;
220  double height = mPictureHeight;
221  sizeChangedByRotation( width, height );
222 
223  //adapt scene rect to have the same center and the new width / height
224  double x = transform().dx() + rect().width() / 2.0 - width / 2.0;
225  double y = transform().dy() + rect().height() / 2.0 - height / 2.0;
226  QgsComposerItem::setSceneRect( QRectF( x, y, width, height ) );
227 
229 }
230 
231 void QgsComposerPicture::setRotationMap( int composerMapId )
232 {
233  if ( !mComposition )
234  {
235  return;
236  }
237 
238  if ( composerMapId == -1 ) //disable rotation from map
239  {
240  QObject::disconnect( mRotationMap, SIGNAL( rotationChanged( double ) ), this, SLOT( setRotation( double ) ) );
241  mRotationMap = 0;
242  }
243 
244  const QgsComposerMap* map = mComposition->getComposerMapById( composerMapId );
245  if ( !map )
246  {
247  return;
248  }
249  if ( mRotationMap )
250  {
251  QObject::disconnect( mRotationMap, SIGNAL( rotationChanged( double ) ), this, SLOT( setRotation( double ) ) );
252  }
253  mRotation = map->rotation();
254  QObject::connect( map, SIGNAL( rotationChanged( double ) ), this, SLOT( setRotation( double ) ) );
255  mRotationMap = map;
256  setRotation( map->rotation() );
257 }
258 
260 {
261  return mSourceFile.fileName();
262 }
263 
264 bool QgsComposerPicture::writeXML( QDomElement& elem, QDomDocument & doc ) const
265 {
266  if ( elem.isNull() )
267  {
268  return false;
269  }
270  QDomElement composerPictureElem = doc.createElement( "ComposerPicture" );
271  composerPictureElem.setAttribute( "file", QgsProject::instance()->writePath( mSourceFile.fileName() ) );
272  composerPictureElem.setAttribute( "pictureWidth", QString::number( mPictureWidth ) );
273  composerPictureElem.setAttribute( "pictureHeight", QString::number( mPictureHeight ) );
274  if ( !mRotationMap )
275  {
276  composerPictureElem.setAttribute( "mapId", -1 );
277  }
278  else
279  {
280  composerPictureElem.setAttribute( "mapId", mRotationMap->id() );
281  }
282 
283  _writeXML( composerPictureElem, doc );
284  elem.appendChild( composerPictureElem );
285  return true;
286 }
287 
288 bool QgsComposerPicture::readXML( const QDomElement& itemElem, const QDomDocument& doc )
289 {
290  if ( itemElem.isNull() )
291  {
292  return false;
293  }
294 
295  mPictureWidth = itemElem.attribute( "pictureWidth", "10" ).toDouble();
296  mPictureHeight = itemElem.attribute( "pictureHeight", "10" ).toDouble();
297 
298  QDomNodeList composerItemList = itemElem.elementsByTagName( "ComposerItem" );
299  if ( composerItemList.size() > 0 )
300  {
301  _readXML( composerItemList.at( 0 ).toElement(), doc );
302  }
303 
304 
305  mDefaultSvgSize = QSize( 0, 0 );
306 
307  QString fileName = QgsProject::instance()->readPath( itemElem.attribute( "file" ) );
308  setPictureFile( fileName );
309 
310  //rotation map
311  int rotationMapId = itemElem.attribute( "mapId", "-1" ).toInt();
312  if ( rotationMapId == -1 )
313  {
314  mRotationMap = 0;
315  }
316  else if ( mComposition )
317  {
318 
319  if ( mRotationMap )
320  {
321  QObject::disconnect( mRotationMap, SIGNAL( rotationChanged( double ) ), this, SLOT( setRotation( double ) ) );
322  }
323  mRotationMap = mComposition->getComposerMapById( rotationMapId );
324  QObject::connect( mRotationMap, SIGNAL( rotationChanged( double ) ), this, SLOT( setRotation( double ) ) );
325  }
326 
327  emit itemChanged();
328  return true;
329 }
330 
332 {
333  if ( !mRotationMap )
334  {
335  return -1;
336  }
337  else
338  {
339  return mRotationMap->id();
340  }
341 }