QGIS API Documentation 3.30.0-'s-Hertogenbosch (f186b8efe0)
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" ), QgsProcessing::TypeVector ) );
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 addOutput( new QgsProcessingOutputMultipleLayers( QStringLiteral( "OUTPUT_LAYERS" ), QObject::tr( "Layers within new package" ) ) );
65}
66
67QString QgsPackageAlgorithm::shortHelpString() const
68{
69 return QObject::tr( "This algorithm collects a number of existing layers and packages them together into a single GeoPackage database." );
70}
71
72QgsPackageAlgorithm *QgsPackageAlgorithm::createInstance() const
73{
74 return new QgsPackageAlgorithm();
75}
76
77bool QgsPackageAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
78{
79
80 const QList< QgsMapLayer * > layers = parameterAsLayerList( parameters, QStringLiteral( "LAYERS" ), context );
81
82 for ( const QgsMapLayer *layer : std::as_const( layers ) )
83 {
84 QgsMapLayer *clonedLayer { layer->clone() };
85 mClonedLayerIds.insert( clonedLayer->id(), layer->id( ) );
86 mLayers.emplace_back( clonedLayer );
87 }
88
89 if ( mLayers.empty() )
90 {
91 feedback->reportError( QObject::tr( "No layers selected, geopackage will be empty" ), false );
92 }
93
94 return true;
95}
96
97QVariantMap QgsPackageAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
98{
99 const bool overwrite = parameterAsBoolean( parameters, QStringLiteral( "OVERWRITE" ), context );
100 const bool saveStyles = parameterAsBoolean( parameters, QStringLiteral( "SAVE_STYLES" ), context );
101 const bool saveMetadata = parameterAsBoolean( parameters, QStringLiteral( "SAVE_METADATA" ), context );
102 const bool selectedFeaturesOnly = parameterAsBoolean( parameters, QStringLiteral( "SELECTED_FEATURES_ONLY" ), context );
103 const bool exportRelatedLayers = parameterAsBoolean( parameters, QStringLiteral( "EXPORT_RELATED_LAYERS" ), context );
104 const QString packagePath = parameterAsString( parameters, QStringLiteral( "OUTPUT" ), context );
105 const QList< QgsMapLayer * > layers = parameterAsLayerList( parameters, QStringLiteral( "LAYERS" ), context );
106
107 if ( packagePath.isEmpty() )
108 throw QgsProcessingException( QObject::tr( "No output file specified." ) );
109
110 // delete existing geopackage if it exists
111 if ( overwrite && QFile::exists( packagePath ) )
112 {
113 feedback->pushInfo( QObject::tr( "Removing existing file '%1'" ).arg( packagePath ) );
114 if ( !QFile( packagePath ).remove() )
115 {
116 throw QgsProcessingException( QObject::tr( "Could not remove existing file '%1'" ).arg( packagePath ) );
117 }
118 }
119
120 OGRSFDriverH hGpkgDriver = OGRGetDriverByName( "GPKG" );
121 if ( !hGpkgDriver )
122 {
123 throw QgsProcessingException( QObject::tr( "GeoPackage driver not found." ) );
124 }
125
126
127 // Collect related layers from project relations
128 if ( exportRelatedLayers )
129 {
130 const QgsProject *project { context.project() };
131 if ( project && ! project->relationManager()->relations().isEmpty() )
132 {
133
134 // Infinite recursion should not happen in the real world but better safe than sorry
135 const int maxRecursion { 10 };
136 int recursionGuard { 0 };
137
138 // This function recursively finds referenced layers
139 const auto findReferenced = [ =, &project, &feedback, &recursionGuard, &layers ]( const QgsVectorLayer * vLayer, bool onlySaveSelected, auto &&findReferenced ) -> void
140 {
141 const QgsVectorLayer *originalLayer { qobject_cast<QgsVectorLayer *>( project->mapLayer( mClonedLayerIds.value( vLayer->id(), vLayer->id() ) ) ) };
142 Q_ASSERT( originalLayer );
143 const QList<QgsRelation> relations { project->relationManager()->referencingRelations( originalLayer ) };
144 for ( const QgsRelation &relation : std::as_const( relations ) )
145 {
146
147 QgsVectorLayer *referencedLayer { relation.referencedLayer() };
148 QgsVectorLayer *relatedLayer { nullptr };
149
150 // Check if the layer was already in the export list
151 bool alreadyAdded { false };
152 for ( const auto &layerToExport : std::as_const( mLayers ) )
153 {
154 const QString originalId { mClonedLayerIds.value( layerToExport->id() ) };
155 if ( originalId == referencedLayer->id() )
156 {
157 relatedLayer = qobject_cast<QgsVectorLayer *>( layerToExport.get() );
158 alreadyAdded = true;
159 break;
160 }
161 }
162
163 if ( !alreadyAdded )
164 {
165 feedback->pushInfo( QObject::tr( "Adding referenced layer '%1'" ).arg( referencedLayer->name() ) );
166 relatedLayer = referencedLayer->clone();
167 mLayers.emplace_back( relatedLayer );
168 mClonedLayerIds.insert( relatedLayer->id(), referencedLayer->id() );
169 }
170
171 // Export only relevant features unless the layer was in the original export list and no selection was made on that layer
172 // in that case the user explicitly marked the layer for export and it is supposed to be exported fully.
173 if ( onlySaveSelected )
174 {
175 if ( ! layers.contains( qobject_cast<QgsMapLayer *>( referencedLayer ) ) || referencedLayer->selectedFeatureCount() > 0 )
176 {
177 Q_ASSERT( relatedLayer );
178 QgsFeatureIds selected;
179 QgsFeatureIterator it { vLayer->getSelectedFeatures() };
180 QgsFeature selectedFeature;
181 while ( it.nextFeature( selectedFeature ) )
182 {
183 QgsFeature referencedFeature { relation.getReferencedFeature( selectedFeature ) };
184 if ( referencedFeature.isValid() )
185 {
186 selected.insert( referencedFeature.id() );
187 }
188 }
189 relatedLayer->selectByIds( selected, Qgis::SelectBehavior::AddToSelection );
190 }
191 }
192
193 // Recursive finding
194 if ( recursionGuard > maxRecursion )
195 {
196 feedback->pushWarning( QObject::tr( "Max recursion (%1) adding referenced layer '%2', layer was not added" ).arg( QLocale().toString( recursionGuard ), referencedLayer->name() ) );
197 }
198 else
199 {
200 recursionGuard++;
201 findReferenced( relatedLayer, onlySaveSelected, findReferenced );
202 }
203 }
204
205 };
206
207 // This function recursively finds referencing layers
208 const auto findReferencing = [ =, &project, &feedback, &recursionGuard, &layers ]( const QgsVectorLayer * vLayer, bool onlySaveSelected, auto &&findReferencing ) -> void
209 {
210 const QgsVectorLayer *originalLayer { qobject_cast<QgsVectorLayer *>( project->mapLayer( mClonedLayerIds.value( vLayer->id(), vLayer->id() ) ) ) };
211 Q_ASSERT( originalLayer );
212 const QList<QgsRelation> relations { project->relationManager()->referencedRelations( originalLayer ) };
213 for ( const QgsRelation &relation : std::as_const( relations ) )
214 {
215
216 QgsVectorLayer *referencingLayer { relation.referencingLayer() };
217 QgsVectorLayer *relatedLayer { nullptr };
218 const bool layerWasExplicitlyAdded { layers.contains( qobject_cast<QgsMapLayer *>( referencingLayer ) ) };
219
220 // Check if the layer was already in the export list
221 bool alreadyAdded { false };
222 for ( const auto &layerToExport : std::as_const( mLayers ) )
223 {
224 const QString originalId { mClonedLayerIds.value( layerToExport->id() ) };
225 if ( originalId == referencingLayer->id() )
226 {
227 relatedLayer = qobject_cast<QgsVectorLayer *>( layerToExport.get() );
228 alreadyAdded = true;
229 break;
230 }
231 }
232
233 // Export only relevant features unless the layer was in the original export list and no selection was made on that layer
234 // in that case the user explicitly marked the layer for export and it is supposed to be exported fully.
235 QgsFeatureIds selected;
236
237 if ( onlySaveSelected && ( ! layerWasExplicitlyAdded || referencingLayer->selectedFeatureCount() > 0 ) )
238 {
239 if ( ! layers.contains( qobject_cast<QgsMapLayer *>( referencingLayer ) ) || referencingLayer->selectedFeatureCount() > 0 )
240 {
241 QgsFeatureIterator it { vLayer->getSelectedFeatures() };
242 QgsFeature selectedFeature;
243 while ( it.nextFeature( selectedFeature ) )
244 {
245 QgsFeatureIterator referencingFeaturesIterator { relation.getRelatedFeatures( selectedFeature ) };
246 QgsFeature referencingFeature;
247 while ( referencingFeaturesIterator.nextFeature( referencingFeature ) )
248 {
249 if ( referencingFeature.isValid() )
250 {
251 selected.insert( referencingFeature.id() );
252 }
253 }
254 }
255 }
256 }
257
258 if ( ! alreadyAdded && ( ! onlySaveSelected || ! selected.isEmpty() ) )
259 {
260 feedback->pushInfo( QObject::tr( "Adding referencing layer '%1'" ).arg( referencingLayer->name() ) );
261 relatedLayer = referencingLayer->clone();
262 mLayers.emplace_back( relatedLayer );
263 mClonedLayerIds.insert( relatedLayer->id(), referencingLayer->id() );
264 }
265
266 if ( relatedLayer && ! selected.isEmpty() )
267 {
268 relatedLayer->selectByIds( selected, Qgis::SelectBehavior::AddToSelection );
269 }
270
271 // Recursive finding
272 if ( recursionGuard > maxRecursion )
273 {
274 feedback->pushWarning( QObject::tr( "Max recursion (%1) adding referencing layer '%2', layer was not added" ).arg( QLocale().toString( recursionGuard ), referencingLayer->name() ) );
275 }
276 else if ( relatedLayer )
277 {
278 recursionGuard++;
279 findReferencing( relatedLayer, onlySaveSelected, findReferencing ) ;
280 }
281 }
282
283 };
284
285 for ( const QgsMapLayer *layer : std::as_const( layers ) )
286 {
287 const QgsVectorLayer *vLayer { qobject_cast<const QgsVectorLayer *>( layer ) };
288 if ( vLayer )
289 {
290 const bool onlySaveSelected = vLayer->selectedFeatureCount() > 0 && selectedFeaturesOnly;
291 recursionGuard = 0;
292 findReferenced( vLayer, onlySaveSelected, findReferenced );
293 recursionGuard = 0;
294 findReferencing( vLayer, onlySaveSelected, findReferencing );
295 }
296 }
297
298 }
299 }
300
302
303 if ( !QFile::exists( packagePath ) )
304 {
305 hDS = gdal::ogr_datasource_unique_ptr( OGR_Dr_CreateDataSource( hGpkgDriver, packagePath.toUtf8().constData(), nullptr ) );
306 if ( !hDS )
307 throw QgsProcessingException( QObject::tr( "Creation of database %1 failed (OGR error: %2)" ).arg( packagePath, QString::fromUtf8( CPLGetLastErrorMsg() ) ) );
308 }
309 else
310 {
311 hDS = gdal::ogr_datasource_unique_ptr( OGROpen( packagePath.toUtf8().constData(), true, nullptr ) );
312 if ( !hDS )
313 throw QgsProcessingException( QObject::tr( "Opening database %1 failed (OGR error: %2)" ).arg( packagePath, QString::fromUtf8( CPLGetLastErrorMsg() ) ) );
314 }
315
316
317 bool errored = false;
318
319 QgsProcessingMultiStepFeedback multiStepFeedback( mLayers.size(), feedback );
320
321 QStringList outputLayers;
322
323 int i = 0;
324 for ( const auto &layer : mLayers )
325 {
326 if ( feedback->isCanceled() )
327 break;
328
329 multiStepFeedback.setCurrentStep( i );
330 i++;
331
332 if ( !layer )
333 {
334 // don't throw immediately - instead do what we can and error out later
335 feedback->pushDebugInfo( QObject::tr( "Error retrieving map layer." ) );
336 errored = true;
337 continue;
338 }
339
340 feedback->pushInfo( QObject::tr( "Packaging layer %1/%2: %3" ).arg( i ).arg( mLayers.size() ).arg( layer ? layer->name() : QString() ) );
341
342 switch ( layer->type() )
343 {
344 case Qgis::LayerType::Vector:
345 {
346 QgsVectorLayer *vectorLayer = qobject_cast<QgsVectorLayer *>( layer.get() );
347 const bool onlySaveSelected = vectorLayer->selectedFeatureCount() > 0 && selectedFeaturesOnly;
348 if ( !packageVectorLayer( vectorLayer, packagePath, context, &multiStepFeedback, saveStyles, saveMetadata, onlySaveSelected ) )
349 errored = true;
350 else
351 outputLayers.append( QStringLiteral( "%1|layername=%2" ).arg( packagePath, layer->name() ) );
352 break;
353 }
354
355 case Qgis::LayerType::Raster:
356 {
357 //not supported
358 feedback->pushDebugInfo( QObject::tr( "Packaging raster layers is not supported." ) );
359 errored = true;
360 break;
361 }
362
363 case Qgis::LayerType::Plugin:
364 //not supported
365 feedback->pushDebugInfo( QObject::tr( "Packaging plugin layers is not supported." ) );
366 errored = true;
367 break;
368
369 case Qgis::LayerType::Mesh:
370 //not supported
371 feedback->pushDebugInfo( QObject::tr( "Packaging mesh layers is not supported." ) );
372 errored = true;
373 break;
374
375 case Qgis::LayerType::PointCloud:
376 //not supported
377 feedback->pushDebugInfo( QObject::tr( "Packaging point cloud layers is not supported." ) );
378 errored = true;
379 break;
380
381 case Qgis::LayerType::VectorTile:
382 //not supported
383 feedback->pushDebugInfo( QObject::tr( "Packaging vector tile layers is not supported." ) );
384 errored = true;
385 break;
386
387 case Qgis::LayerType::Annotation:
388 //not supported
389 feedback->pushDebugInfo( QObject::tr( "Packaging annotation layers is not supported." ) );
390 errored = true;
391 break;
392
393 case Qgis::LayerType::Group:
394 //not supported
395 feedback->pushDebugInfo( QObject::tr( "Packaging group layers is not supported." ) );
396 errored = true;
397 break;
398 }
399 }
400
401 if ( errored )
402 throw QgsProcessingException( QObject::tr( "Error obtained while packaging one or more layers." ) );
403
404 QVariantMap outputs;
405 outputs.insert( QStringLiteral( "OUTPUT" ), packagePath );
406 outputs.insert( QStringLiteral( "OUTPUT_LAYERS" ), outputLayers );
407 return outputs;
408}
409
410bool QgsPackageAlgorithm::packageVectorLayer( QgsVectorLayer *layer, const QString &path, QgsProcessingContext &context,
411 QgsProcessingFeedback *feedback, bool saveStyles, bool saveMetadata, bool selectedFeaturesOnly )
412{
414 options.driverName = QStringLiteral( "GPKG" );
415 options.layerName = layer->name();
417 options.fileEncoding = context.defaultEncoding();
418 options.onlySelectedFeatures = selectedFeaturesOnly;
419 options.feedback = feedback;
420 if ( saveMetadata )
421 {
422 options.layerMetadata = layer->metadata();
423 options.saveMetadata = true;
424 }
425
426 // Check FID compatibility with GPKG and remove any existing FID field if not compatible,
427 // let this be completely recreated since many layer sources have fid fields which are
428 // not compatible with gpkg requirements
429 const QgsFields fields = layer->fields();
430 const int fidIndex = fields.lookupField( QStringLiteral( "fid" ) );
431
432 options.attributes = fields.allAttributesList();
433 if ( fidIndex >= 0 )
434 {
435 const QVariant::Type fidType { layer->fields().field( fidIndex ).type() };
436 if ( ! layer->fieldConstraints( fidIndex ).testFlag( QgsFieldConstraints::Constraint::ConstraintUnique )
437 && ! layer->fieldConstraints( fidIndex ).testFlag( QgsFieldConstraints::Constraint::ConstraintNotNull )
438 && fidType != QVariant::Int
439 && fidType != QVariant::UInt
440 && fidType != QVariant::LongLong
441 && fidType != QVariant::ULongLong )
442 {
443 options.attributes.removeAll( fidIndex );
444 }
445 }
446
447 if ( options.attributes.isEmpty() )
448 {
449 // fid was the only field
450 options.skipAttributeCreation = true;
451 }
452
453 QString error;
454 QString newFilename;
455 QString newLayer;
456 if ( QgsVectorFileWriter::writeAsVectorFormatV3( layer, path, context.transformContext(), options, &error, &newFilename, &newLayer ) != QgsVectorFileWriter::NoError )
457 {
458 feedback->reportError( QObject::tr( "Packaging layer failed: %1" ).arg( error ) );
459 return false;
460 }
461 else
462 {
463 if ( saveStyles )
464 {
465 std::unique_ptr< QgsVectorLayer > res = std::make_unique< QgsVectorLayer >( QStringLiteral( "%1|layername=%2" ).arg( newFilename, newLayer ) );
466 if ( res )
467 {
468 QString errorMsg;
469 QDomDocument doc( QStringLiteral( "qgis" ) );
470 const QgsReadWriteContext context;
471 layer->exportNamedStyle( doc, errorMsg, context );
472 if ( !errorMsg.isEmpty() )
473 {
474 feedback->reportError( QObject::tr( "Could not retrieve existing layer style: %1 " ).arg( errorMsg ) );
475 }
476 else
477 {
478 if ( !res->importNamedStyle( doc, errorMsg ) )
479 {
480 feedback->reportError( QObject::tr( "Could not set existing layer style: %1 " ).arg( errorMsg ) );
481 }
482 else
483 {
484 QgsSettings settings;
485 // this is not nice -- but needed to avoid an "overwrite" prompt messagebox from the provider! This api needs a rework to avoid this.
486 const QVariant prevOverwriteStyle = settings.value( QStringLiteral( "qgis/overwriteStyle" ) );
487 settings.setValue( QStringLiteral( "qgis/overwriteStyle" ), true );
488 res->saveStyleToDatabase( newLayer, QString(), true, QString(), errorMsg );
489 settings.setValue( QStringLiteral( "qgis/overwriteStyle" ), prevOverwriteStyle );
490 if ( !errorMsg.isEmpty() )
491 {
492 feedback->reportError( QObject::tr( "Could not save layer style: %1 " ).arg( errorMsg ) );
493 }
494 }
495 }
496 }
497 else
498 {
499 feedback->reportError( QObject::tr( "Could not save layer style -- error loading: %1 %2" ).arg( newFilename, newLayer ) );
500 }
501 }
502 return true;
503 }
504}
505
@ AddToSelection
Add selection to current selection.
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:56
bool isValid() const
Returns the validity of this feature.
Definition: qgsfeature.cpp:219
Q_GADGET QgsFeatureId id
Definition: qgsfeature.h:64
QVariant::Type type
Definition: qgsfield.h:59
Container of fields for a vector layer.
Definition: qgsfields.h:45
QgsAttributeList allAttributesList() const
Utility function to get list of attribute indexes.
Definition: qgsfields.cpp:386
QgsField field(int fieldIdx) const
Returns the field at particular index (must be in range 0..N-1).
Definition: qgsfields.cpp:168
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
Definition: qgsfields.cpp:359
Base class for all map layer types.
Definition: qgsmaplayer.h:73
QString name
Definition: qgsmaplayer.h:76
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.
QgsLayerMetadata metadata
Definition: qgsmaplayer.h:78
virtual QgsMapLayer * clone() const =0
Returns a new instance equivalent to this one except for the id which is still unique.
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.
Definition: qgsexception.h:83
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.
@ TypeVector
Tables (i.e. vector layers with or without geometry). When used for a sink this indicates the sink ha...
Definition: qgsprocessing.h:55
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition: qgsproject.h:105
The class is used as a container of context for various read/write operations on other objects.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:63
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 writeAsVectorFormat()
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.
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 data sets.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
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.
std::unique_ptr< std::remove_pointer< OGRDataSourceH >::type, OGRDataSourceDeleter > ogr_datasource_unique_ptr
Scoped OGR data source.
Definition: qgsogrutils.h:137
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:37