QGIS API Documentation 4.3.0-Master (ffcfc20b9b4)
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 QGS_MARK_ALGORITHM_SOURCE
119
120 const bool overwrite = parameterAsBoolean( parameters, u"OVERWRITE"_s, context );
121 const bool saveStyles = parameterAsBoolean( parameters, u"SAVE_STYLES"_s, context );
122 const bool saveMetadata = parameterAsBoolean( parameters, u"SAVE_METADATA"_s, context );
123 const bool selectedFeaturesOnly = parameterAsBoolean( parameters, u"SELECTED_FEATURES_ONLY"_s, context );
124 const bool exportRelatedLayers = parameterAsBoolean( parameters, u"EXPORT_RELATED_LAYERS"_s, context );
125 const QString packagePath = parameterAsString( parameters, u"OUTPUT"_s, context );
126 const QList<QgsMapLayer *> layers = parameterAsLayerList( parameters, u"LAYERS"_s, context );
127
128 if ( packagePath.isEmpty() )
129 throw QgsProcessingException( QObject::tr( "No output file specified." ) );
130
131 // delete existing geopackage if it exists
132 if ( overwrite && QFile::exists( packagePath ) )
133 {
134 feedback->pushInfo( QObject::tr( "Removing existing file '%1'" ).arg( packagePath ) );
135 if ( !QFile( packagePath ).remove() )
136 {
137 throw QgsProcessingException( QObject::tr( "Could not remove existing file '%1'" ).arg( packagePath ) );
138 }
139 }
140
141 OGRSFDriverH hGpkgDriver = OGRGetDriverByName( "GPKG" );
142 if ( !hGpkgDriver )
143 {
144 throw QgsProcessingException( QObject::tr( "GeoPackage driver not found." ) );
145 }
146
147
148 // Collect related layers from project relations
149 if ( exportRelatedLayers )
150 {
151 const QgsProject *project { context.project() };
152 if ( project && !project->relationManager()->relations().isEmpty() )
153 {
154 // Infinite recursion should not happen in the real world but better safe than sorry
155 const int maxRecursion { 10 };
156 int recursionGuard { 0 };
157
158 // This function recursively finds referenced layers
159 const auto findReferenced = [this, &project, &feedback, &recursionGuard, &layers]( const QgsVectorLayer *vLayer, bool onlySaveSelected, auto &&findReferenced ) -> void {
160 const QgsVectorLayer *originalLayer { qobject_cast<QgsVectorLayer *>( project->mapLayer( mClonedLayerIds.value( vLayer->id(), vLayer->id() ) ) ) };
161 Q_ASSERT( originalLayer );
162 const QList<QgsRelation> relations { project->relationManager()->referencingRelations( originalLayer ) };
163 for ( const QgsRelation &relation : std::as_const( relations ) )
164 {
165 QgsVectorLayer *referencedLayer { relation.referencedLayer() };
166 QgsVectorLayer *relatedLayer { nullptr };
167
168 // Check if the layer was already in the export list
169 bool alreadyAdded { false };
170 for ( const auto &layerToExport : std::as_const( mLayers ) )
171 {
172 const QString originalId { mClonedLayerIds.value( layerToExport->id() ) };
173 if ( originalId == referencedLayer->id() )
174 {
175 relatedLayer = qobject_cast<QgsVectorLayer *>( layerToExport.get() );
176 alreadyAdded = true;
177 break;
178 }
179 }
180
181 if ( !alreadyAdded )
182 {
183 feedback->pushInfo( QObject::tr( "Adding referenced layer '%1'" ).arg( referencedLayer->name() ) );
184 relatedLayer = referencedLayer->clone();
185 mLayers.emplace_back( relatedLayer );
186 mClonedLayerIds.insert( relatedLayer->id(), referencedLayer->id() );
187 }
188
189 // Export only relevant features unless the layer was in the original export list and no selection was made on that layer
190 // in that case the user explicitly marked the layer for export and it is supposed to be exported fully.
191 if ( onlySaveSelected )
192 {
193 if ( !layers.contains( qobject_cast<QgsMapLayer *>( referencedLayer ) ) || referencedLayer->selectedFeatureCount() > 0 )
194 {
195 Q_ASSERT( relatedLayer );
196 QgsFeatureIds selected;
197 QgsFeatureIterator it { vLayer->getSelectedFeatures() };
198 QgsFeature selectedFeature;
199 while ( it.nextFeature( selectedFeature ) )
200 {
201 QgsFeature referencedFeature { relation.getReferencedFeature( selectedFeature ) };
202 if ( referencedFeature.isValid() )
203 {
204 selected.insert( referencedFeature.id() );
205 }
206 }
207 relatedLayer->selectByIds( selected, Qgis::SelectBehavior::AddToSelection );
208 }
209 }
210
211 // Recursive finding
212 if ( recursionGuard > maxRecursion )
213 {
214 feedback->pushWarning( QObject::tr( "Max recursion (%1) adding referenced layer '%2', layer was not added" ).arg( QLocale().toString( recursionGuard ), referencedLayer->name() ) );
215 }
216 else
217 {
218 recursionGuard++;
219 findReferenced( relatedLayer, onlySaveSelected, findReferenced );
220 }
221 }
222 };
223
224 // This function recursively finds referencing layers
225 const auto findReferencing = [this, &project, &feedback, &recursionGuard, &layers]( const QgsVectorLayer *vLayer, bool onlySaveSelected, auto &&findReferencing ) -> void {
226 const QgsVectorLayer *originalLayer { qobject_cast<QgsVectorLayer *>( project->mapLayer( mClonedLayerIds.value( vLayer->id(), vLayer->id() ) ) ) };
227 Q_ASSERT( originalLayer );
228 const QList<QgsRelation> relations { project->relationManager()->referencedRelations( originalLayer ) };
229 for ( const QgsRelation &relation : std::as_const( relations ) )
230 {
231 QgsVectorLayer *referencingLayer { relation.referencingLayer() };
232 QgsVectorLayer *relatedLayer { nullptr };
233 const bool layerWasExplicitlyAdded { layers.contains( qobject_cast<QgsMapLayer *>( referencingLayer ) ) };
234
235 // Check if the layer was already in the export list
236 bool alreadyAdded { false };
237 for ( const auto &layerToExport : std::as_const( mLayers ) )
238 {
239 const QString originalId { mClonedLayerIds.value( layerToExport->id() ) };
240 if ( originalId == referencingLayer->id() )
241 {
242 relatedLayer = qobject_cast<QgsVectorLayer *>( layerToExport.get() );
243 alreadyAdded = true;
244 break;
245 }
246 }
247
248 // Export only relevant features unless the layer was in the original export list and no selection was made on that layer
249 // in that case the user explicitly marked the layer for export and it is supposed to be exported fully.
250 QgsFeatureIds selected;
251
252 if ( onlySaveSelected && ( !layerWasExplicitlyAdded || referencingLayer->selectedFeatureCount() > 0 ) )
253 {
254 if ( !layers.contains( qobject_cast<QgsMapLayer *>( referencingLayer ) ) || referencingLayer->selectedFeatureCount() > 0 )
255 {
256 QgsFeatureIterator it { vLayer->getSelectedFeatures() };
257 QgsFeature selectedFeature;
258 while ( it.nextFeature( selectedFeature ) )
259 {
260 QgsFeatureIterator referencingFeaturesIterator { relation.getRelatedFeatures( selectedFeature ) };
261 QgsFeature referencingFeature;
262 while ( referencingFeaturesIterator.nextFeature( referencingFeature ) )
263 {
264 if ( referencingFeature.isValid() )
265 {
266 selected.insert( referencingFeature.id() );
267 }
268 }
269 }
270 }
271 }
272
273 if ( !alreadyAdded && ( !onlySaveSelected || !selected.isEmpty() ) )
274 {
275 feedback->pushInfo( QObject::tr( "Adding referencing layer '%1'" ).arg( referencingLayer->name() ) );
276 relatedLayer = referencingLayer->clone();
277 mLayers.emplace_back( relatedLayer );
278 mClonedLayerIds.insert( relatedLayer->id(), referencingLayer->id() );
279 }
280
281 if ( relatedLayer && !selected.isEmpty() )
282 {
283 relatedLayer->selectByIds( selected, Qgis::SelectBehavior::AddToSelection );
284 }
285
286 // Recursive finding
287 if ( recursionGuard > maxRecursion )
288 {
289 feedback->pushWarning( QObject::tr( "Max recursion (%1) adding referencing layer '%2', layer was not added" ).arg( QLocale().toString( recursionGuard ), referencingLayer->name() ) );
290 }
291 else if ( relatedLayer )
292 {
293 recursionGuard++;
294 findReferencing( relatedLayer, onlySaveSelected, findReferencing );
295 }
296 }
297 };
298
299 for ( const QgsMapLayer *layer : std::as_const( layers ) )
300 {
301 const QgsVectorLayer *vLayer { qobject_cast<const QgsVectorLayer *>( layer ) };
302 if ( vLayer )
303 {
304 const bool onlySaveSelected = vLayer->selectedFeatureCount() > 0 && selectedFeaturesOnly;
305 recursionGuard = 0;
306 findReferenced( vLayer, onlySaveSelected, findReferenced );
307 recursionGuard = 0;
308 findReferencing( vLayer, onlySaveSelected, findReferencing );
309 }
310 }
311 }
312 }
313
315
316 if ( !QFile::exists( packagePath ) )
317 {
318 hDS = gdal::ogr_datasource_unique_ptr( OGR_Dr_CreateDataSource( hGpkgDriver, packagePath.toUtf8().constData(), nullptr ) );
319 if ( !hDS )
320 throw QgsProcessingException( QObject::tr( "Creation of database %1 failed (OGR error: %2)" ).arg( packagePath, QString::fromUtf8( CPLGetLastErrorMsg() ) ) );
321 }
322 else
323 {
324 hDS = gdal::ogr_datasource_unique_ptr( OGROpen( packagePath.toUtf8().constData(), true, nullptr ) );
325 if ( !hDS )
326 throw QgsProcessingException( QObject::tr( "Opening database %1 failed (OGR error: %2)" ).arg( packagePath, QString::fromUtf8( CPLGetLastErrorMsg() ) ) );
327 }
328
329 const bool validExtent = parameters.value( u"EXTENT"_s ).isValid();
330
331 bool errored = false;
332
333 QgsProcessingMultiStepFeedback multiStepFeedback( mLayers.size(), feedback );
334
335 QStringList outputLayers;
336
337 int i = 0;
338 for ( const auto &layer : mLayers )
339 {
340 if ( feedback->isCanceled() )
341 break;
342
343 multiStepFeedback.setCurrentStep( i );
344 i++;
345
346 if ( !layer )
347 {
348 // don't throw immediately - instead do what we can and error out later
349 feedback->pushDebugInfo( QObject::tr( "Error retrieving map layer." ) );
350 errored = true;
351 continue;
352 }
353
354 feedback->pushInfo( QObject::tr( "Packaging layer %1/%2: %3" ).arg( i ).arg( mLayers.size() ).arg( layer ? layer->name() : QString() ) );
355
356 QgsRectangle extent;
357
358 switch ( layer->type() )
359 {
361 {
362 QgsVectorLayer *vectorLayer = qobject_cast<QgsVectorLayer *>( layer.get() );
363
364 if ( validExtent )
365 {
367 {
368 feedback->pushWarning( QObject::tr( "No spatial index exists for layer %1, performance will be severely degraded" ).arg( vectorLayer->name() ) );
369 }
370
371 extent = parameterAsExtent( parameters, u"EXTENT"_s, context, mDestinationCrs.isValid() ? mDestinationCrs : layer->crs() );
372 }
373
374 if ( !packageVectorLayer( vectorLayer, packagePath, context, &multiStepFeedback, saveStyles, saveMetadata, selectedFeaturesOnly, extent ) )
375 errored = true;
376 else
377 outputLayers.append( u"%1|layername=%2"_s.arg( packagePath, layer->name() ) );
378 break;
379 }
380
382 {
383 //not supported
384 feedback->pushDebugInfo( QObject::tr( "Packaging raster layers is not supported." ) );
385 errored = true;
386 break;
387 }
388
390 //not supported
391 feedback->pushDebugInfo( QObject::tr( "Packaging plugin layers is not supported." ) );
392 errored = true;
393 break;
394
396 //not supported
397 feedback->pushDebugInfo( QObject::tr( "Packaging mesh layers is not supported." ) );
398 errored = true;
399 break;
400
402 //not supported
403 feedback->pushDebugInfo( QObject::tr( "Packaging point cloud layers is not supported." ) );
404 errored = true;
405 break;
406
408 //not supported
409 feedback->pushDebugInfo( QObject::tr( "Packaging vector tile layers is not supported." ) );
410 errored = true;
411 break;
412
414 //not supported
415 feedback->pushDebugInfo( QObject::tr( "Packaging annotation layers is not supported." ) );
416 errored = true;
417 break;
418
420 //not supported
421 feedback->pushDebugInfo( QObject::tr( "Packaging group layers is not supported." ) );
422 errored = true;
423 break;
424
426 //not supported
427 feedback->pushDebugInfo( QObject::tr( "Packaging tiled scene layers is not supported." ) );
428 errored = true;
429 break;
430 }
431 }
432
433 if ( errored )
434 throw QgsProcessingException( QObject::tr( "Error obtained while packaging one or more layers." ) );
435
436 QVariantMap outputs;
437 outputs.insert( u"OUTPUT"_s, packagePath );
438 outputs.insert( u"OUTPUT_LAYERS"_s, outputLayers );
439 return outputs;
440}
441
442bool QgsPackageAlgorithm::packageVectorLayer(
443 QgsVectorLayer *layer, const QString &path, QgsProcessingContext &context, QgsProcessingFeedback *feedback, bool saveStyles, bool saveMetadata, bool selectedFeaturesOnly, const QgsRectangle &extent
444)
445{
447 options.driverName = u"GPKG"_s;
448 options.layerName = layer->name();
450 options.fileEncoding = context.defaultEncoding();
451 options.onlySelectedFeatures = selectedFeaturesOnly;
452 options.feedback = feedback;
453 if ( saveMetadata )
454 {
455 options.layerMetadata = layer->metadata();
456 options.saveMetadata = true;
457 }
458
459 if ( mDestinationCrs.isValid() )
460 {
461 options.ct = QgsCoordinateTransform( layer->crs(), mDestinationCrs, context.transformContext() );
462 }
463
464 // Check FID compatibility with GPKG and remove any existing FID field if not compatible,
465 // let this be completely recreated since many layer sources have fid fields which are
466 // not compatible with gpkg requirements
467 const QgsFields fields = layer->fields();
468 const int fidIndex = fields.lookupField( u"fid"_s );
469
470 options.attributes = fields.allAttributesList();
471 if ( fidIndex >= 0 )
472 {
473 const QMetaType::Type fidType { layer->fields().field( fidIndex ).type() };
476 && fidType != QMetaType::Type::Int
477 && fidType != QMetaType::Type::UInt
478 && fidType != QMetaType::Type::LongLong
479 && fidType != QMetaType::Type::ULongLong )
480 {
481 options.attributes.removeAll( fidIndex );
482 }
483 }
484
485 if ( options.attributes.isEmpty() )
486 {
487 // fid was the only field
488 options.skipAttributeCreation = true;
489 }
490
491 if ( !extent.isNull() )
492 {
493 options.filterExtent = extent;
494 }
495
496 QString error;
497 QString newFilename;
498 QString newLayer;
499 if ( QgsVectorFileWriter::writeAsVectorFormatV3( layer, path, context.transformContext(), options, &error, &newFilename, &newLayer ) != QgsVectorFileWriter::NoError )
500 {
501 feedback->reportError( QObject::tr( "Packaging layer failed: %1" ).arg( error ) );
502 return false;
503 }
504 else
505 {
506 if ( saveStyles )
507 {
508 auto res = std::make_unique<QgsVectorLayer>( u"%1|layername=%2"_s.arg( newFilename, newLayer ) );
509 if ( res->isValid() )
510 {
511 QString errorMsg;
512 QDomDocument doc( u"qgis"_s );
513 const QgsReadWriteContext context;
514 layer->exportNamedStyle( doc, errorMsg, context );
515 if ( !errorMsg.isEmpty() )
516 {
517 feedback->reportError( QObject::tr( "Could not retrieve existing layer style: %1 " ).arg( errorMsg ) );
518 }
519 else
520 {
521 if ( !res->importNamedStyle( doc, errorMsg ) )
522 {
523 feedback->reportError( QObject::tr( "Could not set existing layer style: %1 " ).arg( errorMsg ) );
524 }
525 else
526 {
527 QgsSettings settings;
528 // this is not nice -- but needed to avoid an "overwrite" prompt messagebox from the provider! This api needs a rework to avoid this.
529 const QVariant prevOverwriteStyle = settings.value( u"qgis/overwriteStyle"_s );
530 settings.setValue( u"qgis/overwriteStyle"_s, true );
531 QgsMapLayer::SaveStyleResults saveStyleResults = res->saveStyleToDatabaseV2( newLayer, QString(), true, QString(), errorMsg );
532 settings.setValue( u"qgis/overwriteStyle"_s, prevOverwriteStyle );
533 if ( saveStyleResults.testFlag( QgsMapLayer::SaveStyleResult::QmlGenerationFailed ) || saveStyleResults.testFlag( QgsMapLayer::SaveStyleResult::DatabaseWriteFailed ) )
534 {
535 feedback->reportError( QObject::tr( "Could not save layer style: %1 " ).arg( errorMsg ) );
536 }
537 }
538 }
539 }
540 else
541 {
542 feedback->reportError( QObject::tr( "Could not save layer style -- error loading: %1 %2" ).arg( newFilename, newLayer ) );
543 }
544 }
545 return true;
546 }
547}
548
@ Vector
Tables (i.e. vector layers with or without geometry). When used for a sink this indicates the sink ha...
Definition qgis.h:3755
@ NotPresent
No spatial index exists for the source.
Definition qgis.h:601
@ Group
Composite group layer. Added in QGIS 3.24.
Definition qgis.h:214
@ Plugin
Plugin based layer.
Definition qgis.h:209
@ TiledScene
Tiled scene layer. Added in QGIS 3.34.
Definition qgis.h:215
@ Annotation
Contains freeform, georeferenced annotations. Added in QGIS 3.16.
Definition qgis.h:212
@ Vector
Vector layer.
Definition qgis.h:207
@ VectorTile
Vector tile layer. Added in QGIS 3.14.
Definition qgis.h:211
@ Mesh
Mesh layer. Added in QGIS 3.2.
Definition qgis.h:210
@ Raster
Raster layer.
Definition qgis.h:208
@ PointCloud
Point cloud layer. Added in QGIS 3.18.
Definition qgis.h:213
@ Advanced
Parameter is an advanced parameter which should be hidden from users by default.
Definition qgis.h:3982
@ AddToSelection
Add selection to current selection.
Definition qgis.h:1923
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:63
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:45
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:114
QgsRelationManager * relationManager
Definition qgsproject.h:125
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, bool validateIds=false)
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