QGIS API Documentation  3.10.0-A Coruña (6c816b4204)
qgslayoutatlas.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgslayoutatlas.cpp
3  ----------------
4  begin : December 2017
5  copyright : (C) 2017 by Nyall Dawson
6  email : nyall dot dawson at gmail 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 <algorithm>
18 #include <stdexcept>
19 #include <QtAlgorithms>
20 
21 #include "qgslayoutatlas.h"
22 #include "qgslayout.h"
23 #include "qgsmessagelog.h"
24 #include "qgsfeaturerequest.h"
25 #include "qgsfeatureiterator.h"
26 #include "qgsvectorlayer.h"
28 
30  : QObject( layout )
31  , mLayout( layout )
32  , mFilenameExpressionString( QStringLiteral( "'output_'||@atlas_featurenumber" ) )
33 {
34 
35  //listen out for layer removal
36  connect( mLayout->project(), static_cast < void ( QgsProject::* )( const QStringList & ) >( &QgsProject::layersWillBeRemoved ), this, &QgsLayoutAtlas::removeLayers );
37 }
38 
40 {
41  return QStringLiteral( "atlas" );
42 }
43 
45 {
46  return mLayout;
47 }
48 
50 {
51  return mLayout.data();
52 }
53 
54 bool QgsLayoutAtlas::writeXml( QDomElement &parentElement, QDomDocument &document, const QgsReadWriteContext & ) const
55 {
56  QDomElement atlasElem = document.createElement( QStringLiteral( "Atlas" ) );
57  atlasElem.setAttribute( QStringLiteral( "enabled" ), mEnabled ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
58 
59  if ( mCoverageLayer )
60  {
61  atlasElem.setAttribute( QStringLiteral( "coverageLayer" ), mCoverageLayer.layerId );
62  atlasElem.setAttribute( QStringLiteral( "coverageLayerName" ), mCoverageLayer.name );
63  atlasElem.setAttribute( QStringLiteral( "coverageLayerSource" ), mCoverageLayer.source );
64  atlasElem.setAttribute( QStringLiteral( "coverageLayerProvider" ), mCoverageLayer.provider );
65  }
66  else
67  {
68  atlasElem.setAttribute( QStringLiteral( "coverageLayer" ), QString() );
69  }
70 
71  atlasElem.setAttribute( QStringLiteral( "hideCoverage" ), mHideCoverage ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
72  atlasElem.setAttribute( QStringLiteral( "filenamePattern" ), mFilenameExpressionString );
73  atlasElem.setAttribute( QStringLiteral( "pageNameExpression" ), mPageNameExpression );
74 
75  atlasElem.setAttribute( QStringLiteral( "sortFeatures" ), mSortFeatures ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
76  if ( mSortFeatures )
77  {
78  atlasElem.setAttribute( QStringLiteral( "sortKey" ), mSortExpression );
79  atlasElem.setAttribute( QStringLiteral( "sortAscending" ), mSortAscending ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
80  }
81  atlasElem.setAttribute( QStringLiteral( "filterFeatures" ), mFilterFeatures ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
82  if ( mFilterFeatures )
83  {
84  atlasElem.setAttribute( QStringLiteral( "featureFilter" ), mFilterExpression );
85  }
86 
87  parentElement.appendChild( atlasElem );
88 
89  return true;
90 }
91 
92 bool QgsLayoutAtlas::readXml( const QDomElement &atlasElem, const QDomDocument &, const QgsReadWriteContext & )
93 {
94  mEnabled = atlasElem.attribute( QStringLiteral( "enabled" ), QStringLiteral( "0" ) ).toInt();
95 
96  // look for stored layer name
97  QString layerId = atlasElem.attribute( QStringLiteral( "coverageLayer" ) );
98  QString layerName = atlasElem.attribute( QStringLiteral( "coverageLayerName" ) );
99  QString layerSource = atlasElem.attribute( QStringLiteral( "coverageLayerSource" ) );
100  QString layerProvider = atlasElem.attribute( QStringLiteral( "coverageLayerProvider" ) );
101 
102  mCoverageLayer = QgsVectorLayerRef( layerId, layerName, layerSource, layerProvider );
103  mCoverageLayer.resolveWeakly( mLayout->project() );
104  mLayout->reportContext().setLayer( mCoverageLayer.get() );
105 
106  mPageNameExpression = atlasElem.attribute( QStringLiteral( "pageNameExpression" ), QString() );
107  QString error;
108  setFilenameExpression( atlasElem.attribute( QStringLiteral( "filenamePattern" ), QString() ), error );
109 
110  mSortFeatures = atlasElem.attribute( QStringLiteral( "sortFeatures" ), QStringLiteral( "0" ) ).toInt();
111  mSortExpression = atlasElem.attribute( QStringLiteral( "sortKey" ) );
112  mSortAscending = atlasElem.attribute( QStringLiteral( "sortAscending" ), QStringLiteral( "1" ) ).toInt();
113  mFilterFeatures = atlasElem.attribute( QStringLiteral( "filterFeatures" ), QStringLiteral( "0" ) ).toInt();
114  mFilterExpression = atlasElem.attribute( QStringLiteral( "featureFilter" ) );
115 
116  mHideCoverage = atlasElem.attribute( QStringLiteral( "hideCoverage" ), QStringLiteral( "0" ) ).toInt();
117 
118  emit toggled( mEnabled );
119  emit changed();
120  return true;
121 }
122 
124 {
125  if ( enabled == mEnabled )
126  {
127  return;
128  }
129 
130  mEnabled = enabled;
131  emit toggled( enabled );
132  emit changed();
133 }
134 
135 void QgsLayoutAtlas::removeLayers( const QStringList &layers )
136 {
137  if ( !mCoverageLayer )
138  {
139  return;
140  }
141 
142  for ( const QString &layerId : layers )
143  {
144  if ( layerId == mCoverageLayer.layerId )
145  {
146  //current coverage layer removed
147  mCoverageLayer.setLayer( nullptr );
148  setEnabled( false );
149  break;
150  }
151  }
152 }
153 
155 {
156  if ( layer == mCoverageLayer.get() )
157  {
158  return;
159  }
160 
161  mCoverageLayer.setLayer( layer );
162  emit coverageLayerChanged( layer );
163 }
164 
165 void QgsLayoutAtlas::setPageNameExpression( const QString &expression )
166 {
167  if ( mPageNameExpression == expression )
168  return;
169 
170  mPageNameExpression = expression;
171  emit changed();
172 }
173 
174 QString QgsLayoutAtlas::nameForPage( int pageNumber ) const
175 {
176  if ( pageNumber < 0 || pageNumber >= mFeatureIds.count() )
177  return QString();
178 
179  return mFeatureIds.at( pageNumber ).second;
180 }
181 
183 {
184  if ( mSortFeatures == enabled )
185  return;
186 
187  mSortFeatures = enabled;
188  emit changed();
189 }
190 
191 void QgsLayoutAtlas::setSortAscending( bool ascending )
192 {
193  if ( mSortAscending == ascending )
194  return;
195 
196  mSortAscending = ascending;
197  emit changed();
198 }
199 
200 void QgsLayoutAtlas::setSortExpression( const QString &expression )
201 {
202  if ( mSortExpression == expression )
203  return;
204 
205  mSortExpression = expression;
206  emit changed();
207 }
208 
210 {
211  if ( mFilterFeatures == filtered )
212  return;
213 
214  mFilterFeatures = filtered;
215  emit changed();
216 }
217 
218 bool QgsLayoutAtlas::setFilterExpression( const QString &expression, QString &errorString )
219 {
220  errorString.clear();
221  const bool hasChanged = mFilterExpression != expression;
222  mFilterExpression = expression;
223 
224  QgsExpression filterExpression( mFilterExpression );
225  if ( hasChanged )
226  emit changed();
227  if ( filterExpression.hasParserError() )
228  {
229  errorString = filterExpression.parserErrorString();
230  return false;
231  }
232 
233  return true;
234 }
235 
236 
238 class AtlasFeatureSorter
239 {
240  public:
241  AtlasFeatureSorter( QgsLayoutAtlas::SorterKeys &keys, bool ascending = true )
242  : mKeys( keys )
243  , mAscending( ascending )
244  {}
245 
246  bool operator()( const QPair< QgsFeatureId, QString > &id1, const QPair< QgsFeatureId, QString > &id2 )
247  {
248  return mAscending ? qgsVariantLessThan( mKeys.value( id1.first ), mKeys.value( id2.first ) )
249  : qgsVariantGreaterThan( mKeys.value( id1.first ), mKeys.value( id2.first ) );
250  }
251 
252  private:
253  QgsLayoutAtlas::SorterKeys &mKeys;
254  bool mAscending;
255 };
256 
258 
260 {
261  mCurrentFeatureNo = -1;
262  if ( !mCoverageLayer )
263  {
264  return 0;
265  }
266 
267  QgsExpressionContext expressionContext = createExpressionContext();
268 
269  QString error;
270  updateFilenameExpression( error );
271 
272  // select all features with all attributes
273  QgsFeatureRequest req;
274 
275  req.setExpressionContext( expressionContext );
276 
277  mFilterParserError.clear();
278  if ( mFilterFeatures && !mFilterExpression.isEmpty() )
279  {
280  QgsExpression filterExpression( mFilterExpression );
281  if ( filterExpression.hasParserError() )
282  {
283  mFilterParserError = filterExpression.parserErrorString();
284  return 0;
285  }
286 
287  //filter good to go
288  req.setFilterExpression( mFilterExpression );
289  }
290 
291  QgsFeatureIterator fit = mCoverageLayer->getFeatures( req );
292 
293  std::unique_ptr<QgsExpression> nameExpression;
294  if ( !mPageNameExpression.isEmpty() )
295  {
296  nameExpression = qgis::make_unique< QgsExpression >( mPageNameExpression );
297  if ( nameExpression->hasParserError() )
298  {
299  nameExpression.reset( nullptr );
300  }
301  else
302  {
303  nameExpression->prepare( &expressionContext );
304  }
305  }
306 
307  // We cannot use nextFeature() directly since the feature pointer is rewinded by the rendering process
308  // We thus store the feature ids for future extraction
309  QgsFeature feat;
310  mFeatureIds.clear();
311  mFeatureKeys.clear();
312 
313  std::unique_ptr<QgsExpression> sortExpression;
314  if ( mSortFeatures && !mSortExpression.isEmpty() )
315  {
316  sortExpression = qgis::make_unique< QgsExpression >( mSortExpression );
317  if ( sortExpression->hasParserError() )
318  {
319  sortExpression.reset( nullptr );
320  }
321  else
322  {
323  sortExpression->prepare( &expressionContext );
324  }
325  }
326 
327  while ( fit.nextFeature( feat ) )
328  {
329  expressionContext.setFeature( feat );
330 
331  QString pageName;
332  if ( nameExpression )
333  {
334  QVariant result = nameExpression->evaluate( &expressionContext );
335  if ( nameExpression->hasEvalError() )
336  {
337  QgsMessageLog::logMessage( tr( "Atlas name eval error: %1" ).arg( nameExpression->evalErrorString() ), tr( "Layout" ) );
338  }
339  pageName = result.toString();
340  }
341 
342  mFeatureIds.push_back( qMakePair( feat.id(), pageName ) );
343 
344  if ( sortExpression )
345  {
346  QVariant result = sortExpression->evaluate( &expressionContext );
347  if ( sortExpression->hasEvalError() )
348  {
349  QgsMessageLog::logMessage( tr( "Atlas sort eval error: %1" ).arg( sortExpression->evalErrorString() ), tr( "Layout" ) );
350  }
351  mFeatureKeys.insert( feat.id(), result );
352  }
353  }
354 
355  // sort features, if asked for
356  if ( !mFeatureKeys.isEmpty() )
357  {
358  AtlasFeatureSorter sorter( mFeatureKeys, mSortAscending );
359  std::sort( mFeatureIds.begin(), mFeatureIds.end(), sorter ); // clazy:exclude=detaching-member
360  }
361 
362  emit numberFeaturesChanged( mFeatureIds.size() );
363  return mFeatureIds.size();
364 }
365 
367 {
368  if ( !mCoverageLayer )
369  {
370  return false;
371  }
372 
373  emit renderBegun();
374 
375  if ( !updateFeatures() )
376  {
377  //no matching features found
378  return false;
379  }
380 
381  return true;
382 }
383 
385 {
386  emit featureChanged( QgsFeature() );
387  emit renderEnded();
388  return true;
389 }
390 
392 {
393  return mFeatureIds.size();
394 }
395 
396 QString QgsLayoutAtlas::filePath( const QString &baseFilePath, const QString &extension )
397 {
398  QFileInfo fi( baseFilePath );
399  QDir dir = fi.dir(); // ignore everything except the directory
400  QString base = dir.filePath( mCurrentFilename );
401  if ( !extension.startsWith( '.' ) )
402  base += '.';
403  base += extension;
404  return base;
405 }
406 
408 {
409  int newFeatureNo = mCurrentFeatureNo + 1;
410  if ( newFeatureNo >= mFeatureIds.size() )
411  {
412  return false;
413  }
414 
415  return prepareForFeature( newFeatureNo );
416 }
417 
419 {
420  int newFeatureNo = mCurrentFeatureNo - 1;
421  if ( newFeatureNo < 0 )
422  {
423  return false;
424  }
425 
426  return prepareForFeature( newFeatureNo );
427 }
428 
430 {
431  return prepareForFeature( 0 );
432 }
433 
435 {
436  return prepareForFeature( mFeatureIds.size() - 1 );
437 }
438 
439 bool QgsLayoutAtlas::seekTo( int feature )
440 {
441  return prepareForFeature( feature );
442 }
443 
444 bool QgsLayoutAtlas::seekTo( const QgsFeature &feature )
445 {
446  int i = -1;
447  auto it = mFeatureIds.constBegin();
448  for ( int currentIdx = 0; it != mFeatureIds.constEnd(); ++it, ++currentIdx )
449  {
450  if ( ( *it ).first == feature.id() )
451  {
452  i = currentIdx;
453  break;
454  }
455  }
456 
457  if ( i < 0 )
458  {
459  //feature not found
460  return false;
461  }
462 
463  return seekTo( i );
464 }
465 
467 {
468  prepareForFeature( mCurrentFeatureNo );
469 }
470 
472 {
473  mLayout->renderContext().setFlag( QgsLayoutRenderContext::FlagHideCoverageLayer, hide );
474  if ( hide == mHideCoverage )
475  return;
476 
477  mHideCoverage = hide;
478  mLayout->refresh();
479  emit changed();
480 }
481 
482 bool QgsLayoutAtlas::setFilenameExpression( const QString &pattern, QString &errorString )
483 {
484  const bool hasChanged = mFilenameExpressionString != pattern;
485  mFilenameExpressionString = pattern;
486 
487  if ( hasChanged )
488  emit changed();
489 
490  return updateFilenameExpression( errorString );
491 }
492 
494 {
495  return mCurrentFilename;
496 }
497 
499 {
500  QgsExpressionContext expressionContext;
501  expressionContext << QgsExpressionContextUtils::globalScope();
502  if ( mLayout )
503  expressionContext << QgsExpressionContextUtils::projectScope( mLayout->project() )
505 
506  expressionContext.appendScope( QgsExpressionContextUtils::atlasScope( this ) );
507 
508  if ( mCoverageLayer )
509  expressionContext.appendScope( mCoverageLayer->createExpressionContextScope() );
510 
511  if ( mLayout && mEnabled )
512  expressionContext.lastScope()->setFeature( mCurrentFeature );
513 
514  return expressionContext;
515 }
516 
517 bool QgsLayoutAtlas::updateFilenameExpression( QString &error )
518 {
519  if ( !mCoverageLayer )
520  {
521  return false;
522  }
523 
524  QgsExpressionContext expressionContext = createExpressionContext();
525 
526  if ( !mFilenameExpressionString.isEmpty() )
527  {
528  mFilenameExpression = QgsExpression( mFilenameExpressionString );
529  // expression used to evaluate each filename
530  // test for evaluation errors
531  if ( mFilenameExpression.hasParserError() )
532  {
533  error = mFilenameExpression.parserErrorString();
534  return false;
535  }
536 
537  // prepare the filename expression
538  mFilenameExpression.prepare( &expressionContext );
539  }
540 
541  // regenerate current filename
542  evalFeatureFilename( expressionContext );
543  return true;
544 }
545 
546 bool QgsLayoutAtlas::evalFeatureFilename( const QgsExpressionContext &context )
547 {
548  //generate filename for current atlas feature
549  if ( !mFilenameExpressionString.isEmpty() && mFilenameExpression.isValid() )
550  {
551  QVariant filenameRes = mFilenameExpression.evaluate( &context );
552  if ( mFilenameExpression.hasEvalError() )
553  {
554  QgsMessageLog::logMessage( tr( "Atlas filename evaluation error: %1" ).arg( mFilenameExpression.evalErrorString() ), tr( "Layout" ) );
555  return false;
556  }
557 
558  mCurrentFilename = filenameRes.toString();
559  }
560  return true;
561 }
562 
563 bool QgsLayoutAtlas::prepareForFeature( const int featureI )
564 {
565  if ( !mCoverageLayer )
566  {
567  return false;
568  }
569 
570  if ( mFeatureIds.isEmpty() )
571  {
572  emit messagePushed( tr( "No matching atlas features" ) );
573  return false;
574  }
575 
576  if ( featureI >= mFeatureIds.size() )
577  {
578  return false;
579  }
580 
581  mCurrentFeatureNo = featureI;
582 
583  // retrieve the next feature, based on its id
584  if ( !mCoverageLayer->getFeatures( QgsFeatureRequest().setFilterFid( mFeatureIds[ featureI ].first ) ).nextFeature( mCurrentFeature ) )
585  return false;
586 
587  mLayout->reportContext().blockSignals( true ); // setFeature emits changed, we don't want 2 signals
588  mLayout->reportContext().setLayer( mCoverageLayer.get() );
589  mLayout->reportContext().blockSignals( false );
590  mLayout->reportContext().setFeature( mCurrentFeature );
591 
592  // must come after we've set the report context feature, or the expression context will have an outdated atlas feature
593  QgsExpressionContext expressionContext = createExpressionContext();
594 
595  // generate filename for current feature
596  if ( !evalFeatureFilename( expressionContext ) )
597  {
598  //error evaluating filename
599  return false;
600  }
601 
602  emit featureChanged( mCurrentFeature );
603  emit messagePushed( QString( tr( "Atlas feature %1 of %2" ) ).arg( featureI + 1 ).arg( mFeatureIds.size() ) );
604 
605  return mCurrentFeature.isValid();
606 }
607 
void setCoverageLayer(QgsVectorLayer *layer)
Sets the coverage layer to use for the atlas features.
Class for parsing and evaluation of expressions (formerly called "search strings").
QgsFeatureId id
Definition: qgsfeature.h:64
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
The class is used as a container of context for various read/write operations on other objects...
Wrapper for iterator of features from vector data provider or vector layer.
QString filePath(const QString &baseFilePath, const QString &extension) override
Returns the file path for the current feature, based on a specified base file path and extension...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
QString sortExpression() const
Returns the expression (or field name) to use for sorting features.
int count() const override
Returns the number of features to iterate over.
void setSortAscending(bool ascending)
Sets whether features should be sorted in an ascending order.
TYPE * resolveWeakly(const QgsProject *project)
Resolves the map layer by attempting to find a matching layer in a project using a weak match...
void setFilterFeatures(bool filtered)
Sets whether features should be filtered in the coverage layer.
QString stringType() const override
Returns the object type as a string.
void toggled(bool)
Emitted when atlas is enabled or disabled.
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
bool qgsVariantGreaterThan(const QVariant &lhs, const QVariant &rhs)
Compares two QVariant values and returns whether the first is greater than the second.
Definition: qgis.cpp:222
static QgsExpressionContextScope * atlasScope(const QgsLayoutAtlas *atlas)
Creates a new scope which contains variables and functions relating to a QgsLayoutAtlas.
bool writeXml(QDomElement &parentElement, QDomDocument &document, const QgsReadWriteContext &context) const override
Stores the objects&#39;s state in a DOM element.
QString parserErrorString() const
Returns parser error.
void setSortExpression(const QString &expression)
Sets the expression (or field name) to use for sorting features.
bool qgsVariantLessThan(const QVariant &lhs, const QVariant &rhs)
Compares two QVariant values and returns whether the first is less than the second.
Definition: qgis.cpp:154
QgsLayoutAtlas(QgsLayout *layout)
Constructor for new QgsLayoutAtlas.
QgsLayout * layout() override
Returns the layout associated with the iterator.
bool endRender() override
Ends the render, performing any required cleanup tasks.
bool setFilenameExpression(const QString &expression, QString &errorString)
Sets the filename expression used for generating output filenames for each atlas page.
QgsFeatureRequest & setExpressionContext(const QgsExpressionContext &context)
Sets the expression context used to evaluate filter expressions.
void refreshCurrentFeature()
Refreshes the current atlas feature, by refetching its attributes from the vector layer provider...
void numberFeaturesChanged(int numFeatures)
Emitted when the number of features for the atlas changes.
QgsExpressionContextScope * lastScope()
Returns the last scope added to the context.
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
QString provider
Weak reference to layer provider.
QString layerId
Original layer ID.
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context...
bool readXml(const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context) override
Sets the objects&#39;s state from a DOM element.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
QString name
Weak reference to layer name.
bool last()
Seeks to the last feature, returning false if no feature was found.
This class wraps a request for features to a vector layer (or directly its vector data provider)...
Encapsulates a QGIS project, including sets of map layers and their styles, layouts, annotations, canvases, etc.
Definition: qgsproject.h:89
QString currentFilename() const
Returns the current feature filename.
void setHideCoverage(bool hide)
Sets whether the coverage layer should be hidden in map items in the layouts.
bool first()
Seeks to the first feature, returning false if no feature was found.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the scope.
void setLayer(TYPE *l)
Sets the reference to point to a specified layer.
void renderBegun()
Emitted when atlas rendering has begun.
QString source
Weak reference to layer public source.
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
Definition: qgslayout.h:49
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
bool previous()
Iterates to the previous feature, returning false if no previous feature exists.
bool next() override
QString filterExpression() const
Returns the expression used for filtering features in the coverage layer.
bool setFilterExpression(const QString &expression, QString &errorString)
Sets the expression used for filtering features in the coverage layer.
void renderEnded()
Emitted when atlas rendering has ended.
void layersWillBeRemoved(const QStringList &layerIds)
Emitted when one or more layers are about to be removed from the registry.
static QgsExpressionContextScope * layoutScope(const QgsLayout *layout)
Creates a new scope which contains variables and functions relating to a QgsLayout layout...
void setEnabled(bool enabled)
Sets whether the atlas is enabled.
friend class AtlasFeatureSorter
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
void featureChanged(const QgsFeature &feature)
Emitted when the current atlas feature changes.
_LayerRef< QgsVectorLayer > QgsVectorLayerRef
int updateFeatures()
Requeries the current atlas coverage layer and applies filtering and sorting.
QString nameForPage(int page) const
Returns the calculated name for a specified atlas page number.
bool enabled() const
Returns whether the atlas generation is enabled.
bool beginRender() override
Called when rendering begins, before iteration commences.
void messagePushed(const QString &message)
Emitted when the atlas has an updated status bar message.
void setSortFeatures(bool enabled)
Sets whether features should be sorted in the atlas.
bool nextFeature(QgsFeature &f)
void setPageNameExpression(const QString &expression)
Sets the expression (or field name) used for calculating the page name.
Represents a vector layer which manages a vector based data sets.
TYPE * get() const
Returns a pointer to the layer, or nullptr if the reference has not yet been matched to a layer...
void changed()
Emitted when one of the atlas parameters changes.
bool seekTo(int feature)
Seeks to the specified feature number.
void coverageLayerChanged(QgsVectorLayer *layer)
Emitted when the coverage layer for the atlas changes.