QGIS API Documentation  3.14.0-Pi (9f7028fd23)
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 
49 const QgsLayout *QgsLayoutAtlas::layout() const
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  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  {
513  if ( mCurrentFeature.isValid() )
514  {
515  expressionContext.lastScope()->setFeature( mCurrentFeature );
516  }
517  else if ( mCoverageLayer ) // Create an empty feature for the expression validation
518  {
519  QgsFeature feature{ mCoverageLayer->fields() };
520  feature.setValid( true );
521  expressionContext.lastScope()->setFeature( feature );
522  }
523  }
524  return expressionContext;
525 }
526 
527 bool QgsLayoutAtlas::updateFilenameExpression( QString &error )
528 {
529  if ( !mCoverageLayer )
530  {
531  return false;
532  }
533 
534  QgsExpressionContext expressionContext = createExpressionContext();
535  bool evalResult { true };
536 
537  if ( !mFilenameExpressionString.isEmpty() )
538  {
539  mFilenameExpression = QgsExpression( mFilenameExpressionString );
540  // expression used to evaluate each filename
541  // test for evaluation errors
542  if ( mFilenameExpression.hasParserError() )
543  {
544  error = mFilenameExpression.parserErrorString();
545  return false;
546  }
547 
548  // prepare the filename expression
549  evalResult = mFilenameExpression.prepare( &expressionContext );
550  }
551 
552  // regenerate current filename
553  if ( evalResult )
554  {
555  evalResult = evalFeatureFilename( expressionContext );
556  }
557 
558  if ( ! evalResult )
559  {
560  error = mFilenameExpression.evalErrorString();
561  }
562 
563  return evalResult;
564 }
565 
566 bool QgsLayoutAtlas::evalFeatureFilename( const QgsExpressionContext &context )
567 {
568  //generate filename for current atlas feature
569  if ( !mFilenameExpressionString.isEmpty() && mFilenameExpression.isValid() )
570  {
571  QVariant filenameRes = mFilenameExpression.evaluate( &context );
572  if ( mFilenameExpression.hasEvalError() )
573  {
574  QgsMessageLog::logMessage( tr( "Atlas filename evaluation error: %1" ).arg( mFilenameExpression.evalErrorString() ), tr( "Layout" ) );
575  return false;
576  }
577 
578  mCurrentFilename = filenameRes.toString();
579  }
580  return true;
581 }
582 
583 bool QgsLayoutAtlas::prepareForFeature( const int featureI )
584 {
585  if ( !mCoverageLayer )
586  {
587  return false;
588  }
589 
590  if ( mFeatureIds.isEmpty() )
591  {
592  emit messagePushed( tr( "No matching atlas features" ) );
593  return false;
594  }
595 
596  if ( featureI >= mFeatureIds.size() )
597  {
598  return false;
599  }
600 
601  mCurrentFeatureNo = featureI;
602 
603  // retrieve the next feature, based on its id
604  if ( !mCoverageLayer->getFeatures( QgsFeatureRequest().setFilterFid( mFeatureIds[ featureI ].first ) ).nextFeature( mCurrentFeature ) )
605  return false;
606 
607  mLayout->reportContext().blockSignals( true ); // setFeature emits changed, we don't want 2 signals
608  mLayout->reportContext().setLayer( mCoverageLayer.get() );
609  mLayout->reportContext().blockSignals( false );
610  mLayout->reportContext().setFeature( mCurrentFeature );
611 
612  // must come after we've set the report context feature, or the expression context will have an outdated atlas feature
613  QgsExpressionContext expressionContext = createExpressionContext();
614 
615  // generate filename for current feature
616  if ( !evalFeatureFilename( expressionContext ) )
617  {
618  //error evaluating filename
619  return false;
620  }
621 
622  emit featureChanged( mCurrentFeature );
623  emit messagePushed( QString( tr( "Atlas feature %1 of %2" ) ).arg( featureI + 1 ).arg( mFeatureIds.size() ) );
624 
625  return mCurrentFeature.isValid();
626 }
627 
QgsVectorLayer::getFeatures
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
Definition: qgsvectorlayer.cpp:993
QgsExpressionContext
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Definition: qgsexpressioncontext.h:369
QgsExpressionContextScope::setFeature
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the scope.
Definition: qgsexpressioncontext.h:317
QgsLayoutAtlas::setPageNameExpression
void setPageNameExpression(const QString &expression)
Sets the expression (or field name) used for calculating the page name.
Definition: qgslayoutatlas.cpp:165
qgsexpressioncontextutils.h
QgsLayoutAtlas::messagePushed
void messagePushed(const QString &message)
Emitted when the atlas has an updated status bar message.
QgsVectorLayer::createExpressionContextScope
QgsExpressionContextScope * createExpressionContextScope() const FINAL
This method needs to be reimplemented in all classes which implement this interface and return an exp...
Definition: qgsvectorlayer.cpp:4938
QgsLayoutAtlas::featureChanged
void featureChanged(const QgsFeature &feature)
Emitted when the current atlas feature changes.
qgsfeaturerequest.h
QgsProject::layersWillBeRemoved
void layersWillBeRemoved(const QStringList &layerIds)
Emitted when one or more layers are about to be removed from the registry.
QgsLayoutAtlas::numberFeaturesChanged
void numberFeaturesChanged(int numFeatures)
Emitted when the number of features for the atlas changes.
_LayerRef::resolveWeakly
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.
Definition: qgsmaplayerref.h:210
QgsExpressionContextUtils::globalScope
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context.
Definition: qgsexpressioncontextutils.cpp:33
QgsReadWriteContext
Definition: qgsreadwritecontext.h:34
QgsExpression::evalErrorString
QString evalErrorString() const
Returns evaluation error.
Definition: qgsexpression.cpp:379
QgsLayoutAtlas::sortExpression
QString sortExpression() const
Returns the expression (or field name) to use for sorting features.
Definition: qgslayoutatlas.h:190
qgsVariantLessThan
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:121
QgsLayoutAtlas::count
int count() const override
Returns the number of features to iterate over.
Definition: qgslayoutatlas.cpp:391
QgsExpressionContext::lastScope
QgsExpressionContextScope * lastScope()
Returns the last scope added to the context.
Definition: qgsexpressioncontext.cpp:373
QgsLayoutAtlas::refreshCurrentFeature
void refreshCurrentFeature()
Refreshes the current atlas feature, by refetching its attributes from the vector layer provider.
Definition: qgslayoutatlas.cpp:466
qgsfeatureiterator.h
QgsExpression::isValid
bool isValid() const
Checks if this expression is valid.
Definition: qgsexpression.cpp:197
QgsLayoutAtlas::updateFeatures
int updateFeatures()
Requeries the current atlas coverage layer and applies filtering and sorting.
Definition: qgslayoutatlas.cpp:259
QgsLayoutAtlas::AtlasFeatureSorter
friend class AtlasFeatureSorter
Definition: qgslayoutatlas.h:397
QgsExpressionContextUtils::layoutScope
static QgsExpressionContextScope * layoutScope(const QgsLayout *layout)
Creates a new scope which contains variables and functions relating to a QgsLayout layout.
Definition: qgsexpressioncontextutils.cpp:476
QgsLayoutAtlas::QgsLayoutAtlas
QgsLayoutAtlas(QgsLayout *layout)
Constructor for new QgsLayoutAtlas.
Definition: qgslayoutatlas.cpp:29
QgsLayoutAtlas::setEnabled
void setEnabled(bool enabled)
Sets whether the atlas is enabled.
Definition: qgslayoutatlas.cpp:123
QgsLayoutAtlas::filePath
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.
Definition: qgslayoutatlas.cpp:396
QgsLayoutAtlas::changed
void changed()
Emitted when one of the atlas parameters changes.
QgsLayoutAtlas::filterExpression
QString filterExpression() const
Returns the expression used for filtering features in the coverage layer.
Definition: qgslayoutatlas.h:225
QgsLayoutAtlas::layout
QgsLayout * layout() override
Returns the layout associated with the iterator.
Definition: qgslayoutatlas.cpp:44
QgsProject
Definition: qgsproject.h:92
QgsLayoutAtlas::createExpressionContext
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
Definition: qgslayoutatlas.cpp:498
QgsFeatureRequest::setExpressionContext
QgsFeatureRequest & setExpressionContext(const QgsExpressionContext &context)
Sets the expression context used to evaluate filter expressions.
Definition: qgsfeaturerequest.cpp:149
QgsFeatureRequest::setFilterExpression
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
Definition: qgsfeaturerequest.cpp:129
qgsVariantGreaterThan
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:189
_LayerRef::layerId
QString layerId
Original layer ID.
Definition: qgsmaplayerref.h:116
QgsVectorLayer::fields
QgsFields fields() const FINAL
Returns the list of fields of this layer.
Definition: qgsvectorlayer.cpp:3280
QgsFeature::id
QgsFeatureId id
Definition: qgsfeature.h:68
QgsFeatureRequest
Definition: qgsfeaturerequest.h:75
QgsExpressionContextUtils::projectScope
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
Definition: qgsexpressioncontextutils.cpp:221
QgsExpression::hasEvalError
bool hasEvalError() const
Returns true if an error occurred when evaluating last input.
Definition: qgsexpression.cpp:374
QgsLayoutAtlas::last
bool last()
Seeks to the last feature, returning false if no feature was found.
Definition: qgslayoutatlas.cpp:434
_LayerRef::setLayer
void setLayer(TYPE *l)
Sets the reference to point to a specified layer.
Definition: qgsmaplayerref.h:77
QgsLayoutAtlas::enabled
bool enabled() const
Returns whether the atlas generation is enabled.
Definition: qgslayoutatlas.h:67
QgsExpression::parserErrorString
QString parserErrorString() const
Returns parser error.
Definition: qgsexpression.cpp:207
_LayerRef::provider
QString provider
Weak reference to layer provider.
Definition: qgsmaplayerref.h:123
QgsFeature::isValid
bool isValid() const
Returns the validity of this feature.
Definition: qgsfeature.cpp:183
QgsLayoutAtlas::beginRender
bool beginRender() override
Called when rendering begins, before iteration commences.
Definition: qgslayoutatlas.cpp:366
QgsLayoutAtlas::seekTo
bool seekTo(int feature)
Seeks to the specified feature number.
Definition: qgslayoutatlas.cpp:439
_LayerRef::name
QString name
Weak reference to layer name.
Definition: qgsmaplayerref.h:121
QgsLayoutAtlas::first
bool first()
Seeks to the first feature, returning false if no feature was found.
Definition: qgslayoutatlas.cpp:429
QgsLayoutAtlas::renderBegun
void renderBegun()
Emitted when atlas rendering has begun.
QgsLayoutAtlas::endRender
bool endRender() override
Ends the render, performing any required cleanup tasks.
Definition: qgslayoutatlas.cpp:384
QgsExpression::prepare
bool prepare(const QgsExpressionContext *context)
Gets the expression ready for evaluation - find out column indexes.
Definition: qgsexpression.cpp:323
qgslayout.h
QgsExpression::evaluate
QVariant evaluate()
Evaluate the feature and return the result.
Definition: qgsexpression.cpp:346
QgsLayoutAtlas::setSortAscending
void setSortAscending(bool ascending)
Sets whether features should be sorted in an ascending order.
Definition: qgslayoutatlas.cpp:191
QgsLayoutAtlas::setHideCoverage
void setHideCoverage(bool hide)
Sets whether the coverage layer should be hidden in map items in the layouts.
Definition: qgslayoutatlas.cpp:471
QgsExpressionContext::appendScope
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
Definition: qgsexpressioncontext.cpp:490
qgsvectorlayer.h
QgsLayoutAtlas::writeXml
bool writeXml(QDomElement &parentElement, QDomDocument &document, const QgsReadWriteContext &context) const override
Stores the objects's state in a DOM element.
Definition: qgslayoutatlas.cpp:54
QgsLayoutAtlas::stringType
QString stringType() const override
Returns the object type as a string.
Definition: qgslayoutatlas.cpp:39
QgsLayoutAtlas::coverageLayerChanged
void coverageLayerChanged(QgsVectorLayer *layer)
Emitted when the coverage layer for the atlas changes.
QgsLayoutAtlas::previous
bool previous()
Iterates to the previous feature, returning false if no previous feature exists.
Definition: qgslayoutatlas.cpp:418
QgsFeatureIterator::nextFeature
bool nextFeature(QgsFeature &f)
Definition: qgsfeatureiterator.h:373
QgsLayoutAtlas::setSortExpression
void setSortExpression(const QString &expression)
Sets the expression (or field name) to use for sorting features.
Definition: qgslayoutatlas.cpp:200
QgsLayoutAtlas::currentFilename
QString currentFilename() const
Returns the current feature filename.
Definition: qgslayoutatlas.cpp:493
QgsLayout
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
Definition: qgslayout.h:49
_LayerRef::source
QString source
Weak reference to layer public source.
Definition: qgsmaplayerref.h:119
QgsVectorLayer
Definition: qgsvectorlayer.h:385
QgsLayoutAtlas::renderEnded
void renderEnded()
Emitted when atlas rendering has ended.
QgsLayoutAtlas::toggled
void toggled(bool)
Emitted when atlas is enabled or disabled.
QgsMessageLog::logMessage
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).
Definition: qgsmessagelog.cpp:27
QgsLayoutAtlas::readXml
bool readXml(const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context) override
Sets the objects's state from a DOM element.
Definition: qgslayoutatlas.cpp:92
QgsLayoutAtlas::setCoverageLayer
void setCoverageLayer(QgsVectorLayer *layer)
Sets the coverage layer to use for the atlas features.
Definition: qgslayoutatlas.cpp:154
QgsExpressionContextUtils::atlasScope
static QgsExpressionContextScope * atlasScope(const QgsLayoutAtlas *atlas)
Creates a new scope which contains variables and functions relating to a QgsLayoutAtlas.
Definition: qgsexpressioncontextutils.cpp:570
QgsVectorLayerRef
_LayerRef< QgsVectorLayer > QgsVectorLayerRef
Definition: qgsvectorlayerref.h:23
QgsLayoutAtlas::next
bool next() override
Definition: qgslayoutatlas.cpp:407
QgsFeature
Definition: qgsfeature.h:55
QgsLayoutAtlas::setFilterExpression
bool setFilterExpression(const QString &expression, QString &errorString)
Sets the expression used for filtering features in the coverage layer.
Definition: qgslayoutatlas.cpp:218
QgsExpression::hasParserError
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
Definition: qgsexpression.cpp:202
QgsExpression
Definition: qgsexpression.h:113
QgsLayoutAtlas::setFilterFeatures
void setFilterFeatures(bool filtered)
Sets whether features should be filtered in the coverage layer.
Definition: qgslayoutatlas.cpp:209
QgsFeatureIterator
Definition: qgsfeatureiterator.h:263
QgsLayoutAtlas::setSortFeatures
void setSortFeatures(bool enabled)
Sets whether features should be sorted in the atlas.
Definition: qgslayoutatlas.cpp:182
QgsLayoutAtlas::setFilenameExpression
bool setFilenameExpression(const QString &expression, QString &errorString)
Sets the filename expression used for generating output filenames for each atlas page.
Definition: qgslayoutatlas.cpp:482
_LayerRef::get
TYPE * get() const
Returns a pointer to the layer, or nullptr if the reference has not yet been matched to a layer.
Definition: qgsmaplayerref.h:107
qgsmessagelog.h
QgsLayoutRenderContext::FlagHideCoverageLayer
@ FlagHideCoverageLayer
Hide coverage layer in outputs.
Definition: qgslayoutrendercontext.h:47
QgsExpressionContext::setFeature
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
Definition: qgsexpressioncontext.cpp:521
qgslayoutatlas.h
QgsLayoutAtlas::nameForPage
QString nameForPage(int page) const
Returns the calculated name for a specified atlas page number.
Definition: qgslayoutatlas.cpp:174