QGIS API Documentation  2.5.0-Master
 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( "$atlasfeature", QVariant::fromValue( QgsFeature() ) );
49  QgsExpression::setSpecialColumn( "$atlasgeometry", QVariant::fromValue( QgsGeometry() ) );
50 }
51 
53 {
54 }
55 
56 void QgsAtlasComposition::setEnabled( bool enabled )
57 {
58  mEnabled = enabled;
60  emit toggled( enabled );
61 }
62 
64 {
65  mCoverageLayer = layer;
66 
67  // update the number of features
68  QgsExpression::setSpecialColumn( "$numfeatures", QVariant(( int )mFeatureIds.size() ) );
69 
70  // Grab the first feature so that user can use it to test the style in rules.
71  if ( layer )
72  {
73  QgsFeature fet;
74  layer->getFeatures().nextFeature( fet );
75  QgsExpression::setSpecialColumn( "$atlasfeatureid", fet.id() );
76  QgsExpression::setSpecialColumn( "$atlasgeometry", QVariant::fromValue( *fet.geometry() ) );
77  QgsExpression::setSpecialColumn( "$atlasfeature", QVariant::fromValue( fet ) );
78  }
79 
80  emit coverageLayerChanged( layer );
81 }
82 
84 {
85  //deprecated method. Until removed just return the first atlas-enabled composer map
86 
87  //build a list of composer maps
88  QList<QgsComposerMap*> maps;
89  mComposition->composerItems( maps );
90  for ( QList<QgsComposerMap*>::iterator mit = maps.begin(); mit != maps.end(); ++mit )
91  {
92  QgsComposerMap* currentMap = ( *mit );
93  if ( currentMap->atlasDriven() )
94  {
95  return currentMap;
96  }
97  }
98 
99  return 0;
100 }
101 
103 {
104  //deprecated
105 
106  if ( !map )
107  {
108  return;
109  }
110 
111  map->setAtlasDriven( true );
112 }
113 
114 
116 {
117  if ( !mCoverageLayer )
118  {
119  return -1;
120  }
122 }
123 
125 {
126  if ( mCoverageLayer )
127  {
128  const QgsFields fields = mCoverageLayer->pendingFields();
129  if ( idx >= 0 && idx < fields.count() )
130  {
131  mSortKeyAttributeName = fields[idx].name();
132  return;
133  }
134  }
136 }
137 
138 //
139 // Private class only used for the sorting of features
141 {
142  public:
143  FieldSorter( QgsAtlasComposition::SorterKeys& keys, bool ascending = true ) : mKeys( keys ), mAscending( ascending ) {}
144 
145  bool operator()( const QgsFeatureId& id1, const QgsFeatureId& id2 )
146  {
147  bool result = true;
148 
149  if ( mKeys[ id1 ].type() == QVariant::Int )
150  {
151  result = mKeys[ id1 ].toInt() < mKeys[ id2 ].toInt();
152  }
153  else if ( mKeys[ id1 ].type() == QVariant::Double )
154  {
155  result = mKeys[ id1 ].toDouble() < mKeys[ id2 ].toDouble();
156  }
157  else if ( mKeys[ id1 ].type() == QVariant::String )
158  {
159  result = ( QString::localeAwareCompare( mKeys[ id1 ].toString(), mKeys[ id2 ].toString() ) < 0 );
160  }
161 
162  return mAscending ? result : !result;
163  }
164  private:
167 };
168 
170 {
171  //needs to be called when layer, filter, sort changes
172 
173  if ( !mCoverageLayer )
174  {
175  return 0;
176  }
177 
179 
180  // select all features with all attributes
182 
183  std::auto_ptr<QgsExpression> filterExpression;
184  if ( mFilterFeatures && !mFeatureFilter.isEmpty() )
185  {
186  filterExpression = std::auto_ptr<QgsExpression>( new QgsExpression( mFeatureFilter ) );
187  if ( filterExpression->hasParserError() )
188  {
189  mFilterParserError = filterExpression->parserErrorString();
190  return 0;
191  }
192  }
193  mFilterParserError = QString();
194 
195  // We cannot use nextFeature() directly since the feature pointer is rewinded by the rendering process
196  // We thus store the feature ids for future extraction
197  QgsFeature feat;
198  mFeatureIds.clear();
199  mFeatureKeys.clear();
201  while ( fit.nextFeature( feat ) )
202  {
203  if ( mFilterFeatures && !mFeatureFilter.isEmpty() )
204  {
205  QVariant result = filterExpression->evaluate( &feat, mCoverageLayer->pendingFields() );
206  if ( filterExpression->hasEvalError() )
207  {
208  QgsMessageLog::logMessage( tr( "Atlas filter eval error: %1" ).arg( filterExpression->evalErrorString() ), tr( "Composer" ) );
209  }
210 
211  // skip this feature if the filter evaluation if false
212  if ( !result.toBool() )
213  {
214  continue;
215  }
216  }
217  mFeatureIds.push_back( feat.id() );
218 
219  if ( mSortFeatures && sortIdx != -1 )
220  {
221  mFeatureKeys.insert( feat.id(), feat.attributes()[ sortIdx ] );
222  }
223  }
224 
225  // sort features, if asked for
226  if ( mFeatureKeys.count() )
227  {
229  qSort( mFeatureIds.begin(), mFeatureIds.end(), sorter );
230  }
231 
232  QgsExpression::setSpecialColumn( "$numfeatures", QVariant(( int )mFeatureIds.size() ) );
233 
234  //jump to first feature if currently using an atlas preview
235  //need to do this in case filtering/layer change has altered matching features
237  {
238  firstFeature();
239  }
240 
241  return mFeatureIds.size();
242 }
243 
244 
246 {
247  if ( !mCoverageLayer )
248  {
249  return false;
250  }
251 
252  emit renderBegun();
253 
254  bool featuresUpdated = updateFeatures();
255  if ( !featuresUpdated )
256  {
257  //no matching features found
258  return false;
259  }
260 
261  // special columns for expressions
262  QgsExpression::setSpecialColumn( "$numpages", QVariant( mComposition->numPages() ) );
263  QgsExpression::setSpecialColumn( "$numfeatures", QVariant(( int )mFeatureIds.size() ) );
264 
265  return true;
266 }
267 
269 {
270  if ( !mCoverageLayer )
271  {
272  return;
273  }
274 
275  emit featureChanged( 0 );
276 
277  updateAtlasMaps();
278 
279  emit renderEnded();
280 }
281 
283 {
284  //update atlas-enabled composer maps
285  QList<QgsComposerMap*> maps;
286  mComposition->composerItems( maps );
287  for ( QList<QgsComposerMap*>::iterator mit = maps.begin(); mit != maps.end(); ++mit )
288  {
289  QgsComposerMap* currentMap = ( *mit );
290  if ( !currentMap->atlasDriven() )
291  {
292  continue;
293  }
294 
295  currentMap->cache();
296  }
297 }
298 
300 {
301  return mFeatureIds.size();
302 }
303 
305 {
306  int newFeatureNo = mCurrentFeatureNo + 1;
307  if ( newFeatureNo >= mFeatureIds.size() )
308  {
309  newFeatureNo = mFeatureIds.size() - 1;
310  }
311 
312  prepareForFeature( newFeatureNo );
313 }
314 
316 {
317  int newFeatureNo = mCurrentFeatureNo - 1;
318  if ( newFeatureNo < 0 )
319  {
320  newFeatureNo = 0;
321  }
322 
323  prepareForFeature( newFeatureNo );
324 }
325 
327 {
328  prepareForFeature( 0 );
329 }
330 
332 {
333  prepareForFeature( mFeatureIds.size() - 1 );
334 }
335 
337 {
338  int featureI = mFeatureIds.indexOf( feat->id() );
339  if ( featureI < 0 )
340  {
341  //feature not found
342  return false;
343  }
344 
345  return prepareForFeature( featureI );
346 }
347 
348 bool QgsAtlasComposition::prepareForFeature( const int featureI )
349 {
350  if ( !mCoverageLayer )
351  {
352  return false;
353  }
354 
355  if ( mFeatureIds.size() == 0 )
356  {
357  emit statusMsgChanged( tr( "No matching atlas features" ) );
358  return false;
359  }
360 
361  mCurrentFeatureNo = featureI;
362 
363  // retrieve the next feature, based on its id
365 
366  QgsExpression::setSpecialColumn( "$atlasfeatureid", mCurrentFeature.id() );
367  QgsExpression::setSpecialColumn( "$atlasgeometry", QVariant::fromValue( *mCurrentFeature.geometry() ) );
368  QgsExpression::setSpecialColumn( "$atlasfeature", QVariant::fromValue( mCurrentFeature ) );
369  QgsExpression::setSpecialColumn( "$feature", QVariant(( int )featureI + 1 ) );
370 
371  // generate filename for current feature
372  if ( !evalFeatureFilename() )
373  {
374  //error evaluating filename
375  return false;
376  }
377 
379  emit statusMsgChanged( QString( tr( "Atlas feature %1 of %2" ) ).arg( featureI + 1 ).arg( mFeatureIds.size() ) );
380 
381  if ( !mCurrentFeature.isValid() )
382  {
383  //bad feature
384  return true;
385  }
386 
387  //update composer maps
388 
389  //build a list of atlas-enabled composer maps
390  QList<QgsComposerMap*> maps;
391  QList<QgsComposerMap*> atlasMaps;
392  mComposition->composerItems( maps );
393  for ( QList<QgsComposerMap*>::iterator mit = maps.begin(); mit != maps.end(); ++mit )
394  {
395  QgsComposerMap* currentMap = ( *mit );
396  if ( !currentMap->atlasDriven() )
397  {
398  continue;
399  }
400  atlasMaps << currentMap;
401  }
402 
403  //clear the transformed bounds of the previous feature
405 
406  if ( atlasMaps.isEmpty() )
407  {
408  //no atlas enabled maps
409  return true;
410  }
411 
412  // compute extent of current feature in the map CRS. This should be set on a per-atlas map basis,
413  // but given that it's not currently possible to have maps with different CRSes we can just
414  // calculate it once based on the first atlas maps' CRS.
415  computeExtent( atlasMaps[0] );
416 
417  //update atlas bounds of every atlas enabled composer map
418  for ( QList<QgsComposerMap*>::iterator mit = atlasMaps.begin(); mit != atlasMaps.end(); ++mit )
419  {
420  prepareMap( *mit );
421  }
422 
423  return true;
424 }
425 
427 {
428  // compute the extent of the current feature, in the crs of the specified map
429 
430  const QgsCoordinateReferenceSystem& coverage_crs = mCoverageLayer->crs();
431  // transformation needed for feature geometries
432  const QgsCoordinateReferenceSystem& destination_crs = map->composition()->mapSettings().destinationCrs();
433  mTransform.setSourceCrs( coverage_crs );
434  mTransform.setDestCRS( destination_crs );
435 
436  // QgsGeometry::boundingBox is expressed in the geometry"s native CRS
437  // We have to transform the grometry to the destination CRS and ask for the bounding box
438  // Note: we cannot directly take the transformation of the bounding box, since transformations are not linear
440  tgeom.transform( mTransform );
441  mTransformedFeatureBounds = tgeom.boundingBox();
442 }
443 
445 {
446  if ( !map->atlasDriven() )
447  {
448  return;
449  }
450 
452  {
453  //transformed extent of current feature hasn't been calculated yet. This can happen if
454  //a map has been set to be atlas controlled after prepare feature was called
455  computeExtent( map );
456  }
457 
458  double xa1 = mTransformedFeatureBounds.xMinimum();
459  double xa2 = mTransformedFeatureBounds.xMaximum();
460  double ya1 = mTransformedFeatureBounds.yMinimum();
461  double ya2 = mTransformedFeatureBounds.yMaximum();
463  QgsRectangle mOrigExtent = map->extent();
464 
465  //sanity check - only allow fixed scale mode for point layers
466  bool isPointLayer = false;
467  switch ( mCoverageLayer->wkbType() )
468  {
469  case QGis::WKBPoint:
470  case QGis::WKBPoint25D:
471  case QGis::WKBMultiPoint:
473  isPointLayer = true;
474  break;
475  default:
476  isPointLayer = false;
477  break;
478  }
479 
480  if ( map->atlasScalingMode() == QgsComposerMap::Fixed || map->atlasScalingMode() == QgsComposerMap::Predefined || isPointLayer )
481  {
482  QgsScaleCalculator calc;
483  calc.setMapUnits( composition()->mapSettings().mapUnits() );
484  calc.setDpi( 25.4 );
485  double originalScale = calc.calculate( mOrigExtent, map->rect().width() );
486  double geomCenterX = ( xa1 + xa2 ) / 2.0;
487  double geomCenterY = ( ya1 + ya2 ) / 2.0;
488 
489  if ( map->atlasScalingMode() == QgsComposerMap::Fixed || isPointLayer )
490  {
491  // only translate, keep the original scale (i.e. width x height)
492  double xMin = geomCenterX - mOrigExtent.width() / 2.0;
493  double yMin = geomCenterY - mOrigExtent.height() / 2.0;
494  newExtent = QgsRectangle( xMin,
495  yMin,
496  xMin + mOrigExtent.width(),
497  yMin + mOrigExtent.height() );
498 
499  //scale newExtent to match original scale of map
500  //this is required for geographic coordinate systems, where the scale varies by extent
501  double newScale = calc.calculate( newExtent, map->rect().width() );
502  newExtent.scale( originalScale / newScale );
503  }
504  else if ( map->atlasScalingMode() == QgsComposerMap::Predefined )
505  {
506  // choose one of the predefined scales
507  double newWidth = mOrigExtent.width();
508  double newHeight = mOrigExtent.height();
509  const QVector<double>& scales = mPredefinedScales;
510  for ( int i = 0; i < scales.size(); i++ )
511  {
512  double ratio = scales[i] / originalScale;
513  newWidth = mOrigExtent.width() * ratio;
514  newHeight = mOrigExtent.height() * ratio;
515 
516  // compute new extent, centered on feature
517  double xMin = geomCenterX - newWidth / 2.0;
518  double yMin = geomCenterY - newHeight / 2.0;
519  newExtent = QgsRectangle( xMin,
520  yMin,
521  xMin + newWidth,
522  yMin + newHeight );
523 
524  //scale newExtent to match desired map scale
525  //this is required for geographic coordinate systems, where the scale varies by extent
526  double newScale = calc.calculate( newExtent, map->rect().width() );
527  newExtent.scale( scales[i] / newScale );
528 
529  if (( newExtent.width() >= mTransformedFeatureBounds.width() ) && ( newExtent.height() >= mTransformedFeatureBounds.height() ) )
530  {
531  // this is the smallest extent that embeds the feature, stop here
532  break;
533  }
534  }
535  }
536  }
537  else if ( map->atlasScalingMode() == QgsComposerMap::Auto )
538  {
539  // auto scale
540 
542  double mapRatio = mOrigExtent.width() / mOrigExtent.height();
543 
544  // geometry height is too big
545  if ( geomRatio < mapRatio )
546  {
547  // extent the bbox's width
548  double adjWidth = ( mapRatio * mTransformedFeatureBounds.height() - mTransformedFeatureBounds.width() ) / 2.0;
549  xa1 -= adjWidth;
550  xa2 += adjWidth;
551  }
552  // geometry width is too big
553  else if ( geomRatio > mapRatio )
554  {
555  // extent the bbox's height
556  double adjHeight = ( mTransformedFeatureBounds.width() / mapRatio - mTransformedFeatureBounds.height() ) / 2.0;
557  ya1 -= adjHeight;
558  ya2 += adjHeight;
559  }
560  newExtent = QgsRectangle( xa1, ya1, xa2, ya2 );
561 
562  if ( map->atlasMargin() > 0.0 )
563  {
564  newExtent.scale( 1 + map->atlasMargin() );
565  }
566  }
567 
568  // set the new extent (and render)
569  map->setNewAtlasFeatureExtent( newExtent );
570 }
571 
573 {
574  return mCurrentFilename;
575 }
576 
577 void QgsAtlasComposition::writeXML( QDomElement& elem, QDomDocument& doc ) const
578 {
579  QDomElement atlasElem = doc.createElement( "Atlas" );
580  atlasElem.setAttribute( "enabled", mEnabled ? "true" : "false" );
581  if ( !mEnabled )
582  {
583  return;
584  }
585 
586  if ( mCoverageLayer )
587  {
588  atlasElem.setAttribute( "coverageLayer", mCoverageLayer->id() );
589  }
590  else
591  {
592  atlasElem.setAttribute( "coverageLayer", "" );
593  }
594 
595  atlasElem.setAttribute( "hideCoverage", mHideCoverage ? "true" : "false" );
596  atlasElem.setAttribute( "singleFile", mSingleFile ? "true" : "false" );
597  atlasElem.setAttribute( "filenamePattern", mFilenamePattern );
598 
599  atlasElem.setAttribute( "sortFeatures", mSortFeatures ? "true" : "false" );
600  if ( mSortFeatures )
601  {
602  atlasElem.setAttribute( "sortKey", mSortKeyAttributeName );
603  atlasElem.setAttribute( "sortAscending", mSortAscending ? "true" : "false" );
604  }
605  atlasElem.setAttribute( "filterFeatures", mFilterFeatures ? "true" : "false" );
606  if ( mFilterFeatures )
607  {
608  atlasElem.setAttribute( "featureFilter", mFeatureFilter );
609  }
610 
611  elem.appendChild( atlasElem );
612 }
613 
614 void QgsAtlasComposition::readXML( const QDomElement& atlasElem, const QDomDocument& )
615 {
616  mEnabled = atlasElem.attribute( "enabled", "false" ) == "true" ? true : false;
617  emit toggled( mEnabled );
618  if ( !mEnabled )
619  {
620  emit parameterChanged();
621  return;
622  }
623 
624  // look for stored layer name
625  mCoverageLayer = 0;
626  QMap<QString, QgsMapLayer*> layers = QgsMapLayerRegistry::instance()->mapLayers();
627  for ( QMap<QString, QgsMapLayer*>::const_iterator it = layers.begin(); it != layers.end(); ++it )
628  {
629  if ( it.key() == atlasElem.attribute( "coverageLayer" ) )
630  {
631  mCoverageLayer = dynamic_cast<QgsVectorLayer*>( it.value() );
632  break;
633  }
634  }
635 
636  mSingleFile = atlasElem.attribute( "singleFile", "false" ) == "true" ? true : false;
637  mFilenamePattern = atlasElem.attribute( "filenamePattern", "" );
638 
639  mSortFeatures = atlasElem.attribute( "sortFeatures", "false" ) == "true" ? true : false;
640  if ( mSortFeatures )
641  {
642  mSortKeyAttributeName = atlasElem.attribute( "sortKey", "" );
643  // since 2.3, the field name is saved instead of the field index
644  // following code keeps compatibility with version 2.2 projects
645  // to be removed in QGIS 3.0
646  bool isIndex;
647  int idx = mSortKeyAttributeName.toInt( &isIndex );
648  if ( isIndex && mCoverageLayer )
649  {
650  const QgsFields fields = mCoverageLayer->pendingFields();
651  if ( idx >= 0 && idx < fields.count() )
652  {
653  mSortKeyAttributeName = fields[idx].name();
654  }
655  }
656  mSortAscending = atlasElem.attribute( "sortAscending", "true" ) == "true" ? true : false;
657  }
658  mFilterFeatures = atlasElem.attribute( "filterFeatures", "false" ) == "true" ? true : false;
659  if ( mFilterFeatures )
660  {
661  mFeatureFilter = atlasElem.attribute( "featureFilter", "" );
662  }
663 
664  mHideCoverage = atlasElem.attribute( "hideCoverage", "false" ) == "true" ? true : false;
665 
666  emit parameterChanged();
667 }
668 
669 void QgsAtlasComposition::readXMLMapSettings( const QDomElement &elem, const QDomDocument &doc )
670 {
671  Q_UNUSED( doc );
672  //look for stored composer map, to upgrade pre 2.1 projects
673  int composerMapNo = elem.attribute( "composerMap", "-1" ).toInt();
675  if ( composerMapNo != -1 )
676  {
677  QList<QgsComposerMap*> maps;
678  mComposition->composerItems( maps );
679  for ( QList<QgsComposerMap*>::iterator it = maps.begin(); it != maps.end(); ++it )
680  {
681  if (( *it )->id() == composerMapNo )
682  {
683  composerMap = ( *it );
684  composerMap->setAtlasDriven( true );
685  break;
686  }
687  }
688  }
689 
690  //upgrade pre 2.1 projects
691  double margin = elem.attribute( "margin", "0.0" ).toDouble();
692  if ( composerMap && margin != 0 )
693  {
694  composerMap->setAtlasMargin( margin );
695  }
696  bool fixedScale = elem.attribute( "fixedScale", "false" ) == "true" ? true : false;
697  if ( composerMap && fixedScale )
698  {
700  }
701 }
702 
704 {
705  mHideCoverage = hide;
706 
708  {
709  //an atlas preview is enabled, so reflect changes in coverage layer visibility immediately
710  updateAtlasMaps();
711  mComposition->update();
712  }
713 
714 }
715 
716 bool QgsAtlasComposition::setFilenamePattern( const QString& pattern )
717 {
718  mFilenamePattern = pattern;
719  return updateFilenameExpression();
720 }
721 
723 {
724  if ( !mCoverageLayer )
725  {
726  return false;
727  }
728 
729  const QgsFields& fields = mCoverageLayer->pendingFields();
730 
731  if ( mFilenamePattern.size() > 0 )
732  {
733  mFilenameExpr = std::auto_ptr<QgsExpression>( new QgsExpression( mFilenamePattern ) );
734  // expression used to evaluate each filename
735  // test for evaluation errors
736  if ( mFilenameExpr->hasParserError() )
737  {
738  mFilenameParserError = mFilenameExpr->parserErrorString();
739  return false;
740  }
741 
742  // prepare the filename expression
743  mFilenameExpr->prepare( fields );
744  }
745 
746  //if atlas preview is currently enabled, regenerate filename for current feature
748  {
750  }
751  return true;
752 }
753 
755 {
756  //generate filename for current atlas feature
757  if ( mFilenamePattern.size() > 0 )
758  {
759  QVariant filenameRes = mFilenameExpr->evaluate( &mCurrentFeature, mCoverageLayer->pendingFields() );
760  if ( mFilenameExpr->hasEvalError() )
761  {
762  QgsMessageLog::logMessage( tr( "Atlas filename evaluation error: %1" ).arg( mFilenameExpr->evalErrorString() ), tr( "Composer" ) );
763  return false;
764  }
765 
766  mCurrentFilename = filenameRes.toString();
767  }
768  return true;
769 }
770 
771 void QgsAtlasComposition::setPredefinedScales( const QVector<double>& scales )
772 {
773  mPredefinedScales = scales;
774  // make sure the list is sorted
775  qSort( mPredefinedScales.begin(), mPredefinedScales.end() );
776 }
777 
780 {
781  //deprecated method. Until removed just return the property for the first atlas-enabled composer map
782  QgsComposerMap * map = composerMap();
783  if ( !map )
784  {
785  return false;
786  }
787 
788  return map->atlasFixedScale();
789 }
790 
792 {
793  //deprecated method. Until removed just set the property for the first atlas-enabled composer map
794  QgsComposerMap * map = composerMap();
795  if ( !map )
796  {
797  return;
798  }
799 
801 }
802 
804 {
805  //deprecated method. Until removed just return the property for the first atlas-enabled composer map
806  QgsComposerMap * map = composerMap();
807  if ( !map )
808  {
809  return 0;
810  }
811 
812  return map->atlasMargin();
813 }
814 
815 void QgsAtlasComposition::setMargin( float margin )
816 {
817  //deprecated method. Until removed just set the property for the first atlas-enabled composer map
818  QgsComposerMap * map = composerMap();
819  if ( !map )
820  {
821  return;
822  }
823 
824  map->setAtlasMargin(( double ) margin );
825 }
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
bool isValid() const
Return the validity of this feature.
Definition: qgsfeature.cpp:171
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:163
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)
Reads general atlas settings from xml.
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 QgsComposition * composition() const
Returns the composition the item is attached to.
const QgsCoordinateReferenceSystem & destinationCrs() const
returns CRS of destination coordinate reference system
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:95
int count() const
Return number of items.
Definition: qgsfield.h:200
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.
bool prepareForFeature(const int i)
Prepare the atlas map for the given feature.
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.
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 setAtlasMode(const QgsComposition::AtlasMode mode)
Sets the current atlas mode of the composition.
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.
void readXMLMapSettings(const QDomElement &elem, const QDomDocument &doc)
Reads old (pre 2.2) map related atlas settings from xml.
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 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.