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