QGIS API Documentation  2.4.0-Chugiak
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
qgsatlascomposition.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsatlascomposition.cpp
3  -----------------------
4  begin : October 2012
5  copyright : (C) 2005 by Hugo Mercier
6  email : hugo dot mercier at oslandia dot com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 #include <stdexcept>
18 #include <QtAlgorithms>
19 
20 #include "qgsatlascomposition.h"
21 #include "qgsvectorlayer.h"
22 #include "qgscomposermap.h"
23 #include "qgscomposition.h"
24 #include "qgsvectordataprovider.h"
25 #include "qgsexpression.h"
26 #include "qgsgeometry.h"
27 #include "qgsmaplayerregistry.h"
28 #include "qgsproject.h"
29 #include "qgsmessagelog.h"
30 
32  mComposition( composition ),
33  mEnabled( false ),
34  mHideCoverage( false ), mFilenamePattern( "'output_'||$feature" ),
35  mCoverageLayer( 0 ), mSingleFile( false ),
36  mSortFeatures( false ), mSortAscending( true ), mCurrentFeatureNo( 0 ),
37  mFilterFeatures( false ), mFeatureFilter( "" ),
38  mFilenameParserError( QString() ),
39  mFilterParserError( QString() )
40 {
41 
42  // declare special columns with a default value
43  QgsExpression::setSpecialColumn( "$page", QVariant(( int )1 ) );
44  QgsExpression::setSpecialColumn( "$feature", QVariant(( int )0 ) );
45  QgsExpression::setSpecialColumn( "$numpages", QVariant(( int )1 ) );
46  QgsExpression::setSpecialColumn( "$numfeatures", QVariant(( int )0 ) );
47  QgsExpression::setSpecialColumn( "$atlasfeatureid", QVariant(( int )0 ) );
48  QgsExpression::setSpecialColumn( "$atlasgeometry", QVariant::fromValue( QgsGeometry() ) );
49 }
50 
52 {
53 }
54 
55 void QgsAtlasComposition::setEnabled( bool enabled )
56 {
57  mEnabled = enabled;
59  emit toggled( enabled );
60 }
61 
63 {
64  mCoverageLayer = layer;
65 
66  // update the number of features
67  QgsExpression::setSpecialColumn( "$numfeatures", QVariant(( int )mFeatureIds.size() ) );
68 
69  // Grab the first feature so that user can use it to test the style in rules.
70  if ( layer )
71  {
72  QgsFeature fet;
73  layer->getFeatures().nextFeature( fet );
74  QgsExpression::setSpecialColumn( "$atlasfeatureid", fet.id() );
75  QgsExpression::setSpecialColumn( "$atlasgeometry", QVariant::fromValue( *fet.geometry() ) );
76  }
77 
78  emit coverageLayerChanged( layer );
79 }
80 
82 {
83  //deprecated method. Until removed just return the first atlas-enabled composer map
84 
85  //build a list of composer maps
86  QList<QgsComposerMap*> maps;
87  mComposition->composerItems( maps );
88  for ( QList<QgsComposerMap*>::iterator mit = maps.begin(); mit != maps.end(); ++mit )
89  {
90  QgsComposerMap* currentMap = ( *mit );
91  if ( currentMap->atlasDriven() )
92  {
93  return currentMap;
94  }
95  }
96 
97  return 0;
98 }
99 
101 {
102  //deprecated
103 
104  if ( !map )
105  {
106  return;
107  }
108 
109  map->setAtlasDriven( true );
110 }
111 
112 
114 {
115  if ( !mCoverageLayer )
116  {
117  return -1;
118  }
120 }
121 
123 {
124  if ( mCoverageLayer )
125  {
126  const QgsFields fields = mCoverageLayer->pendingFields();
127  if ( idx >= 0 && idx < fields.count() )
128  {
129  mSortKeyAttributeName = fields[idx].name();
130  return;
131  }
132  }
134 }
135 
136 //
137 // Private class only used for the sorting of features
139 {
140  public:
141  FieldSorter( QgsAtlasComposition::SorterKeys& keys, bool ascending = true ) : mKeys( keys ), mAscending( ascending ) {}
142 
143  bool operator()( const QgsFeatureId& id1, const QgsFeatureId& id2 )
144  {
145  bool result = true;
146 
147  if ( mKeys[ id1 ].type() == QVariant::Int )
148  {
149  result = mKeys[ id1 ].toInt() < mKeys[ id2 ].toInt();
150  }
151  else if ( mKeys[ id1 ].type() == QVariant::Double )
152  {
153  result = mKeys[ id1 ].toDouble() < mKeys[ id2 ].toDouble();
154  }
155  else if ( mKeys[ id1 ].type() == QVariant::String )
156  {
157  result = ( QString::localeAwareCompare( mKeys[ id1 ].toString(), mKeys[ id2 ].toString() ) < 0 );
158  }
159 
160  return mAscending ? result : !result;
161  }
162  private:
165 };
166 
168 {
169  //needs to be called when layer, filter, sort changes
170 
171  if ( !mCoverageLayer )
172  {
173  return 0;
174  }
175 
177 
178  // select all features with all attributes
180 
181  std::auto_ptr<QgsExpression> filterExpression;
182  if ( mFilterFeatures && !mFeatureFilter.isEmpty() )
183  {
184  filterExpression = std::auto_ptr<QgsExpression>( new QgsExpression( mFeatureFilter ) );
185  if ( filterExpression->hasParserError() )
186  {
187  mFilterParserError = filterExpression->parserErrorString();
188  return 0;
189  }
190  }
191  mFilterParserError = QString();
192 
193  // We cannot use nextFeature() directly since the feature pointer is rewinded by the rendering process
194  // We thus store the feature ids for future extraction
195  QgsFeature feat;
196  mFeatureIds.clear();
197  mFeatureKeys.clear();
199  while ( fit.nextFeature( feat ) )
200  {
201  if ( mFilterFeatures && !mFeatureFilter.isEmpty() )
202  {
203  QVariant result = filterExpression->evaluate( &feat, mCoverageLayer->pendingFields() );
204  if ( filterExpression->hasEvalError() )
205  {
206  QgsMessageLog::logMessage( tr( "Atlas filter eval error: %1" ).arg( filterExpression->evalErrorString() ), tr( "Composer" ) );
207  }
208 
209  // skip this feature if the filter evaluation if false
210  if ( !result.toBool() )
211  {
212  continue;
213  }
214  }
215  mFeatureIds.push_back( feat.id() );
216 
217  if ( mSortFeatures && sortIdx != -1 )
218  {
219  mFeatureKeys.insert( feat.id(), feat.attributes()[ sortIdx ] );
220  }
221  }
222 
223  // sort features, if asked for
224  if ( mFeatureKeys.count() )
225  {
227  qSort( mFeatureIds.begin(), mFeatureIds.end(), sorter );
228  }
229 
230  QgsExpression::setSpecialColumn( "$numfeatures", QVariant(( int )mFeatureIds.size() ) );
231 
232  //jump to first feature if currently using an atlas preview
233  //need to do this in case filtering/layer change has altered matching features
235  {
236  firstFeature();
237  }
238 
239  return mFeatureIds.size();
240 }
241 
242 
244 {
245  if ( !mCoverageLayer )
246  {
247  return false;
248  }
249 
250  emit renderBegun();
251 
252  bool featuresUpdated = updateFeatures();
253  if ( !featuresUpdated )
254  {
255  //no matching features found
256  return false;
257  }
258 
259  // special columns for expressions
260  QgsExpression::setSpecialColumn( "$numpages", QVariant( mComposition->numPages() ) );
261  QgsExpression::setSpecialColumn( "$numfeatures", QVariant(( int )mFeatureIds.size() ) );
262 
263  return true;
264 }
265 
267 {
268  if ( !mCoverageLayer )
269  {
270  return;
271  }
272 
273  emit featureChanged( 0 );
274 
275  updateAtlasMaps();
276 
277  emit renderEnded();
278 }
279 
281 {
282  //update atlas-enabled composer maps
283  QList<QgsComposerMap*> maps;
284  mComposition->composerItems( maps );
285  for ( QList<QgsComposerMap*>::iterator mit = maps.begin(); mit != maps.end(); ++mit )
286  {
287  QgsComposerMap* currentMap = ( *mit );
288  if ( !currentMap->atlasDriven() )
289  {
290  continue;
291  }
292 
293  currentMap->cache();
294  }
295 }
296 
298 {
299  return mFeatureIds.size();
300 }
301 
303 {
304  int newFeatureNo = mCurrentFeatureNo + 1;
305  if ( newFeatureNo >= mFeatureIds.size() )
306  {
307  newFeatureNo = mFeatureIds.size() - 1;
308  }
309 
310  prepareForFeature( newFeatureNo );
311 }
312 
314 {
315  int newFeatureNo = mCurrentFeatureNo - 1;
316  if ( newFeatureNo < 0 )
317  {
318  newFeatureNo = 0;
319  }
320 
321  prepareForFeature( newFeatureNo );
322 }
323 
325 {
326  prepareForFeature( 0 );
327 }
328 
330 {
331  prepareForFeature( mFeatureIds.size() - 1 );
332 }
333 
335 {
336  int featureI = mFeatureIds.indexOf( feat->id() );
337  return prepareForFeature( featureI );
338 }
339 
341 {
342  if ( !mCoverageLayer )
343  {
344  return false;
345  }
346 
347  if ( mFeatureIds.size() == 0 )
348  {
349  emit statusMsgChanged( tr( "No matching atlas features" ) );
350  return false;
351  }
352 
353  mCurrentFeatureNo = featureI;
354 
355  // retrieve the next feature, based on its id
357 
358  QgsExpression::setSpecialColumn( "$atlasfeatureid", mCurrentFeature.id() );
359  QgsExpression::setSpecialColumn( "$atlasgeometry", QVariant::fromValue( *mCurrentFeature.geometry() ) );
360  QgsExpression::setSpecialColumn( "$feature", QVariant(( int )featureI + 1 ) );
361 
362  // generate filename for current feature
363  if ( !evalFeatureFilename() )
364  {
365  //error evaluating filename
366  return false;
367  }
368 
370  emit statusMsgChanged( QString( tr( "Atlas feature %1 of %2" ) ).arg( featureI + 1 ).arg( mFeatureIds.size() ) );
371 
372  //update composer maps
373 
374  //build a list of atlas-enabled composer maps
375  QList<QgsComposerMap*> maps;
376  QList<QgsComposerMap*> atlasMaps;
377  mComposition->composerItems( maps );
378  for ( QList<QgsComposerMap*>::iterator mit = maps.begin(); mit != maps.end(); ++mit )
379  {
380  QgsComposerMap* currentMap = ( *mit );
381  if ( !currentMap->atlasDriven() )
382  {
383  continue;
384  }
385  atlasMaps << currentMap;
386  }
387 
388  //clear the transformed bounds of the previous feature
390 
391  if ( atlasMaps.isEmpty() )
392  {
393  //no atlas enabled maps
394  return true;
395  }
396 
397  // compute extent of current feature in the map CRS. This should be set on a per-atlas map basis,
398  // but given that it's not currently possible to have maps with different CRSes we can just
399  // calculate it once based on the first atlas maps' CRS.
400  computeExtent( atlasMaps[0] );
401 
402  //update atlas bounds of every atlas enabled composer map
403  for ( QList<QgsComposerMap*>::iterator mit = atlasMaps.begin(); mit != atlasMaps.end(); ++mit )
404  {
405  prepareMap( *mit );
406  }
407 
408  return true;
409 }
410 
412 {
413  // compute the extent of the current feature, in the crs of the specified map
414 
415  const QgsCoordinateReferenceSystem& coverage_crs = mCoverageLayer->crs();
416  // transformation needed for feature geometries
417  const QgsCoordinateReferenceSystem& destination_crs = map->composition()->mapSettings().destinationCrs();
418  mTransform.setSourceCrs( coverage_crs );
419  mTransform.setDestCRS( destination_crs );
420 
421  // QgsGeometry::boundingBox is expressed in the geometry"s native CRS
422  // We have to transform the grometry to the destination CRS and ask for the bounding box
423  // Note: we cannot directly take the transformation of the bounding box, since transformations are not linear
425  tgeom.transform( mTransform );
426  mTransformedFeatureBounds = tgeom.boundingBox();
427 }
428 
430 {
431  if ( !map->atlasDriven() )
432  {
433  return;
434  }
435 
437  {
438  //transformed extent of current feature hasn't been calculated yet. This can happen if
439  //a map has been set to be atlas controlled after prepare feature was called
440  computeExtent( map );
441  }
442 
443  double xa1 = mTransformedFeatureBounds.xMinimum();
444  double xa2 = mTransformedFeatureBounds.xMaximum();
445  double ya1 = mTransformedFeatureBounds.yMinimum();
446  double ya2 = mTransformedFeatureBounds.yMaximum();
448  QgsRectangle mOrigExtent = map->extent();
449 
450  //sanity check - only allow fixed scale mode for point layers
451  bool isPointLayer = false;
452  switch ( mCoverageLayer->wkbType() )
453  {
454  case QGis::WKBPoint:
455  case QGis::WKBPoint25D:
456  case QGis::WKBMultiPoint:
458  isPointLayer = true;
459  break;
460  default:
461  isPointLayer = false;
462  break;
463  }
464 
465  if ( map->atlasScalingMode() == QgsComposerMap::Fixed || map->atlasScalingMode() == QgsComposerMap::Predefined || isPointLayer )
466  {
467  QgsScaleCalculator calc;
468  calc.setMapUnits( composition()->mapSettings().mapUnits() );
469  calc.setDpi( 25.4 );
470  double originalScale = calc.calculate( mOrigExtent, map->rect().width() );
471  double geomCenterX = ( xa1 + xa2 ) / 2.0;
472  double geomCenterY = ( ya1 + ya2 ) / 2.0;
473 
474  if ( map->atlasScalingMode() == QgsComposerMap::Fixed || isPointLayer )
475  {
476  // only translate, keep the original scale (i.e. width x height)
477  double xMin = geomCenterX - mOrigExtent.width() / 2.0;
478  double yMin = geomCenterY - mOrigExtent.height() / 2.0;
479  newExtent = QgsRectangle( xMin,
480  yMin,
481  xMin + mOrigExtent.width(),
482  yMin + mOrigExtent.height() );
483 
484  //scale newExtent to match original scale of map
485  //this is required for geographic coordinate systems, where the scale varies by extent
486  double newScale = calc.calculate( newExtent, map->rect().width() );
487  newExtent.scale( originalScale / newScale );
488  }
489  else if ( map->atlasScalingMode() == QgsComposerMap::Predefined )
490  {
491  // choose one of the predefined scales
492  double newWidth = mOrigExtent.width();
493  double newHeight = mOrigExtent.height();
494  const QVector<double>& scales = mPredefinedScales;
495  for ( int i = 0; i < scales.size(); i++ )
496  {
497  double ratio = scales[i] / originalScale;
498  newWidth = mOrigExtent.width() * ratio;
499  newHeight = mOrigExtent.height() * ratio;
500 
501  // compute new extent, centered on feature
502  double xMin = geomCenterX - newWidth / 2.0;
503  double yMin = geomCenterY - newHeight / 2.0;
504  newExtent = QgsRectangle( xMin,
505  yMin,
506  xMin + newWidth,
507  yMin + newHeight );
508 
509  //scale newExtent to match desired map scale
510  //this is required for geographic coordinate systems, where the scale varies by extent
511  double newScale = calc.calculate( newExtent, map->rect().width() );
512  newExtent.scale( scales[i] / newScale );
513 
514  if (( newExtent.width() >= mTransformedFeatureBounds.width() ) && ( newExtent.height() >= mTransformedFeatureBounds.height() ) )
515  {
516  // this is the smallest extent that embeds the feature, stop here
517  break;
518  }
519  }
520  }
521  }
522  else if ( map->atlasScalingMode() == QgsComposerMap::Auto )
523  {
524  // auto scale
525 
527  double mapRatio = mOrigExtent.width() / mOrigExtent.height();
528 
529  // geometry height is too big
530  if ( geomRatio < mapRatio )
531  {
532  // extent the bbox's width
533  double adjWidth = ( mapRatio * mTransformedFeatureBounds.height() - mTransformedFeatureBounds.width() ) / 2.0;
534  xa1 -= adjWidth;
535  xa2 += adjWidth;
536  }
537  // geometry width is too big
538  else if ( geomRatio > mapRatio )
539  {
540  // extent the bbox's height
541  double adjHeight = ( mTransformedFeatureBounds.width() / mapRatio - mTransformedFeatureBounds.height() ) / 2.0;
542  ya1 -= adjHeight;
543  ya2 += adjHeight;
544  }
545  newExtent = QgsRectangle( xa1, ya1, xa2, ya2 );
546 
547  if ( map->atlasMargin() > 0.0 )
548  {
549  newExtent.scale( 1 + map->atlasMargin() );
550  }
551  }
552 
553  // set the new extent (and render)
554  map->setNewAtlasFeatureExtent( newExtent );
555 }
556 
558 {
559  return mCurrentFilename;
560 }
561 
562 void QgsAtlasComposition::writeXML( QDomElement& elem, QDomDocument& doc ) const
563 {
564  QDomElement atlasElem = doc.createElement( "Atlas" );
565  atlasElem.setAttribute( "enabled", mEnabled ? "true" : "false" );
566  if ( !mEnabled )
567  {
568  return;
569  }
570 
571  if ( mCoverageLayer )
572  {
573  atlasElem.setAttribute( "coverageLayer", mCoverageLayer->id() );
574  }
575  else
576  {
577  atlasElem.setAttribute( "coverageLayer", "" );
578  }
579 
580  atlasElem.setAttribute( "hideCoverage", mHideCoverage ? "true" : "false" );
581  atlasElem.setAttribute( "singleFile", mSingleFile ? "true" : "false" );
582  atlasElem.setAttribute( "filenamePattern", mFilenamePattern );
583 
584  atlasElem.setAttribute( "sortFeatures", mSortFeatures ? "true" : "false" );
585  if ( mSortFeatures )
586  {
587  atlasElem.setAttribute( "sortKey", mSortKeyAttributeName );
588  atlasElem.setAttribute( "sortAscending", mSortAscending ? "true" : "false" );
589  }
590  atlasElem.setAttribute( "filterFeatures", mFilterFeatures ? "true" : "false" );
591  if ( mFilterFeatures )
592  {
593  atlasElem.setAttribute( "featureFilter", mFeatureFilter );
594  }
595 
596  elem.appendChild( atlasElem );
597 }
598 
599 void QgsAtlasComposition::readXML( const QDomElement& atlasElem, const QDomDocument& )
600 {
601  mEnabled = atlasElem.attribute( "enabled", "false" ) == "true" ? true : false;
602  emit toggled( mEnabled );
603  if ( !mEnabled )
604  {
605  emit parameterChanged();
606  return;
607  }
608 
609  // look for stored layer name
610  mCoverageLayer = 0;
611  QMap<QString, QgsMapLayer*> layers = QgsMapLayerRegistry::instance()->mapLayers();
612  for ( QMap<QString, QgsMapLayer*>::const_iterator it = layers.begin(); it != layers.end(); ++it )
613  {
614  if ( it.key() == atlasElem.attribute( "coverageLayer" ) )
615  {
616  mCoverageLayer = dynamic_cast<QgsVectorLayer*>( it.value() );
617  break;
618  }
619  }
620  //look for stored composer map, to upgrade pre 2.1 projects
621  int composerMapNo = atlasElem.attribute( "composerMap", "-1" ).toInt();
623  if ( composerMapNo != -1 )
624  {
625  QList<QgsComposerMap*> maps;
626  mComposition->composerItems( maps );
627  for ( QList<QgsComposerMap*>::iterator it = maps.begin(); it != maps.end(); ++it )
628  {
629  if (( *it )->id() == composerMapNo )
630  {
631  composerMap = ( *it );
632  composerMap->setAtlasDriven( true );
633  break;
634  }
635  }
636  }
637  mHideCoverage = atlasElem.attribute( "hideCoverage", "false" ) == "true" ? true : false;
638 
639  //upgrade pre 2.1 projects
640  double margin = atlasElem.attribute( "margin", "0.0" ).toDouble();
641  if ( composerMap && margin != 0 )
642  {
643  composerMap->setAtlasMargin( margin );
644  }
645  bool fixedScale = atlasElem.attribute( "fixedScale", "false" ) == "true" ? true : false;
646  if ( composerMap && fixedScale )
647  {
649  }
650 
651  mSingleFile = atlasElem.attribute( "singleFile", "false" ) == "true" ? true : false;
652  mFilenamePattern = atlasElem.attribute( "filenamePattern", "" );
653 
654  mSortFeatures = atlasElem.attribute( "sortFeatures", "false" ) == "true" ? true : false;
655  if ( mSortFeatures )
656  {
657  mSortKeyAttributeName = atlasElem.attribute( "sortKey", "" );
658  // since 2.3, the field name is saved instead of the field index
659  // following code keeps compatibility with version 2.2 projects
660  // to be removed in QGIS 3.0
661  bool isIndex;
662  int idx = mSortKeyAttributeName.toInt( &isIndex );
663  if ( isIndex && mCoverageLayer )
664  {
665  const QgsFields fields = mCoverageLayer->pendingFields();
666  if ( idx >= 0 && idx < fields.count() )
667  {
668  mSortKeyAttributeName = fields[idx].name();
669  }
670  }
671  mSortAscending = atlasElem.attribute( "sortAscending", "true" ) == "true" ? true : false;
672  }
673  mFilterFeatures = atlasElem.attribute( "filterFeatures", "false" ) == "true" ? true : false;
674  if ( mFilterFeatures )
675  {
676  mFeatureFilter = atlasElem.attribute( "featureFilter", "" );
677  }
678 
679  emit parameterChanged();
680 }
681 
683 {
684  mHideCoverage = hide;
685 
687  {
688  //an atlas preview is enabled, so reflect changes in coverage layer visibility immediately
689  updateAtlasMaps();
690  mComposition->update();
691  }
692 
693 }
694 
695 bool QgsAtlasComposition::setFilenamePattern( const QString& pattern )
696 {
697  mFilenamePattern = pattern;
698  return updateFilenameExpression();
699 }
700 
702 {
703  if ( !mCoverageLayer )
704  {
705  return false;
706  }
707 
708  const QgsFields& fields = mCoverageLayer->pendingFields();
709 
710  if ( mFilenamePattern.size() > 0 )
711  {
712  mFilenameExpr = std::auto_ptr<QgsExpression>( new QgsExpression( mFilenamePattern ) );
713  // expression used to evaluate each filename
714  // test for evaluation errors
715  if ( mFilenameExpr->hasParserError() )
716  {
717  mFilenameParserError = mFilenameExpr->parserErrorString();
718  return false;
719  }
720 
721  // prepare the filename expression
722  mFilenameExpr->prepare( fields );
723  }
724 
725  //if atlas preview is currently enabled, regenerate filename for current feature
727  {
729  }
730  return true;
731 }
732 
734 {
735  //generate filename for current atlas feature
736  if ( mFilenamePattern.size() > 0 )
737  {
738  QVariant filenameRes = mFilenameExpr->evaluate( &mCurrentFeature, mCoverageLayer->pendingFields() );
739  if ( mFilenameExpr->hasEvalError() )
740  {
741  QgsMessageLog::logMessage( tr( "Atlas filename evaluation error: %1" ).arg( mFilenameExpr->evalErrorString() ), tr( "Composer" ) );
742  return false;
743  }
744 
745  mCurrentFilename = filenameRes.toString();
746  }
747  return true;
748 }
749 
750 void QgsAtlasComposition::setPredefinedScales( const QVector<double>& scales )
751 {
752  mPredefinedScales = scales;
753  // make sure the list is sorted
754  qSort( mPredefinedScales.begin(), mPredefinedScales.end() );
755 }
756 
759 {
760  //deprecated method. Until removed just return the property for the first atlas-enabled composer map
761  QgsComposerMap * map = composerMap();
762  if ( !map )
763  {
764  return false;
765  }
766 
767  return map->atlasFixedScale();
768 }
769 
771 {
772  //deprecated method. Until removed just set the property for the first atlas-enabled composer map
773  QgsComposerMap * map = composerMap();
774  if ( !map )
775  {
776  return;
777  }
778 
780 }
781 
783 {
784  //deprecated method. Until removed just return the property for the first atlas-enabled composer map
785  QgsComposerMap * map = composerMap();
786  if ( !map )
787  {
788  return 0;
789  }
790 
791  return map->atlasMargin();
792 }
793 
794 void QgsAtlasComposition::setMargin( float margin )
795 {
796  //deprecated method. Until removed just set the property for the first atlas-enabled composer map
797  QgsComposerMap * map = composerMap();
798  if ( !map )
799  {
800  return;
801  }
802 
803  map->setAtlasMargin(( double ) margin );
804 }
QgsFeatureId id() const
Get the feature id for this feature.
Definition: qgsfeature.cpp:100
Class for parsing and evaluation of expressions (formerly called "search strings").
Definition: qgsexpression.h:89
void setMapUnits(QGis::UnitType mapUnits)
Set the map units.
QMap< QgsFeatureId, QVariant > SorterKeys
Wrapper for iterator of features from vector data provider or vector layer.
QgsComposition::AtlasMode atlasMode() const
Returns the current atlas mode of the composition.
A rectangle specified with double values.
Definition: qgsrectangle.h:35
bool isEmpty() const
test if rectangle is empty.
void renderEnded()
Is emitted when atlas rendering has ended.
QgsVectorLayer * mCoverageLayer
QVector< QgsFeatureId > mFeatureIds
Q_DECL_DEPRECATED int sortKeyAttributeIndex() const
void setNewAtlasFeatureExtent(const QgsRectangle &extent)
Sets new Extent for the current atlas preview and changes width, height (and implicitely also scale)...
QgsAtlasComposition(QgsComposition *composition)
double yMaximum() const
Get the y maximum value (top side of rectangle)
Definition: qgsrectangle.h:194
double atlasMargin() const
Returns the margin size (percentage) used when the map is in atlas mode.
Q_DECL_DEPRECATED bool fixedScale() const
Returns whether the atlas map uses a fixed scale.
void setSourceCrs(const QgsCoordinateReferenceSystem &theCRS)
const QgsMapSettings & mapSettings() const
Return setting of QGIS map canvas.
void computeExtent(QgsComposerMap *map)
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest())
Query the provider for features specified in request.
QgsGeometry * geometry() const
Get the geometry object associated with this feature.
Definition: qgsfeature.cpp:112
void cache()
Create cache image.
QVector< double > mPredefinedScales
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:439
void setDpi(double dpi)
Set the dpi to be used in scale calculations.
QgsComposition * composition()
bool enabled() const
Returns whether the atlas generation is enabled.
Container of fields for a vector layer.
Definition: qgsfield.h:161
QgsCoordinateTransform mTransform
void toggled(bool)
emitted when atlas is enabled or disabled
void setHideCoverage(bool hide)
Sets whether the coverage layer should be hidden in map items in the composition. ...
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:113
int numPages() const
Note: added in version 1.9.
void endRender()
Ends the rendering.
static void logMessage(QString message, QString tag=QString::null, MessageLevel level=WARNING)
add a message to the instance (and create it if necessary)
void readXML(const QDomElement &elem, const QDomDocument &doc)
QGis::WkbType wkbType() const
Returns the WKBType or WKBUnknown in case of error.
Q_DECL_DEPRECATED void setFixedScale(bool fixed)
Sets whether the atlas map should use a fixed scale.
Q_DECL_DEPRECATED float margin() const
Returns the margin for the atlas map.
void setAtlasMargin(double margin)
Sets the margin size (percentage) used when the map is in atlas mode.
bool setFilenamePattern(const QString &pattern)
Sets the filename expression used for generating output filenames for each atlas page.
Q_DECL_DEPRECATED void setSortKeyAttributeIndex(int idx)
QgsRectangle mTransformedFeatureBounds
void setCoverageLayer(QgsVectorLayer *layer)
Sets the coverage layer to use for the atlas features.
void setAtlasScalingMode(AtlasScalingMode mode)
Sets the current atlas scaling mode.
bool beginRender()
Begins the rendering.
Q_DECL_DEPRECATED void setComposerMap(QgsComposerMap *map)
Sets the map used by the atlas.
double calculate(const QgsRectangle &mapExtent, int canvasWidth)
Calculate the scale denominator.
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
Definition: qgsrectangle.h:199
double xMaximum() const
Get the x maximum value (right side of rectangle)
Definition: qgsrectangle.h:184
void setPredefinedScales(const QVector< double > &scales)
Sets the list of predefined scales for the atlas.
void prepareMap(QgsComposerMap *map)
Recalculates the bounds of an atlas driven map.
void statusMsgChanged(QString message)
Is emitted when the atlas has an updated status bar message for the composer window.
const QgsCoordinateReferenceSystem & destinationCrs() const
returns CRS of destination coordinate reference system
bool setAtlasMode(QgsComposition::AtlasMode mode)
Sets the current atlas mode of the composition.
This class wraps a request for features to a vector layer (or directly its vector data provider)...
int numFeatures() const
Returns the number of features in the coverage layer.
const QgsAttributes & attributes() const
Definition: qgsfeature.h:142
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
int count() const
Return number of items.
Definition: qgsfield.h:195
Q_DECL_DEPRECATED bool atlasFixedScale() const
Returns true if the map uses a fixed scale when in atlas mode.
void setEnabled(bool enabled)
Sets whether the atlas is enabled.
int updateFeatures()
Requeries the current atlas coverage layer and applies filtering and sorting.
void writeXML(QDomElement &elem, QDomDocument &doc) const
Graphics scene for map printing.
bool prepareForFeature(int i)
Prepare the atlas map for the given feature.
Object representing map window.
QgsComposition * mComposition
void featureChanged(QgsFeature *feature)
Is emitted when the current atlas feature changes.
void coverageLayerChanged(QgsVectorLayer *layer)
Is emitted when the coverage layer for an atlas changes.
Calculates scale for a given combination of canvas size, map extent, and monitor dpi.
bool operator()(const QgsFeatureId &id1, const QgsFeatureId &id2)
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:440
void setDestCRS(const QgsCoordinateReferenceSystem &theCRS)
void renderBegun()
Is emitted when atlas rendering has begun.
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
QgsRectangle extent() const
FieldSorter(QgsAtlasComposition::SorterKeys &keys, bool ascending=true)
Q_DECL_DEPRECATED QgsComposerMap * composerMap() const
Returns the map used by the atlas.
Q_DECL_DEPRECATED void setMargin(float margin)
Sets the margin for the atlas map.
bool evalFeatureFilename()
Evaluates filename for current feature.
AtlasScalingMode atlasScalingMode() const
Returns the current atlas scaling mode.
Class for storing a coordinate reference system (CRS)
const QgsComposition * composition() const
const QMap< QString, QgsMapLayer * > & mapLayers()
Retrieve the mapLayers collection (mainly intended for use by projection)
void parameterChanged()
emitted when one of the parameters changes
int transform(const QgsCoordinateTransform &ct)
Transform this geometry as described by CoordinateTranasform ct.
qint64 QgsFeatureId
Definition: qgsfeature.h:30
const QgsCoordinateReferenceSystem & crs() const
Returns layer's spatial reference system.
const QString & currentFilename() const
Returns the current filename.
std::auto_ptr< QgsExpression > mFilenameExpr
bool atlasDriven() const
Returns whether the map extent is set to follow the current atlas feature.
const QgsFields & pendingFields() const
returns field list in the to-be-committed state
static void setSpecialColumn(const QString &name, QVariant value)
Assign a special column.
void setAtlasDriven(bool enabled)
Sets whether the map extent will follow the current atlas feature.
bool nextFeature(QgsFeature &f)
void composerItems(QList< T * > &itemList)
Return composer items of a specific type.
double width() const
Width of the rectangle.
Definition: qgsrectangle.h:204
Represents a vector layer which manages a vector based data sets.
int fieldNameIndex(const QString &fieldName) const
Returns the index of a field name or -1 if the field does not exist.
double xMinimum() const
Get the x minimum value (left side of rectangle)
Definition: qgsrectangle.h:189
QgsAtlasComposition::SorterKeys & mKeys
double height() const
Height of the rectangle.
Definition: qgsrectangle.h:209
bool updateFilenameExpression()
Updates the filename expression.
#define tr(sourceText)
void scale(double scaleFactor, const QgsPoint *c=0)
Scale the rectangle around its center point.