QGIS API Documentation  3.20.0-Odense (decaadbb31)
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 
123 void QgsLayoutAtlas::setEnabled( bool enabled )
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 #ifdef HAVE_SERVER_PYTHON_PLUGINS
292  if ( mLayout->renderContext().featureFilterProvider() )
293  {
294  mLayout->renderContext().featureFilterProvider()->filterFeatures( mCoverageLayer.get(), req );
295  }
296 #endif
297 
298  QgsFeatureIterator fit = mCoverageLayer->getFeatures( req );
299 
300  std::unique_ptr<QgsExpression> nameExpression;
301  if ( !mPageNameExpression.isEmpty() )
302  {
303  nameExpression = std::make_unique< QgsExpression >( mPageNameExpression );
304  if ( nameExpression->hasParserError() )
305  {
306  nameExpression.reset( nullptr );
307  }
308  else
309  {
310  nameExpression->prepare( &expressionContext );
311  }
312  }
313 
314  // We cannot use nextFeature() directly since the feature pointer is rewinded by the rendering process
315  // We thus store the feature ids for future extraction
316  QgsFeature feat;
317  mFeatureIds.clear();
318  mFeatureKeys.clear();
319 
320  std::unique_ptr<QgsExpression> sortExpression;
321  if ( mSortFeatures && !mSortExpression.isEmpty() )
322  {
323  sortExpression = std::make_unique< QgsExpression >( mSortExpression );
324  if ( sortExpression->hasParserError() )
325  {
326  sortExpression.reset( nullptr );
327  }
328  else
329  {
330  sortExpression->prepare( &expressionContext );
331  }
332  }
333 
334  while ( fit.nextFeature( feat ) )
335  {
336  expressionContext.setFeature( feat );
337 
338  QString pageName;
339  if ( nameExpression )
340  {
341  QVariant result = nameExpression->evaluate( &expressionContext );
342  if ( nameExpression->hasEvalError() )
343  {
344  QgsMessageLog::logMessage( tr( "Atlas name eval error: %1" ).arg( nameExpression->evalErrorString() ), tr( "Layout" ) );
345  }
346  pageName = result.toString();
347  }
348 
349  mFeatureIds.push_back( qMakePair( feat.id(), pageName ) );
350 
351  if ( sortExpression )
352  {
353  QVariant result = sortExpression->evaluate( &expressionContext );
354  if ( sortExpression->hasEvalError() )
355  {
356  QgsMessageLog::logMessage( tr( "Atlas sort eval error: %1" ).arg( sortExpression->evalErrorString() ), tr( "Layout" ) );
357  }
358  mFeatureKeys.insert( feat.id(), result );
359  }
360  }
361 
362  // sort features, if asked for
363  if ( !mFeatureKeys.isEmpty() )
364  {
365  AtlasFeatureSorter sorter( mFeatureKeys, mSortAscending );
366  std::sort( mFeatureIds.begin(), mFeatureIds.end(), sorter ); // clazy:exclude=detaching-member
367  }
368 
369  emit numberFeaturesChanged( mFeatureIds.size() );
370  return mFeatureIds.size();
371 }
372 
374 {
375  if ( !mCoverageLayer )
376  {
377  return false;
378  }
379 
380  emit renderBegun();
381 
382  if ( !updateFeatures() )
383  {
384  //no matching features found
385  return false;
386  }
387 
388  return true;
389 }
390 
392 {
393  emit featureChanged( QgsFeature() );
394  emit renderEnded();
395  return true;
396 }
397 
399 {
400  return mFeatureIds.size();
401 }
402 
403 QString QgsLayoutAtlas::filePath( const QString &baseFilePath, const QString &extension )
404 {
405  QFileInfo fi( baseFilePath );
406  QDir dir = fi.dir(); // ignore everything except the directory
407  QString base = dir.filePath( mCurrentFilename );
408  if ( !extension.startsWith( '.' ) )
409  base += '.';
410  base += extension;
411  return base;
412 }
413 
415 {
416  int newFeatureNo = mCurrentFeatureNo + 1;
417  if ( newFeatureNo >= mFeatureIds.size() )
418  {
419  return false;
420  }
421 
422  return prepareForFeature( newFeatureNo );
423 }
424 
426 {
427  int newFeatureNo = mCurrentFeatureNo - 1;
428  if ( newFeatureNo < 0 )
429  {
430  return false;
431  }
432 
433  return prepareForFeature( newFeatureNo );
434 }
435 
437 {
438  return prepareForFeature( 0 );
439 }
440 
442 {
443  return prepareForFeature( mFeatureIds.size() - 1 );
444 }
445 
446 bool QgsLayoutAtlas::seekTo( int feature )
447 {
448  return prepareForFeature( feature );
449 }
450 
451 bool QgsLayoutAtlas::seekTo( const QgsFeature &feature )
452 {
453  int i = -1;
454  auto it = mFeatureIds.constBegin();
455  for ( int currentIdx = 0; it != mFeatureIds.constEnd(); ++it, ++currentIdx )
456  {
457  if ( ( *it ).first == feature.id() )
458  {
459  i = currentIdx;
460  break;
461  }
462  }
463 
464  if ( i < 0 )
465  {
466  //feature not found
467  return false;
468  }
469 
470  return seekTo( i );
471 }
472 
474 {
475  prepareForFeature( mCurrentFeatureNo );
476 }
477 
479 {
480  mLayout->renderContext().setFlag( QgsLayoutRenderContext::FlagHideCoverageLayer, hide );
481  if ( hide == mHideCoverage )
482  return;
483 
484  mHideCoverage = hide;
485  mLayout->refresh();
486  emit changed();
487 }
488 
489 bool QgsLayoutAtlas::setFilenameExpression( const QString &pattern, QString &errorString )
490 {
491  const bool hasChanged = mFilenameExpressionString != pattern;
492  mFilenameExpressionString = pattern;
493 
494  if ( hasChanged )
495  emit changed();
496 
497  return updateFilenameExpression( errorString );
498 }
499 
501 {
502  return mCurrentFilename;
503 }
504 
506 {
507  QgsExpressionContext expressionContext;
508  expressionContext << QgsExpressionContextUtils::globalScope();
509  if ( mLayout )
510  expressionContext << QgsExpressionContextUtils::projectScope( mLayout->project() )
512 
513  expressionContext.appendScope( QgsExpressionContextUtils::atlasScope( this ) );
514 
515  if ( mCoverageLayer )
516  expressionContext.appendScope( mCoverageLayer->createExpressionContextScope() );
517 
518  if ( mLayout && mEnabled )
519  {
520  if ( mCurrentFeature.isValid() )
521  {
522  expressionContext.lastScope()->setFeature( mCurrentFeature );
523  }
524  else if ( mCoverageLayer ) // Create an empty feature for the expression validation
525  {
526  QgsFeature feature{ mCoverageLayer->fields() };
527  feature.setValid( true );
528  expressionContext.lastScope()->setFeature( feature );
529  }
530  }
531  return expressionContext;
532 }
533 
534 bool QgsLayoutAtlas::updateFilenameExpression( QString &error )
535 {
536  if ( !mCoverageLayer )
537  {
538  return false;
539  }
540 
541  QgsExpressionContext expressionContext = createExpressionContext();
542  bool evalResult { true };
543 
544  if ( !mFilenameExpressionString.isEmpty() )
545  {
546  QgsExpression filenameExpression( mFilenameExpressionString );
547  // expression used to evaluate each filename
548  // test for evaluation errors
549  if ( filenameExpression.hasParserError() )
550  {
551  error = filenameExpression.parserErrorString();
552  return false;
553  }
554 
555  // prepare the filename expression
556  evalResult = filenameExpression.prepare( &expressionContext );
557  }
558 
559  // regenerate current filename
560  if ( evalResult )
561  {
562  evalResult = evalFeatureFilename( expressionContext );
563  }
564 
565  if ( ! evalResult )
566  {
567  error = mFilenameExpressionError;
568  }
569 
570  return evalResult;
571 }
572 
573 bool QgsLayoutAtlas::evalFeatureFilename( const QgsExpressionContext &context )
574 {
575  //generate filename for current atlas feature
576  mFilenameExpressionError.clear();
577  if ( !mFilenameExpressionString.isEmpty() )
578  {
579  QgsExpression filenameExpression( mFilenameExpressionString );
580  filenameExpression.prepare( &context );
581  QVariant filenameRes = filenameExpression.evaluate( &context );
582  if ( filenameExpression.hasEvalError() )
583  {
584  mFilenameExpressionError = filenameExpression.evalErrorString();
585  QgsMessageLog::logMessage( tr( "Atlas filename evaluation error: %1" ).arg( filenameExpression.evalErrorString() ), tr( "Layout" ) );
586  return false;
587  }
588 
589  mCurrentFilename = filenameRes.toString();
590  }
591  return true;
592 }
593 
594 bool QgsLayoutAtlas::prepareForFeature( const int featureI )
595 {
596  if ( !mCoverageLayer )
597  {
598  return false;
599  }
600 
601  if ( mFeatureIds.isEmpty() )
602  {
603  emit messagePushed( tr( "No matching atlas features" ) );
604  return false;
605  }
606 
607  if ( featureI >= mFeatureIds.size() )
608  {
609  return false;
610  }
611 
612  mCurrentFeatureNo = featureI;
613 
614  // retrieve the next feature, based on its id
615  if ( !mCoverageLayer->getFeatures( QgsFeatureRequest().setFilterFid( mFeatureIds[ featureI ].first ) ).nextFeature( mCurrentFeature ) )
616  return false;
617 
618  mLayout->reportContext().blockSignals( true ); // setFeature emits changed, we don't want 2 signals
619  mLayout->reportContext().setLayer( mCoverageLayer.get() );
620  mLayout->reportContext().blockSignals( false );
621  mLayout->reportContext().setFeature( mCurrentFeature );
622 
623  // must come after we've set the report context feature, or the expression context will have an outdated atlas feature
624  QgsExpressionContext expressionContext = createExpressionContext();
625 
626  // generate filename for current feature
627  if ( !evalFeatureFilename( expressionContext ) )
628  {
629  //error evaluating filename
630  return false;
631  }
632 
633  emit featureChanged( mCurrentFeature );
634  emit messagePushed( tr( "Atlas feature %1 of %2" ).arg( featureI + 1 ).arg( mFeatureIds.size() ) );
635 
636  return mCurrentFeature.isValid();
637 }
638 
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the scope.
static QgsExpressionContextScope * layoutScope(const QgsLayout *layout)
Creates a new scope which contains variables and functions relating to a QgsLayout layout.
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
static QgsExpressionContextScope * atlasScope(const QgsLayoutAtlas *atlas)
Creates a new scope which contains variables and functions relating to a QgsLayoutAtlas.
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
QgsExpressionContextScope * lastScope()
Returns the last scope added to the context.
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
Class for parsing and evaluation of expressions (formerly called "search strings").
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
QgsFeatureRequest & setExpressionContext(const QgsExpressionContext &context)
Sets the expression context used to evaluate filter expressions.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:56
bool isValid() const
Returns the validity of this feature.
Definition: qgsfeature.cpp:191
Q_GADGET QgsFeatureId id
Definition: qgsfeature.h:64
QString nameForPage(int page) const
Returns the calculated name for a specified atlas page number.
QString sortExpression() const
Returns the expression (or field name) to use for sorting features.
bool writeXml(QDomElement &parentElement, QDomDocument &document, const QgsReadWriteContext &context) const override
Stores the objects's state in a DOM element.
QString filenameExpression() const
Returns the filename expression used for generating output filenames for each atlas page.
void setCoverageLayer(QgsVectorLayer *layer)
Sets the coverage layer to use for the atlas features.
bool beginRender() override
Called when rendering begins, before iteration commences.
bool setFilterExpression(const QString &expression, QString &errorString)
Sets the expression used for filtering features in the coverage layer.
void toggled(bool)
Emitted when atlas is enabled or disabled.
void setSortAscending(bool ascending)
Sets whether features should be sorted in an ascending order.
bool seekTo(int feature)
Seeks to the specified feature number.
void featureChanged(const QgsFeature &feature)
Emitted when the current atlas feature changes.
void setEnabled(bool enabled)
Sets whether the atlas is enabled.
friend class AtlasFeatureSorter
void setPageNameExpression(const QString &expression)
Sets the expression (or field name) used for calculating the page name.
bool first()
Seeks to the first feature, returning false if no feature was found.
QString filterExpression() const
Returns the expression used for filtering features in the coverage layer.
QgsLayout * layout() override
Returns the layout associated with the iterator.
bool enabled() const
Returns whether the atlas generation is enabled.
bool setFilenameExpression(const QString &expression, QString &errorString)
Sets the filename expression used for generating output filenames for each atlas page.
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
void setSortFeatures(bool enabled)
Sets whether features should be sorted in the atlas.
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.
QString currentFilename() const
Returns the current feature filename.
bool readXml(const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context) override
Sets the objects's state from a DOM element.
bool last()
Seeks to the last feature, returning false if no feature was found.
QgsLayoutAtlas(QgsLayout *layout)
Constructor for new QgsLayoutAtlas.
int count() const override
Returns the number of features to iterate over.
void numberFeaturesChanged(int numFeatures)
Emitted when the number of features for the atlas changes.
void messagePushed(const QString &message)
Emitted when the atlas has an updated status bar message.
void setSortExpression(const QString &expression)
Sets the expression (or field name) to use for sorting features.
void coverageLayerChanged(QgsVectorLayer *layer)
Emitted when the coverage layer for the atlas changes.
void setFilterFeatures(bool filtered)
Sets whether features should be filtered in the coverage layer.
bool next() override
void renderBegun()
Emitted when atlas rendering has begun.
void renderEnded()
Emitted when atlas rendering has ended.
void changed()
Emitted when one of the atlas parameters changes.
bool previous()
Iterates to the previous feature, returning false if no previous feature exists.
void refreshCurrentFeature()
Refreshes the current atlas feature, by refetching its attributes from the vector layer provider.
bool endRender() override
Ends the render, performing any required cleanup tasks.
int updateFeatures()
Requeries the current atlas coverage layer and applies filtering and sorting.
QString stringType() const override
Returns the object type as a string.
void setHideCoverage(bool hide)
Sets whether the coverage layer should be hidden in map items in the layouts.
@ FlagHideCoverageLayer
Hide coverage layer in outputs.
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
Definition: qgslayout.h:51
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition: qgsproject.h:99
void layersWillBeRemoved(const QStringList &layerIds)
Emitted when one or more layers are about to be removed from the registry.
The class is used as a container of context for various read/write operations on other objects.
Represents a vector layer which manages a vector based data sets.
QgsExpressionContextScope * createExpressionContextScope() const FINAL
This method needs to be reimplemented in all classes which implement this interface and return an exp...
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
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:127
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:195
_LayerRef< QgsVectorLayer > QgsVectorLayerRef
QString source
Weak reference to layer public source.
QString name
Weak reference to layer name.
TYPE * get() const
Returns a pointer to the layer, or nullptr if the reference has not yet been matched to a layer.
QString provider
Weak reference to layer provider.
TYPE * resolveWeakly(const QgsProject *project, MatchType matchType=MatchType::All)
Resolves the map layer by attempting to find a matching layer in a project using a weak match.
void setLayer(TYPE *l)
Sets the reference to point to a specified layer.
QString layerId
Original layer ID.