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