QGIS API Documentation  2.4.0-Chugiak
qgscomposermap.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgscomposermap.cpp
3  -------------------
4  begin : January 2005
5  copyright : (C) 2005 by Radim Blazek
6  email : blazek@itc.it
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 "qgscomposermap.h"
19 #include "qgscomposition.h"
20 #include "qgscoordinatetransform.h"
21 #include "qgslogger.h"
22 #include "qgsmaprenderer.h"
24 #include "qgsmaplayerregistry.h"
25 #include "qgsmaptopixel.h"
26 #include "qgsproject.h"
27 #include "qgsrasterlayer.h"
28 #include "qgsrendercontext.h"
29 #include "qgsscalecalculator.h"
30 #include "qgsvectorlayer.h"
31 #include "qgspallabeling.h"
32 #include "qgsexpression.h"
33 
34 #include "qgslabel.h"
35 #include "qgslabelattributes.h"
36 #include "qgssymbollayerv2utils.h" //for pointOnLineWithDistance
37 
38 #include <QGraphicsScene>
39 #include <QGraphicsView>
40 #include <QPainter>
41 #include <QSettings>
42 #include <cmath>
43 
44 QgsComposerMap::QgsComposerMap( QgsComposition *composition, int x, int y, int width, int height )
45  : QgsComposerItem( x, y, width, height, composition ), mMapRotation( 0 ), mKeepLayerSet( false )
46  , mOverviewFrameMapId( -1 ), mOverviewBlendMode( QPainter::CompositionMode_SourceOver ), mOverviewInverted( false ), mOverviewCentered( false )
47  , mUpdatesEnabled( true ), mGridEnabled( false ), mGridStyle( Solid )
48  , mGridIntervalX( 0.0 ), mGridIntervalY( 0.0 ), mGridOffsetX( 0.0 ), mGridOffsetY( 0.0 ), mGridAnnotationFontColor( QColor( 0, 0, 0 ) )
49  , mGridAnnotationPrecision( 3 ), mShowGridAnnotation( false ), mGridBlendMode( QPainter::CompositionMode_SourceOver )
50  , mLeftGridAnnotationPosition( OutsideMapFrame ), mRightGridAnnotationPosition( OutsideMapFrame )
51  , mTopGridAnnotationPosition( OutsideMapFrame ), mBottomGridAnnotationPosition( OutsideMapFrame ), mAnnotationFrameDistance( 1.0 )
52  , mLeftGridAnnotationDirection( Horizontal ), mRightGridAnnotationDirection( Horizontal ), mTopGridAnnotationDirection( Horizontal )
53  , mBottomGridAnnotationDirection( Horizontal ), mGridFrameStyle( NoGridFrame ), mGridFrameWidth( 2.0 )
54  , mGridFramePenThickness( 0.5 ), mGridFramePenColor( QColor( 0, 0, 0 ) ), mGridFrameFillColor1( Qt::white ), mGridFrameFillColor2( Qt::black )
55  , mCrossLength( 3 ), mMapCanvas( 0 ), mDrawCanvasItems( true ), mAtlasDriven( false ), mAtlasScalingMode( Auto ), mAtlasMargin( 0.10 )
56 {
59  mGridLineSymbol = 0;
62 
63  mId = 0;
64  assignFreeId();
65 
67  mCurrentRectangle = rect();
68 
69  // Cache
70  mCacheUpdated = false;
71  mDrawing = false;
72 
73  //Offset
74  mXOffset = 0.0;
75  mYOffset = 0.0;
76 
77  //get default composer font from settings
78  QSettings settings;
79  QString defaultFontString = settings.value( "/Composer/defaultFont" ).toString();
80  if ( !defaultFontString.isEmpty() )
81  {
82  mGridAnnotationFont.setFamily( defaultFontString );
83  }
84 
85  //get the color for map canvas background and set map background color accordingly
86  int bgRedInt = QgsProject::instance()->readNumEntry( "Gui", "/CanvasColorRedPart", 255 );
87  int bgGreenInt = QgsProject::instance()->readNumEntry( "Gui", "/CanvasColorGreenPart", 255 );
88  int bgBlueInt = QgsProject::instance()->readNumEntry( "Gui", "/CanvasColorBluePart", 255 );
89  setBackgroundColor( QColor( bgRedInt, bgGreenInt, bgBlueInt ) );
90 
92 
93  //calculate mExtent based on width/height ratio and map canvas extent
95 
96  setSceneRect( QRectF( x, y, width, height ) );
97  setToolTip( tr( "Map %1" ).arg( mId ) );
98 
100 }
101 
103  : QgsComposerItem( 0, 0, 10, 10, composition ), mMapRotation( 0 ), mKeepLayerSet( false ), mOverviewFrameMapId( -1 )
104  , mOverviewBlendMode( QPainter::CompositionMode_SourceOver ), mOverviewInverted( false ), mOverviewCentered( false )
105  , mUpdatesEnabled( true ), mGridEnabled( false ), mGridStyle( Solid )
106  , mGridIntervalX( 0.0 ), mGridIntervalY( 0.0 ), mGridOffsetX( 0.0 ), mGridOffsetY( 0.0 ), mGridAnnotationFontColor( QColor( 0, 0, 0 ) )
107  , mGridAnnotationPrecision( 3 ), mShowGridAnnotation( false ), mGridBlendMode( QPainter::CompositionMode_SourceOver )
108  , mLeftGridAnnotationPosition( OutsideMapFrame ), mRightGridAnnotationPosition( OutsideMapFrame )
109  , mTopGridAnnotationPosition( OutsideMapFrame ), mBottomGridAnnotationPosition( OutsideMapFrame ), mAnnotationFrameDistance( 1.0 )
110  , mLeftGridAnnotationDirection( Horizontal ), mRightGridAnnotationDirection( Horizontal ), mTopGridAnnotationDirection( Horizontal )
111  , mBottomGridAnnotationDirection( Horizontal ), mGridFrameStyle( NoGridFrame ), mGridFrameWidth( 2.0 ), mGridFramePenThickness( 0.5 )
112  , mGridFramePenColor( QColor( 0, 0, 0 ) ), mGridFrameFillColor1( Qt::white ), mGridFrameFillColor2( Qt::black )
113  , mCrossLength( 3 ), mMapCanvas( 0 ), mDrawCanvasItems( true ), mAtlasDriven( false ), mAtlasScalingMode( Auto ), mAtlasMargin( 0.10 )
114 {
116  mGridLineSymbol = 0;
119 
120  //Offset
121  mXOffset = 0.0;
122  mYOffset = 0.0;
123 
125 
127  mId = mComposition->composerMapItems().size();
129  mCurrentRectangle = rect();
130 
131  setToolTip( tr( "Map %1" ).arg( mId ) );
132 
134 }
135 
136 void QgsComposerMap::adjustExtentToItemShape( double itemWidth, double itemHeight, QgsRectangle& extent ) const
137 {
138  double itemWidthHeightRatio = itemWidth / itemHeight;
139  double newWidthHeightRatio = extent.width() / extent.height();
140 
141  if ( itemWidthHeightRatio <= newWidthHeightRatio )
142  {
143  //enlarge height of new extent, ensuring the map center stays the same
144  double newHeight = extent.width() / itemWidthHeightRatio;
145  double deltaHeight = newHeight - extent.height();
146  extent.setYMinimum( extent.yMinimum() - deltaHeight / 2 );
147  extent.setYMaximum( extent.yMaximum() + deltaHeight / 2 );
148  }
149  else
150  {
151  //enlarge width of new extent, ensuring the map center stays the same
152  double newWidth = itemWidthHeightRatio * extent.height();
153  double deltaWidth = newWidth - extent.width();
154  extent.setXMinimum( extent.xMinimum() - deltaWidth / 2 );
155  extent.setXMaximum( extent.xMaximum() + deltaWidth / 2 );
156  }
157 }
158 
160 {
162  delete mGridLineSymbol;
163 }
164 
165 /* This function is called by paint() and cache() to render the map. It does not override any functions
166 from QGraphicsItem. */
167 void QgsComposerMap::draw( QPainter *painter, const QgsRectangle& extent, const QSizeF& size, double dpi, double* forceWidthScale )
168 {
169  Q_UNUSED( forceWidthScale );
170 
171  if ( !painter )
172  {
173  return;
174  }
175  if ( size.width() == 0 || size.height() == 0 )
176  {
177  //don't attempt to draw if size is invalid
178  return;
179  }
180 
181  const QgsMapSettings& ms = mComposition->mapSettings();
182 
183  QgsMapSettings jobMapSettings;
184  jobMapSettings.setExtent( extent );
185  jobMapSettings.setOutputSize( size.toSize() );
186  jobMapSettings.setOutputDpi( dpi );
187  jobMapSettings.setMapUnits( ms.mapUnits() );
188  jobMapSettings.setBackgroundColor( Qt::transparent );
189  jobMapSettings.setOutputImageFormat( ms.outputImageFormat() );
190 
191  //set layers to render
192  QStringList theLayerSet = layersToRender();
193  if ( -1 != mCurrentExportLayer )
194  {
195  //exporting with separate layers (eg, to svg layers), so we only want to render a single map layer
196  const int layerIdx = mCurrentExportLayer - ( hasBackground() ? 1 : 0 );
197  theLayerSet =
198  ( layerIdx >= 0 && layerIdx < theLayerSet.length() )
199  ? QStringList( theLayerSet[ theLayerSet.length() - layerIdx - 1 ] )
200  : QStringList(); //exporting decorations such as map frame/grid/overview, so no map layers required
201  }
202  jobMapSettings.setLayers( theLayerSet );
203  jobMapSettings.setDestinationCrs( ms.destinationCrs() );
204  jobMapSettings.setCrsTransformEnabled( ms.hasCrsTransformEnabled() );
205  jobMapSettings.setFlags( ms.flags() );
206  jobMapSettings.setFlag( QgsMapSettings::DrawSelection, false );
207 
210  {
211  //if outputing composer, disable optimisations like layer simplification
212  jobMapSettings.setFlag( QgsMapSettings::UseRenderingOptimization, false );
213  }
214 
215  //update $map variable. Use QgsComposerItem's id since that is user-definable
217 
218  // composer-specific overrides of flags
219  jobMapSettings.setFlag( QgsMapSettings::ForceVectorOutput ); // force vector output (no caching of marker images etc.)
220  jobMapSettings.setFlag( QgsMapSettings::DrawEditingInfo, false );
221  jobMapSettings.setFlag( QgsMapSettings::UseAdvancedEffects, mComposition->useAdvancedEffects() ); // respect the composition's useAdvancedEffects flag
222 
223  // render
224  QgsMapRendererCustomPainterJob job( jobMapSettings, painter );
225  // Render the map in this thread. This is done because of problems
226  // with printing to printer on Windows (printing to PDF is fine though).
227  // Raster images were not displayed - see #10599
228  job.renderSynchronously();
229 }
230 
232 {
233  if ( mPreviewMode == Rectangle )
234  {
235  return;
236  }
237 
238  if ( mDrawing )
239  {
240  return;
241  }
242 
243  mDrawing = true;
244 
245  //in case of rotation, we need to request a larger rectangle and create a larger cache image
246  QgsRectangle requestExtent;
247  requestedExtent( requestExtent );
248 
249  double horizontalVScaleFactor = horizontalViewScaleFactor();
250  if ( horizontalVScaleFactor < 0 )
251  {
252  //make sure scale factor is positive
253  horizontalVScaleFactor = mLastValidViewScaleFactor > 0 ? mLastValidViewScaleFactor : 1;
254  }
255 
256  double widthMM = requestExtent.width() * mapUnitsToMM();
257  double heightMM = requestExtent.height() * mapUnitsToMM();
258 
259  int w = widthMM * horizontalVScaleFactor;
260  int h = heightMM * horizontalVScaleFactor;
261 
262  if ( w > 5000 ) //limit size of image for better performance
263  {
264  w = 5000;
265  }
266 
267  if ( h > 5000 )
268  {
269  h = 5000;
270  }
271 
272  mCacheImage = QImage( w, h, QImage::Format_ARGB32 );
273 
274  // set DPI of the image
275  mCacheImage.setDotsPerMeterX( 1000 * w / widthMM );
276  mCacheImage.setDotsPerMeterY( 1000 * h / heightMM );
277 
278  if ( hasBackground() )
279  {
280  //Initially fill image with specified background color. This ensures that layers with blend modes will
281  //preview correctly
282  mCacheImage.fill( backgroundColor().rgba() );
283  }
284  else
285  {
286  //no background, but start with empty fill to avoid artifacts
287  mCacheImage.fill( QColor( 255, 255, 255, 0 ).rgba() );
288  }
289 
290  QPainter p( &mCacheImage );
291 
292  draw( &p, requestExtent, QSizeF( w, h ), mCacheImage.logicalDpiX() );
293  p.end();
294  mCacheUpdated = true;
295 
296  mDrawing = false;
297 }
298 
299 void QgsComposerMap::paint( QPainter* painter, const QStyleOptionGraphicsItem* itemStyle, QWidget* pWidget )
300 {
301  Q_UNUSED( pWidget );
302 
303  if ( !mComposition || !painter )
304  {
305  return;
306  }
307 
308  QRectF thisPaintRect = QRectF( 0, 0, QGraphicsRectItem::rect().width(), QGraphicsRectItem::rect().height() );
309  painter->save();
310  painter->setClipRect( thisPaintRect );
311 
313  {
314  // Fill with background color
315  drawBackground( painter );
316  QFont messageFont( "", 12 );
317  painter->setFont( messageFont );
318  painter->setPen( QColor( 0, 0, 0, 125 ) );
319  painter->drawText( thisPaintRect, tr( "Map will be printed here" ) );
320  }
322  {
323  //draw cached pixmap. This function does not call cache() any more because
324  //Qt 4.4.0 and 4.4.1 have problems with recursive paintings
325  //QgsComposerMap::cache() and QgsComposerMap::update() need to be called by
326  //client functions
327 
328  //Background color is already included in cached image, so no need to draw
329 
330  QgsRectangle requestRectangle;
331  requestedExtent( requestRectangle );
332 
333  QgsRectangle cExtent = *currentMapExtent();
334 
335  double imagePixelWidth = cExtent.width() / requestRectangle.width() * mCacheImage.width() ; //how many pixels of the image are for the map extent?
336  double scale = rect().width() / imagePixelWidth;
337  QgsPoint rotationPoint = QgsPoint(( cExtent.xMaximum() + cExtent.xMinimum() ) / 2.0, ( cExtent.yMaximum() + cExtent.yMinimum() ) / 2.0 );
338 
339  //shift such that rotation point is at 0/0 point in the coordinate system
340  double yShiftMM = ( requestRectangle.yMaximum() - rotationPoint.y() ) * mapUnitsToMM();
341  double xShiftMM = ( requestRectangle.xMinimum() - rotationPoint.x() ) * mapUnitsToMM();
342 
343  //shift such that top left point of the extent at point 0/0 in item coordinate system
344  double xTopLeftShift = ( rotationPoint.x() - cExtent.xMinimum() ) * mapUnitsToMM();
345  double yTopLeftShift = ( cExtent.yMaximum() - rotationPoint.y() ) * mapUnitsToMM();
346 
347  painter->save();
348 
349  painter->translate( mXOffset, mYOffset );
350  painter->translate( xTopLeftShift, yTopLeftShift );
351  painter->rotate( mMapRotation );
352  painter->translate( xShiftMM, -yShiftMM );
353  painter->scale( scale, scale );
354  painter->drawImage( 0, 0, mCacheImage );
355 
356  //restore rotation
357  painter->restore();
358 
359  //draw canvas items
360  drawCanvasItems( painter, itemStyle );
361  }
362  else if ( mComposition->plotStyle() == QgsComposition::Print ||
364  {
365  if ( mDrawing )
366  {
367  return;
368  }
369 
370  mDrawing = true;
371  QPaintDevice* thePaintDevice = painter->device();
372  if ( !thePaintDevice )
373  {
374  return;
375  }
376 
377  // Fill with background color
378  if ( shouldDrawPart( Background ) )
379  {
380  drawBackground( painter );
381  }
382 
383  QgsRectangle requestRectangle;
384  requestedExtent( requestRectangle );
385 
386  QgsRectangle cExtent = *currentMapExtent();
387 
388  QSizeF theSize( requestRectangle.width() * mapUnitsToMM(), requestRectangle.height() * mapUnitsToMM() );
389 
390  QgsPoint rotationPoint = QgsPoint(( cExtent.xMaximum() + cExtent.xMinimum() ) / 2.0, ( cExtent.yMaximum() + cExtent.yMinimum() ) / 2.0 );
391 
392  //shift such that rotation point is at 0/0 point in the coordinate system
393  double yShiftMM = ( requestRectangle.yMaximum() - rotationPoint.y() ) * mapUnitsToMM();
394  double xShiftMM = ( requestRectangle.xMinimum() - rotationPoint.x() ) * mapUnitsToMM();
395 
396  //shift such that top left point of the extent at point 0/0 in item coordinate system
397  double xTopLeftShift = ( rotationPoint.x() - cExtent.xMinimum() ) * mapUnitsToMM();
398  double yTopLeftShift = ( cExtent.yMaximum() - rotationPoint.y() ) * mapUnitsToMM();
399  painter->save();
400  painter->translate( mXOffset, mYOffset );
401  painter->translate( xTopLeftShift, yTopLeftShift );
402  painter->rotate( mMapRotation );
403  painter->translate( xShiftMM, -yShiftMM );
404 
405  double dotsPerMM = thePaintDevice->logicalDpiX() / 25.4;
406  theSize *= dotsPerMM; // output size will be in dots (pixels)
407  painter->scale( 1 / dotsPerMM, 1 / dotsPerMM ); // scale painter from mm to dots
408  draw( painter, requestRectangle, theSize, thePaintDevice->logicalDpiX() );
409 
410  //restore rotation
411  painter->restore();
412 
413  //draw canvas items
414  drawCanvasItems( painter, itemStyle );
415 
416  mDrawing = false;
417  }
418 
419  painter->setClipRect( thisPaintRect , Qt::NoClip );
420 
421  if ( mGridEnabled && shouldDrawPart( Grid ) )
422  {
423  drawGrid( painter );
424  }
426  {
427  drawOverviewMapExtent( painter );
428  }
429  if ( shouldDrawPart( Frame ) )
430  {
431  drawFrame( painter );
432  }
433  if ( isSelected() && shouldDrawPart( SelectionBoxes ) )
434  {
435  drawSelectionBoxes( painter );
436  }
437 
438  painter->restore();
439 }
440 
442 {
443  return
444  ( hasBackground() ? 1 : 0 )
445  + layersToRender().length()
446  + ( mGridEnabled ? 1 : 0 )
447  + ( mOverviewFrameMapId != -1 ? 1 : 0 )
448  + ( hasFrame() ? 1 : 0 )
449  + ( isSelected() ? 1 : 0 )
450  ;
451 }
452 
454 {
455  if ( -1 == mCurrentExportLayer )
456  {
457  //all parts of the composer map are visible
458  return true;
459  }
460 
461  int idx = numberExportLayers();
462  if ( isSelected() )
463  {
464  --idx;
465  if ( SelectionBoxes == part )
466  {
467  return mCurrentExportLayer == idx;
468  }
469  }
470 
471  if ( hasFrame() )
472  {
473  --idx;
474  if ( Frame == part )
475  {
476  return mCurrentExportLayer == idx;
477  }
478  }
479  if ( mOverviewFrameMapId )
480  {
481  --idx;
482  if ( OverviewMapExtent == part )
483  {
484  return mCurrentExportLayer == idx;
485  }
486  }
487  if ( mGridEnabled )
488  {
489  --idx;
490  if ( Grid == part )
491  {
492  return mCurrentExportLayer == idx;
493  }
494  }
495  if ( hasBackground() )
496  {
497  if ( Background == part )
498  {
499  return mCurrentExportLayer == 0;
500  }
501  }
502 
503  return true; // for Layer
504 }
505 
506 
508 {
509  syncLayerSet(); //layer list may have changed
510  mCacheUpdated = false;
511  cache();
512  QGraphicsRectItem::update();
513 }
514 
516 {
517  if ( mPreviewMode == Render )
518  {
520  }
521 }
522 
524 {
525  mCacheUpdated = u;
526 }
527 
529 {
531  return mComposition->mapRenderer();
533 }
534 
536 {
537  //use stored layer set or read current set from main canvas
538  QStringList renderLayerSet;
539  if ( mKeepLayerSet )
540  {
541  renderLayerSet = mLayerSet;
542  }
543  else
544  {
545  renderLayerSet = mComposition->mapSettings().layers();
546  }
547 
548  //remove atlas coverage layer if required
549  //TODO - move setting for hiding coverage layer to map item properties
551  {
553  {
554  //hiding coverage layer
555  int removeAt = renderLayerSet.indexOf( mComposition->atlasComposition().coverageLayer()->id() );
556  if ( removeAt != -1 )
557  {
558  renderLayerSet.removeAt( removeAt );
559  }
560  }
561  }
562 
563  return renderLayerSet;
564 }
565 
566 double QgsComposerMap::scale() const
567 {
568  QgsScaleCalculator calculator;
569  calculator.setMapUnits( mComposition->mapSettings().mapUnits() );
570  calculator.setDpi( 25.4 ); //QGraphicsView units are mm
571  return calculator.calculate( *currentMapExtent(), rect().width() );
572 }
573 
574 void QgsComposerMap::resize( double dx, double dy )
575 {
576  //setRect
577  QRectF currentRect = rect();
578  QRectF newSceneRect = QRectF( pos().x(), pos().y(), currentRect.width() + dx, currentRect.height() + dy );
579  setSceneRect( newSceneRect );
580  updateItem();
581 }
582 
583 void QgsComposerMap::moveContent( double dx, double dy )
584 {
585  if ( !mDrawing )
586  {
587  transformShift( dx, dy );
588  currentMapExtent()->setXMinimum( currentMapExtent()->xMinimum() + dx );
589  currentMapExtent()->setXMaximum( currentMapExtent()->xMaximum() + dx );
590  currentMapExtent()->setYMinimum( currentMapExtent()->yMinimum() + dy );
591  currentMapExtent()->setYMaximum( currentMapExtent()->yMaximum() + dy );
592  cache();
593  update();
594  emit itemChanged();
595  emit extentChanged();
596  }
597 }
598 
599 void QgsComposerMap::zoomContent( int delta, double x, double y )
600 {
601  if ( mDrawing )
602  {
603  return;
604  }
605 
606  QSettings settings;
607 
608  //read zoom mode
609  //0: zoom, 1: zoom and recenter, 2: zoom to cursor, 3: nothing
610  int zoomMode = settings.value( "/qgis/wheel_action", 2 ).toInt();
611  if ( zoomMode == 3 ) //do nothing
612  {
613  return;
614  }
615 
616  double zoomFactor = settings.value( "/qgis/zoom_factor", 2.0 ).toDouble();
617 
618  //find out new center point
619  double centerX = ( currentMapExtent()->xMaximum() + currentMapExtent()->xMinimum() ) / 2;
620  double centerY = ( currentMapExtent()->yMaximum() + currentMapExtent()->yMinimum() ) / 2;
621 
622  if ( zoomMode != 0 )
623  {
624  //find out map coordinates of mouse position
625  double mapMouseX = currentMapExtent()->xMinimum() + ( x / rect().width() ) * ( currentMapExtent()->xMaximum() - currentMapExtent()->xMinimum() );
626  double mapMouseY = currentMapExtent()->yMinimum() + ( 1 - ( y / rect().height() ) ) * ( currentMapExtent()->yMaximum() - currentMapExtent()->yMinimum() );
627  if ( zoomMode == 1 ) //zoom and recenter
628  {
629  centerX = mapMouseX;
630  centerY = mapMouseY;
631  }
632  else if ( zoomMode == 2 ) //zoom to cursor
633  {
634  centerX = mapMouseX + ( centerX - mapMouseX ) * ( 1.0 / zoomFactor );
635  centerY = mapMouseY + ( centerY - mapMouseY ) * ( 1.0 / zoomFactor );
636  }
637  }
638 
639  double newIntervalX, newIntervalY;
640 
641  if ( delta > 0 )
642  {
643  newIntervalX = ( currentMapExtent()->xMaximum() - currentMapExtent()->xMinimum() ) / zoomFactor;
644  newIntervalY = ( currentMapExtent()->yMaximum() - currentMapExtent()->yMinimum() ) / zoomFactor;
645  }
646  else if ( delta < 0 )
647  {
648  newIntervalX = ( currentMapExtent()->xMaximum() - currentMapExtent()->xMinimum() ) * zoomFactor;
649  newIntervalY = ( currentMapExtent()->yMaximum() - currentMapExtent()->yMinimum() ) * zoomFactor;
650  }
651  else //no need to zoom
652  {
653  return;
654  }
655 
656  currentMapExtent()->setXMaximum( centerX + newIntervalX / 2 );
657  currentMapExtent()->setXMinimum( centerX - newIntervalX / 2 );
658  currentMapExtent()->setYMaximum( centerY + newIntervalY / 2 );
659  currentMapExtent()->setYMinimum( centerY - newIntervalY / 2 );
660 
662  {
663  //if map is atlas controlled and set to fixed scaling mode, then scale changes should be treated as permanant
664  //and also apply to the map's original extent (see #9602)
665  //we can't use the scaleRatio calculated earlier, as the scale can vary depending on extent for geographic coordinate systems
666  QgsScaleCalculator calculator;
667  calculator.setMapUnits( mComposition->mapSettings().mapUnits() );
668  calculator.setDpi( 25.4 ); //QGraphicsView units are mm
669  double scaleRatio = scale() / calculator.calculate( mExtent, rect().width() );
670  mExtent.scale( scaleRatio );
671  }
672 
673  cache();
674  update();
675  emit itemChanged();
676  emit extentChanged();
677 }
678 
679 void QgsComposerMap::setSceneRect( const QRectF& rectangle )
680 {
681  double w = rectangle.width();
682  double h = rectangle.height();
683  //prepareGeometryChange();
684 
685  QgsComposerItem::setSceneRect( rectangle );
686 
687  //QGraphicsRectItem::update();
688  double newHeight = mExtent.width() * h / w ;
690  mCacheUpdated = false;
691 
693  update();
694  emit itemChanged();
695  emit extentChanged();
696 }
697 
699 {
700  if ( mExtent == extent )
701  {
702  return;
703  }
704  mExtent = extent;
705 
706  //adjust height
707  QRectF currentRect = rect();
708 
709  double newHeight = currentRect.width() * extent.height() / extent.width();
710 
711  setSceneRect( QRectF( pos().x(), pos().y(), currentRect.width(), newHeight ) );
712  updateItem();
713 }
714 
716 {
717  if ( mAtlasFeatureExtent == extent )
718  {
719  emit preparedForAtlas();
720  return;
721  }
722 
723  //don't adjust size of item, instead adjust size of bounds to fit
724  QgsRectangle newExtent = extent;
725 
726  //Make sure the width/height ratio is the same as the map item size
727  double currentWidthHeightRatio = rect().width() / rect().height();
728  double newWidthHeightRatio = newExtent.width() / newExtent.height();
729 
730  if ( currentWidthHeightRatio < newWidthHeightRatio )
731  {
732  //enlarge height of new extent, ensuring the map center stays the same
733  double newHeight = newExtent.width() / currentWidthHeightRatio;
734  double deltaHeight = newHeight - newExtent.height();
735  newExtent.setYMinimum( extent.yMinimum() - deltaHeight / 2 );
736  newExtent.setYMaximum( extent.yMaximum() + deltaHeight / 2 );
737  }
738  else if ( currentWidthHeightRatio >= newWidthHeightRatio )
739  {
740  //enlarge width of new extent, ensuring the map center stays the same
741  double newWidth = currentWidthHeightRatio * newExtent.height();
742  double deltaWidth = newWidth - newExtent.width();
743  newExtent.setXMinimum( extent.xMinimum() - deltaWidth / 2 );
744  newExtent.setXMaximum( extent.xMaximum() + deltaWidth / 2 );
745  }
746 
747  mAtlasFeatureExtent = newExtent;
748  mCacheUpdated = false;
749  emit preparedForAtlas();
750  updateItem();
751  emit itemChanged();
752  emit extentChanged();
753 }
754 
756 {
757  //atlas preview has been toggled, so update item and extents
758  mCacheUpdated = false;
759  updateItem();
760  emit itemChanged();
761  emit extentChanged();
762 }
763 
765 {
766  //non-const version
768  {
769  //if atlas is enabled, and we are either exporting the composition or previewing the atlas, then
770  //return the current temporary atlas feature extent
771  return &mAtlasFeatureExtent;
772  }
773  else
774  {
775  //otherwise return permenant user set extent
776  return &mExtent;
777  }
778 }
779 
781 {
782  //const version
784  {
785  //if atlas is enabled, and we are either exporting the composition or previewing the atlas, then
786  //return the current temporary atlas feature extent
787  return &mAtlasFeatureExtent;
788  }
789  else
790  {
791  //otherwise return permenant user set extent
792  return &mExtent;
793  }
794 }
795 
796 void QgsComposerMap::setNewScale( double scaleDenominator )
797 {
798  double currentScaleDenominator = scale();
799 
800  if ( scaleDenominator == currentScaleDenominator || scaleDenominator == 0 )
801  {
802  return;
803  }
804 
805  double scaleRatio = scaleDenominator / currentScaleDenominator;
806  currentMapExtent()->scale( scaleRatio );
807 
809  {
810  //if map is atlas controlled and set to fixed scaling mode, then scale changes should be treated as permanant
811  //and also apply to the map's original extent (see #9602)
812  //we can't use the scaleRatio calculated earlier, as the scale can vary depending on extent for geographic coordinate systems
813  QgsScaleCalculator calculator;
814  calculator.setMapUnits( mComposition->mapSettings().mapUnits() );
815  calculator.setDpi( 25.4 ); //QGraphicsView units are mm
816  scaleRatio = scaleDenominator / calculator.calculate( mExtent, rect().width() );
817  mExtent.scale( scaleRatio );
818  }
819 
820  mCacheUpdated = false;
821  cache();
822  update();
823  emit itemChanged();
824  emit extentChanged();
825 }
826 
828 {
829  mPreviewMode = m;
830  emit itemChanged();
831 }
832 
833 void QgsComposerMap::setOffset( double xOffset, double yOffset )
834 {
835  mXOffset = xOffset;
836  mYOffset = yOffset;
837 }
838 
840 {
841  //kept for api compatibility with QGIS 2.0
842  setMapRotation( r );
843 }
844 
846 {
847  mMapRotation = r;
848  emit mapRotationChanged( r );
849  emit itemChanged();
850  update();
851 }
852 
854 {
855  if ( !mUpdatesEnabled )
856  {
857  return;
858  }
859 
861  {
862  cache();
863  }
865 }
866 
868 {
869  QStringList layers = mComposition->mapSettings().layers();
870 
871  QStringList::const_iterator layer_it = layers.constBegin();
872  QgsMapLayer* currentLayer = 0;
873 
874  for ( ; layer_it != layers.constEnd(); ++layer_it )
875  {
876  currentLayer = QgsMapLayerRegistry::instance()->mapLayer( *layer_it );
877  if ( currentLayer )
878  {
879  QgsRasterLayer* currentRasterLayer = qobject_cast<QgsRasterLayer *>( currentLayer );
880  if ( currentRasterLayer )
881  {
882  const QgsRasterDataProvider* rasterProvider = 0;
883  if (( rasterProvider = currentRasterLayer->dataProvider() ) )
884  {
885  if ( rasterProvider->name() == "wms" )
886  {
887  return true;
888  }
889  }
890  }
891  }
892  }
893  return false;
894 }
895 
897 {
898  // check if map contains advanced effects like blend modes, or flattened layers for transparency
899 
900  QStringList layers = mComposition->mapSettings().layers();
901 
902  QStringList::const_iterator layer_it = layers.constBegin();
903  QgsMapLayer* currentLayer = 0;
904 
905  for ( ; layer_it != layers.constEnd(); ++layer_it )
906  {
907  currentLayer = QgsMapLayerRegistry::instance()->mapLayer( *layer_it );
908  if ( currentLayer )
909  {
910  if ( currentLayer->blendMode() != QPainter::CompositionMode_SourceOver )
911  {
912  return true;
913  }
914  // if vector layer, check labels and feature blend mode
915  QgsVectorLayer* currentVectorLayer = qobject_cast<QgsVectorLayer *>( currentLayer );
916  if ( currentVectorLayer )
917  {
918  if ( currentVectorLayer->layerTransparency() != 0 )
919  {
920  return true;
921  }
922  if ( currentVectorLayer->featureBlendMode() != QPainter::CompositionMode_SourceOver )
923  {
924  return true;
925  }
926  // check label blend modes
927  if ( QgsPalLabeling::staticWillUseLayer( currentVectorLayer ) )
928  {
929  // Check all label blending properties
930  QgsPalLayerSettings layerSettings = QgsPalLayerSettings::fromLayer( currentVectorLayer );
931  if (( layerSettings.blendMode != QPainter::CompositionMode_SourceOver ) ||
932  ( layerSettings.bufferSize != 0 && layerSettings.bufferBlendMode != QPainter::CompositionMode_SourceOver ) ||
933  ( layerSettings.shadowDraw && layerSettings.shadowBlendMode != QPainter::CompositionMode_SourceOver ) ||
934  ( layerSettings.shapeDraw && layerSettings.shapeBlendMode != QPainter::CompositionMode_SourceOver ) )
935  {
936  return true;
937  }
938  }
939  }
940  }
941  }
942 
943  return false;
944 }
945 
947 {
948  //connect signal from layer registry to update in case of new or deleted layers
950  if ( layerRegistry )
951  {
952  connect( layerRegistry, SIGNAL( layerWillBeRemoved( QString ) ), this, SLOT( updateCachedImage() ) );
953  connect( layerRegistry, SIGNAL( layerWasAdded( QgsMapLayer* ) ), this, SLOT( updateCachedImage() ) );
954  }
955 }
956 
957 bool QgsComposerMap::writeXML( QDomElement& elem, QDomDocument & doc ) const
958 {
959  if ( elem.isNull() )
960  {
961  return false;
962  }
963 
964  QDomElement composerMapElem = doc.createElement( "ComposerMap" );
965  composerMapElem.setAttribute( "id", mId );
966 
967  //previewMode
968  if ( mPreviewMode == Cache )
969  {
970  composerMapElem.setAttribute( "previewMode", "Cache" );
971  }
972  else if ( mPreviewMode == Render )
973  {
974  composerMapElem.setAttribute( "previewMode", "Render" );
975  }
976  else //rectangle
977  {
978  composerMapElem.setAttribute( "previewMode", "Rectangle" );
979  }
980 
981  if ( mKeepLayerSet )
982  {
983  composerMapElem.setAttribute( "keepLayerSet", "true" );
984  }
985  else
986  {
987  composerMapElem.setAttribute( "keepLayerSet", "false" );
988  }
989 
990  if ( mDrawCanvasItems )
991  {
992  composerMapElem.setAttribute( "drawCanvasItems", "true" );
993  }
994  else
995  {
996  composerMapElem.setAttribute( "drawCanvasItems", "false" );
997  }
998 
999  //overview map frame
1000  QDomElement overviewFrameElem = doc.createElement( "overviewFrame" );
1001  overviewFrameElem.setAttribute( "overviewFrameMap", mOverviewFrameMapId );
1002  overviewFrameElem.setAttribute( "overviewBlendMode", QgsMapRenderer::getBlendModeEnum( mOverviewBlendMode ) );
1003  if ( mOverviewInverted )
1004  {
1005  overviewFrameElem.setAttribute( "overviewInverted", "true" );
1006  }
1007  else
1008  {
1009  overviewFrameElem.setAttribute( "overviewInverted", "false" );
1010  }
1011 
1012  overviewFrameElem.setAttribute( "overviewCentered", mOverviewCentered ? "true" : "false" );
1013 
1014  QDomElement overviewFrameStyleElem = QgsSymbolLayerV2Utils::saveSymbol( QString(), mOverviewFrameMapSymbol, doc );
1015  overviewFrameElem.appendChild( overviewFrameStyleElem );
1016  composerMapElem.appendChild( overviewFrameElem );
1017 
1018 
1019  //extent
1020  QDomElement extentElem = doc.createElement( "Extent" );
1021  extentElem.setAttribute( "xmin", qgsDoubleToString( mExtent.xMinimum() ) );
1022  extentElem.setAttribute( "xmax", qgsDoubleToString( mExtent.xMaximum() ) );
1023  extentElem.setAttribute( "ymin", qgsDoubleToString( mExtent.yMinimum() ) );
1024  extentElem.setAttribute( "ymax", qgsDoubleToString( mExtent.yMaximum() ) );
1025  composerMapElem.appendChild( extentElem );
1026 
1027  //map rotation
1028  composerMapElem.setAttribute( "mapRotation", QString::number( mMapRotation ) );
1029 
1030  //layer set
1031  QDomElement layerSetElem = doc.createElement( "LayerSet" );
1032  QStringList::const_iterator layerIt = mLayerSet.constBegin();
1033  for ( ; layerIt != mLayerSet.constEnd(); ++layerIt )
1034  {
1035  QDomElement layerElem = doc.createElement( "Layer" );
1036  QDomText layerIdText = doc.createTextNode( *layerIt );
1037  layerElem.appendChild( layerIdText );
1038  layerSetElem.appendChild( layerElem );
1039  }
1040  composerMapElem.appendChild( layerSetElem );
1041 
1042  //overview map frame
1043  composerMapElem.setAttribute( "overviewFrameMap", mOverviewFrameMapId );
1044 
1045  //grid
1046  QDomElement gridElem = doc.createElement( "Grid" );
1047  gridElem.setAttribute( "show", mGridEnabled );
1048  gridElem.setAttribute( "gridStyle", mGridStyle );
1049  gridElem.setAttribute( "intervalX", qgsDoubleToString( mGridIntervalX ) );
1050  gridElem.setAttribute( "intervalY", qgsDoubleToString( mGridIntervalY ) );
1051  gridElem.setAttribute( "offsetX", qgsDoubleToString( mGridOffsetX ) );
1052  gridElem.setAttribute( "offsetY", qgsDoubleToString( mGridOffsetY ) );
1053  gridElem.setAttribute( "crossLength", qgsDoubleToString( mCrossLength ) );
1054  gridElem.setAttribute( "gridFrameStyle", mGridFrameStyle );
1055  gridElem.setAttribute( "gridFrameWidth", qgsDoubleToString( mGridFrameWidth ) );
1056  gridElem.setAttribute( "gridFramePenThickness", qgsDoubleToString( mGridFramePenThickness ) );
1057  //grid frame pen color
1058  QDomElement framePenColorElem = doc.createElement( "framePenColor" );
1059  framePenColorElem.setAttribute( "red", mGridFramePenColor.red() );
1060  framePenColorElem.setAttribute( "green", mGridFramePenColor.green() );
1061  framePenColorElem.setAttribute( "blue", mGridFramePenColor.blue() );
1062  framePenColorElem.setAttribute( "alpha", mGridFramePenColor.alpha() );
1063  gridElem.appendChild( framePenColorElem );
1064  //grid frame fill colors
1065  QDomElement frameFillColor1Elem = doc.createElement( "frameFillColor1" );
1066  frameFillColor1Elem.setAttribute( "red", mGridFrameFillColor1.red() );
1067  frameFillColor1Elem.setAttribute( "green", mGridFrameFillColor1.green() );
1068  frameFillColor1Elem.setAttribute( "blue", mGridFrameFillColor1.blue() );
1069  frameFillColor1Elem.setAttribute( "alpha", mGridFrameFillColor1.alpha() );
1070  gridElem.appendChild( frameFillColor1Elem );
1071  QDomElement frameFillColor2Elem = doc.createElement( "frameFillColor2" );
1072  frameFillColor2Elem.setAttribute( "red", mGridFrameFillColor2.red() );
1073  frameFillColor2Elem.setAttribute( "green", mGridFrameFillColor2.green() );
1074  frameFillColor2Elem.setAttribute( "blue", mGridFrameFillColor2.blue() );
1075  frameFillColor2Elem.setAttribute( "alpha", mGridFrameFillColor2.alpha() );
1076  gridElem.appendChild( frameFillColor2Elem );
1077 
1078  gridElem.setAttribute( "gridBlendMode", QgsMapRenderer::getBlendModeEnum( mGridBlendMode ) );
1079  QDomElement gridLineStyleElem = QgsSymbolLayerV2Utils::saveSymbol( QString(), mGridLineSymbol, doc );
1080  gridElem.appendChild( gridLineStyleElem );
1081 
1082  //grid annotation
1083  QDomElement annotationElem = doc.createElement( "Annotation" );
1084  annotationElem.setAttribute( "format", mGridAnnotationFormat );
1085  annotationElem.setAttribute( "show", mShowGridAnnotation );
1086  annotationElem.setAttribute( "leftPosition", mLeftGridAnnotationPosition );
1087  annotationElem.setAttribute( "rightPosition", mRightGridAnnotationPosition );
1088  annotationElem.setAttribute( "topPosition", mTopGridAnnotationPosition );
1089  annotationElem.setAttribute( "bottomPosition", mBottomGridAnnotationPosition );
1090  annotationElem.setAttribute( "leftDirection", mLeftGridAnnotationDirection );
1091  annotationElem.setAttribute( "rightDirection", mRightGridAnnotationDirection );
1092  annotationElem.setAttribute( "topDirection", mTopGridAnnotationDirection );
1093  annotationElem.setAttribute( "bottomDirection", mBottomGridAnnotationDirection );
1094  annotationElem.setAttribute( "frameDistance", QString::number( mAnnotationFrameDistance ) );
1095  annotationElem.setAttribute( "font", mGridAnnotationFont.toString() );
1096  annotationElem.setAttribute( "precision", mGridAnnotationPrecision );
1097  //annotation font color
1098  QDomElement annotationFontColorElem = doc.createElement( "fontColor" );
1099  annotationFontColorElem.setAttribute( "red", mGridAnnotationFontColor.red() );
1100  annotationFontColorElem.setAttribute( "green", mGridAnnotationFontColor.green() );
1101  annotationFontColorElem.setAttribute( "blue", mGridAnnotationFontColor.blue() );
1102  annotationFontColorElem.setAttribute( "alpha", mGridAnnotationFontColor.alpha() );
1103  annotationElem.appendChild( annotationFontColorElem );
1104 
1105  gridElem.appendChild( annotationElem );
1106  composerMapElem.appendChild( gridElem );
1107 
1108  //atlas
1109  QDomElement atlasElem = doc.createElement( "AtlasMap" );
1110  atlasElem.setAttribute( "atlasDriven", mAtlasDriven );
1111  atlasElem.setAttribute( "scalingMode", mAtlasScalingMode );
1112  atlasElem.setAttribute( "margin", qgsDoubleToString( mAtlasMargin ) );
1113  composerMapElem.appendChild( atlasElem );
1114 
1115  elem.appendChild( composerMapElem );
1116  return _writeXML( composerMapElem, doc );
1117 }
1118 
1119 bool QgsComposerMap::readXML( const QDomElement& itemElem, const QDomDocument& doc )
1120 {
1121  if ( itemElem.isNull() )
1122  {
1123  return false;
1124  }
1125 
1126  QString idRead = itemElem.attribute( "id", "not found" );
1127  if ( idRead != "not found" )
1128  {
1129  mId = idRead.toInt();
1130  }
1132 
1133  //previewMode
1134  QString previewMode = itemElem.attribute( "previewMode" );
1135  if ( previewMode == "Cache" )
1136  {
1137  mPreviewMode = Cache;
1138  }
1139  else if ( previewMode == "Render" )
1140  {
1141  mPreviewMode = Render;
1142  }
1143  else
1144  {
1146  }
1147 
1148  QDomElement overviewFrameElem = itemElem.firstChildElement( "overviewFrame" );
1149  if ( !overviewFrameElem.isNull() )
1150  {
1151  setOverviewFrameMap( overviewFrameElem.attribute( "overviewFrameMap", "-1" ).toInt() );
1152  setOverviewBlendMode( QgsMapRenderer::getCompositionMode(( QgsMapRenderer::BlendMode ) overviewFrameElem.attribute( "overviewBlendMode", "0" ).toUInt() ) );
1153 
1154  QString overviewInvertedFlag = overviewFrameElem.attribute( "overviewInverted" );
1155  if ( overviewInvertedFlag.compare( "true", Qt::CaseInsensitive ) == 0 )
1156  {
1157  setOverviewInverted( true );
1158  }
1159  else
1160  {
1161  setOverviewInverted( false );
1162  }
1163 
1164  if ( overviewFrameElem.attribute( "overviewCentered" ).compare( "true", Qt::CaseInsensitive ) == 0 )
1165  {
1166  mOverviewCentered = true;
1167  }
1168  else
1169  {
1170  mOverviewCentered = false;
1171  }
1172 
1173  QDomElement overviewFrameSymbolElem = overviewFrameElem.firstChildElement( "symbol" );
1174  if ( !overviewFrameSymbolElem.isNull() )
1175  {
1176  delete mOverviewFrameMapSymbol;
1177  mOverviewFrameMapSymbol = dynamic_cast<QgsFillSymbolV2*>( QgsSymbolLayerV2Utils::loadSymbol( overviewFrameSymbolElem ) );
1178  }
1179  }
1180 
1181  //extent
1182  QDomNodeList extentNodeList = itemElem.elementsByTagName( "Extent" );
1183  if ( extentNodeList.size() > 0 )
1184  {
1185  QDomElement extentElem = extentNodeList.at( 0 ).toElement();
1186  double xmin, xmax, ymin, ymax;
1187  xmin = extentElem.attribute( "xmin" ).toDouble();
1188  xmax = extentElem.attribute( "xmax" ).toDouble();
1189  ymin = extentElem.attribute( "ymin" ).toDouble();
1190  ymax = extentElem.attribute( "ymax" ).toDouble();
1191  setNewExtent( QgsRectangle( xmin, ymin, xmax, ymax ) );
1192  }
1193 
1194  //map rotation
1195  if ( itemElem.attribute( "mapRotation", "0" ).toDouble() != 0 )
1196  {
1197  mMapRotation = itemElem.attribute( "mapRotation", "0" ).toDouble();
1198  }
1199 
1200  //mKeepLayerSet flag
1201  QString keepLayerSetFlag = itemElem.attribute( "keepLayerSet" );
1202  if ( keepLayerSetFlag.compare( "true", Qt::CaseInsensitive ) == 0 )
1203  {
1204  mKeepLayerSet = true;
1205  }
1206  else
1207  {
1208  mKeepLayerSet = false;
1209  }
1210 
1211  QString drawCanvasItemsFlag = itemElem.attribute( "drawCanvasItems", "true" );
1212  if ( drawCanvasItemsFlag.compare( "true", Qt::CaseInsensitive ) == 0 )
1213  {
1214  mDrawCanvasItems = true;
1215  }
1216  else
1217  {
1218  mDrawCanvasItems = false;
1219  }
1220 
1221  //mLayerSet
1222  QDomNodeList layerSetNodeList = itemElem.elementsByTagName( "LayerSet" );
1223  QStringList layerSet;
1224  if ( layerSetNodeList.size() > 0 )
1225  {
1226  QDomElement layerSetElem = layerSetNodeList.at( 0 ).toElement();
1227  QDomNodeList layerIdNodeList = layerSetElem.elementsByTagName( "Layer" );
1228  for ( int i = 0; i < layerIdNodeList.size(); ++i )
1229  {
1230  layerSet << layerIdNodeList.at( i ).toElement().text();
1231  }
1232  }
1233  mLayerSet = layerSet;
1234 
1235  mDrawing = false;
1236  mNumCachedLayers = 0;
1237  mCacheUpdated = false;
1238 
1239  //grid
1240  QDomNodeList gridNodeList = itemElem.elementsByTagName( "Grid" );
1241  if ( gridNodeList.size() > 0 )
1242  {
1243  QDomElement gridElem = gridNodeList.at( 0 ).toElement();
1244  mGridEnabled = ( gridElem.attribute( "show", "0" ) != "0" );
1245  mGridStyle = QgsComposerMap::GridStyle( gridElem.attribute( "gridStyle", "0" ).toInt() );
1246  mGridIntervalX = gridElem.attribute( "intervalX", "0" ).toDouble();
1247  mGridIntervalY = gridElem.attribute( "intervalY", "0" ).toDouble();
1248  mGridOffsetX = gridElem.attribute( "offsetX", "0" ).toDouble();
1249  mGridOffsetY = gridElem.attribute( "offsetY", "0" ).toDouble();
1250  mCrossLength = gridElem.attribute( "crossLength", "3" ).toDouble();
1251  mGridFrameStyle = ( QgsComposerMap::GridFrameStyle )gridElem.attribute( "gridFrameStyle", "0" ).toInt();
1252  mGridFrameWidth = gridElem.attribute( "gridFrameWidth", "2.0" ).toDouble();
1253  mGridFramePenThickness = gridElem.attribute( "gridFramePenThickness", "0.5" ).toDouble();
1254 
1255  //grid frame pen color
1256  QDomNodeList gridFramePenColorList = gridElem.elementsByTagName( "framePenColor" );
1257  if ( gridFramePenColorList.size() > 0 )
1258  {
1259  QDomElement penColorElem = gridFramePenColorList.at( 0 ).toElement();
1260  int red = penColorElem.attribute( "red", "0" ).toInt();
1261  int green = penColorElem.attribute( "green", "0" ).toInt();
1262  int blue = penColorElem.attribute( "blue", "0" ).toInt();
1263  int alpha = penColorElem.attribute( "alpha", "255" ).toInt();
1264  mGridFramePenColor = QColor( red, green, blue, alpha );
1265  }
1266  else
1267  {
1268  mGridFramePenColor = QColor( 0, 0, 0 );
1269  }
1270  //grid frame fill color 1
1271  QDomNodeList gridFrameFillColor1List = gridElem.elementsByTagName( "frameFillColor1" );
1272  if ( gridFrameFillColor1List.size() > 0 )
1273  {
1274  QDomElement fillColorElem = gridFrameFillColor1List.at( 0 ).toElement();
1275  int red = fillColorElem.attribute( "red", "0" ).toInt();
1276  int green = fillColorElem.attribute( "green", "0" ).toInt();
1277  int blue = fillColorElem.attribute( "blue", "0" ).toInt();
1278  int alpha = fillColorElem.attribute( "alpha", "255" ).toInt();
1279  mGridFrameFillColor1 = QColor( red, green, blue, alpha );
1280  }
1281  else
1282  {
1283  mGridFrameFillColor1 = Qt::white;
1284  }
1285  //grid frame fill color 2
1286  QDomNodeList gridFrameFillColor2List = gridElem.elementsByTagName( "frameFillColor2" );
1287  if ( gridFrameFillColor2List.size() > 0 )
1288  {
1289  QDomElement fillColorElem = gridFrameFillColor2List.at( 0 ).toElement();
1290  int red = fillColorElem.attribute( "red", "0" ).toInt();
1291  int green = fillColorElem.attribute( "green", "0" ).toInt();
1292  int blue = fillColorElem.attribute( "blue", "0" ).toInt();
1293  int alpha = fillColorElem.attribute( "alpha", "255" ).toInt();
1294  mGridFrameFillColor2 = QColor( red, green, blue, alpha );
1295  }
1296  else
1297  {
1298  mGridFrameFillColor2 = Qt::black;
1299  }
1300 
1301  setGridBlendMode( QgsMapRenderer::getCompositionMode(( QgsMapRenderer::BlendMode ) gridElem.attribute( "gridBlendMode", "0" ).toUInt() ) );
1302 
1303  QDomElement gridSymbolElem = gridElem.firstChildElement( "symbol" );
1304  delete mGridLineSymbol;
1305  if ( gridSymbolElem.isNull( ) )
1306  {
1307  //old project file, read penWidth /penColorRed, penColorGreen, penColorBlue
1309  mGridLineSymbol->setWidth( gridElem.attribute( "penWidth", "0" ).toDouble() );
1310  mGridLineSymbol->setColor( QColor( gridElem.attribute( "penColorRed", "0" ).toInt(),
1311  gridElem.attribute( "penColorGreen", "0" ).toInt(),
1312  gridElem.attribute( "penColorBlue", "0" ).toInt() ) );
1313  }
1314  else
1315  {
1316  mGridLineSymbol = dynamic_cast<QgsLineSymbolV2*>( QgsSymbolLayerV2Utils::loadSymbol( gridSymbolElem ) );
1317  }
1318 
1319  QDomNodeList annotationNodeList = gridElem.elementsByTagName( "Annotation" );
1320  if ( annotationNodeList.size() > 0 )
1321  {
1322  QDomElement annotationElem = annotationNodeList.at( 0 ).toElement();
1323  mShowGridAnnotation = ( annotationElem.attribute( "show", "0" ) != "0" );
1324  mGridAnnotationFormat = QgsComposerMap::GridAnnotationFormat( annotationElem.attribute( "format", "0" ).toInt() );
1325  mLeftGridAnnotationPosition = QgsComposerMap::GridAnnotationPosition( annotationElem.attribute( "leftPosition", "0" ).toInt() );
1326  mRightGridAnnotationPosition = QgsComposerMap::GridAnnotationPosition( annotationElem.attribute( "rightPosition", "0" ).toInt() );
1327  mTopGridAnnotationPosition = QgsComposerMap::GridAnnotationPosition( annotationElem.attribute( "topPosition", "0" ).toInt() );
1328  mBottomGridAnnotationPosition = QgsComposerMap::GridAnnotationPosition( annotationElem.attribute( "bottomPosition", "0" ).toInt() );
1329  mLeftGridAnnotationDirection = QgsComposerMap::GridAnnotationDirection( annotationElem.attribute( "leftDirection", "0" ).toInt() );
1330  mRightGridAnnotationDirection = QgsComposerMap::GridAnnotationDirection( annotationElem.attribute( "rightDirection", "0" ).toInt() );
1331  mTopGridAnnotationDirection = QgsComposerMap::GridAnnotationDirection( annotationElem.attribute( "topDirection", "0" ).toInt() );
1332  mBottomGridAnnotationDirection = QgsComposerMap::GridAnnotationDirection( annotationElem.attribute( "bottomDirection", "0" ).toInt() );
1333  mAnnotationFrameDistance = annotationElem.attribute( "frameDistance", "0" ).toDouble();
1334  mGridAnnotationFont.fromString( annotationElem.attribute( "font", "" ) );
1335 
1336  //annotation font color
1337  QDomNodeList annotationFontColorList = annotationElem.elementsByTagName( "fontColor" );
1338  if ( annotationFontColorList.size() > 0 )
1339  {
1340  QDomElement fontColorElem = annotationFontColorList.at( 0 ).toElement();
1341  int red = fontColorElem.attribute( "red", "0" ).toInt();
1342  int green = fontColorElem.attribute( "green", "0" ).toInt();
1343  int blue = fontColorElem.attribute( "blue", "0" ).toInt();
1344  int alpha = fontColorElem.attribute( "alpha", "255" ).toInt();
1345  mGridAnnotationFontColor = QColor( red, green, blue, alpha );
1346  }
1347  else
1348  {
1349  mGridAnnotationFontColor = QColor( 0, 0, 0 );
1350  }
1351 
1352  mGridAnnotationPrecision = annotationElem.attribute( "precision", "3" ).toInt();
1353  }
1354  }
1355 
1356  //atlas
1357  QDomNodeList atlasNodeList = itemElem.elementsByTagName( "AtlasMap" );
1358  if ( atlasNodeList.size() > 0 )
1359  {
1360  QDomElement atlasElem = atlasNodeList.at( 0 ).toElement();
1361  mAtlasDriven = ( atlasElem.attribute( "atlasDriven", "0" ) != "0" );
1362  if ( atlasElem.hasAttribute( "fixedScale" ) ) // deprecated XML
1363  {
1364  mAtlasScalingMode = ( atlasElem.attribute( "fixedScale", "0" ) != "0" ) ? Fixed : Auto;
1365  }
1366  else if ( atlasElem.hasAttribute( "scalingMode" ) )
1367  {
1368  mAtlasScalingMode = static_cast<AtlasScalingMode>( atlasElem.attribute( "scalingMode" ).toInt() );
1369  }
1370  mAtlasMargin = atlasElem.attribute( "margin", "0.1" ).toDouble();
1371  }
1372 
1373  //restore general composer item properties
1374  QDomNodeList composerItemList = itemElem.elementsByTagName( "ComposerItem" );
1375  if ( composerItemList.size() > 0 )
1376  {
1377  QDomElement composerItemElem = composerItemList.at( 0 ).toElement();
1378 
1379  if ( composerItemElem.attribute( "rotation", "0" ).toDouble() != 0 )
1380  {
1381  //in versions prior to 2.1 map rotation was stored in the rotation attribute
1382  mMapRotation = composerItemElem.attribute( "rotation", "0" ).toDouble();
1383  }
1384 
1385  _readXML( composerItemElem, doc );
1386  }
1387 
1389  emit itemChanged();
1390  return true;
1391 }
1392 
1394 {
1396 }
1397 
1399 {
1400  if ( mLayerSet.size() < 1 )
1401  {
1402  return;
1403  }
1404 
1405  //if layer set is fixed, do a lookup in the layer registry to also find the non-visible layers
1406  QStringList currentLayerSet;
1407  if ( mKeepLayerSet )
1408  {
1409  currentLayerSet = QgsMapLayerRegistry::instance()->mapLayers().uniqueKeys();
1410  }
1411  else //only consider layers visible in the map
1412  {
1413  currentLayerSet = mComposition->mapSettings().layers();
1414  }
1415 
1416  for ( int i = mLayerSet.size() - 1; i >= 0; --i )
1417  {
1418  if ( !currentLayerSet.contains( mLayerSet.at( i ) ) )
1419  {
1420  mLayerSet.removeAt( i );
1421  }
1422  }
1423 }
1424 
1425 void QgsComposerMap::drawGrid( QPainter* p )
1426 {
1427  QList< QPair< double, QLineF > > verticalLines;
1428  yGridLines( verticalLines );
1429  QList< QPair< double, QLineF > >::const_iterator vIt = verticalLines.constBegin();
1430  QList< QPair< double, QLineF > > horizontalLines;
1431  xGridLines( horizontalLines );
1432  QList< QPair< double, QLineF > >::const_iterator hIt = horizontalLines.constBegin();
1433 
1434  QRectF thisPaintRect = QRectF( 0, 0, QGraphicsRectItem::rect().width(), QGraphicsRectItem::rect().height() );
1435  p->setClipRect( thisPaintRect );
1436 
1437  QPaintDevice* thePaintDevice = p->device();
1438  if ( !thePaintDevice )
1439  {
1440  return;
1441  }
1442 
1443  // set the blend mode for drawing grid lines
1444  p->save();
1445  p->setCompositionMode( mGridBlendMode );
1446  p->setRenderHint( QPainter::Antialiasing );
1447 
1448  //setup painter scaling to dots so that raster symbology is drawn to scale
1449  double dotsPerMM = thePaintDevice->logicalDpiX() / 25.4;
1450  p->scale( 1 / dotsPerMM, 1 / dotsPerMM ); // scale painter from mm to dots
1451 
1452  //setup render context
1454  //context units should be in dots
1455  ms.setOutputSize( QSizeF( rect().width() * dotsPerMM, rect().height() * dotsPerMM ).toSize() );
1456  ms.setExtent( *currentMapExtent() );
1457  ms.setOutputDpi( p->device()->logicalDpiX() );
1459  context.setForceVectorOutput( true );
1460  context.setPainter( p );
1461 
1462  //simpler approach: draw vertical lines first, then horizontal ones
1464  {
1465  //need to scale line to dots, rather then mm, since the painter has been scaled to dots
1466  QLineF line;
1467  for ( ; vIt != verticalLines.constEnd(); ++vIt )
1468  {
1469  line = QLineF( vIt->second.p1() * dotsPerMM, vIt->second.p2() * dotsPerMM ) ;
1470  drawGridLine( line, context );
1471  }
1472 
1473  for ( ; hIt != horizontalLines.constEnd(); ++hIt )
1474  {
1475  line = QLineF( hIt->second.p1() * dotsPerMM, hIt->second.p2() * dotsPerMM ) ;
1476  drawGridLine( line, context );
1477  }
1478  }
1479  else //cross
1480  {
1481  QPointF intersectionPoint, crossEnd1, crossEnd2;
1482  for ( ; vIt != verticalLines.constEnd(); ++vIt )
1483  {
1484  //start mark
1485  crossEnd1 = QgsSymbolLayerV2Utils::pointOnLineWithDistance( vIt->second.p1(), vIt->second.p2(), mCrossLength );
1486  drawGridLine( QLineF( vIt->second.p1() * dotsPerMM, crossEnd1 * dotsPerMM ), context );
1487 
1488  //test for intersection with every horizontal line
1489  hIt = horizontalLines.constBegin();
1490  for ( ; hIt != horizontalLines.constEnd(); ++hIt )
1491  {
1492  if ( hIt->second.intersect( vIt->second, &intersectionPoint ) == QLineF::BoundedIntersection )
1493  {
1494  crossEnd1 = QgsSymbolLayerV2Utils::pointOnLineWithDistance( intersectionPoint, vIt->second.p1(), mCrossLength );
1495  crossEnd2 = QgsSymbolLayerV2Utils::pointOnLineWithDistance( intersectionPoint, vIt->second.p2(), mCrossLength );
1496  drawGridLine( QLineF( crossEnd1 * dotsPerMM, crossEnd2 * dotsPerMM ), context );
1497  }
1498  }
1499  //end mark
1500  QPointF crossEnd2 = QgsSymbolLayerV2Utils::pointOnLineWithDistance( vIt->second.p2(), vIt->second.p1(), mCrossLength );
1501  drawGridLine( QLineF( vIt->second.p2() * dotsPerMM, crossEnd2 * dotsPerMM ), context );
1502  }
1503 
1504  hIt = horizontalLines.constBegin();
1505  for ( ; hIt != horizontalLines.constEnd(); ++hIt )
1506  {
1507  //start mark
1508  crossEnd1 = QgsSymbolLayerV2Utils::pointOnLineWithDistance( hIt->second.p1(), hIt->second.p2(), mCrossLength );
1509  drawGridLine( QLineF( hIt->second.p1() * dotsPerMM, crossEnd1 * dotsPerMM ), context );
1510 
1511  vIt = verticalLines.constBegin();
1512  for ( ; vIt != verticalLines.constEnd(); ++vIt )
1513  {
1514  if ( vIt->second.intersect( hIt->second, &intersectionPoint ) == QLineF::BoundedIntersection )
1515  {
1516  crossEnd1 = QgsSymbolLayerV2Utils::pointOnLineWithDistance( intersectionPoint, hIt->second.p1(), mCrossLength );
1517  crossEnd2 = QgsSymbolLayerV2Utils::pointOnLineWithDistance( intersectionPoint, hIt->second.p2(), mCrossLength );
1518  drawGridLine( QLineF( crossEnd1 * dotsPerMM, crossEnd2 * dotsPerMM ), context );
1519  }
1520  }
1521  //end mark
1522  crossEnd1 = QgsSymbolLayerV2Utils::pointOnLineWithDistance( hIt->second.p2(), hIt->second.p1(), mCrossLength );
1523  drawGridLine( QLineF( hIt->second.p2() * dotsPerMM, crossEnd1 * dotsPerMM ), context );
1524  }
1525  }
1526  // reset composition mode
1527  p->restore();
1528 
1529  p->setClipRect( thisPaintRect , Qt::NoClip );
1530 
1532  {
1533  drawGridFrame( p, horizontalLines, verticalLines );
1534  }
1535 
1536  if ( mShowGridAnnotation )
1537  {
1538  drawCoordinateAnnotations( p, horizontalLines, verticalLines );
1539  }
1540 
1541 }
1542 
1543 void QgsComposerMap::drawGridFrame( QPainter* p, const QList< QPair< double, QLineF > >& hLines, const QList< QPair< double, QLineF > >& vLines )
1544 {
1545  //Sort the coordinate positions for each side
1546  QMap< double, double > leftGridFrame;
1547  QMap< double, double > rightGridFrame;
1548  QMap< double, double > topGridFrame;
1549  QMap< double, double > bottomGridFrame;
1550 
1551  sortGridLinesOnBorders( hLines, vLines, leftGridFrame, rightGridFrame, topGridFrame, bottomGridFrame );
1552 
1553  drawGridFrameBorder( p, leftGridFrame, QgsComposerMap::Left );
1554  drawGridFrameBorder( p, rightGridFrame, QgsComposerMap::Right );
1555  drawGridFrameBorder( p, topGridFrame, QgsComposerMap::Top );
1556  drawGridFrameBorder( p, bottomGridFrame, QgsComposerMap::Bottom );
1557 }
1558 
1559 void QgsComposerMap::drawGridLine( const QLineF& line, QgsRenderContext& context )
1560 {
1561  if ( !mGridLineSymbol )
1562  {
1563  return;
1564  }
1565  if ( mPreviewMode == Rectangle )
1566  {
1567  return;
1568  }
1569 
1570  QPolygonF poly;
1571  poly << line.p1() << line.p2();
1572  mGridLineSymbol->startRender( context );
1573  mGridLineSymbol->renderPolyline( poly, 0, context );
1574  mGridLineSymbol->stopRender( context );
1575 }
1576 
1577 void QgsComposerMap::drawGridFrameBorder( QPainter* p, const QMap< double, double >& borderPos, Border border )
1578 {
1579  double currentCoord = - mGridFrameWidth;
1580  bool color1 = true;
1581  double x = 0;
1582  double y = 0;
1583  double width = 0;
1584  double height = 0;
1585 
1586  QMap< double, double > pos = borderPos;
1587  pos.insert( 0, 0 );
1588  if ( border == Left || border == Right )
1589  {
1590  pos.insert( rect().height(), rect().height() );
1591  pos.insert( rect().height() + mGridFrameWidth, rect().height() + mGridFrameWidth );
1592  }
1593  else //top or bottom
1594  {
1595  pos.insert( rect().width(), rect().width() );
1596  pos.insert( rect().width() + mGridFrameWidth, rect().width() + mGridFrameWidth );
1597  }
1598 
1599  //set pen to current frame pen
1600  QPen framePen = QPen( mGridFramePenColor );
1601  framePen.setWidthF( mGridFramePenThickness );
1602  framePen.setJoinStyle( Qt::MiterJoin );
1603  p->setPen( framePen );
1604 
1605  QMap< double, double >::const_iterator posIt = pos.constBegin();
1606  for ( ; posIt != pos.constEnd(); ++posIt )
1607  {
1608  p->setBrush( QBrush( color1 ? mGridFrameFillColor1 : mGridFrameFillColor2 ) );
1609  if ( border == Left || border == Right )
1610  {
1611  height = posIt.key() - currentCoord;
1612  width = mGridFrameWidth;
1613  x = ( border == Left ) ? -mGridFrameWidth : rect().width();
1614  y = currentCoord;
1615  }
1616  else //top or bottom
1617  {
1618  height = mGridFrameWidth;
1619  width = posIt.key() - currentCoord;
1620  x = currentCoord;
1621  y = ( border == Top ) ? -mGridFrameWidth : rect().height();
1622  }
1623  p->drawRect( QRectF( x, y, width, height ) );
1624  currentCoord = posIt.key();
1625  color1 = !color1;
1626  }
1627 }
1628 
1629 void QgsComposerMap::drawCoordinateAnnotations( QPainter* p, const QList< QPair< double, QLineF > >& hLines, const QList< QPair< double, QLineF > >& vLines )
1630 {
1631  if ( !p )
1632  {
1633  return;
1634  }
1635 
1636 
1637  QString currentAnnotationString;
1638  QList< QPair< double, QLineF > >::const_iterator it = hLines.constBegin();
1639  for ( ; it != hLines.constEnd(); ++it )
1640  {
1641  currentAnnotationString = gridAnnotationString( it->first, Latitude );
1642  drawCoordinateAnnotation( p, it->second.p1(), currentAnnotationString );
1643  drawCoordinateAnnotation( p, it->second.p2(), currentAnnotationString );
1644  }
1645 
1646  it = vLines.constBegin();
1647  for ( ; it != vLines.constEnd(); ++it )
1648  {
1649  currentAnnotationString = gridAnnotationString( it->first, Longitude );
1650  drawCoordinateAnnotation( p, it->second.p1(), currentAnnotationString );
1651  drawCoordinateAnnotation( p, it->second.p2(), currentAnnotationString );
1652  }
1653 }
1654 
1655 void QgsComposerMap::drawCoordinateAnnotation( QPainter* p, const QPointF& pos, QString annotationString )
1656 {
1657  Border frameBorder = borderForLineCoord( pos );
1658  double textWidth = textWidthMillimeters( mGridAnnotationFont, annotationString );
1659  //relevant for annotations is the height of digits
1660  double textHeight = fontHeightCharacterMM( mGridAnnotationFont, QChar( '0' ) );
1661  double xpos = pos.x();
1662  double ypos = pos.y();
1663  int rotation = 0;
1664 
1665  double gridFrameDistance = ( mGridFrameStyle == NoGridFrame ) ? 0 : mGridFrameWidth + ( mGridFramePenThickness / 2.0 );
1666 
1667  if ( frameBorder == Left )
1668  {
1669 
1671  {
1673  {
1674  xpos += textHeight + mAnnotationFrameDistance;
1675  ypos += textWidth / 2.0;
1676  rotation = 270;
1677  }
1678  else
1679  {
1680  xpos += mAnnotationFrameDistance;
1681  ypos += textHeight / 2.0;
1682  }
1683  }
1684  else if ( mLeftGridAnnotationPosition == OutsideMapFrame ) //Outside map frame
1685  {
1687  {
1688  xpos -= ( mAnnotationFrameDistance + gridFrameDistance );
1689  ypos += textWidth / 2.0;
1690  rotation = 270;
1691  }
1692  else
1693  {
1694  xpos -= ( textWidth + mAnnotationFrameDistance + gridFrameDistance );
1695  ypos += textHeight / 2.0;
1696  }
1697  }
1698  else
1699  {
1700  return;
1701  }
1702 
1703  }
1704  else if ( frameBorder == Right )
1705  {
1707  {
1709  {
1710  xpos -= mAnnotationFrameDistance;
1711  ypos += textWidth / 2.0;
1712  rotation = 270;
1713  }
1714  else
1715  {
1716  xpos -= textWidth + mAnnotationFrameDistance;
1717  ypos += textHeight / 2.0;
1718  }
1719  }
1720  else if ( mRightGridAnnotationPosition == OutsideMapFrame )//OutsideMapFrame
1721  {
1723  {
1724  xpos += ( textHeight + mAnnotationFrameDistance + gridFrameDistance );
1725  ypos += textWidth / 2.0;
1726  rotation = 270;
1727  }
1728  else //Horizontal
1729  {
1730  xpos += ( mAnnotationFrameDistance + gridFrameDistance );
1731  ypos += textHeight / 2.0;
1732  }
1733  }
1734  else
1735  {
1736  return;
1737  }
1738  }
1739  else if ( frameBorder == Bottom )
1740  {
1742  {
1744  {
1745  ypos -= mAnnotationFrameDistance;
1746  xpos -= textWidth / 2.0;
1747  }
1748  else //Vertical
1749  {
1750  xpos += textHeight / 2.0;
1751  ypos -= mAnnotationFrameDistance;
1752  rotation = 270;
1753  }
1754  }
1755  else if ( mBottomGridAnnotationPosition == OutsideMapFrame ) //OutsideMapFrame
1756  {
1758  {
1759  ypos += ( mAnnotationFrameDistance + textHeight + gridFrameDistance );
1760  xpos -= textWidth / 2.0;
1761  }
1762  else //Vertical
1763  {
1764  xpos += textHeight / 2.0;
1765  ypos += ( textWidth + mAnnotationFrameDistance + gridFrameDistance );
1766  rotation = 270;
1767  }
1768  }
1769  else
1770  {
1771  return;
1772  }
1773  }
1774  else //Top
1775  {
1777  {
1779  {
1780  xpos -= textWidth / 2.0;
1781  ypos += textHeight + mAnnotationFrameDistance;
1782  }
1783  else //Vertical
1784  {
1785  xpos += textHeight / 2.0;
1786  ypos += textWidth + mAnnotationFrameDistance;
1787  rotation = 270;
1788  }
1789  }
1790  else if ( mTopGridAnnotationPosition == OutsideMapFrame ) //OutsideMapFrame
1791  {
1793  {
1794  xpos -= textWidth / 2.0;
1795  ypos -= ( mAnnotationFrameDistance + gridFrameDistance );
1796  }
1797  else //Vertical
1798  {
1799  xpos += textHeight / 2.0;
1800  ypos -= ( mAnnotationFrameDistance + gridFrameDistance );
1801  rotation = 270;
1802  }
1803  }
1804  else
1805  {
1806  return;
1807  }
1808  }
1809 
1810  drawAnnotation( p, QPointF( xpos, ypos ), rotation, annotationString );
1811 }
1812 
1813 void QgsComposerMap::drawAnnotation( QPainter* p, const QPointF& pos, int rotation, const QString& annotationText )
1814 {
1815  p->save();
1816  p->translate( pos );
1817  p->rotate( rotation );
1818  p->setPen( QPen( QColor( mGridAnnotationFontColor ) ) );
1819  drawText( p, 0, 0, annotationText, mGridAnnotationFont );
1820  p->restore();
1821 }
1822 
1824 {
1825  if ( mGridAnnotationFormat == Decimal )
1826  {
1827  return QString::number( value, 'f', mGridAnnotationPrecision );
1828  }
1829 
1830  QgsPoint p;
1831  p.setX( coord == Longitude ? value : 0 );
1832  p.setY( coord == Longitude ? 0 : value );
1833 
1834  QString annotationString;
1836  {
1837  annotationString = p.toDegreesMinutes( mGridAnnotationPrecision );
1838  }
1839  else //DegreeMinuteSecond
1840  {
1841  annotationString = p.toDegreesMinutesSeconds( mGridAnnotationPrecision );
1842  }
1843 
1844  QStringList split = annotationString.split( "," );
1845  if ( coord == Longitude )
1846  {
1847  return split.at( 0 );
1848  }
1849  else
1850  {
1851  if ( split.size() < 2 )
1852  {
1853  return "";
1854  }
1855  return split.at( 1 );
1856  }
1857 }
1858 
1859 int QgsComposerMap::xGridLines( QList< QPair< double, QLineF > >& lines ) const
1860 {
1861  lines.clear();
1862  if ( mGridIntervalY <= 0.0 )
1863  {
1864  return 1;
1865  }
1866 
1867 
1868  QPolygonF mapPolygon = transformedMapPolygon();
1869  QRectF mapBoundingRect = mapPolygon.boundingRect();
1870 
1871  //consider to round up to the next step in case the left boundary is > 0
1872  double roundCorrection = mapBoundingRect.top() > 0 ? 1.0 : 0.0;
1873  double currentLevel = ( int )(( mapBoundingRect.top() - mGridOffsetY ) / mGridIntervalY + roundCorrection ) * mGridIntervalY + mGridOffsetY;
1874 
1875  if ( qgsDoubleNear( mMapRotation, 0.0 ) )
1876  {
1877  //no rotation. Do it 'the easy way'
1878 
1879  double yCanvasCoord;
1880 
1881  while ( currentLevel <= mapBoundingRect.bottom() )
1882  {
1883  yCanvasCoord = rect().height() * ( 1 - ( currentLevel - mapBoundingRect.top() ) / mapBoundingRect.height() );
1884  lines.push_back( qMakePair( currentLevel, QLineF( 0, yCanvasCoord, rect().width(), yCanvasCoord ) ) );
1885  currentLevel += mGridIntervalY;
1886  }
1887  }
1888 
1889  //the four border lines
1890  QVector<QLineF> borderLines;
1891  borderLines << QLineF( mapPolygon.at( 0 ), mapPolygon.at( 1 ) );
1892  borderLines << QLineF( mapPolygon.at( 1 ), mapPolygon.at( 2 ) );
1893  borderLines << QLineF( mapPolygon.at( 2 ), mapPolygon.at( 3 ) );
1894  borderLines << QLineF( mapPolygon.at( 3 ), mapPolygon.at( 0 ) );
1895 
1896  QList<QPointF> intersectionList; //intersects between border lines and grid lines
1897 
1898  while ( currentLevel <= mapBoundingRect.bottom() )
1899  {
1900  intersectionList.clear();
1901  QLineF gridLine( mapBoundingRect.left(), currentLevel, mapBoundingRect.right(), currentLevel );
1902 
1903  QVector<QLineF>::const_iterator it = borderLines.constBegin();
1904  for ( ; it != borderLines.constEnd(); ++it )
1905  {
1906  QPointF intersectionPoint;
1907  if ( it->intersect( gridLine, &intersectionPoint ) == QLineF::BoundedIntersection )
1908  {
1909  intersectionList.push_back( intersectionPoint );
1910  if ( intersectionList.size() >= 2 )
1911  {
1912  break; //we already have two intersections, skip further tests
1913  }
1914  }
1915  }
1916 
1917  if ( intersectionList.size() >= 2 )
1918  {
1919  lines.push_back( qMakePair( currentLevel, QLineF( mapToItemCoords( intersectionList.at( 0 ) ), mapToItemCoords( intersectionList.at( 1 ) ) ) ) );
1920  }
1921  currentLevel += mGridIntervalY;
1922  }
1923 
1924 
1925  return 0;
1926 }
1927 
1928 int QgsComposerMap::yGridLines( QList< QPair< double, QLineF > >& lines ) const
1929 {
1930  lines.clear();
1931  if ( mGridIntervalX <= 0.0 )
1932  {
1933  return 1;
1934  }
1935 
1936  QPolygonF mapPolygon = transformedMapPolygon();
1937  QRectF mapBoundingRect = mapPolygon.boundingRect();
1938 
1939  //consider to round up to the next step in case the left boundary is > 0
1940  double roundCorrection = mapBoundingRect.left() > 0 ? 1.0 : 0.0;
1941  double currentLevel = ( int )(( mapBoundingRect.left() - mGridOffsetX ) / mGridIntervalX + roundCorrection ) * mGridIntervalX + mGridOffsetX;
1942 
1943  if ( qgsDoubleNear( mMapRotation, 0.0 ) )
1944  {
1945  //no rotation. Do it 'the easy way'
1946  double xCanvasCoord;
1947 
1948  while ( currentLevel <= mapBoundingRect.right() )
1949  {
1950  xCanvasCoord = rect().width() * ( currentLevel - mapBoundingRect.left() ) / mapBoundingRect.width();
1951  lines.push_back( qMakePair( currentLevel, QLineF( xCanvasCoord, 0, xCanvasCoord, rect().height() ) ) );
1952  currentLevel += mGridIntervalX;
1953  }
1954  }
1955 
1956  //the four border lines
1957  QVector<QLineF> borderLines;
1958  borderLines << QLineF( mapPolygon.at( 0 ), mapPolygon.at( 1 ) );
1959  borderLines << QLineF( mapPolygon.at( 1 ), mapPolygon.at( 2 ) );
1960  borderLines << QLineF( mapPolygon.at( 2 ), mapPolygon.at( 3 ) );
1961  borderLines << QLineF( mapPolygon.at( 3 ), mapPolygon.at( 0 ) );
1962 
1963  QList<QPointF> intersectionList; //intersects between border lines and grid lines
1964 
1965  while ( currentLevel <= mapBoundingRect.right() )
1966  {
1967  intersectionList.clear();
1968  QLineF gridLine( currentLevel, mapBoundingRect.bottom(), currentLevel, mapBoundingRect.top() );
1969 
1970  QVector<QLineF>::const_iterator it = borderLines.constBegin();
1971  for ( ; it != borderLines.constEnd(); ++it )
1972  {
1973  QPointF intersectionPoint;
1974  if ( it->intersect( gridLine, &intersectionPoint ) == QLineF::BoundedIntersection )
1975  {
1976  intersectionList.push_back( intersectionPoint );
1977  if ( intersectionList.size() >= 2 )
1978  {
1979  break; //we already have two intersections, skip further tests
1980  }
1981  }
1982  }
1983 
1984  if ( intersectionList.size() >= 2 )
1985  {
1986  lines.push_back( qMakePair( currentLevel, QLineF( mapToItemCoords( intersectionList.at( 0 ) ), mapToItemCoords( intersectionList.at( 1 ) ) ) ) );
1987  }
1988  currentLevel += mGridIntervalX;
1989  }
1990 
1991  return 0;
1992 }
1993 
1995 {
1996  if ( mGridLineSymbol )
1997  {
1998  mGridLineSymbol->setWidth( w );
1999  }
2000 }
2001 
2002 void QgsComposerMap::setGridPenColor( const QColor& c )
2003 {
2004  if ( mGridLineSymbol )
2005  {
2006  mGridLineSymbol->setColor( c );
2007  }
2008 }
2009 
2010 void QgsComposerMap::setGridPen( const QPen& p )
2011 {
2012  setGridPenWidth( p.widthF() );
2013  setGridPenColor( p.color() );
2014 }
2015 
2017 {
2018  QPen p;
2019  if ( mGridLineSymbol )
2020  {
2021  p.setWidthF( mGridLineSymbol->width() );
2022  p.setColor( mGridLineSymbol->color() );
2023  p.setCapStyle( Qt::FlatCap );
2024  }
2025  return p;
2026 }
2027 
2028 void QgsComposerMap::setGridBlendMode( QPainter::CompositionMode blendMode )
2029 {
2031  update();
2032 }
2033 
2035 {
2036  return mCurrentRectangle;
2037 }
2038 
2040 {
2041  QRectF rectangle = rect();
2042  double extension = maxExtension();
2043  rectangle.setLeft( rectangle.left() - extension );
2044  rectangle.setRight( rectangle.right() + extension );
2045  rectangle.setTop( rectangle.top() - extension );
2046  rectangle.setBottom( rectangle.bottom() + extension );
2047  if ( rectangle != mCurrentRectangle )
2048  {
2049  prepareGeometryChange();
2050  mCurrentRectangle = rectangle;
2051  }
2052 }
2053 
2055 {
2056  QgsComposerItem::setFrameOutlineWidth( outlineWidth );
2058 }
2059 
2061 {
2062  double dx = mXOffset;
2063  double dy = mYOffset;
2064  transformShift( dx, dy );
2065  return QgsRectangle( currentMapExtent()->xMinimum() - dx, currentMapExtent()->yMinimum() - dy, currentMapExtent()->xMaximum() - dx, currentMapExtent()->yMaximum() - dy );
2066 }
2067 
2069 {
2070  double dx = mXOffset;
2071  double dy = mYOffset;
2072  //qWarning("offset");
2073  //qWarning(QString::number(dx).toLocal8Bit().data());
2074  //qWarning(QString::number(dy).toLocal8Bit().data());
2075  transformShift( dx, dy );
2076  //qWarning("transformed:");
2077  //qWarning(QString::number(dx).toLocal8Bit().data());
2078  //qWarning(QString::number(dy).toLocal8Bit().data());
2079  QPolygonF poly = visibleExtentPolygon();
2080  poly.translate( -dx, -dy );
2081  return poly;
2082 }
2083 
2085 {
2086  double frameExtension = mFrame ? pen().widthF() / 2.0 : 0.0;
2089  {
2090  return frameExtension;
2091  }
2092 
2093  QList< QPair< double, QLineF > > xLines;
2094  QList< QPair< double, QLineF > > yLines;
2095 
2096  int xGridReturn = xGridLines( xLines );
2097  int yGridReturn = yGridLines( yLines );
2098 
2099  if ( xGridReturn != 0 && yGridReturn != 0 )
2100  {
2101  return frameExtension;
2102  }
2103 
2104  double maxExtension = 0;
2105  double currentExtension = 0;
2106  QString currentAnnotationString;
2107 
2108  QList< QPair< double, QLineF > >::const_iterator it = xLines.constBegin();
2109  for ( ; it != xLines.constEnd(); ++it )
2110  {
2111  currentAnnotationString = gridAnnotationString( it->first, Latitude );
2112  currentExtension = qMax( textWidthMillimeters( mGridAnnotationFont, currentAnnotationString ), fontAscentMillimeters( mGridAnnotationFont ) );
2113  maxExtension = qMax( maxExtension, currentExtension );
2114  }
2115 
2116  it = yLines.constBegin();
2117  for ( ; it != yLines.constEnd(); ++it )
2118  {
2119  currentAnnotationString = gridAnnotationString( it->first, Longitude );
2120  currentExtension = qMax( textWidthMillimeters( mGridAnnotationFont, currentAnnotationString ), fontAscentMillimeters( mGridAnnotationFont ) );
2121  maxExtension = qMax( maxExtension, currentExtension );
2122  }
2123 
2124  //grid frame
2125  double gridFrameDist = ( mGridFrameStyle == NoGridFrame ) ? 0 : mGridFrameWidth + ( mGridFramePenThickness / 2.0 );
2126  return qMax( frameExtension, maxExtension + mAnnotationFrameDistance + gridFrameDist );
2127 }
2128 
2129 void QgsComposerMap::mapPolygon( const QgsRectangle& extent, QPolygonF& poly ) const
2130 {
2131  poly.clear();
2132  if ( mMapRotation == 0 )
2133  {
2134  poly << QPointF( extent.xMinimum(), extent.yMaximum() );
2135  poly << QPointF( extent.xMaximum(), extent.yMaximum() );
2136  poly << QPointF( extent.xMaximum(), extent.yMinimum() );
2137  poly << QPointF( extent.xMinimum(), extent.yMinimum() );
2138  return;
2139  }
2140 
2141  //there is rotation
2142  QgsPoint rotationPoint(( extent.xMaximum() + extent.xMinimum() ) / 2.0, ( extent.yMaximum() + extent.yMinimum() ) / 2.0 );
2143  double dx, dy; //x-, y- shift from rotation point to corner point
2144 
2145  //top left point
2146  dx = rotationPoint.x() - extent.xMinimum();
2147  dy = rotationPoint.y() - extent.yMaximum();
2148  rotate( mMapRotation, dx, dy );
2149  poly << QPointF( rotationPoint.x() - dx, rotationPoint.y() - dy );
2150 
2151  //top right point
2152  dx = rotationPoint.x() - extent.xMaximum();
2153  dy = rotationPoint.y() - extent.yMaximum();
2154  rotate( mMapRotation, dx, dy );
2155  poly << QPointF( rotationPoint.x() - dx, rotationPoint.y() - dy );
2156 
2157  //bottom right point
2158  dx = rotationPoint.x() - extent.xMaximum();
2159  dy = rotationPoint.y() - extent.yMinimum();
2160  rotate( mMapRotation, dx, dy );
2161  poly << QPointF( rotationPoint.x() - dx, rotationPoint.y() - dy );
2162 
2163  //bottom left point
2164  dx = rotationPoint.x() - extent.xMinimum();
2165  dy = rotationPoint.y() - extent.yMinimum();
2166  rotate( mMapRotation, dx, dy );
2167  poly << QPointF( rotationPoint.x() - dx, rotationPoint.y() - dy );
2168 }
2169 
2171 {
2172  QPolygonF poly;
2173  mapPolygon( *currentMapExtent(), poly );
2174  return poly;
2175 }
2176 
2178 {
2179  QgsRectangle newExtent = *currentMapExtent();
2180  if ( mMapRotation == 0 )
2181  {
2182  extent = newExtent;
2183  }
2184  else
2185  {
2186  QPolygonF poly;
2187  mapPolygon( newExtent, poly );
2188  QRectF bRect = poly.boundingRect();
2189  extent.setXMinimum( bRect.left() );
2190  extent.setXMaximum( bRect.right() );
2191  extent.setYMinimum( bRect.top() );
2192  extent.setYMaximum( bRect.bottom() );
2193  }
2194 }
2195 
2197 {
2198  double extentWidth = currentMapExtent()->width();
2199  if ( extentWidth <= 0 )
2200  {
2201  return 1;
2202  }
2203  return rect().width() / extentWidth;
2204 }
2205 
2207 {
2208  if ( mOverviewFrameMapId != -1 )
2209  {
2210  const QgsComposerMap* map = mComposition->getComposerMapById( mapId );
2211  if ( map )
2212  {
2213  QObject::disconnect( map, SIGNAL( extentChanged() ), this, SLOT( overviewExtentChanged() ) );
2214  }
2215  }
2216  mOverviewFrameMapId = mapId;
2217  if ( mOverviewFrameMapId != -1 )
2218  {
2219  const QgsComposerMap* map = mComposition->getComposerMapById( mapId );
2220  if ( map )
2221  {
2222  QObject::connect( map, SIGNAL( extentChanged() ), this, SLOT( overviewExtentChanged() ) );
2223  }
2224  }
2225  update();
2226 }
2227 
2229 {
2230  //if using overview centering, update the map's extent
2231  if ( mOverviewCentered && mOverviewFrameMapId != -1 )
2232  {
2234 
2235  const QgsComposerMap* overviewFrameMap = mComposition->getComposerMapById( mOverviewFrameMapId );
2236  QgsRectangle otherExtent = *overviewFrameMap->currentMapExtent();
2237 
2238  QgsPoint center = otherExtent.center();
2239  QgsRectangle movedExtent( center.x() - currentMapExtent()->width() / 2,
2240  center.y() - currentMapExtent()->height() / 2,
2241  center.x() - currentMapExtent()->width() / 2 + currentMapExtent()->width(),
2242  center.y() - currentMapExtent()->height() / 2 + currentMapExtent()->height() );
2243  *currentMapExtent() = movedExtent;
2244 
2245  emit itemChanged();
2246  emit extentChanged();
2247  }
2248 
2249  //redraw so that overview gets updated
2250  cache();
2251  update();
2252 }
2253 
2254 
2256 {
2257  delete mOverviewFrameMapSymbol;
2258  mOverviewFrameMapSymbol = symbol;
2259 }
2260 
2261 void QgsComposerMap::setOverviewBlendMode( QPainter::CompositionMode blendMode )
2262 {
2264  update();
2265 }
2266 
2268 {
2269  mOverviewInverted = inverted;
2270  update();
2271 }
2272 
2274 {
2275  mOverviewCentered = centered;
2277 }
2278 
2280 {
2281  delete mGridLineSymbol;
2282  mGridLineSymbol = symbol;
2283 }
2284 
2285 void QgsComposerMap::transformShift( double& xShift, double& yShift ) const
2286 {
2287  double mmToMapUnits = 1.0 / mapUnitsToMM();
2288  double dxScaled = xShift * mmToMapUnits;
2289  double dyScaled = - yShift * mmToMapUnits;
2290 
2291  rotate( mMapRotation, dxScaled, dyScaled );
2292 
2293  xShift = dxScaled;
2294  yShift = dyScaled;
2295 }
2296 
2297 QPointF QgsComposerMap::mapToItemCoords( const QPointF& mapCoords ) const
2298 {
2299  QPolygonF mapPoly = transformedMapPolygon();
2300  if ( mapPoly.size() < 1 )
2301  {
2302  return QPointF( 0, 0 );
2303  }
2304 
2305  QgsRectangle tExtent = transformedExtent();
2306  QgsPoint rotationPoint(( tExtent.xMaximum() + tExtent.xMinimum() ) / 2.0, ( tExtent.yMaximum() + tExtent.yMinimum() ) / 2.0 );
2307  double dx = mapCoords.x() - rotationPoint.x();
2308  double dy = mapCoords.y() - rotationPoint.y();
2309  rotate( -mMapRotation, dx, dy );
2310  QgsPoint backRotatedCoords( rotationPoint.x() + dx, rotationPoint.y() + dy );
2311 
2312  QgsRectangle unrotatedExtent = transformedExtent();
2313  double xItem = rect().width() * ( backRotatedCoords.x() - unrotatedExtent.xMinimum() ) / unrotatedExtent.width();
2314  double yItem = rect().height() * ( 1 - ( backRotatedCoords.y() - unrotatedExtent.yMinimum() ) / unrotatedExtent.height() );
2315  return QPointF( xItem, yItem );
2316 }
2317 
2319 {
2320  if ( p.x() <= pen().widthF() )
2321  {
2322  return Left;
2323  }
2324  else if ( p.x() >= ( rect().width() - pen().widthF() ) )
2325  {
2326  return Right;
2327  }
2328  else if ( p.y() <= pen().widthF() )
2329  {
2330  return Top;
2331  }
2332  else
2333  {
2334  return Bottom;
2335  }
2336 }
2337 
2338 void QgsComposerMap::drawCanvasItems( QPainter* painter, const QStyleOptionGraphicsItem* itemStyle )
2339 {
2340  if ( !mMapCanvas || !mDrawCanvasItems )
2341  {
2342  return;
2343  }
2344 
2345  QList<QGraphicsItem*> itemList = mMapCanvas->items();
2346  if ( itemList.size() < 1 )
2347  {
2348  return;
2349  }
2350  QGraphicsItem* currentItem = 0;
2351 
2352  for ( int i = itemList.size() - 1; i >= 0; --i )
2353  {
2354  currentItem = itemList.at( i );
2355  //don't draw mapcanvasmap (has z value -10)
2356  if ( !currentItem || currentItem->data( 0 ).toString() != "AnnotationItem" )
2357  {
2358  continue;
2359  }
2360  drawCanvasItem( currentItem, painter, itemStyle );
2361  }
2362 }
2363 
2364 void QgsComposerMap::drawCanvasItem( QGraphicsItem* item, QPainter* painter, const QStyleOptionGraphicsItem* itemStyle )
2365 {
2366  if ( !item || !mMapCanvas || !item->isVisible() )
2367  {
2368  return;
2369  }
2370 
2371  painter->save();
2372 
2373  //determine scale factor according to graphics view dpi
2374  double scaleFactor = 1.0 / mMapCanvas->logicalDpiX() * 25.4;
2375 
2376  double itemX, itemY;
2377  QGraphicsItem* parent = item->parentItem();
2378  if ( !parent )
2379  {
2380  QPointF mapPos = composerMapPosForItem( item );
2381  itemX = mapPos.x();
2382  itemY = mapPos.y();
2383  }
2384  else //place item relative to the parent item
2385  {
2386  QPointF itemScenePos = item->scenePos();
2387  QPointF parentScenePos = parent->scenePos();
2388 
2389  QPointF mapPos = composerMapPosForItem( parent );
2390 
2391  itemX = mapPos.x() + ( itemScenePos.x() - parentScenePos.x() ) * scaleFactor;
2392  itemY = mapPos.y() + ( itemScenePos.y() - parentScenePos.y() ) * scaleFactor;
2393  }
2394  painter->translate( itemX, itemY );
2395 
2396 
2397  painter->scale( scaleFactor, scaleFactor );
2398 
2399  //a little trick to let the item know that the paint request comes from the composer
2400  item->setData( 1, "composer" );
2401  item->paint( painter, itemStyle, 0 );
2402  item->setData( 1, "" );
2403  painter->restore();
2404 }
2405 
2406 QPointF QgsComposerMap::composerMapPosForItem( const QGraphicsItem* item ) const
2407 {
2408  if ( !item || !mMapCanvas )
2409  {
2410  return QPointF( 0, 0 );
2411  }
2412 
2413  if ( currentMapExtent()->height() <= 0 || currentMapExtent()->width() <= 0 || mMapCanvas->width() <= 0 || mMapCanvas->height() <= 0 )
2414  {
2415  return QPointF( 0, 0 );
2416  }
2417 
2418  QRectF graphicsSceneRect = mMapCanvas->sceneRect();
2419  QPointF itemScenePos = item->scenePos();
2420  QgsRectangle mapRendererExtent = mComposition->mapSettings().visibleExtent();
2421 
2422  double mapX = itemScenePos.x() / graphicsSceneRect.width() * mapRendererExtent.width() + mapRendererExtent.xMinimum();
2423  double mapY = mapRendererExtent.yMaximum() - itemScenePos.y() / graphicsSceneRect.height() * mapRendererExtent.height();
2424  return mapToItemCoords( QPointF( mapX, mapY ) );
2425 }
2426 
2428 {
2429  switch ( border )
2430  {
2431  case QgsComposerMap::Left:
2433  break;
2434  case QgsComposerMap::Right:
2436  break;
2437  case QgsComposerMap::Top:
2439  break;
2442  break;
2443  default:
2444  return;
2445  }
2447  update();
2448 }
2449 
2451 {
2452  switch ( border )
2453  {
2454  case QgsComposerMap::Left:
2456  break;
2457  case QgsComposerMap::Right:
2459  break;
2460  case QgsComposerMap::Top:
2462  break;
2464  default:
2466  break;
2467  }
2468 }
2469 
2471 {
2472  switch ( border )
2473  {
2474  case QgsComposerMap::Left:
2476  break;
2477  case QgsComposerMap::Right:
2479  break;
2480  case QgsComposerMap::Top:
2482  break;
2485  break;
2486  default:
2487  return;
2488  break;
2489  }
2491  update();
2492 }
2493 
2495 {
2496  switch ( border )
2497  {
2498  case QgsComposerMap::Left:
2500  break;
2501  case QgsComposerMap::Right:
2503  break;
2504  case QgsComposerMap::Top:
2506  break;
2508  default:
2510  break;
2511  }
2512 }
2513 
2514 void QgsComposerMap::sortGridLinesOnBorders( const QList< QPair< double, QLineF > >& hLines, const QList< QPair< double, QLineF > >& vLines, QMap< double, double >& leftFrameEntries,
2515  QMap< double, double >& rightFrameEntries, QMap< double, double >& topFrameEntries, QMap< double, double >& bottomFrameEntries ) const
2516 {
2517  QList< QPair< double, QPointF > > borderPositions;
2518  QList< QPair< double, QLineF > >::const_iterator it = hLines.constBegin();
2519  for ( ; it != hLines.constEnd(); ++it )
2520  {
2521  borderPositions << qMakePair( it->first, it->second.p1() );
2522  borderPositions << qMakePair( it->first, it->second.p2() );
2523  }
2524  it = vLines.constBegin();
2525  for ( ; it != vLines.constEnd(); ++it )
2526  {
2527  borderPositions << qMakePair( it->first, it->second.p1() );
2528  borderPositions << qMakePair( it->first, it->second.p2() );
2529  }
2530 
2531  QList< QPair< double, QPointF > >::const_iterator bIt = borderPositions.constBegin();
2532  for ( ; bIt != borderPositions.constEnd(); ++bIt )
2533  {
2534  Border frameBorder = borderForLineCoord( bIt->second );
2535  if ( frameBorder == QgsComposerMap::Left )
2536  {
2537  leftFrameEntries.insert( bIt->second.y(), bIt->first );
2538  }
2539  else if ( frameBorder == QgsComposerMap::Right )
2540  {
2541  rightFrameEntries.insert( bIt->second.y(), bIt->first );
2542  }
2543  else if ( frameBorder == QgsComposerMap::Top )
2544  {
2545  topFrameEntries.insert( bIt->second.x(), bIt->first );
2546  }
2547  else //Bottom
2548  {
2549  bottomFrameEntries.insert( bIt->second.x(), bIt->first );
2550  }
2551  }
2552 }
2553 
2555 {
2556  if ( mOverviewFrameMapId == -1 || !mComposition )
2557  {
2558  return;
2559  }
2560 
2562  {
2563  //if map item is set to rectangle preview mode and we are not exporting the composition
2564  //then don't draw an overview rectangle
2565  return;
2566  }
2567 
2568  const QgsComposerMap* overviewFrameMap = mComposition->getComposerMapById( mOverviewFrameMapId );
2569  if ( !overviewFrameMap )
2570  {
2571  return;
2572  }
2573 
2574  //get polygon for other overview frame map's extent (use visibleExtentPolygon as it accounts for map rotation)
2575  QPolygonF otherExtent = overviewFrameMap->visibleExtentPolygon();
2576 
2577  //get current map's extent as a QPolygonF
2578  QPolygonF thisExtent = visibleExtentPolygon();
2579  //intersect the two
2580  QPolygonF intersectExtent = thisExtent.intersected( otherExtent );
2581 
2582  //setup painter scaling to dots so that raster symbology is drawn to scale
2583  double dotsPerMM = p->device()->logicalDpiX() / 25.4;
2584 
2585  //setup render context
2587  //context units should be in dots
2588  ms.setOutputSize( QSizeF( rect().width() * dotsPerMM, rect().height() * dotsPerMM ).toSize() );
2589  ms.setExtent( *currentMapExtent() );
2590  ms.setOutputDpi( p->device()->logicalDpiX() );
2592  context.setForceVectorOutput( true );
2593  context.setPainter( p );
2594 
2595  p->save();
2596  p->setCompositionMode( mOverviewBlendMode );
2597  p->translate( mXOffset, mYOffset );
2598  p->scale( 1 / dotsPerMM, 1 / dotsPerMM ); // scale painter from mm to dots
2599  p->setRenderHint( QPainter::Antialiasing );
2600 
2602 
2603  //construct a polygon corresponding to the intersecting map extent
2604  //need to scale line to dots, rather then mm, since the painter has been scaled to dots
2605  QTransform mapTransform;
2606  QPolygonF thisRectPoly = QPolygonF( QRectF( 0, 0, dotsPerMM * rect().width(), dotsPerMM * rect().height() ) );
2607 
2608  //workaround QT Bug #21329
2609  thisRectPoly.pop_back();
2610  //create transform from map coordinates to painter coordinates
2611  QTransform::quadToQuad( thisExtent, thisRectPoly, mapTransform );
2612  QPolygonF intersectPolygon;
2613  intersectPolygon = mapTransform.map( intersectExtent );
2614 
2615  QList<QPolygonF> rings; //empty list
2616  if ( !mOverviewInverted )
2617  {
2618  //Render the intersecting map extent
2619  mOverviewFrameMapSymbol->renderPolygon( intersectPolygon, &rings, 0, context );;
2620  }
2621  else
2622  {
2623  //We are inverting the overview frame (ie, shading outside the intersecting extent)
2624  //Construct a polygon corresponding to the overview map extent
2625  QPolygonF outerPolygon;
2626  outerPolygon << QPointF( 0, 0 ) << QPointF( rect().width() * dotsPerMM, 0 ) << QPointF( rect().width() * dotsPerMM, rect().height() * dotsPerMM ) << QPointF( 0, rect().height() * dotsPerMM ) << QPointF( 0, 0 );
2627 
2628  //Intersecting extent is an inner ring for the shaded area
2629  rings.append( intersectPolygon );
2630  mOverviewFrameMapSymbol->renderPolygon( outerPolygon, &rings, 0, context );
2631  }
2632 
2633  mOverviewFrameMapSymbol->stopRender( context );
2634  p->restore();
2635 }
2636 
2638 {
2639  delete mOverviewFrameMapSymbol;
2640  QgsStringMap properties;
2641  properties.insert( "color", "255,0,0,255" );
2642  properties.insert( "style", "solid" );
2643  properties.insert( "style_border", "no" );
2646 }
2647 
2649 {
2650  delete mGridLineSymbol;
2651  QgsStringMap properties;
2652  properties.insert( "color", "0,0,0,255" );
2653  properties.insert( "width", "0.3" );
2654  properties.insert( "capstyle", "flat" );
2656 }
2657 
2659 {
2660  QString format = QgsProject::instance()->readEntry( "PositionPrecision", "/DegreeFormat", "D" );
2661 
2662  bool degreeUnits = ( mComposition->mapSettings().mapUnits() == QGis::Degrees );
2663 
2664  if ( format == "DM" && degreeUnits )
2665  {
2667  }
2668  else if ( format == "DMS" && degreeUnits )
2669  {
2671  }
2672  else
2673  {
2675  }
2676 }
2677 
2679 {
2680  if ( !mComposition )
2681  {
2682  return;
2683  }
2684 
2685  const QgsComposerMap* existingMap = mComposition->getComposerMapById( mId );
2686  if ( !existingMap )
2687  {
2688  return; //keep mId as it is still available
2689  }
2690 
2691  int maxId = -1;
2692  QList<const QgsComposerMap*> mapList = mComposition->composerMapItems();
2693  QList<const QgsComposerMap*>::const_iterator mapIt = mapList.constBegin();
2694  for ( ; mapIt != mapList.constEnd(); ++mapIt )
2695  {
2696  if (( *mapIt )->id() > maxId )
2697  {
2698  maxId = ( *mapIt )->id();
2699  }
2700  }
2701  mId = maxId + 1;
2702 }
2703 
2704 bool QgsComposerMap::imageSizeConsideringRotation( double& width, double& height ) const
2705 {
2706  //kept for api compatibility with QGIS 2.0 - use mMapRotation
2708 }
2709 
2710 bool QgsComposerMap::cornerPointOnRotatedAndScaledRect( double& x, double& y, double width, double height ) const
2711 {
2712  //kept for api compatibility with QGIS 2.0 - use mMapRotation
2714 }
2715 
2716 void QgsComposerMap::sizeChangedByRotation( double& width, double& height )
2717 {
2718  //kept for api compatibility with QGIS 2.0 - use mMapRotation
2719  return QgsComposerItem::sizeChangedByRotation( width, height, mMapRotation );
2720 }
2721 
2723 {
2724  return mAtlasScalingMode == Fixed;
2725 }
2726 
2728 {
2729  // implicit : if set to false => auto scaling
2730  mAtlasScalingMode = fixed ? Fixed : Auto;
2731 }
2732 
QString toDegreesMinutesSeconds(int thePrecision) const
Return a string representation as degrees minutes seconds.
Definition: qgspoint.cpp:137
int mOverviewFrameMapId
Id of map which displays its extent rectangle into this composer map (overview map functionality)...
double mGridFrameWidth
double mXOffset
Offset in x direction for showing map cache image.
void setMapUnits(QGis::UnitType mapUnits)
Set the map units.
void setForceVectorOutput(bool force)
Added in QGIS v1.5.
void preparedForAtlas()
Is emitted when the map has been prepared for atlas rendering, just before actual rendering...
AtlasScalingMode
Scaling modes used for the serial rendering (atlas)
QgsComposition::AtlasMode atlasMode() const
Returns the current atlas mode of the composition.
bool mGridEnabled
True if coordinate grid has to be displayed.
void draw(QPainter *painter, const QgsRectangle &extent, const QSizeF &size, double dpi, double *forceWidthScale=0)
Draw to paint device.
bool imageSizeConsideringRotation(double &width, double &height, double rotation) const
Calculates width and hight of the picture (in mm) such that it fits into the item frame with the give...
double outlineWidth
Definition: qgssvgcache.cpp:78
void setDestinationCrs(const QgsCoordinateReferenceSystem &crs)
sets destination coordinate reference system
A rectangle specified with double values.
Definition: qgsrectangle.h:35
Base class for all map layer types.
Definition: qgsmaplayer.h:47
void renderPolygon(const QPolygonF &points, QList< QPolygonF > *rings, const QgsFeature *f, QgsRenderContext &context, int layer=-1, bool selected=false)
bool mDrawing
set to true if in state of drawing.
Job implementation that renders everything sequentially using a custom painter.
double mGridIntervalY
Grid line interval in y-direction (map units)
double mMapRotation
Map rotation.
GridAnnotationDirection gridAnnotationDirection(QgsComposerMap::Border border) const
void overviewExtentChanged()
double fontHeightCharacterMM(const QFont &font, const QChar &c) const
Returns the font height of a character in millimeters.
void setOverviewCentered(bool centered)
Set the overview's centering mode.
bool containsWMSLayer() const
True if composer map renders a WMS layer.
void setXMaximum(double x)
Set the maximum x value.
Definition: qgsrectangle.h:169
double mapUnitsToMM() const
Returns the conversion factor map units -> mm.
bool hideCoverage() const
Returns true if the atlas is set to hide the coverage layer.
void assignFreeId()
Sets mId to a number not yet used in the composition.
void setNewAtlasFeatureExtent(const QgsRectangle &extent)
Sets new Extent for the current atlas preview and changes width, height (and implicitely also scale)...
void setOffset(double xOffset, double yOffset)
Sets offset values to shift image (useful for live updates when moving item content) ...
Q_DECL_DEPRECATED QgsMapRenderer * mapRenderer()
Returns pointer to map renderer of qgis map canvas.
double yMaximum() const
Get the y maximum value (top side of rectangle)
Definition: qgsrectangle.h:194
QStringList mLayerSet
Stored layer list (used if layer live-link mKeepLayerSet is disabled)
QFont mGridAnnotationFont
Font for grid line annotation.
This class provides qgis with the ability to render raster datasets onto the mapcanvas.
void setOutputDpi(int dpi)
Set DPI used for conversion between real world units (e.g. mm) and pixels.
void requestedExtent(QgsRectangle &extent) const
Calculates the extent to request and the yShift of the top-left point in case of rotation.
bool mDrawCanvasItems
True if annotation items, rubber band, etc.
QString toDegreesMinutes(int thePrecision) const
Return a string representation as degrees minutes.
Definition: qgspoint.cpp:162
void mapPolygon(const QgsRectangle &extent, QPolygonF &poly) const
mapPolygon variant using a given extent
const QgsMapSettings & mapSettings() const
Return setting of QGIS map canvas.
QPainter::CompositionMode bufferBlendMode
QStringList layerSet() const
Getter for stored layer set that is used if mKeepLayerSet is true.
double maxExtension() const
static QgsFillSymbolV2 * createSimple(const QgsStringMap &properties)
Create a fill symbol with one symbol layer: SimpleFill with specified properties. ...
void cache()
Create cache image.
Q_DECL_DEPRECATED bool imageSizeConsideringRotation(double &width, double &height) const
Calculates width and hight of the picture (in mm) such that it fits into the item frame with the give...
QList< const QgsComposerMap * > composerMapItems() const
Returns pointers to all composer maps in the scene.
A item that forms part of a map composition.
void connectUpdateSlot()
Establishes signal/slot connection for update in case of layer change.
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:439
Border
Enum for different frame borders.
QgsRectangle visibleExtent() const
Return the actual extent derived from requested extent that takes takes output image size into accoun...
void updateItem()
Updates item, with the possibility to do custom update for subclasses.
QPointF composerMapPosForItem(const QGraphicsItem *item) const
QPainter::CompositionMode mOverviewBlendMode
Blend mode for overview.
void setDpi(double dpi)
Set the dpi to be used in scale calculations.
AtlasScalingMode mAtlasScalingMode
Current atlas scaling mode.
QGraphicsView * mMapCanvas
double mLastValidViewScaleFactor
Backup to restore item appearance if no view scale factor is available.
bool hasCrsTransformEnabled() const
returns true if projections are enabled for this layer set
void mapRotationChanged(double newRotation)
Is emitted on rotation change to notify north arrow pictures.
static QgsPalLayerSettings fromLayer(QgsVectorLayer *layer)
virtual void drawFrame(QPainter *p)
Draw black frame around item.
void updateCachedImage()
Called if map canvas has changed.
Flags flags() const
Return combination of flags used for rendering.
Q_DECL_DEPRECATED bool cornerPointOnRotatedAndScaledRect(double &x, double &y, double width, double height) const
Calculates corner point after rotation and scaling.
bool readXML(const QDomElement &itemElem, const QDomDocument &doc)
sets state from Dom document
void createDefaultGridLineSymbol()
QPolygonF transformedMapPolygon() const
Returns extent that considers rotation and shift with mOffsetX / mOffsetY.
QColor backgroundColor() const
Gets the background color for this item.
A non GUI class for rendering a map layer set onto a QPainter.
void setLayers(const QStringList &layers)
Set list of layer IDs for map rendering.
Enable layer transparency and blending effects.
void initGridAnnotationFormatFromProject()
bool mShowGridAnnotation
True if coordinate values should be drawn.
void setSceneRect(const QRectF &rectangle)
Sets new scene rectangle bounds and recalculates hight and extent.
bool containsAdvancedEffects() const
True if composer map contains layers with blend modes or flattened layers for vectors.
QMap< QString, QString > QgsStringMap
Definition: qgis.h:416
int readNumEntry(const QString &scope, const QString &key, int def=0, bool *ok=0) const
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Definition: qgis.h:324
QRectF boundingRect() const
In case of annotations, the bounding rectangle can be larger than the map item rectangle.
bool mOverviewCentered
Centering mode for overview.
double x() const
Definition: qgspoint.h:110
void zoomContent(int delta, double x, double y)
Zoom content of map.
void setGridPenColor(const QColor &c)
Sets the color of the grid pen.
virtual QString name() const =0
return a provider name
void setWidth(double width)
GridFrameStyle mGridFrameStyle
Vector graphics should not be cached and drawn as raster images.
QColor mGridFrameFillColor1
QColor mGridFramePenColor
void setFlag(Flag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
int mGridAnnotationPrecision
Digits after the dot.
The QgsMapSettings class contains configuration for rendering of the map.
void itemChanged()
Used e.g.
void setNewScale(double scaleDenominator)
Sets new scale and changes only mExtent.
bool _readXML(const QDomElement &itemElem, const QDomDocument &doc)
Reads parameter that are not subclass specific in document.
static bool staticWillUseLayer(QgsVectorLayer *layer)
called to find out whether the layer is used for labeling
static QDomElement saveSymbol(QString symbolName, QgsSymbolV2 *symbol, QDomDocument &doc)
Q_DECL_DEPRECATED const QgsMapRenderer * mapRenderer() const
QgsRectangle mExtent
QgsLineSymbolV2 * mGridLineSymbol
void storeCurrentLayerSet()
Stores the current layer set of the qgis mapcanvas in mLayerSet.
GridAnnotationDirection mLeftGridAnnotationDirection
Annotation direction on left side ( horizontal or vertical )
void setColor(const QColor &color)
double mAnnotationFrameDistance
Distance between map frame and annotation.
bool shouldDrawPart(PartType part) const
Test if a part of the copmosermap needs to be drawn, considering mCurrentExportLayer.
double scale() const
Scale.
GridAnnotationDirection mRightGridAnnotationDirection
Annotation direction on right side ( horizontal or vertical )
void drawCoordinateAnnotations(QPainter *p, const QList< QPair< double, QLineF > > &hLines, const QList< QPair< double, QLineF > > &vLines)
Draw coordinates for mGridAnnotationType Coordinate.
QPainter::CompositionMode blendMode() const
Read blend mode for layer.
double horizontalViewScaleFactor() const
Returns the zoom factor of the graphics view.
QRectF mCurrentRectangle
Current bounding rectangle.
double mCrossLength
The length of the cross sides for mGridStyle Cross.
double mGridFramePenThickness
QPainter::CompositionMode featureBlendMode() const
Read blend mode for layer.
double calculate(const QgsRectangle &mapExtent, int canvasWidth)
Calculate the scale denominator.
void updateBoundingRect()
Updates the bounding rect of this item.
double mGridOffsetY
Grid line offset in y-direction.
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
Definition: qgsrectangle.h:199
void toggleAtlasPreview()
Called when atlas preview is toggled, to force map item to update its extent and redraw.
double xMaximum() const
Get the x maximum value (right side of rectangle)
Definition: qgsrectangle.h:184
virtual void updateItem()
Updates item, with the possibility to do custom update for subclasses.
void drawOverviewMapExtent(QPainter *p)
void startRender(QgsRenderContext &context, const QgsFields *fields=0)
virtual void drawSelectionBoxes(QPainter *p)
Draw selection boxes around item.
double textWidthMillimeters(const QFont &font, const QString &text) const
Returns the font width in millimeters (considers upscaling and downscaling with FONT_WORKAROUND_SCALE...
static QgsLineSymbolV2 * createSimple(const QgsStringMap &properties)
Create a line symbol with one symbol layer: SimpleLine with specified properties. ...
void rotate(double angle, double &x, double &y) const
Rotates a point / vector.
QPainter::CompositionMode blendMode
QString gridAnnotationString(double value, AnnotationCoordinate coord) const
bool mFrame
True if item fram needs to be painted.
bool writeXML(QDomElement &elem, QDomDocument &doc) const
stores state in Dom node
Whether vector selections should be shown in the rendered map.
void setMapUnits(QGis::UnitType u)
Set units of map's geographical coordinates - used for scale calculation.
bool drawCanvasItems() const
void setCacheUpdated(bool u=false)
const QgsCoordinateReferenceSystem & destinationCrs() const
returns CRS of destination coordinate reference system
void setYMinimum(double y)
Set the minimum y value.
Definition: qgsrectangle.h:174
int yGridLines(QList< QPair< double, QLineF > > &lines) const
Returns the grid lines for the y-coordinates.
double mYOffset
Offset in y direction for showing map cache image.
void renderPolyline(const QPolygonF &points, const QgsFeature *f, QgsRenderContext &context, int layer=-1, bool selected=false)
virtual void setFrameOutlineWidth(double outlineWidth)
Sets frame outline width.
QColor mGridFrameFillColor2
void drawAnnotation(QPainter *p, const QPointF &pos, int rotation, const QString &annotationText)
Draws a single annotation.
void setNewExtent(const QgsRectangle &extent)
Sets new Extent and changes width, height (and implicitely also scale)
void setGridPen(const QPen &p)
Sets the pen to draw composer grid.
void setPainter(QPainter *p)
void moveContent(double dx, double dy)
Move content of map.
QString id() const
Get this layer's unique ID, this ID is used to access this layer from map layer registry.
Definition: qgsmaplayer.cpp:92
Q_DECL_DEPRECATED bool atlasFixedScale() const
Returns true if the map uses a fixed scale when in atlas mode.
QGis::UnitType mapUnits() const
Get units of map's geographical coordinates - used for scale calculation.
void drawText(QPainter *p, double x, double y, const QString &text, const QFont &font) const
Draws Text.
void drawGridFrame(QPainter *p, const QList< QPair< double, QLineF > > &hLines, const QList< QPair< double, QLineF > > &vLines)
double mGridIntervalX
Grid line interval in x-direction (map units)
GridAnnotationPosition mTopGridAnnotationPosition
Annotation position for top map side (inside / outside / not shown)
QPainter::CompositionMode shapeBlendMode
void setOutputImageFormat(QImage::Format format)
sets format of internal QImage
void drawCanvasItem(QGraphicsItem *item, QPainter *painter, const QStyleOptionGraphicsItem *itemStyle)
Q_DECL_DEPRECATED void sizeChangedByRotation(double &width, double &height)
Calculates width / height of the bounding box of a rotated rectangle.
void setOverviewFrameMapSymbol(QgsFillSymbolV2 *symbol)
bool mAtlasDriven
True if map is being controlled by an atlas.
PreviewMode
Preview style.
GridAnnotationPosition gridAnnotationPosition(QgsComposerMap::Border border) const
QPolygonF visibleExtentPolygon() const
Returns a polygon representing the current visible map extent, considering map extents and rotation...
GridAnnotationPosition mLeftGridAnnotationPosition
Annotation position for left map side (inside / outside / not shown)
QgsComposition * mComposition
A class to represent a point geometry.
Definition: qgspoint.h:63
GridAnnotationFormat mGridAnnotationFormat
Graphics scene for map printing.
void sortGridLinesOnBorders(const QList< QPair< double, QLineF > > &hLines, const QList< QPair< double, QLineF > > &vLines, QMap< double, double > &leftFrameEntries, QMap< double, double > &rightFrameEntries, QMap< double, double > &topFrameEntries, QMap< double, double > &bottomFrameEntries) const
This class tracks map layers that are currently loaded and provides a means to fetch a pointer to a m...
Object representing map window.
BlendMode
Blending modes enum defining the available composition modes that can be used when rendering a layer...
Enable drawing of vertex markers for layers in editing mode.
GridStyle mGridStyle
Solid or crosses.
QPen gridPen() const
QgsRectangle * currentMapExtent()
Returns a pointer to the current map extent, which is either the original user specified extent or th...
QgsFillSymbolV2 * mOverviewFrameMapSymbol
Drawing style for overview farme.
GridAnnotationPosition mRightGridAnnotationPosition
Annotation position for right map side (inside / outside / not shown)
void setX(double x)
Definition: qgspoint.h:87
GridAnnotationDirection mTopGridAnnotationDirection
Annotation direction on top side ( horizontal or vertical )
void renderModeUpdateCachedImage()
Call updateCachedImage if item is in render mode.
QString qgsDoubleToString(const double &a, const int &precision=17)
Definition: qgis.h:316
PreviewMode previewMode() const
virtual ~QgsComposerMap()
void setY(double y)
Definition: qgspoint.h:95
void setGridAnnotationDirection(GridAnnotationDirection d, QgsComposerMap::Border border)
Calculates scale for a given combination of canvas size, map extent, and monitor dpi.
int layerTransparency() const
Read transparency for layer.
int xGridLines(QList< QPair< double, QLineF > > &lines) const
Returns the grid lines with associated coordinate value.
static QPainter::CompositionMode getCompositionMode(const QgsMapRenderer::BlendMode &blendMode)
Returns a QPainter::CompositionMode corresponding to a BlendMode Added in 1.9.
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:440
bool useAdvancedEffects() const
Returns true if a composition should use advanced effects such as blend modes.
void paint(QPainter *painter, const QStyleOptionGraphicsItem *itemStyle, QWidget *pWidget)
Reimplementation of QCanvasItem::paint - draw on canvas.
double mAtlasMargin
Margin size for atlas driven extents (percentage of feature size) - when in auto scaling mode...
void setBackgroundColor(const QColor &color)
Set the background color of the map.
void drawGridLine(const QLineF &line, QgsRenderContext &context)
Contains information about the context of a rendering operation.
bool mKeepLayerSet
Flag if layers to be displayed should be read from qgis canvas (true) or from stored list in mLayerSe...
bool cornerPointOnRotatedAndScaledRect(double &x, double &y, double width, double height, double rotation) const
Calculates corner point after rotation and scaling.
QString readEntry(const QString &scope, const QString &key, const QString &def=QString::null, bool *ok=0) const
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
virtual void setFrameOutlineWidth(double outlineWidth)
Sets frame outline width.
void stopRender(QgsRenderContext &context)
double mGridOffsetX
Grid line offset in x-direction.
void setBackgroundColor(const QColor &backgroundColor)
Sets the background color for this item.
void setOverviewInverted(bool inverted)
Sets the overview's inversion mode.
Q_DECL_DEPRECATED double rotation() const
Returns the rotation used for drawing the map within the composer item.
bool _writeXML(QDomElement &itemElem, QDomDocument &doc) const
Writes parameter that are not subclass specific in document.
int mCurrentExportLayer
The layer that needs to be exported.
QgsRectangle extent() const
GridAnnotationDirection mBottomGridAnnotationDirection
Annotation direction on bottom side ( horizontal or vertical )
QPainter::CompositionMode blendMode() const
Returns the item's composition blending mode.
int mId
Unique identifier.
void setOutputSize(const QSize &size)
Set the size of the resulting map image.
void setYMaximum(double y)
Set the maximum y value.
Definition: qgsrectangle.h:179
static QgsRenderContext fromMapSettings(const QgsMapSettings &mapSettings)
create initialized QgsRenderContext instance from given QgsMapSettings
virtual void drawBackground(QPainter *p)
Draw background.
bool mUpdatesEnabled
Whether updates to the map are enabled.
bool hasFrame() const
Whether this item has a frame or not.
QImage::Format outputImageFormat() const
format of internal QImage, default QImage::Format_ARGB32_Premultiplied
static QgsProject * instance()
access to canonical QgsProject instance
Definition: qgsproject.cpp:362
void setExtent(const QgsRectangle &rect)
Set coordinates of the rectangle which should be rendered.
void setMapRotation(double r)
Sets rotation for the map - this does not affect the composer item shape, only the way the map is dra...
virtual void setSceneRect(const QRectF &rectangle)
Sets this items bound in scene coordinates such that 1 item size units corresponds to 1 scene size un...
void setGridAnnotationPosition(GridAnnotationPosition p, QgsComposerMap::Border border)
void drawCoordinateAnnotation(QPainter *p, const QPointF &pos, QString annotationString)
void transformShift(double &xShift, double &yShift) const
Scales a composer map shift (in MM) and rotates it by mRotation.
const QgsComposition * composition() const
void adjustExtentToItemShape(double itemWidth, double itemHeight, QgsRectangle &extent) const
Adjusts an extent rectangle to match the provided item width and height, so that extent center of ext...
void drawGridFrameBorder(QPainter *p, const QMap< double, double > &borderPos, Border border)
bool hasBackground() const
Whether this item has a Background or not.
const QMap< QString, QgsMapLayer * > & mapLayers()
Retrieve the mapLayers collection (mainly intended for use by projection)
QgsComposerMap(QgsComposition *composition, int x, int y, int width, int height)
Constructor.
QgsRectangle mAtlasFeatureExtent
Q_DECL_DEPRECATED void setAtlasFixedScale(bool fixed)
Set to true if the map should use a fixed scale when in atlas mode.
void resize(double dx, double dy)
resizes an item in x- and y direction (canvas coordinates)
double y() const
Definition: qgspoint.h:118
QStringList layers() const
Get list of layer IDs for map rendering The layers are stored in the reverse order of how they are re...
QgsAtlasComposition & atlasComposition()
QgsMapLayer * mapLayer(QString theLayerId)
Retrieve a pointer to a loaded layer by id.
Enable vector simplification and other rendering optimizations.
QPainter::CompositionMode shadowBlendMode
static QgsSymbolV2 * loadSymbol(QDomElement &element)
QgsRasterDataProvider * dataProvider()
Returns the data provider.
static QgsMapRenderer::BlendMode getBlendModeEnum(const QPainter::CompositionMode &blendMode)
Returns a BlendMode corresponding to a QPainter::CompositionMode Added in 1.9.
void setOverviewBlendMode(QPainter::CompositionMode blendMode)
Sets the overview's blending mode.
QgsVectorLayer * coverageLayer() const
Returns the coverage layer used for the atlas features.
GridAnnotationPosition mBottomGridAnnotationPosition
Annotation position for bottom map side (inside / outside / not shown)
void setGridLineSymbol(QgsLineSymbolV2 *symbol)
void extentChanged()
void setGridPenWidth(double w)
Sets with of grid pen.
void createDefaultOverviewFrameSymbol()
static void setSpecialColumn(const QString &name, QVariant value)
Assign a special column.
void drawGrid(QPainter *p)
Draws the map grid.
QColor mGridAnnotationFontColor
Font color for grid line annotation.
QPointF mapToItemCoords(const QPointF &mapCoords) const
Transforms map coordinates to item coordinates (considering rotation and move offset) ...
void setPreviewMode(PreviewMode m)
QgsComposition::PlotStyle plotStyle() const
double width() const
Width of the rectangle.
Definition: qgsrectangle.h:204
static QPointF pointOnLineWithDistance(const QPointF &startPoint, const QPointF &directionPoint, double distance)
Returns a point on the line from startPoint to directionPoint that is a certain distance away from th...
Represents a vector layer which manages a vector based data sets.
double size
Definition: qgssvgcache.cpp:77
const QgsComposerMap * getComposerMapById(int id) const
Returns the composer map with specified id.
void setFlags(Flags flags)
Set combination of flags that will be used for rendering.
double xMinimum() const
Get the x minimum value (left side of rectangle)
Definition: qgsrectangle.h:189
PreviewMode mPreviewMode
Preview style.
Q_DECL_DEPRECATED void setRotation(double r)
Sets rotation for the map - this does not affect the composer item shape, only the way the map is dra...
QgsPoint center() const
Center point of the rectangle.
Definition: qgsrectangle.h:214
void renderSynchronously()
Render the map synchronously in this thread.
void setAlpha(qreal alpha)
Set alpha transparency 1 for opaque, 0 for invisible.
Definition: qgssymbolv2.h:127
QPainter::CompositionMode mGridBlendMode
Blend mode for grid.
QStringList layersToRender() const
Returns a list of the layers to render for this map item.
int numberExportLayers() const
Get the number of layers that this item requires for exporting as layers.
void setGridBlendMode(QPainter::CompositionMode blendMode)
Sets the grid's blending mode.
void syncLayerSet()
Removes layer ids from mLayerSet that are no longer present in the qgis main map. ...
double fontAscentMillimeters(const QFont &font) const
Returns the font ascent in Millimeters (considers upscaling and downscaling with FONT_WORKAROUND_SCAL...
void setOverviewFrameMap(int mapId)
Sets overview frame map.
int mNumCachedLayers
Number of layers when cache was created.
void setXMinimum(double x)
Set the minimum x value.
Definition: qgsrectangle.h:164
QgsRectangle transformedExtent() const
Returns extent that considers mOffsetX / mOffsetY (during content move)
void sizeChangedByRotation(double &width, double &height, double rotation)
Calculates width / height of the bounding box of a rotated rectangle.
double height() const
Height of the rectangle.
Definition: qgsrectangle.h:209
void setCrsTransformEnabled(bool enabled)
sets whether to use projections for this layer set
Base class for raster data providers.
QColor color() const
#define tr(sourceText)
void scale(double scaleFactor, const QgsPoint *c=0)
Scale the rectangle around its center point.
Border borderForLineCoord(const QPointF &p) const
Returns the item border of a point (in item coordinates)
QString id() const
Get item's id (which is not necessarly unique)