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