QGIS API Documentation 3.99.0-Master (f78f5286a64)
qgsalgorithmpackage.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsalgorithmpackage.cpp
3 ---------------------
4 begin : November 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
18#include "qgsalgorithmpackage.h"
19#include "qgsogrutils.h"
20#include "qgsvectorfilewriter.h"
21#include "qgsvectorlayer.h"
22#include "qgssettings.h"
23
24#include <QLocale>
25
27
28QString QgsPackageAlgorithm::name() const
29{
30 return QStringLiteral( "package" );
31}
32
33QString QgsPackageAlgorithm::displayName() const
34{
35 return QObject::tr( "Package layers" );
36}
37
38QStringList QgsPackageAlgorithm::tags() const
39{
40 return QObject::tr( "geopackage,collect,merge,combine,styles" ).split( ',' );
41}
42
43QString QgsPackageAlgorithm::group() const
44{
45 return QObject::tr( "Database" );
46}
47
48QString QgsPackageAlgorithm::groupId() const
49{
50 return QStringLiteral( "database" );
51}
52
53void QgsPackageAlgorithm::initAlgorithm( const QVariantMap & )
54{
55 addParameter( new QgsProcessingParameterMultipleLayers( QStringLiteral( "LAYERS" ), QObject::tr( "Input layers" ), Qgis::ProcessingSourceType::Vector ) );
56 QgsProcessingParameterFileDestination *outputParameter = new QgsProcessingParameterFileDestination( QStringLiteral( "OUTPUT" ), QObject::tr( "Destination GeoPackage" ), QObject::tr( "GeoPackage files (*.gpkg)" ) );
57 outputParameter->setMetadata( QVariantMap( { { QStringLiteral( "widget_wrapper" ), QVariantMap( { { QStringLiteral( "dontconfirmoverwrite" ), true } } ) } } ) );
58 addParameter( outputParameter );
59 addParameter( new QgsProcessingParameterBoolean( QStringLiteral( "OVERWRITE" ), QObject::tr( "Overwrite existing GeoPackage" ), false ) );
60 addParameter( new QgsProcessingParameterBoolean( QStringLiteral( "SAVE_STYLES" ), QObject::tr( "Save layer styles into GeoPackage" ), true ) );
61 addParameter( new QgsProcessingParameterBoolean( QStringLiteral( "SAVE_METADATA" ), QObject::tr( "Save layer metadata into GeoPackage" ), true ) );
62 addParameter( new QgsProcessingParameterBoolean( QStringLiteral( "SELECTED_FEATURES_ONLY" ), QObject::tr( "Save only selected features" ), false ) );
63 addParameter( new QgsProcessingParameterBoolean( QStringLiteral( "EXPORT_RELATED_LAYERS" ), QObject::tr( "Export related layers following relations defined in the project" ), false ) );
64 auto extentParam = std::make_unique<QgsProcessingParameterExtent>( QStringLiteral( "EXTENT" ), QObject::tr( "Extent" ), QVariant(), true );
65 extentParam->setHelp( QObject::tr( "Limit exported features to those with geometries intersecting the provided extent" ) );
66 addParameter( extentParam.release() );
67
68 auto crsParam = std::make_unique< QgsProcessingParameterCrs >( QStringLiteral( "CRS" ), QObject::tr( "Destination CRS" ), QVariant(), true );
69 crsParam->setFlags( crsParam->flags() | Qgis::ProcessingParameterFlag::Advanced );
70 crsParam->setHelp( QObject::tr( "If set, all layers will be transformed to the destination CRS during packaging." ) );
71 addParameter( std::move( crsParam ) );
72
73 addOutput( new QgsProcessingOutputMultipleLayers( QStringLiteral( "OUTPUT_LAYERS" ), QObject::tr( "Layers within new package" ) ) );
74}
75
76QString QgsPackageAlgorithm::shortHelpString() const
77{
78 return QObject::tr( "This algorithm collects a number of existing layers and packages them together into a single GeoPackage database." );
79}
80
81QString QgsPackageAlgorithm::shortDescription() const
82{
83 return QObject::tr( "Packages a number of existing layers together into a single GeoPackage database." );
84}
85
86QgsPackageAlgorithm *QgsPackageAlgorithm::createInstance() const
87{
88 return new QgsPackageAlgorithm();
89}
90
91bool QgsPackageAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
92{
93 const QList<QgsMapLayer *> layers = parameterAsLayerList( parameters, QStringLiteral( "LAYERS" ), context );
94
95 for ( const QgsMapLayer *layer : std::as_const( layers ) )
96 {
97 QgsMapLayer *clonedLayer { layer->clone() };
98 mClonedLayerIds.insert( clonedLayer->id(), layer->id() );
99 mLayers.emplace_back( clonedLayer );
100 }
101
102 if ( mLayers.empty() )
103 {
104 feedback->reportError( QObject::tr( "No layers selected, geopackage will be empty" ), false );
105 }
106
107 mDestinationCrs = parameterAsCrs( parameters, QStringLiteral( "CRS" ), context );
108
109 return true;
110}
111
112QVariantMap QgsPackageAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
113{
114 const bool overwrite = parameterAsBoolean( parameters, QStringLiteral( "OVERWRITE" ), context );
115 const bool saveStyles = parameterAsBoolean( parameters, QStringLiteral( "SAVE_STYLES" ), context );
116 const bool saveMetadata = parameterAsBoolean( parameters, QStringLiteral( "SAVE_METADATA" ), context );
117 const bool selectedFeaturesOnly = parameterAsBoolean( parameters, QStringLiteral( "SELECTED_FEATURES_ONLY" ), context );
118 const bool exportRelatedLayers = parameterAsBoolean( parameters, QStringLiteral( "EXPORT_RELATED_LAYERS" ), context );
119 const QString packagePath = parameterAsString( parameters, QStringLiteral( "OUTPUT" ), context );
120 const QList<QgsMapLayer *> layers = parameterAsLayerList( parameters, QStringLiteral( "LAYERS" ), context );
121
122 if ( packagePath.isEmpty() )
123 throw QgsProcessingException( QObject::tr( "No output file specified." ) );
124
125 // delete existing geopackage if it exists
126 if ( overwrite && QFile::exists( packagePath ) )
127 {
128 feedback->pushInfo( QObject::tr( "Removing existing file '%1'" ).arg( packagePath ) );
129 if ( !QFile( packagePath ).remove() )
130 {
131 throw QgsProcessingException( QObject::tr( "Could not remove existing file '%1'" ).arg( packagePath ) );
132 }
133 }
134
135 OGRSFDriverH hGpkgDriver = OGRGetDriverByName( "GPKG" );
136 if ( !hGpkgDriver )
137 {
138 throw QgsProcessingException( QObject::tr( "GeoPackage driver not found." ) );
139 }
140
141
142 // Collect related layers from project relations
143 if ( exportRelatedLayers )
144 {
145 const QgsProject *project { context.project() };
146 if ( project && !project->relationManager()->relations().isEmpty() )
147 {
148 // Infinite recursion should not happen in the real world but better safe than sorry
149 const int maxRecursion { 10 };
150 int recursionGuard { 0 };
151
152 // This function recursively finds referenced layers
153 const auto findReferenced = [this, &project, &feedback, &recursionGuard, &layers]( const QgsVectorLayer *vLayer, bool onlySaveSelected, auto &&findReferenced ) -> void {
154 const QgsVectorLayer *originalLayer { qobject_cast<QgsVectorLayer *>( project->mapLayer( mClonedLayerIds.value( vLayer->id(), vLayer->id() ) ) ) };
155 Q_ASSERT( originalLayer );
156 const QList<QgsRelation> relations { project->relationManager()->referencingRelations( originalLayer ) };
157 for ( const QgsRelation &relation : std::as_const( relations ) )
158 {
159 QgsVectorLayer *referencedLayer { relation.referencedLayer() };
160 QgsVectorLayer *relatedLayer { nullptr };
161
162 // Check if the layer was already in the export list
163 bool alreadyAdded { false };
164 for ( const auto &layerToExport : std::as_const( mLayers ) )
165 {
166 const QString originalId { mClonedLayerIds.value( layerToExport->id() ) };
167 if ( originalId == referencedLayer->id() )
168 {
169 relatedLayer = qobject_cast<QgsVectorLayer *>( layerToExport.get() );
170 alreadyAdded = true;
171 break;
172 }
173 }
174
175 if ( !alreadyAdded )
176 {
177 feedback->pushInfo( QObject::tr( "Adding referenced layer '%1'" ).arg( referencedLayer->name() ) );
178 relatedLayer = referencedLayer->clone();
179 mLayers.emplace_back( relatedLayer );
180 mClonedLayerIds.insert( relatedLayer->id(), referencedLayer->id() );
181 }
182
183 // Export only relevant features unless the layer was in the original export list and no selection was made on that layer
184 // in that case the user explicitly marked the layer for export and it is supposed to be exported fully.
185 if ( onlySaveSelected )
186 {
187 if ( !layers.contains( qobject_cast<QgsMapLayer *>( referencedLayer ) ) || referencedLayer->selectedFeatureCount() > 0 )
188 {
189 Q_ASSERT( relatedLayer );
190 QgsFeatureIds selected;
191 QgsFeatureIterator it { vLayer->getSelectedFeatures() };
192 QgsFeature selectedFeature;
193 while ( it.nextFeature( selectedFeature ) )
194 {
195 QgsFeature referencedFeature { relation.getReferencedFeature( selectedFeature ) };
196 if ( referencedFeature.isValid() )
197 {
198 selected.insert( referencedFeature.id() );
199 }
200 }
201 relatedLayer->selectByIds( selected, Qgis::SelectBehavior::AddToSelection );
202 }
203 }
204
205 // Recursive finding
206 if ( recursionGuard > maxRecursion )
207 {
208 feedback->pushWarning( QObject::tr( "Max recursion (%1) adding referenced layer '%2', layer was not added" ).arg( QLocale().toString( recursionGuard ), referencedLayer->name() ) );
209 }
210 else
211 {
212 recursionGuard++;
213 findReferenced( relatedLayer, onlySaveSelected, findReferenced );
214 }
215 }
216 };
217
218 // This function recursively finds referencing layers
219 const auto findReferencing = [this, &project, &feedback, &recursionGuard, &layers]( const QgsVectorLayer *vLayer, bool onlySaveSelected, auto &&findReferencing ) -> void {
220 const QgsVectorLayer *originalLayer { qobject_cast<QgsVectorLayer *>( project->mapLayer( mClonedLayerIds.value( vLayer->id(), vLayer->id() ) ) ) };
221 Q_ASSERT( originalLayer );
222 const QList<QgsRelation> relations { project->relationManager()->referencedRelations( originalLayer ) };
223 for ( const QgsRelation &relation : std::as_const( relations ) )
224 {
225 QgsVectorLayer *referencingLayer { relation.referencingLayer() };
226 QgsVectorLayer *relatedLayer { nullptr };
227 const bool layerWasExplicitlyAdded { layers.contains( qobject_cast<QgsMapLayer *>( referencingLayer ) ) };
228
229 // Check if the layer was already in the export list
230 bool alreadyAdded { false };
231 for ( const auto &layerToExport : std::as_const( mLayers ) )
232 {
233 const QString originalId { mClonedLayerIds.value( layerToExport->id() ) };
234 if ( originalId == referencingLayer->id() )
235 {
236 relatedLayer = qobject_cast<QgsVectorLayer *>( layerToExport.get() );
237 alreadyAdded = true;
238 break;
239 }
240 }
241
242 // Export only relevant features unless the layer was in the original export list and no selection was made on that layer
243 // in that case the user explicitly marked the layer for export and it is supposed to be exported fully.
244 QgsFeatureIds selected;
245
246 if ( onlySaveSelected && ( !layerWasExplicitlyAdded || referencingLayer->selectedFeatureCount() > 0 ) )
247 {
248 if ( !layers.contains( qobject_cast<QgsMapLayer *>( referencingLayer ) ) || referencingLayer->selectedFeatureCount() > 0 )
249 {
250 QgsFeatureIterator it { vLayer->getSelectedFeatures() };
251 QgsFeature selectedFeature;
252 while ( it.nextFeature( selectedFeature ) )
253 {
254 QgsFeatureIterator referencingFeaturesIterator { relation.getRelatedFeatures( selectedFeature ) };
255 QgsFeature referencingFeature;
256 while ( referencingFeaturesIterator.nextFeature( referencingFeature ) )
257 {
258 if ( referencingFeature.isValid() )
259 {
260 selected.insert( referencingFeature.id() );
261 }
262 }
263 }
264 }
265 }
266
267 if ( !alreadyAdded && ( !onlySaveSelected || !selected.isEmpty() ) )
268 {
269 feedback->pushInfo( QObject::tr( "Adding referencing layer '%1'" ).arg( referencingLayer->name() ) );
270 relatedLayer = referencingLayer->clone();
271 mLayers.emplace_back( relatedLayer );
272 mClonedLayerIds.insert( relatedLayer->id(), referencingLayer->id() );
273 }
274
275 if ( relatedLayer && !selected.isEmpty() )
276 {
277 relatedLayer->selectByIds( selected, Qgis::SelectBehavior::AddToSelection );
278 }
279
280 // Recursive finding
281 if ( recursionGuard > maxRecursion )
282 {
283 feedback->pushWarning( QObject::tr( "Max recursion (%1) adding referencing layer '%2', layer was not added" ).arg( QLocale().toString( recursionGuard ), referencingLayer->name() ) );
284 }
285 else if ( relatedLayer )
286 {
287 recursionGuard++;
288 findReferencing( relatedLayer, onlySaveSelected, findReferencing );
289 }
290 }
291 };
292
293 for ( const QgsMapLayer *layer : std::as_const( layers ) )
294 {
295 const QgsVectorLayer *vLayer { qobject_cast<const QgsVectorLayer *>( layer ) };
296 if ( vLayer )
297 {
298 const bool onlySaveSelected = vLayer->selectedFeatureCount() > 0 && selectedFeaturesOnly;
299 recursionGuard = 0;
300 findReferenced( vLayer, onlySaveSelected, findReferenced );
301 recursionGuard = 0;
302 findReferencing( vLayer, onlySaveSelected, findReferencing );
303 }
304 }
305 }
306 }
307
309
310 if ( !QFile::exists( packagePath ) )
311 {
312 hDS = gdal::ogr_datasource_unique_ptr( OGR_Dr_CreateDataSource( hGpkgDriver, packagePath.toUtf8().constData(), nullptr ) );
313 if ( !hDS )
314 throw QgsProcessingException( QObject::tr( "Creation of database %1 failed (OGR error: %2)" ).arg( packagePath, QString::fromUtf8( CPLGetLastErrorMsg() ) ) );
315 }
316 else
317 {
318 hDS = gdal::ogr_datasource_unique_ptr( OGROpen( packagePath.toUtf8().constData(), true, nullptr ) );
319 if ( !hDS )
320 throw QgsProcessingException( QObject::tr( "Opening database %1 failed (OGR error: %2)" ).arg( packagePath, QString::fromUtf8( CPLGetLastErrorMsg() ) ) );
321 }
322
323 const bool validExtent = parameters.value( QStringLiteral( "EXTENT" ) ).isValid();
324
325 bool errored = false;
326
327 QgsProcessingMultiStepFeedback multiStepFeedback( mLayers.size(), feedback );
328
329 QStringList outputLayers;
330
331 int i = 0;
332 for ( const auto &layer : mLayers )
333 {
334 if ( feedback->isCanceled() )
335 break;
336
337 multiStepFeedback.setCurrentStep( i );
338 i++;
339
340 if ( !layer )
341 {
342 // don't throw immediately - instead do what we can and error out later
343 feedback->pushDebugInfo( QObject::tr( "Error retrieving map layer." ) );
344 errored = true;
345 continue;
346 }
347
348 feedback->pushInfo( QObject::tr( "Packaging layer %1/%2: %3" ).arg( i ).arg( mLayers.size() ).arg( layer ? layer->name() : QString() ) );
349
350 QgsRectangle extent;
351
352 switch ( layer->type() )
353 {
355 {
356 QgsVectorLayer *vectorLayer = qobject_cast<QgsVectorLayer *>( layer.get() );
357
358 if ( validExtent )
359 {
361 {
362 feedback->pushWarning( QObject::tr( "No spatial index exists for layer %1, performance will be severely degraded" ).arg( vectorLayer->name() ) );
363 }
364
365 extent = parameterAsExtent( parameters, QStringLiteral( "EXTENT" ), context, mDestinationCrs.isValid() ? mDestinationCrs : layer->crs() );
366 }
367
368 if ( !packageVectorLayer( vectorLayer, packagePath, context, &multiStepFeedback, saveStyles, saveMetadata, selectedFeaturesOnly, extent ) )
369 errored = true;
370 else
371 outputLayers.append( QStringLiteral( "%1|layername=%2" ).arg( packagePath, layer->name() ) );
372 break;
373 }
374
376 {
377 //not supported
378 feedback->pushDebugInfo( QObject::tr( "Packaging raster layers is not supported." ) );
379 errored = true;
380 break;
381 }
382
384 //not supported
385 feedback->pushDebugInfo( QObject::tr( "Packaging plugin layers is not supported." ) );
386 errored = true;
387 break;
388
390 //not supported
391 feedback->pushDebugInfo( QObject::tr( "Packaging mesh layers is not supported." ) );
392 errored = true;
393 break;
394
396 //not supported
397 feedback->pushDebugInfo( QObject::tr( "Packaging point cloud layers is not supported." ) );
398 errored = true;
399 break;
400
402 //not supported
403 feedback->pushDebugInfo( QObject::tr( "Packaging vector tile layers is not supported." ) );
404 errored = true;
405 break;
406
408 //not supported
409 feedback->pushDebugInfo( QObject::tr( "Packaging annotation layers is not supported." ) );
410 errored = true;
411 break;
412
414 //not supported
415 feedback->pushDebugInfo( QObject::tr( "Packaging group layers is not supported." ) );
416 errored = true;
417 break;
418
420 //not supported
421 feedback->pushDebugInfo( QObject::tr( "Packaging tiled scene layers is not supported." ) );
422 errored = true;
423 break;
424 }
425 }
426
427 if ( errored )
428 throw QgsProcessingException( QObject::tr( "Error obtained while packaging one or more layers." ) );
429
430 QVariantMap outputs;
431 outputs.insert( QStringLiteral( "OUTPUT" ), packagePath );
432 outputs.insert( QStringLiteral( "OUTPUT_LAYERS" ), outputLayers );
433 return outputs;
434}
435
436bool QgsPackageAlgorithm::packageVectorLayer( QgsVectorLayer *layer, const QString &path, QgsProcessingContext &context, QgsProcessingFeedback *feedback, bool saveStyles, bool saveMetadata, bool selectedFeaturesOnly, const QgsRectangle &extent )
437{
439 options.driverName = QStringLiteral( "GPKG" );
440 options.layerName = layer->name();
442 options.fileEncoding = context.defaultEncoding();
443 options.onlySelectedFeatures = selectedFeaturesOnly;
444 options.feedback = feedback;
445 if ( saveMetadata )
446 {
447 options.layerMetadata = layer->metadata();
448 options.saveMetadata = true;
449 }
450
451 if ( mDestinationCrs.isValid() )
452 {
453 options.ct = QgsCoordinateTransform( layer->crs(), mDestinationCrs, context.transformContext() );
454 }
455
456 // Check FID compatibility with GPKG and remove any existing FID field if not compatible,
457 // let this be completely recreated since many layer sources have fid fields which are
458 // not compatible with gpkg requirements
459 const QgsFields fields = layer->fields();
460 const int fidIndex = fields.lookupField( QStringLiteral( "fid" ) );
461
462 options.attributes = fields.allAttributesList();
463 if ( fidIndex >= 0 )
464 {
465 const QMetaType::Type fidType { layer->fields().field( fidIndex ).type() };
468 && fidType != QMetaType::Type::Int
469 && fidType != QMetaType::Type::UInt
470 && fidType != QMetaType::Type::LongLong
471 && fidType != QMetaType::Type::ULongLong )
472 {
473 options.attributes.removeAll( fidIndex );
474 }
475 }
476
477 if ( options.attributes.isEmpty() )
478 {
479 // fid was the only field
480 options.skipAttributeCreation = true;
481 }
482
483 if ( !extent.isNull() )
484 {
485 options.filterExtent = extent;
486 }
487
488 QString error;
489 QString newFilename;
490 QString newLayer;
491 if ( QgsVectorFileWriter::writeAsVectorFormatV3( layer, path, context.transformContext(), options, &error, &newFilename, &newLayer ) != QgsVectorFileWriter::NoError )
492 {
493 feedback->reportError( QObject::tr( "Packaging layer failed: %1" ).arg( error ) );
494 return false;
495 }
496 else
497 {
498 if ( saveStyles )
499 {
500 auto res = std::make_unique<QgsVectorLayer>( QStringLiteral( "%1|layername=%2" ).arg( newFilename, newLayer ) );
501 if ( res )
502 {
503 QString errorMsg;
504 QDomDocument doc( QStringLiteral( "qgis" ) );
505 const QgsReadWriteContext context;
506 layer->exportNamedStyle( doc, errorMsg, context );
507 if ( !errorMsg.isEmpty() )
508 {
509 feedback->reportError( QObject::tr( "Could not retrieve existing layer style: %1 " ).arg( errorMsg ) );
510 }
511 else
512 {
513 if ( !res->importNamedStyle( doc, errorMsg ) )
514 {
515 feedback->reportError( QObject::tr( "Could not set existing layer style: %1 " ).arg( errorMsg ) );
516 }
517 else
518 {
519 QgsSettings settings;
520 // this is not nice -- but needed to avoid an "overwrite" prompt messagebox from the provider! This api needs a rework to avoid this.
521 const QVariant prevOverwriteStyle = settings.value( QStringLiteral( "qgis/overwriteStyle" ) );
522 settings.setValue( QStringLiteral( "qgis/overwriteStyle" ), true );
523 QgsMapLayer::SaveStyleResults saveStyleResults = res->saveStyleToDatabaseV2( newLayer, QString(), true, QString(), errorMsg );
524 settings.setValue( QStringLiteral( "qgis/overwriteStyle" ), prevOverwriteStyle );
525 if ( saveStyleResults.testFlag( QgsMapLayer::SaveStyleResult::QmlGenerationFailed )
526 || saveStyleResults.testFlag( QgsMapLayer::SaveStyleResult::DatabaseWriteFailed ) )
527 {
528 feedback->reportError( QObject::tr( "Could not save layer style: %1 " ).arg( errorMsg ) );
529 }
530 }
531 }
532 }
533 else
534 {
535 feedback->reportError( QObject::tr( "Could not save layer style -- error loading: %1 %2" ).arg( newFilename, newLayer ) );
536 }
537 }
538 return true;
539 }
540}
541
@ Vector
Tables (i.e. vector layers with or without geometry). When used for a sink this indicates the sink ha...
@ NotPresent
No spatial index exists for the source.
@ Group
Composite group layer. Added in QGIS 3.24.
@ Plugin
Plugin based layer.
@ TiledScene
Tiled scene layer. Added in QGIS 3.34.
@ Annotation
Contains freeform, georeferenced annotations. Added in QGIS 3.16.
@ Vector
Vector layer.
@ VectorTile
Vector tile layer. Added in QGIS 3.14.
@ Mesh
Mesh layer. Added in QGIS 3.2.
@ Raster
Raster layer.
@ PointCloud
Point cloud layer. Added in QGIS 3.18.
@ Advanced
Parameter is an advanced parameter which should be hidden from users by default.
@ AddToSelection
Add selection to current selection.
Handles coordinate transforms between two coordinate systems.
Wrapper for iterator of features from vector data provider or vector layer.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:58
QgsFeatureId id
Definition qgsfeature.h:66
bool isValid() const
Returns the validity of this feature.
@ ConstraintNotNull
Field may not be null.
@ ConstraintUnique
Field must have a unique value.
QMetaType::Type type
Definition qgsfield.h:60
Container of fields for a vector layer.
Definition qgsfields.h:46
QgsAttributeList allAttributesList() const
Utility function to get list of attribute indexes.
QgsField field(int fieldIdx) const
Returns the field at particular index (must be in range 0..N-1).
Q_INVOKABLE int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
Base class for all map layer types.
Definition qgsmaplayer.h:78
QString name
Definition qgsmaplayer.h:82
virtual void exportNamedStyle(QDomDocument &doc, QString &errorMsg, const QgsReadWriteContext &context=QgsReadWriteContext(), QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories) const
Export the properties of this layer as named style in a QDomDocument.
@ DatabaseWriteFailed
An error occurred when attempting to write to the database.
@ QmlGenerationFailed
Generation of the QML failed, and was not written to the database.
QgsCoordinateReferenceSystem crs
Definition qgsmaplayer.h:85
QgsLayerMetadata metadata
Definition qgsmaplayer.h:84
virtual QgsMapLayer * clone() const =0
Returns a new instance equivalent to this one except for the id which is still unique.
QFlags< SaveStyleResult > SaveStyleResults
Results of saving styles to database.
Contains information about the context in which a processing algorithm is executed.
QString defaultEncoding() const
Returns the default encoding to use for newly created files.
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context.
QgsProject * project() const
Returns the project in which the algorithm is being executed.
Custom exception class for processing related exceptions.
Base class for providing feedback from a processing algorithm.
virtual void pushInfo(const QString &info)
Pushes a general informational message from the algorithm.
virtual void reportError(const QString &error, bool fatalError=false)
Reports that the algorithm encountered an error while executing.
Processing feedback object for multi-step operations.
A multi-layer output for processing algorithms which create map layers, when the number and nature of...
A boolean parameter for processing algorithms.
void setMetadata(const QVariantMap &metadata)
Sets the parameter's freeform metadata.
A generic file based destination parameter, for specifying the destination path for a file (non-map l...
A parameter for processing algorithms which accepts multiple map layers.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition qgsproject.h:107
A container for the context for various read/write operations on objects.
A rectangle specified with double values.
Represents a relationship between two vector layers.
Definition qgsrelation.h:44
Stores settings for use within QGIS.
Definition qgssettings.h:65
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
Options to pass to QgsVectorFileWriter::writeAsVectorFormat().
QgsCoordinateTransform ct
Transform to reproject exported geometries with, or invalid transform for no transformation.
QgsLayerMetadata layerMetadata
Layer metadata to save for the exported vector file.
QString layerName
Layer name. If let empty, it will be derived from the filename.
QgsRectangle filterExtent
If not empty, only features intersecting the extent will be saved.
bool saveMetadata
Set to true to save layer metadata for the exported vector file.
QgsVectorFileWriter::ActionOnExistingFile actionOnExistingFile
Action on existing file.
QgsAttributeList attributes
Attributes to export (empty means all unless skipAttributeCreation is set)
bool onlySelectedFeatures
Write only selected features of layer.
bool skipAttributeCreation
Only write geometries.
QgsFeedback * feedback
Optional feedback object allowing cancellation of layer save.
static QgsVectorFileWriter::WriterError writeAsVectorFormatV3(QgsVectorLayer *layer, const QString &fileName, const QgsCoordinateTransformContext &transformContext, const QgsVectorFileWriter::SaveVectorOptions &options, QString *errorMessage=nullptr, QString *newFilename=nullptr, QString *newLayer=nullptr)
Writes a layer out to a vector file.
@ CreateOrOverwriteLayer
Create or overwrite layer.
Represents a vector layer which manages a vector based dataset.
QgsFieldConstraints::Constraints fieldConstraints(int fieldIndex) const
Returns any constraints which are present for a specified field index.
int selectedFeatureCount() const
Returns the number of features that are selected in this layer.
Qgis::SpatialIndexPresence hasSpatialIndex() const override
std::unique_ptr< std::remove_pointer< OGRDataSourceH >::type, OGRDataSourceDeleter > ogr_datasource_unique_ptr
Scoped OGR data source.
QSet< QgsFeatureId > QgsFeatureIds
const QgsCoordinateReferenceSystem & crs