QGIS API Documentation 3.99.0-Master (26c88405ac0)
Loading...
Searching...
No Matches
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 "qgslayoutatlas.h"
18
19#include <algorithm>
20#include <stdexcept>
21
23#include "qgsfeatureiterator.h"
24#include "qgsfeaturerequest.h"
25#include "qgslayout.h"
28#include "qgsmessagelog.h"
29#include "qgsvariantutils.h"
30#include "qgsvectorlayer.h"
31
32#include <QtAlgorithms>
33
34#include "moc_qgslayoutatlas.cpp"
35
37 : QObject( layout )
38 , mLayout( layout )
39 , mFilenameExpressionString( QStringLiteral( "'output_'||@atlas_featurenumber" ) )
40{
41
42 //listen out for layer removal
43 connect( mLayout->project(), static_cast < void ( QgsProject::* )( const QStringList & ) >( &QgsProject::layersWillBeRemoved ), this, &QgsLayoutAtlas::removeLayers );
44
45 if ( QgsVariantUtils::isNull( mLayout->customProperty( QStringLiteral( "singleFile" ) ) ) )
46 mLayout->setCustomProperty( QStringLiteral( "singleFile" ), true );
47}
48
50{
51 return QStringLiteral( "atlas" );
52}
53
55{
56 return mLayout;
57}
58
59const QgsLayout *QgsLayoutAtlas::layout() const // cppcheck-suppress duplInheritedMember
60{
61 return mLayout.data();
62}
63
64bool QgsLayoutAtlas::writeXml( QDomElement &parentElement, QDomDocument &document, const QgsReadWriteContext & ) const
65{
66 QDomElement atlasElem = document.createElement( QStringLiteral( "Atlas" ) );
67 atlasElem.setAttribute( QStringLiteral( "enabled" ), mEnabled ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
68
69 if ( mCoverageLayer )
70 {
71 atlasElem.setAttribute( QStringLiteral( "coverageLayer" ), mCoverageLayer.layerId );
72 atlasElem.setAttribute( QStringLiteral( "coverageLayerName" ), mCoverageLayer.name );
73 atlasElem.setAttribute( QStringLiteral( "coverageLayerSource" ), mCoverageLayer.source );
74 atlasElem.setAttribute( QStringLiteral( "coverageLayerProvider" ), mCoverageLayer.provider );
75 }
76 else
77 {
78 atlasElem.setAttribute( QStringLiteral( "coverageLayer" ), QString() );
79 }
80
81 if ( mLimitCoverageLayerRenderToCurrentFeature )
82 atlasElem.setAttribute( QStringLiteral( "limitCoverageLayerRenderToCurrentFeature" ), QStringLiteral( "1" ) );
83
84 atlasElem.setAttribute( QStringLiteral( "hideCoverage" ), mHideCoverage ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
85 atlasElem.setAttribute( QStringLiteral( "filenamePattern" ), mFilenameExpressionString );
86 atlasElem.setAttribute( QStringLiteral( "pageNameExpression" ), mPageNameExpression );
87
88 atlasElem.setAttribute( QStringLiteral( "sortFeatures" ), mSortFeatures ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
89 if ( mSortFeatures )
90 {
91 atlasElem.setAttribute( QStringLiteral( "sortKey" ), mSortExpression );
92 atlasElem.setAttribute( QStringLiteral( "sortAscending" ), mSortAscending ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
93 }
94 atlasElem.setAttribute( QStringLiteral( "filterFeatures" ), mFilterFeatures ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
95 if ( mFilterFeatures )
96 {
97 atlasElem.setAttribute( QStringLiteral( "featureFilter" ), mFilterExpression );
98 }
99
100 parentElement.appendChild( atlasElem );
101
102 return true;
103}
104
105bool QgsLayoutAtlas::readXml( const QDomElement &atlasElem, const QDomDocument &, const QgsReadWriteContext & )
106{
107 mEnabled = atlasElem.attribute( QStringLiteral( "enabled" ), QStringLiteral( "0" ) ).toInt();
108
109 // look for stored layer name
110 const QString layerId = atlasElem.attribute( QStringLiteral( "coverageLayer" ) );
111 const QString layerName = atlasElem.attribute( QStringLiteral( "coverageLayerName" ) );
112 const QString layerSource = atlasElem.attribute( QStringLiteral( "coverageLayerSource" ) );
113 const QString layerProvider = atlasElem.attribute( QStringLiteral( "coverageLayerProvider" ) );
114
115 mCoverageLayer = QgsVectorLayerRef( layerId, layerName, layerSource, layerProvider );
116 mCoverageLayer.resolveWeakly( mLayout->project() );
117 mLayout->reportContext().setLayer( mCoverageLayer.get() );
118
119 mPageNameExpression = atlasElem.attribute( QStringLiteral( "pageNameExpression" ), QString() );
120 QString error;
121 setFilenameExpression( atlasElem.attribute( QStringLiteral( "filenamePattern" ), QString() ), error );
122
123 mSortFeatures = atlasElem.attribute( QStringLiteral( "sortFeatures" ), QStringLiteral( "0" ) ).toInt();
124 mSortExpression = atlasElem.attribute( QStringLiteral( "sortKey" ) );
125 mSortAscending = atlasElem.attribute( QStringLiteral( "sortAscending" ), QStringLiteral( "1" ) ).toInt();
126 mFilterFeatures = atlasElem.attribute( QStringLiteral( "filterFeatures" ), QStringLiteral( "0" ) ).toInt();
127 mFilterExpression = atlasElem.attribute( QStringLiteral( "featureFilter" ) );
128
129 mLimitCoverageLayerRenderToCurrentFeature = atlasElem.attribute( QStringLiteral( "limitCoverageLayerRenderToCurrentFeature" ), QStringLiteral( "0" ) ).toInt();
130 mLayout->renderContext().setFlag( Qgis::LayoutRenderFlag::LimitCoverageLayerRenderToCurrentFeature, mLimitCoverageLayerRenderToCurrentFeature );
131 mHideCoverage = atlasElem.attribute( QStringLiteral( "hideCoverage" ), QStringLiteral( "0" ) ).toInt();
132 mLayout->renderContext().setFlag( Qgis::LayoutRenderFlag::HideCoverageLayer, mHideCoverage );
133
134 emit toggled( mEnabled );
135 emit changed();
136 return true;
137}
138
140{
141 if ( enabled == mEnabled )
142 {
143 return;
144 }
145
146 mEnabled = enabled;
147 emit toggled( enabled );
148 emit changed();
149}
150
151void QgsLayoutAtlas::removeLayers( const QStringList &layers )
152{
153 if ( !mCoverageLayer )
154 {
155 return;
156 }
157
158 for ( const QString &layerId : layers )
159 {
160 if ( layerId == mCoverageLayer.layerId )
161 {
162 //current coverage layer removed
163 mCoverageLayer.setLayer( nullptr );
164 setEnabled( false );
165 break;
166 }
167 }
168}
169
171{
172 if ( layer == mCoverageLayer.get() )
173 {
174 return;
175 }
176
177 mCoverageLayer.setLayer( layer );
178 emit coverageLayerChanged( layer );
179}
180
181void QgsLayoutAtlas::setPageNameExpression( const QString &expression )
182{
183 if ( mPageNameExpression == expression )
184 return;
185
186 mPageNameExpression = expression;
187 emit changed();
188}
189
190QString QgsLayoutAtlas::nameForPage( int pageNumber ) const
191{
192 if ( pageNumber < 0 || pageNumber >= mFeatureIds.count() )
193 return QString();
194
195 return mFeatureIds.at( pageNumber ).second;
196}
197
199{
200 if ( mSortFeatures == enabled )
201 return;
202
203 mSortFeatures = enabled;
204 emit changed();
205}
206
208{
209 if ( mSortAscending == ascending )
210 return;
211
212 mSortAscending = ascending;
213 emit changed();
214}
215
216void QgsLayoutAtlas::setSortExpression( const QString &expression )
217{
218 if ( mSortExpression == expression )
219 return;
220
221 mSortExpression = expression;
222 emit changed();
223}
224
226{
227 if ( mFilterFeatures == filtered )
228 return;
229
230 mFilterFeatures = filtered;
231 emit changed();
232}
233
234bool QgsLayoutAtlas::setFilterExpression( const QString &expression, QString &errorString )
235{
236 errorString.clear();
237 const bool hasChanged = mFilterExpression != expression;
238 mFilterExpression = expression;
239
240 const QgsExpression filterExpression( mFilterExpression );
241 if ( hasChanged )
242 emit changed();
243 if ( filterExpression.hasParserError() )
244 {
245 errorString = filterExpression.parserErrorString();
246 return false;
247 }
248
249 return true;
250}
251
252
254class AtlasFeatureSorter
255{
256 public:
257 AtlasFeatureSorter( QgsLayoutAtlas::SorterKeys &keys, bool ascending = true )
258 : mKeys( keys )
259 , mAscending( ascending )
260 {}
261
262 bool operator()( const QPair< QgsFeatureId, QString > &id1, const QPair< QgsFeatureId, QString > &id2 )
263 {
264 return mAscending ? qgsVariantLessThan( mKeys.value( id1.first ), mKeys.value( id2.first ) )
265 : qgsVariantGreaterThan( mKeys.value( id1.first ), mKeys.value( id2.first ) );
266 }
267
268 private:
269 QgsLayoutAtlas::SorterKeys &mKeys;
270 bool mAscending;
271};
272
274
276{
277 mCurrentFeatureNo = -1;
278 if ( !mCoverageLayer )
279 {
280 return 0;
281 }
282
283 QgsExpressionContext expressionContext = createExpressionContext();
284
285 QString error;
286 updateFilenameExpression( error );
287
288 // select all features with all attributes
290
291 req.setExpressionContext( expressionContext );
292
293 mFilterParserError.clear();
294 if ( mFilterFeatures && !mFilterExpression.isEmpty() )
295 {
296 const QgsExpression filterExpression( mFilterExpression );
297 if ( filterExpression.hasParserError() )
298 {
299 mFilterParserError = filterExpression.parserErrorString();
300 return 0;
301 }
302
303 //filter good to go
304 req.setFilterExpression( mFilterExpression );
305 }
306
307#ifdef HAVE_SERVER_PYTHON_PLUGINS
308 if ( mLayout->renderContext().featureFilterProvider() )
309 {
310 // NOLINTBEGIN(bugprone-branch-clone)
312 if ( mLayout->renderContext().featureFilterProvider()->isFilterThreadSafe() )
313 {
314 mLayout->renderContext().featureFilterProvider()->filterFeatures( mCoverageLayer.get()->id(), req );
315 }
316 else
317 {
318 mLayout->renderContext().featureFilterProvider()->filterFeatures( mCoverageLayer.get(), req );
319 }
321 // NOLINTEND(bugprone-branch-clone)
322 }
323#endif
324
325 QgsFeatureIterator fit = mCoverageLayer->getFeatures( req );
326
327 std::unique_ptr<QgsExpression> nameExpression;
328 if ( !mPageNameExpression.isEmpty() )
329 {
330 nameExpression = std::make_unique< QgsExpression >( mPageNameExpression );
331 if ( nameExpression->hasParserError() )
332 {
333 nameExpression.reset( nullptr );
334 }
335 else
336 {
337 nameExpression->prepare( &expressionContext );
338 }
339 }
340
341 // We cannot use nextFeature() directly since the feature pointer is rewinded by the rendering process
342 // We thus store the feature ids for future extraction
343 QgsFeature feat;
344 mFeatureIds.clear();
345 mFeatureKeys.clear();
346
347 std::unique_ptr<QgsExpression> sortExpression;
348 if ( mSortFeatures && !mSortExpression.isEmpty() )
349 {
350 sortExpression = std::make_unique< QgsExpression >( mSortExpression );
351 if ( sortExpression->hasParserError() )
352 {
353 sortExpression.reset( nullptr );
354 }
355 else
356 {
357 sortExpression->prepare( &expressionContext );
358 }
359 }
360
361 while ( fit.nextFeature( feat ) )
362 {
363 expressionContext.setFeature( feat );
364
365 QString pageName;
366 if ( nameExpression )
367 {
368 const QVariant result = nameExpression->evaluate( &expressionContext );
369 if ( nameExpression->hasEvalError() )
370 {
371 QgsMessageLog::logMessage( tr( "Atlas name eval error: %1" ).arg( nameExpression->evalErrorString() ), tr( "Layout" ) );
372 }
373 pageName = result.toString();
374 }
375
376 mFeatureIds.push_back( qMakePair( feat.id(), pageName ) );
377
378 if ( sortExpression )
379 {
380 const QVariant result = sortExpression->evaluate( &expressionContext );
381 if ( sortExpression->hasEvalError() )
382 {
383 QgsMessageLog::logMessage( tr( "Atlas sort eval error: %1" ).arg( sortExpression->evalErrorString() ), tr( "Layout" ) );
384 }
385 mFeatureKeys.insert( feat.id(), result );
386 }
387 }
388
389 // sort features, if asked for
390 if ( !mFeatureKeys.isEmpty() )
391 {
392 const AtlasFeatureSorter sorter( mFeatureKeys, mSortAscending );
393 std::sort( mFeatureIds.begin(), mFeatureIds.end(), sorter ); // clazy:exclude=detaching-member
394 }
395
396 emit numberFeaturesChanged( mFeatureIds.size() );
397 return mFeatureIds.size();
398}
399
401{
402 if ( !mCoverageLayer )
403 {
404 return false;
405 }
406
407 emit renderBegun();
408
409 if ( !updateFeatures() )
410 {
411 //no matching features found
412 return false;
413 }
414
415 return true;
416}
417
419{
420 emit featureChanged( QgsFeature() );
421 emit renderEnded();
422 return true;
423}
424
426{
427 return mFeatureIds.size();
428}
429
430QString QgsLayoutAtlas::filePath( const QString &baseFilePath, const QString &extension )
431{
432 const QFileInfo fi( baseFilePath );
433 const QDir dir = fi.dir(); // ignore everything except the directory
434 QString base = dir.filePath( mCurrentFilename );
435 if ( !extension.startsWith( '.' ) )
436 base += '.';
437 base += extension;
438 return base;
439}
440
442{
443 const int newFeatureNo = mCurrentFeatureNo + 1;
444 if ( newFeatureNo >= mFeatureIds.size() )
445 {
446 return false;
447 }
448
449 return prepareForFeature( newFeatureNo );
450}
451
453{
454 const int newFeatureNo = mCurrentFeatureNo - 1;
455 if ( newFeatureNo < 0 )
456 {
457 return false;
458 }
459
460 return prepareForFeature( newFeatureNo );
461}
462
464{
465 return prepareForFeature( 0 );
466}
467
469{
470 return prepareForFeature( mFeatureIds.size() - 1 );
471}
472
473bool QgsLayoutAtlas::seekTo( int feature )
474{
475 return prepareForFeature( feature );
476}
477
478bool QgsLayoutAtlas::seekTo( const QgsFeature &feature )
479{
480 int i = -1;
481 auto it = mFeatureIds.constBegin();
482 for ( int currentIdx = 0; it != mFeatureIds.constEnd(); ++it, ++currentIdx )
483 {
484 if ( ( *it ).first == feature.id() )
485 {
486 i = currentIdx;
487 break;
488 }
489 }
490
491 if ( i < 0 )
492 {
493 //feature not found
494 return false;
495 }
496
497 return seekTo( i );
498}
499
501{
502 prepareForFeature( mCurrentFeatureNo );
503}
504
506{
507 mLayout->renderContext().setFlag( Qgis::LayoutRenderFlag::HideCoverageLayer, hide );
508 if ( hide == mHideCoverage )
509 return;
510
511 mHideCoverage = hide;
512 mLayout->refresh();
513 emit changed();
514}
515
517{
518 mLayout->renderContext().setFlag( Qgis::LayoutRenderFlag::LimitCoverageLayerRenderToCurrentFeature, limit );
519 if ( limit == mLimitCoverageLayerRenderToCurrentFeature )
520 return;
521
522 mLimitCoverageLayerRenderToCurrentFeature = limit;
523 mLayout->refresh();
524 emit changed();
525}
526
527bool QgsLayoutAtlas::setFilenameExpression( const QString &pattern, QString &errorString )
528{
529 const bool hasChanged = mFilenameExpressionString != pattern;
530 mFilenameExpressionString = pattern;
531
532 if ( hasChanged )
533 emit changed();
534
535 return updateFilenameExpression( errorString );
536}
537
539{
540 return mCurrentFilename;
541}
542
544{
545 QgsExpressionContext expressionContext;
546 expressionContext << QgsExpressionContextUtils::globalScope();
547 if ( mLayout )
548 expressionContext << QgsExpressionContextUtils::projectScope( mLayout->project() )
550
551 expressionContext.appendScope( QgsExpressionContextUtils::atlasScope( this ) );
552
553 if ( mCoverageLayer )
554 expressionContext.appendScope( mCoverageLayer->createExpressionContextScope() );
555
556 if ( mLayout && mEnabled )
557 {
558 if ( mCurrentFeature.isValid() )
559 {
560 expressionContext.lastScope()->setFeature( mCurrentFeature );
561 }
562 else if ( mCoverageLayer ) // Create an empty feature for the expression validation
563 {
564 QgsFeature feature{ mCoverageLayer->fields() };
565 feature.setValid( true );
566 expressionContext.lastScope()->setFeature( feature );
567 }
568 }
569 return expressionContext;
570}
571
572bool QgsLayoutAtlas::updateFilenameExpression( QString &error )
573{
574 if ( !mCoverageLayer )
575 {
576 return false;
577 }
578
579 const QgsExpressionContext expressionContext = createExpressionContext();
580 bool evalResult { true };
581
582 if ( !mFilenameExpressionString.isEmpty() )
583 {
584 QgsExpression filenameExpression( mFilenameExpressionString );
585 // expression used to evaluate each filename
586 // test for evaluation errors
587 if ( filenameExpression.hasParserError() )
588 {
589 error = filenameExpression.parserErrorString();
590 return false;
591 }
592
593 // prepare the filename expression
594 evalResult = filenameExpression.prepare( &expressionContext );
595 }
596
597 // regenerate current filename
598 if ( evalResult )
599 {
600 evalResult = evalFeatureFilename( expressionContext );
601 }
602
603 if ( ! evalResult )
604 {
605 error = mFilenameExpressionError;
606 }
607
608 return evalResult;
609}
610
611bool QgsLayoutAtlas::evalFeatureFilename( const QgsExpressionContext &context )
612{
613 //generate filename for current atlas feature
614 mFilenameExpressionError.clear();
615 if ( !mFilenameExpressionString.isEmpty() )
616 {
617 QgsExpression filenameExpression( mFilenameExpressionString );
618 filenameExpression.prepare( &context );
619 const QVariant filenameRes = filenameExpression.evaluate( &context );
620 if ( filenameExpression.hasEvalError() )
621 {
622 mFilenameExpressionError = filenameExpression.evalErrorString();
623 QgsMessageLog::logMessage( tr( "Atlas filename evaluation error: %1" ).arg( filenameExpression.evalErrorString() ), tr( "Layout" ) );
624 return false;
625 }
626
627 mCurrentFilename = filenameRes.toString();
628 }
629 return true;
630}
631
632bool QgsLayoutAtlas::prepareForFeature( const int featureI )
633{
634 if ( !mCoverageLayer )
635 {
636 return false;
637 }
638
639 if ( mFeatureIds.isEmpty() )
640 {
641 emit messagePushed( tr( "No matching atlas features" ) );
642 return false;
643 }
644
645 if ( featureI >= mFeatureIds.size() )
646 {
647 return false;
648 }
649
650 mCurrentFeatureNo = featureI;
651
652 // retrieve the next feature, based on its id
653 if ( !mCoverageLayer->getFeatures( QgsFeatureRequest().setFilterFid( mFeatureIds[ featureI ].first ) ).nextFeature( mCurrentFeature ) )
654 return false;
655
656 mLayout->reportContext().blockSignals( true ); // setFeature emits changed, we don't want 2 signals
657 mLayout->reportContext().setLayer( mCoverageLayer.get() );
658 mLayout->reportContext().blockSignals( false );
659 mLayout->reportContext().setFeature( mCurrentFeature );
660
661 // must come after we've set the report context feature, or the expression context will have an outdated atlas feature
662 const QgsExpressionContext expressionContext = createExpressionContext();
663
664 // generate filename for current feature
665 if ( !evalFeatureFilename( expressionContext ) )
666 {
667 //error evaluating filename
668 return false;
669 }
670
671 emit featureChanged( mCurrentFeature );
672 emit messagePushed( tr( "Atlas feature %1 of %2" ).arg( featureI + 1 ).arg( mFeatureIds.size() ) );
673
674 return mCurrentFeature.isValid();
675}
676
@ LimitCoverageLayerRenderToCurrentFeature
Limit coverage layer rendering to the current atlas feature.
Definition qgis.h:5250
@ HideCoverageLayer
Hide coverage layer in outputs.
Definition qgis.h:5243
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.
Handles 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)
Fetch next feature and stores in f, returns true on success.
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:58
QgsFeatureId id
Definition qgsfeature.h:66
void setValid(bool validity)
Sets the validity of the feature.
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 toggled(bool enabled)
Emitted when atlas is enabled or disabled.
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 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 setLimitCoverageLayerRenderToCurrentFeature(bool limit)
Sets whether the rendering of the coverage layer should be limited to the current feature.
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.
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
Definition qgslayout.h:50
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE())
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:109
void layersWillBeRemoved(const QStringList &layerIds)
Emitted when one or more layers are about to be removed from the registry.
A container for the context for various read/write operations on objects.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
Represents a vector layer which manages a vector based dataset.
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:588
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:593
#define Q_NOWARN_DEPRECATED_POP
Definition qgis.h:7170
#define Q_NOWARN_DEPRECATED_PUSH
Definition qgis.h:7169
_LayerRef< QgsVectorLayer > QgsVectorLayerRef