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