~ubuntu-branches/ubuntu/trusty/qgis/trusty

« back to all changes in this revision

Viewing changes to src/core/composer/qgscomposerpicture.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Johan Van de Wauw
  • Date: 2010-07-11 20:23:24 UTC
  • mfrom: (3.1.4 squeeze)
  • Revision ID: james.westby@ubuntu.com-20100711202324-5ktghxa7hracohmr
Tags: 1.4.0+12730-3ubuntu1
* Merge from Debian unstable (LP: #540941).
* Fix compilation issues with QT 4.7
* Add build-depends on libqt4-webkit-dev 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
                           qgscomposerpicture.cpp
 
3
                             -------------------
 
4
    begin                : September 2005
 
5
    copyright            : (C) 2005 by Radim Blazek
 
6
    email                : radim.blazek@gmail.com
 
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
/* $Id$ */
 
18
 
 
19
#include "qgscomposerpicture.h"
 
20
#include "qgscomposermap.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
 
 
30
QgsComposerPicture::QgsComposerPicture( QgsComposition *composition ): QgsComposerItem( composition ), mMode( Unknown ), \
 
31
    mSvgCacheUpToDate( false ), mCachedDpi( 0 ), mCachedRotation( 0 ), mCachedViewScaleFactor( -1 ), mRotationMap( 0 )
 
32
{
 
33
  mPictureWidth = rect().width();
 
34
}
 
35
 
 
36
QgsComposerPicture::QgsComposerPicture(): QgsComposerItem( 0 ), mMode( Unknown ), mSvgCacheUpToDate( false ), mCachedRotation( 0 ), mCachedViewScaleFactor( -1 ), mRotationMap( 0 )
 
37
{
 
38
  mPictureHeight = rect().height();
 
39
}
 
40
 
 
41
QgsComposerPicture::~QgsComposerPicture()
 
42
{
 
43
 
 
44
}
 
45
 
 
46
void QgsComposerPicture::paint( QPainter* painter, const QStyleOptionGraphicsItem* itemStyle, QWidget* pWidget )
 
47
{
 
48
  if ( !painter )
 
49
  {
 
50
    return;
 
51
  }
 
52
 
 
53
  drawBackground( painter );
 
54
 
 
55
  int newDpi = ( painter->device()->logicalDpiX() + painter->device()->logicalDpiY() ) / 2;
 
56
  double viewScaleFactor = horizontalViewScaleFactor();
 
57
 
 
58
  if ( newDpi != mCachedDpi || mCachedRotation != mRotation || mCachedViewScaleFactor != viewScaleFactor )
 
59
  {
 
60
    mSvgCacheUpToDate = false;
 
61
  }
 
62
 
 
63
  if ( mMode != Unknown )
 
64
  {
 
65
    double rectPixelWidth = /*rect().width()*/mPictureWidth * newDpi / 25.4;
 
66
    double rectPixelHeight = /*rect().height()*/ mPictureHeight * newDpi / 25.4;
 
67
    QRectF boundRect;
 
68
    if ( mMode == SVG )
 
69
    {
 
70
      boundRect = boundedSVGRect( rectPixelWidth, rectPixelHeight );
 
71
    }
 
72
    else if ( mMode == RASTER )
 
73
    {
 
74
      boundRect = boundedImageRect( rectPixelWidth, rectPixelHeight );
 
75
    }
 
76
 
 
77
    double boundRectWidthMM = boundRect.width() / newDpi * 25.4;
 
78
    double boundRectHeightMM = boundRect.height() / newDpi * 25.4;
 
79
    double boundImageWidth = boundRect.width();
 
80
    double boundImageHeight = boundRect.height();
 
81
 
 
82
    if ( mMode == SVG )
 
83
    {
 
84
      if ( !mSvgCacheUpToDate )
 
85
      {
 
86
        //make nicer preview
 
87
        if ( mComposition && mComposition->plotStyle() == QgsComposition::Preview )
 
88
        {
 
89
          boundImageWidth *= std::min( viewScaleFactor, 10.0 );
 
90
          boundImageHeight *= std::min( viewScaleFactor, 10.0 );
 
91
        }
 
92
        mImage = QImage( boundImageWidth, boundImageHeight, QImage::Format_ARGB32 );
 
93
        updateImageFromSvg();
 
94
      }
 
95
    }
 
96
 
 
97
    painter->save();
 
98
    painter->translate( rect().width() / 2.0, rect().height() / 2.0 );
 
99
    painter->rotate( mRotation );
 
100
    painter->translate( -boundRectWidthMM / 2.0, -boundRectHeightMM / 2.0 );
 
101
 
 
102
    painter->drawImage( QRectF( 0, 0, boundRectWidthMM,  boundRectHeightMM ), mImage, QRectF( 0, 0, mImage.width(), mImage.height() ) );
 
103
 
 
104
    painter->restore();
 
105
  }
 
106
 
 
107
  mCachedDpi = newDpi;
 
108
  mCachedRotation = mRotation;
 
109
  mCachedViewScaleFactor = viewScaleFactor;
 
110
 
 
111
  //frame and selection boxes
 
112
  drawFrame( painter );
 
113
  if ( isSelected() )
 
114
  {
 
115
    drawSelectionBoxes( painter );
 
116
  }
 
117
}
 
118
 
 
119
void QgsComposerPicture::setPictureFile( const QString& path )
 
120
{
 
121
  mSourceFile.setFileName( path );
 
122
  if ( !mSourceFile.exists() )
 
123
  {
 
124
    mMode = Unknown;
 
125
  }
 
126
 
 
127
  QFileInfo sourceFileInfo( mSourceFile );
 
128
  QString sourceFileSuffix = sourceFileInfo.suffix();
 
129
  if ( sourceFileSuffix.compare( "svg", Qt::CaseInsensitive ) == 0 )
 
130
  {
 
131
    //try to open svg
 
132
    QSvgRenderer validTestRenderer( mSourceFile.fileName() );
 
133
    if ( validTestRenderer.isValid() )
 
134
    {
 
135
      mMode = SVG;
 
136
      QRect viewBox = validTestRenderer.viewBox(); //take width/height ratio from view box instead of default size
 
137
      mDefaultSvgSize.setWidth( viewBox.width() );
 
138
      mDefaultSvgSize.setHeight( viewBox.height() );
 
139
      mSvgCacheUpToDate = false;
 
140
    }
 
141
    else
 
142
    {
 
143
      mMode = Unknown;
 
144
    }
 
145
  }
 
146
  else
 
147
  {
 
148
    //try to open raster with QImageReader
 
149
    QImageReader imageReader( mSourceFile.fileName() );
 
150
    if ( imageReader.read( &mImage ) )
 
151
    {
 
152
      mMode = RASTER;
 
153
    }
 
154
    else
 
155
    {
 
156
      mMode = Unknown;
 
157
    }
 
158
  }
 
159
 
 
160
  if ( mMode != Unknown ) //make sure we start with a new QImage
 
161
  {
 
162
    setSceneRect( QRectF( transform().dx(), transform().dy(), rect().width(), rect().height() ) );
 
163
  }
 
164
  emit settingsChanged();
 
165
}
 
166
 
 
167
QRectF QgsComposerPicture::boundedImageRect( double deviceWidth, double deviceHeight )
 
168
{
 
169
  double imageToDeviceRatio;
 
170
  if ( mImage.width() / deviceWidth > mImage.height() / deviceHeight )
 
171
  {
 
172
    imageToDeviceRatio =  deviceWidth / mImage.width();
 
173
    double height = imageToDeviceRatio * mImage.height();
 
174
    return QRectF( 0, 0, deviceWidth, height );
 
175
  }
 
176
  else
 
177
  {
 
178
    imageToDeviceRatio = deviceHeight / mImage.height();
 
179
    double width = imageToDeviceRatio * mImage.width();
 
180
    return QRectF( 0, 0, width, deviceHeight );
 
181
  }
 
182
}
 
183
 
 
184
QRectF QgsComposerPicture::boundedSVGRect( double deviceWidth, double deviceHeight )
 
185
{
 
186
  double imageToSvgRatio;
 
187
  if ( deviceWidth / mDefaultSvgSize.width() > deviceHeight / mDefaultSvgSize.height() )
 
188
  {
 
189
    imageToSvgRatio = deviceHeight / mDefaultSvgSize.height();
 
190
    double width = mDefaultSvgSize.width() * imageToSvgRatio;
 
191
    return QRectF( 0, 0, width, deviceHeight );
 
192
  }
 
193
  else
 
194
  {
 
195
    imageToSvgRatio = deviceWidth / mDefaultSvgSize.width();
 
196
    double height = mDefaultSvgSize.height() * imageToSvgRatio;
 
197
    return QRectF( 0, 0, deviceWidth, height );
 
198
  }
 
199
}
 
200
 
 
201
#if 0
 
202
QRectF QgsComposerPicture::boundedSVGRect( double deviceWidth, double deviceHeight )
 
203
{
 
204
  double imageToSvgRatio;
 
205
  if ( deviceWidth / mDefaultSvgSize.width() < deviceHeight / mDefaultSvgSize.height() )
 
206
  {
 
207
    imageToSvgRatio = deviceWidth / mDefaultSvgSize.width();
 
208
    double height = mDefaultSvgSize.height() * imageToSvgRatio;
 
209
    return QRectF( 0, 0, deviceWidth, height );
 
210
  }
 
211
  else
 
212
  {
 
213
    imageToSvgRatio = deviceHeight / mDefaultSvgSize.height();
 
214
    double width = mDefaultSvgSize.width() * imageToSvgRatio;
 
215
    return QRectF( 0, 0, width, deviceHeight );
 
216
  }
 
217
}
 
218
#endif //0
 
219
 
 
220
void QgsComposerPicture::updateImageFromSvg()
 
221
{
 
222
  mImage.fill( 0 );
 
223
  QPainter p( &mImage );
 
224
  p.setRenderHints( QPainter::Antialiasing | QPainter::TextAntialiasing, true );
 
225
  QSvgRenderer theRenderer( mSourceFile.fileName() );
 
226
  theRenderer.render( &p );
 
227
  mSvgCacheUpToDate = true;
 
228
}
 
229
 
 
230
 
 
231
 
 
232
void QgsComposerPicture::setSceneRect( const QRectF& rectangle )
 
233
{
 
234
  mSvgCacheUpToDate = false;
 
235
  QgsComposerItem::setSceneRect( rectangle );
 
236
 
 
237
  //consider to change size of the shape if the rectangle changes width and/or height
 
238
  double newPictureWidth = rectangle.width();
 
239
  double newPictureHeight = rectangle.height();
 
240
  imageSizeConsideringRotation( newPictureWidth, newPictureHeight );
 
241
  mPictureWidth = newPictureWidth;
 
242
  mPictureHeight = newPictureHeight;
 
243
 
 
244
  emit settingsChanged();
 
245
}
 
246
 
 
247
void QgsComposerPicture::setRotation( double r )
 
248
{
 
249
  //adapt rectangle size
 
250
  double width = mPictureWidth;
 
251
  double height = mPictureHeight;
 
252
  sizeChangedByRotation( width, height );
 
253
 
 
254
  //adapt scene rect to have the same center and the new width / height
 
255
  double x = transform().dx() + rect().width() / 2.0 - width / 2.0;
 
256
  double y = transform().dy() + rect().height() / 2.0 - height / 2.0;
 
257
  QgsComposerItem::setSceneRect( QRectF( x, y, width, height ) );
 
258
 
 
259
  QgsComposerItem::setRotation( r );
 
260
}
 
261
 
 
262
void QgsComposerPicture::setRotationMap( int composerMapId )
 
263
{
 
264
  if ( !mComposition )
 
265
  {
 
266
    return;
 
267
  }
 
268
 
 
269
  if ( composerMapId == -1 ) //disable rotation from map
 
270
  {
 
271
    QObject::disconnect( mRotationMap, SIGNAL( rotationChanged( double ) ), this, SLOT( setRotation( double ) ) );
 
272
    mRotationMap = 0;
 
273
  }
 
274
 
 
275
  const QgsComposerMap* map = mComposition->getComposerMapById( composerMapId );
 
276
  if ( !map )
 
277
  {
 
278
    return;
 
279
  }
 
280
  if ( mRotationMap )
 
281
  {
 
282
    QObject::disconnect( mRotationMap, SIGNAL( rotationChanged( double ) ), this, SLOT( setRotation( double ) ) );
 
283
  }
 
284
  mRotation = map->rotation();
 
285
  QObject::connect( map, SIGNAL( rotationChanged( double ) ), this, SLOT( setRotation( double ) ) );
 
286
  mRotationMap = map;
 
287
  setRotation( map->rotation() );
 
288
}
 
289
 
 
290
QString QgsComposerPicture::pictureFile() const
 
291
{
 
292
  return mSourceFile.fileName();
 
293
}
 
294
 
 
295
bool QgsComposerPicture::writeXML( QDomElement& elem, QDomDocument & doc ) const
 
296
{
 
297
  if ( elem.isNull() )
 
298
  {
 
299
    return false;
 
300
  }
 
301
  QDomElement composerPictureElem = doc.createElement( "ComposerPicture" );
 
302
  composerPictureElem.setAttribute( "file", QgsProject::instance()->writePath( mSourceFile.fileName() ) );
 
303
  composerPictureElem.setAttribute( "pictureWidth", mPictureWidth );
 
304
  composerPictureElem.setAttribute( "pictureHeight", mPictureHeight );
 
305
  if ( !mRotationMap )
 
306
  {
 
307
    composerPictureElem.setAttribute( "mapId", -1 );
 
308
  }
 
309
  else
 
310
  {
 
311
    composerPictureElem.setAttribute( "mapId", mRotationMap->id() );
 
312
  }
 
313
 
 
314
  _writeXML( composerPictureElem, doc );
 
315
  elem.appendChild( composerPictureElem );
 
316
  return true;
 
317
}
 
318
 
 
319
bool QgsComposerPicture::readXML( const QDomElement& itemElem, const QDomDocument& doc )
 
320
{
 
321
  if ( itemElem.isNull() )
 
322
  {
 
323
    return false;
 
324
  }
 
325
 
 
326
  mPictureWidth = itemElem.attribute( "pictureWidth", "10" ).toDouble();
 
327
  mPictureHeight = itemElem.attribute( "pictureHeight", "10" ).toDouble();
 
328
 
 
329
  QDomNodeList composerItemList = itemElem.elementsByTagName( "ComposerItem" );
 
330
  if ( composerItemList.size() > 0 )
 
331
  {
 
332
    _readXML( composerItemList.at( 0 ).toElement(), doc );
 
333
  }
 
334
 
 
335
 
 
336
  mSvgCacheUpToDate = false;
 
337
  mDefaultSvgSize = QSize( 0, 0 );
 
338
  mCachedDpi = 0;
 
339
 
 
340
  QString fileName = QgsProject::instance()->readPath( itemElem.attribute( "file" ) );
 
341
  setPictureFile( fileName );
 
342
 
 
343
  //rotation map
 
344
  int rotationMapId = itemElem.attribute( "mapId", "-1" ).toInt();
 
345
  if ( rotationMapId == -1 )
 
346
  {
 
347
    mRotationMap = 0;
 
348
  }
 
349
  else if ( mComposition )
 
350
  {
 
351
 
 
352
    if ( mRotationMap )
 
353
    {
 
354
      QObject::disconnect( mRotationMap, SIGNAL( rotationChanged( double ) ), this, SLOT( setRotation( double ) ) );
 
355
    }
 
356
    mRotationMap = mComposition->getComposerMapById( rotationMapId );
 
357
    QObject::connect( mRotationMap, SIGNAL( rotationChanged( double ) ), this, SLOT( setRotation( double ) ) );
 
358
  }
 
359
 
 
360
  return true;
 
361
}
 
362
 
 
363
int QgsComposerPicture::rotationMap() const
 
364
{
 
365
  if ( !mRotationMap )
 
366
  {
 
367
    return -1;
 
368
  }
 
369
  else
 
370
  {
 
371
    return mRotationMap->id();
 
372
  }
 
373
}