QGIS API Documentation 3.37.0-Master (fa0c88a90b0)
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
124 emit toggled( mEnabled );
125 emit changed();
126 return true;
127}
128
129void QgsLayoutAtlas::setEnabled( bool enabled )
130{
131 if ( enabled == mEnabled )
132 {
133 return;
134 }
135
136 mEnabled = enabled;
137 emit toggled( enabled );
138 emit changed();
139}
140
141void QgsLayoutAtlas::removeLayers( const QStringList &layers )
142{
143 if ( !mCoverageLayer )
144 {
145 return;
146 }
147
148 for ( const QString &layerId : layers )
149 {
150 if ( layerId == mCoverageLayer.layerId )
151 {
152 //current coverage layer removed
153 mCoverageLayer.setLayer( nullptr );
154 setEnabled( false );
155 break;
156 }
157 }
158}
159
161{
162 if ( layer == mCoverageLayer.get() )
163 {
164 return;
165 }
166
167 mCoverageLayer.setLayer( layer );
168 emit coverageLayerChanged( layer );
169}
170
171void QgsLayoutAtlas::setPageNameExpression( const QString &expression )
172{
173 if ( mPageNameExpression == expression )
174 return;
175
176 mPageNameExpression = expression;
177 emit changed();
178}
179
180QString QgsLayoutAtlas::nameForPage( int pageNumber ) const
181{
182 if ( pageNumber < 0 || pageNumber >= mFeatureIds.count() )
183 return QString();
184
185 return mFeatureIds.at( pageNumber ).second;
186}
187
189{
190 if ( mSortFeatures == enabled )
191 return;
192
193 mSortFeatures = enabled;
194 emit changed();
195}
196
198{
199 if ( mSortAscending == ascending )
200 return;
201
202 mSortAscending = ascending;
203 emit changed();
204}
205
206void QgsLayoutAtlas::setSortExpression( const QString &expression )
207{
208 if ( mSortExpression == expression )
209 return;
210
211 mSortExpression = expression;
212 emit changed();
213}
214
216{
217 if ( mFilterFeatures == filtered )
218 return;
219
220 mFilterFeatures = filtered;
221 emit changed();
222}
223
224bool QgsLayoutAtlas::setFilterExpression( const QString &expression, QString &errorString )
225{
226 errorString.clear();
227 const bool hasChanged = mFilterExpression != expression;
228 mFilterExpression = expression;
229
230 const QgsExpression filterExpression( mFilterExpression );
231 if ( hasChanged )
232 emit changed();
233 if ( filterExpression.hasParserError() )
234 {
235 errorString = filterExpression.parserErrorString();
236 return false;
237 }
238
239 return true;
240}
241
242
244class AtlasFeatureSorter
245{
246 public:
247 AtlasFeatureSorter( QgsLayoutAtlas::SorterKeys &keys, bool ascending = true )
248 : mKeys( keys )
249 , mAscending( ascending )
250 {}
251
252 bool operator()( const QPair< QgsFeatureId, QString > &id1, const QPair< QgsFeatureId, QString > &id2 )
253 {
254 return mAscending ? qgsVariantLessThan( mKeys.value( id1.first ), mKeys.value( id2.first ) )
255 : qgsVariantGreaterThan( mKeys.value( id1.first ), mKeys.value( id2.first ) );
256 }
257
258 private:
259 QgsLayoutAtlas::SorterKeys &mKeys;
260 bool mAscending;
261};
262
264
266{
267 mCurrentFeatureNo = -1;
268 if ( !mCoverageLayer )
269 {
270 return 0;
271 }
272
273 QgsExpressionContext expressionContext = createExpressionContext();
274
275 QString error;
276 updateFilenameExpression( error );
277
278 // select all features with all attributes
280
281 req.setExpressionContext( expressionContext );
282
283 mFilterParserError.clear();
284 if ( mFilterFeatures && !mFilterExpression.isEmpty() )
285 {
286 const QgsExpression filterExpression( mFilterExpression );
287 if ( filterExpression.hasParserError() )
288 {
289 mFilterParserError = filterExpression.parserErrorString();
290 return 0;
291 }
292
293 //filter good to go
294 req.setFilterExpression( mFilterExpression );
295 }
296
297#ifdef HAVE_SERVER_PYTHON_PLUGINS
298 if ( mLayout->renderContext().featureFilterProvider() )
299 {
300 mLayout->renderContext().featureFilterProvider()->filterFeatures( mCoverageLayer.get(), req );
301 }
302#endif
303
304 QgsFeatureIterator fit = mCoverageLayer->getFeatures( req );
305
306 std::unique_ptr<QgsExpression> nameExpression;
307 if ( !mPageNameExpression.isEmpty() )
308 {
309 nameExpression = std::make_unique< QgsExpression >( mPageNameExpression );
310 if ( nameExpression->hasParserError() )
311 {
312 nameExpression.reset( nullptr );
313 }
314 else
315 {
316 nameExpression->prepare( &expressionContext );
317 }
318 }
319
320 // We cannot use nextFeature() directly since the feature pointer is rewinded by the rendering process
321 // We thus store the feature ids for future extraction
322 QgsFeature feat;
323 mFeatureIds.clear();
324 mFeatureKeys.clear();
325
326 std::unique_ptr<QgsExpression> sortExpression;
327 if ( mSortFeatures && !mSortExpression.isEmpty() )
328 {
329 sortExpression = std::make_unique< QgsExpression >( mSortExpression );
330 if ( sortExpression->hasParserError() )
331 {
332 sortExpression.reset( nullptr );
333 }
334 else
335 {
336 sortExpression->prepare( &expressionContext );
337 }
338 }
339
340 while ( fit.nextFeature( feat ) )
341 {
342 expressionContext.setFeature( feat );
343
344 QString pageName;
345 if ( nameExpression )
346 {
347 const QVariant result = nameExpression->evaluate( &expressionContext );
348 if ( nameExpression->hasEvalError() )
349 {
350 QgsMessageLog::logMessage( tr( "Atlas name eval error: %1" ).arg( nameExpression->evalErrorString() ), tr( "Layout" ) );
351 }
352 pageName = result.toString();
353 }
354
355 mFeatureIds.push_back( qMakePair( feat.id(), pageName ) );
356
357 if ( sortExpression )
358 {
359 const QVariant result = sortExpression->evaluate( &expressionContext );
360 if ( sortExpression->hasEvalError() )
361 {
362 QgsMessageLog::logMessage( tr( "Atlas sort eval error: %1" ).arg( sortExpression->evalErrorString() ), tr( "Layout" ) );
363 }
364 mFeatureKeys.insert( feat.id(), result );
365 }
366 }
367
368 // sort features, if asked for
369 if ( !mFeatureKeys.isEmpty() )
370 {
371 const AtlasFeatureSorter sorter( mFeatureKeys, mSortAscending );
372 std::sort( mFeatureIds.begin(), mFeatureIds.end(), sorter ); // clazy:exclude=detaching-member
373 }
374
375 emit numberFeaturesChanged( mFeatureIds.size() );
376 return mFeatureIds.size();
377}
378
380{
381 if ( !mCoverageLayer )
382 {
383 return false;
384 }
385
386 emit renderBegun();
387
388 if ( !updateFeatures() )
389 {
390 //no matching features found
391 return false;
392 }
393
394 return true;
395}
396
398{
399 emit featureChanged( QgsFeature() );
400 emit renderEnded();
401 return true;
402}
403
405{
406 return mFeatureIds.size();
407}
408
409QString QgsLayoutAtlas::filePath( const QString &baseFilePath, const QString &extension )
410{
411 const QFileInfo fi( baseFilePath );
412 const QDir dir = fi.dir(); // ignore everything except the directory
413 QString base = dir.filePath( mCurrentFilename );
414 if ( !extension.startsWith( '.' ) )
415 base += '.';
416 base += extension;
417 return base;
418}
419
421{
422 const int newFeatureNo = mCurrentFeatureNo + 1;
423 if ( newFeatureNo >= mFeatureIds.size() )
424 {
425 return false;
426 }
427
428 return prepareForFeature( newFeatureNo );
429}
430
432{
433 const int newFeatureNo = mCurrentFeatureNo - 1;
434 if ( newFeatureNo < 0 )
435 {
436 return false;
437 }
438
439 return prepareForFeature( newFeatureNo );
440}
441
443{
444 return prepareForFeature( 0 );
445}
446
448{
449 return prepareForFeature( mFeatureIds.size() - 1 );
450}
451
452bool QgsLayoutAtlas::seekTo( int feature )
453{
454 return prepareForFeature( feature );
455}
456
457bool QgsLayoutAtlas::seekTo( const QgsFeature &feature )
458{
459 int i = -1;
460 auto it = mFeatureIds.constBegin();
461 for ( int currentIdx = 0; it != mFeatureIds.constEnd(); ++it, ++currentIdx )
462 {
463 if ( ( *it ).first == feature.id() )
464 {
465 i = currentIdx;
466 break;
467 }
468 }
469
470 if ( i < 0 )
471 {
472 //feature not found
473 return false;
474 }
475
476 return seekTo( i );
477}
478
480{
481 prepareForFeature( mCurrentFeatureNo );
482}
483
485{
486 mLayout->renderContext().setFlag( QgsLayoutRenderContext::FlagHideCoverageLayer, hide );
487 if ( hide == mHideCoverage )
488 return;
489
490 mHideCoverage = hide;
491 mLayout->refresh();
492 emit changed();
493}
494
495bool QgsLayoutAtlas::setFilenameExpression( const QString &pattern, QString &errorString )
496{
497 const bool hasChanged = mFilenameExpressionString != pattern;
498 mFilenameExpressionString = pattern;
499
500 if ( hasChanged )
501 emit changed();
502
503 return updateFilenameExpression( errorString );
504}
505
507{
508 return mCurrentFilename;
509}
510
512{
513 QgsExpressionContext expressionContext;
514 expressionContext << QgsExpressionContextUtils::globalScope();
515 if ( mLayout )
516 expressionContext << QgsExpressionContextUtils::projectScope( mLayout->project() )
518
519 expressionContext.appendScope( QgsExpressionContextUtils::atlasScope( this ) );
520
521 if ( mCoverageLayer )
522 expressionContext.appendScope( mCoverageLayer->createExpressionContextScope() );
523
524 if ( mLayout && mEnabled )
525 {
526 if ( mCurrentFeature.isValid() )
527 {
528 expressionContext.lastScope()->setFeature( mCurrentFeature );
529 }
530 else if ( mCoverageLayer ) // Create an empty feature for the expression validation
531 {
532 QgsFeature feature{ mCoverageLayer->fields() };
533 feature.setValid( true );
534 expressionContext.lastScope()->setFeature( feature );
535 }
536 }
537 return expressionContext;
538}
539
540bool QgsLayoutAtlas::updateFilenameExpression( QString &error )
541{
542 if ( !mCoverageLayer )
543 {
544 return false;
545 }
546
547 const QgsExpressionContext expressionContext = createExpressionContext();
548 bool evalResult { true };
549
550 if ( !mFilenameExpressionString.isEmpty() )
551 {
552 QgsExpression filenameExpression( mFilenameExpressionString );
553 // expression used to evaluate each filename
554 // test for evaluation errors
555 if ( filenameExpression.hasParserError() )
556 {
557 error = filenameExpression.parserErrorString();
558 return false;
559 }
560
561 // prepare the filename expression
562 evalResult = filenameExpression.prepare( &expressionContext );
563 }
564
565 // regenerate current filename
566 if ( evalResult )
567 {
568 evalResult = evalFeatureFilename( expressionContext );
569 }
570
571 if ( ! evalResult )
572 {
573 error = mFilenameExpressionError;
574 }
575
576 return evalResult;
577}
578
579bool QgsLayoutAtlas::evalFeatureFilename( const QgsExpressionContext &context )
580{
581 //generate filename for current atlas feature
582 mFilenameExpressionError.clear();
583 if ( !mFilenameExpressionString.isEmpty() )
584 {
585 QgsExpression filenameExpression( mFilenameExpressionString );
586 filenameExpression.prepare( &context );
587 const QVariant filenameRes = filenameExpression.evaluate( &context );
588 if ( filenameExpression.hasEvalError() )
589 {
590 mFilenameExpressionError = filenameExpression.evalErrorString();
591 QgsMessageLog::logMessage( tr( "Atlas filename evaluation error: %1" ).arg( filenameExpression.evalErrorString() ), tr( "Layout" ) );
592 return false;
593 }
594
595 mCurrentFilename = filenameRes.toString();
596 }
597 return true;
598}
599
600bool QgsLayoutAtlas::prepareForFeature( const int featureI )
601{
602 if ( !mCoverageLayer )
603 {
604 return false;
605 }
606
607 if ( mFeatureIds.isEmpty() )
608 {
609 emit messagePushed( tr( "No matching atlas features" ) );
610 return false;
611 }
612
613 if ( featureI >= mFeatureIds.size() )
614 {
615 return false;
616 }
617
618 mCurrentFeatureNo = featureI;
619
620 // retrieve the next feature, based on its id
621 if ( !mCoverageLayer->getFeatures( QgsFeatureRequest().setFilterFid( mFeatureIds[ featureI ].first ) ).nextFeature( mCurrentFeature ) )
622 return false;
623
624 mLayout->reportContext().blockSignals( true ); // setFeature emits changed, we don't want 2 signals
625 mLayout->reportContext().setLayer( mCoverageLayer.get() );
626 mLayout->reportContext().blockSignals( false );
627 mLayout->reportContext().setFeature( mCurrentFeature );
628
629 // must come after we've set the report context feature, or the expression context will have an outdated atlas feature
630 const QgsExpressionContext expressionContext = createExpressionContext();
631
632 // generate filename for current feature
633 if ( !evalFeatureFilename( expressionContext ) )
634 {
635 //error evaluating filename
636 return false;
637 }
638
639 emit featureChanged( mCurrentFeature );
640 emit messagePushed( tr( "Atlas feature %1 of %2" ).arg( featureI + 1 ).arg( mFeatureIds.size() ) );
641
642 return mCurrentFeature.isValid();
643}
644
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.