QGIS API Documentation  3.9.0-Master (224899f119)
qgsvectorlayerexporter.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsvectorlayerexporter.cpp
3  -------------------
4  begin : Thu Aug 25 2011
5  copyright : (C) 2011 by Giuseppe Sucameli
6  email : brush.tyler at gmail.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 "qgsfields.h"
19 #include "qgsfeature.h"
20 #include "qgsfeatureiterator.h"
21 #include "qgsgeometry.h"
22 #include "qgslogger.h"
23 #include "qgsmessagelog.h"
25 #include "qgsvectorlayerexporter.h"
26 #include "qgsproviderregistry.h"
27 #include "qgsdatasourceuri.h"
28 #include "qgsexception.h"
29 #include "qgsvectordataprovider.h"
30 #include "qgsvectorlayer.h"
31 
32 #include <QProgressDialog>
33 
34 #define FEATURE_BUFFER_SIZE 200
35 
37  const QString &uri,
38  const QgsFields &fields,
39  QgsWkbTypes::Type geometryType,
40  const QgsCoordinateReferenceSystem &destCRS,
41  bool overwrite,
42  QMap<int, int> *oldToNewAttrIdx,
43  QString *errorMessage,
44  const QMap<QString, QVariant> *options
45 );
46 
47 
49  const QString &providerKey,
50  const QgsFields &fields,
51  QgsWkbTypes::Type geometryType,
53  bool overwrite,
54  const QMap<QString, QVariant> &options,
55  QgsFeatureSink::SinkFlags sinkFlags )
56  : mErrorCount( 0 )
57  , mAttributeCount( -1 )
58 
59 {
60  mProvider = nullptr;
61 
62  // create an empty layer
63  QString errMsg;
65  mError = pReg->createEmptyLayer( providerKey, uri, fields, geometryType, crs, overwrite, mOldToNewAttrIdx,
66  errMsg, !options.isEmpty() ? &options : nullptr );
67  if ( errorCode() )
68  {
69  mErrorMessage = errMsg;
70  return;
71  }
72 
73  const auto constMOldToNewAttrIdx = mOldToNewAttrIdx;
74  for ( int idx : constMOldToNewAttrIdx )
75  {
76  if ( idx > mAttributeCount )
77  mAttributeCount = idx;
78  }
79 
80  mAttributeCount++;
81 
82  QgsDebugMsg( QStringLiteral( "Created empty layer" ) );
83 
84  QString uriUpdated( uri );
85  // HACK sorry...
86  if ( providerKey == QLatin1String( "ogr" ) )
87  {
88  QString layerName;
89  if ( options.contains( QStringLiteral( "layerName" ) ) )
90  layerName = options.value( QStringLiteral( "layerName" ) ).toString();
91  if ( !layerName.isEmpty() )
92  {
93  uriUpdated += QLatin1String( "|layername=" );
94  uriUpdated += layerName;
95  }
96  }
97 
98  QgsDataProvider::ProviderOptions providerOptions;
99  QgsVectorDataProvider *vectorProvider = qobject_cast< QgsVectorDataProvider * >( pReg->createProvider( providerKey, uriUpdated, providerOptions ) );
100  if ( !vectorProvider || !vectorProvider->isValid() || ( vectorProvider->capabilities() & QgsVectorDataProvider::AddFeatures ) == 0 )
101  {
102  mError = ErrInvalidLayer;
103  mErrorMessage = QObject::tr( "Loading of layer failed" );
104 
105  delete vectorProvider;
106  return;
107  }
108 
109  // If the result is a geopackage layer and there is already a field name FID requested which
110  // might contain duplicates, make sure to generate a new field with a unique name instead
111  // that will be filled by ogr with unique values.
112 
113  // HACK sorry
114  const QString path = QgsProviderRegistry::instance()->decodeUri( QStringLiteral( "ogr" ), uri ).value( QStringLiteral( "path" ) ).toString();
115  if ( sinkFlags.testFlag( QgsFeatureSink::SinkFlag::RegeneratePrimaryKey ) && path.endsWith( QLatin1String( ".gpkg" ), Qt::CaseInsensitive ) )
116  {
117  QString fidName = options.value( QStringLiteral( "FID" ), QStringLiteral( "FID" ) ).toString();
118  int fidIdx = vectorProvider->fields().lookupField( fidName );
119  if ( fidIdx != -1 )
120  {
121  mOldToNewAttrIdx.remove( fidIdx );
122  }
123  }
124 
125  mProvider = vectorProvider;
126  mError = NoError;
127 }
128 
130 {
131  flushBuffer();
132  delete mProvider;
133 }
134 
136 {
137  return mError;
138 }
139 
141 {
142  return mErrorMessage;
143 }
144 
146 {
147  QgsFeatureList::iterator fIt = features.begin();
148  bool result = true;
149  for ( ; fIt != features.end(); ++fIt )
150  {
151  result = result && addFeature( *fIt, flags );
152  }
153  return result;
154 }
155 
157 {
158  QgsAttributes attrs = feat.attributes();
159 
160  QgsFeature newFeat;
161  if ( feat.hasGeometry() )
162  newFeat.setGeometry( feat.geometry() );
163 
164  newFeat.initAttributes( mAttributeCount );
165 
166  for ( int i = 0; i < attrs.count(); ++i )
167  {
168  // add only mapped attributes (un-mapped ones will not be present in the
169  // destination layer)
170  int dstIdx = mOldToNewAttrIdx.value( i, -1 );
171  if ( dstIdx < 0 )
172  continue;
173 
174  QgsDebugMsgLevel( QStringLiteral( "moving field from pos %1 to %2" ).arg( i ).arg( dstIdx ), 3 );
175  newFeat.setAttribute( dstIdx, attrs.at( i ) );
176  }
177 
178  mFeatureBuffer.append( newFeat );
179 
180  if ( mFeatureBuffer.count() >= FEATURE_BUFFER_SIZE )
181  {
182  return flushBuffer();
183  }
184 
185  return true;
186 }
187 
189 {
190  if ( mFeatureBuffer.count() <= 0 )
191  return true;
192 
193  if ( !mProvider->addFeatures( mFeatureBuffer, QgsFeatureSink::FastInsert ) )
194  {
195  QStringList errors = mProvider->errors();
196  mProvider->clearErrors();
197 
198  mErrorMessage = QObject::tr( "Creation error for features from #%1 to #%2. Provider errors was: \n%3" )
199  .arg( mFeatureBuffer.first().id() )
200  .arg( mFeatureBuffer.last().id() )
201  .arg( errors.join( QStringLiteral( "\n" ) ) );
202 
203  mError = ErrFeatureWriteFailed;
204  mErrorCount += mFeatureBuffer.count();
205 
206  mFeatureBuffer.clear();
207  QgsDebugMsg( mErrorMessage );
208  return false;
209  }
210 
211  mFeatureBuffer.clear();
212  return true;
213 }
214 
215 bool QgsVectorLayerExporter::createSpatialIndex()
216 {
217  if ( mProvider && ( mProvider->capabilities() & QgsVectorDataProvider::CreateSpatialIndex ) != 0 )
218  {
219  return mProvider->createSpatialIndex();
220  }
221  else
222  {
223  return true;
224  }
225 }
226 
229  const QString &uri,
230  const QString &providerKey,
231  const QgsCoordinateReferenceSystem &destCRS,
232  bool onlySelected,
233  QString *errorMessage,
234  const QMap<QString, QVariant> &options,
235  QgsFeedback *feedback )
236 {
239  bool shallTransform = false;
240 
241  if ( !layer )
242  return ErrInvalidLayer;
243 
244  if ( destCRS.isValid() )
245  {
246  // This means we should transform
247  outputCRS = destCRS;
248  shallTransform = true;
249  }
250  else
251  {
252  // This means we shouldn't transform, use source CRS as output (if defined)
253  outputCRS = layer->crs();
254  }
255 
256 
257  bool overwrite = false;
258  bool forceSinglePartGeom = false;
259  QMap<QString, QVariant> providerOptions = options;
260  if ( !options.isEmpty() )
261  {
262  overwrite = providerOptions.take( QStringLiteral( "overwrite" ) ).toBool();
263  forceSinglePartGeom = providerOptions.take( QStringLiteral( "forceSinglePartGeometryType" ) ).toBool();
264  }
265 
266  QgsFields fields = layer->fields();
267  QgsWkbTypes::Type wkbType = layer->wkbType();
268 
269  // Special handling for Shapefiles
270  if ( layer->providerType() == QLatin1String( "ogr" ) && layer->storageType() == QLatin1String( "ESRI Shapefile" ) )
271  {
272  // convert field names to lowercase
273  for ( int fldIdx = 0; fldIdx < fields.count(); ++fldIdx )
274  {
275  fields[fldIdx].setName( fields.at( fldIdx ).name().toLower() );
276  }
277 
278  if ( !forceSinglePartGeom )
279  {
280  // convert wkbtype to multipart (see #5547)
281  switch ( wkbType )
282  {
283  case QgsWkbTypes::Point:
284  wkbType = QgsWkbTypes::MultiPoint;
285  break;
288  break;
290  wkbType = QgsWkbTypes::MultiPolygon;
291  break;
293  wkbType = QgsWkbTypes::MultiPoint25D;
294  break;
297  break;
300  break;
301  default:
302  break;
303  }
304  }
305  }
306 
307  QgsVectorLayerExporter *writer =
308  new QgsVectorLayerExporter( uri, providerKey, fields, wkbType, outputCRS, overwrite, providerOptions );
309 
310  // check whether file creation was successful
311  ExportError err = writer->errorCode();
312  if ( err != NoError )
313  {
314  if ( errorMessage )
315  *errorMessage = writer->errorMessage();
316  delete writer;
317  return err;
318  }
319 
320  if ( errorMessage )
321  {
322  errorMessage->clear();
323  }
324 
325  QgsFeature fet;
326 
327  QgsFeatureRequest req;
328  if ( wkbType == QgsWkbTypes::NoGeometry )
330  if ( onlySelected )
331  req.setFilterFids( layer->selectedFeatureIds() );
332 
333  QgsFeatureIterator fit = layer->getFeatures( req );
334 
335  // Create our transform
336  if ( destCRS.isValid() )
337  {
338  ct = QgsCoordinateTransform( layer->crs(), destCRS, layer->transformContext() );
339  }
340 
341  // Check for failure
342  if ( !ct.isValid() )
343  shallTransform = false;
344 
345  long n = 0;
346  long approxTotal = onlySelected ? layer->selectedFeatureCount() : layer->featureCount();
347 
348  if ( errorMessage )
349  {
350  *errorMessage = QObject::tr( "Feature write errors:" );
351  }
352 
353  bool canceled = false;
354 
355  // write all features
356  while ( fit.nextFeature( fet ) )
357  {
358  if ( feedback && feedback->isCanceled() )
359  {
360  canceled = true;
361  if ( errorMessage )
362  {
363  *errorMessage += '\n' + QObject::tr( "Import was canceled at %1 of %2" ).arg( n ).arg( approxTotal );
364  }
365  break;
366  }
367 
368  if ( writer->errorCount() > 1000 )
369  {
370  if ( errorMessage )
371  {
372  *errorMessage += '\n' + QObject::tr( "Stopping after %1 errors" ).arg( writer->errorCount() );
373  }
374  break;
375  }
376 
377  if ( shallTransform )
378  {
379  try
380  {
381  if ( fet.hasGeometry() )
382  {
383  QgsGeometry g = fet.geometry();
384  g.transform( ct );
385  fet.setGeometry( g );
386  }
387  }
388  catch ( QgsCsException &e )
389  {
390  delete writer;
391 
392  QString msg = QObject::tr( "Failed to transform a point while drawing a feature with ID '%1'. Writing stopped. (Exception: %2)" )
393  .arg( fet.id() ).arg( e.what() );
394  QgsMessageLog::logMessage( msg, QObject::tr( "Vector import" ) );
395  if ( errorMessage )
396  *errorMessage += '\n' + msg;
397 
398  return ErrProjection;
399  }
400  }
401  if ( !writer->addFeature( fet ) )
402  {
403  if ( writer->errorCode() && errorMessage )
404  {
405  *errorMessage += '\n' + writer->errorMessage();
406  }
407  }
408  n++;
409 
410  if ( feedback )
411  {
412  feedback->setProgress( 100.0 * static_cast< double >( n ) / approxTotal );
413  }
414 
415  }
416 
417  // flush the buffer to be sure that all features are written
418  if ( !writer->flushBuffer() )
419  {
420  if ( writer->errorCode() && errorMessage )
421  {
422  *errorMessage += '\n' + writer->errorMessage();
423  }
424  }
425  int errors = writer->errorCount();
426 
427  if ( !writer->createSpatialIndex() )
428  {
429  if ( writer->errorCode() && errorMessage )
430  {
431  *errorMessage += '\n' + writer->errorMessage();
432  }
433  }
434 
435  delete writer;
436 
437  if ( errorMessage )
438  {
439  if ( errors > 0 )
440  {
441  *errorMessage += '\n' + QObject::tr( "Only %1 of %2 features written." ).arg( n - errors ).arg( n );
442  }
443  else
444  {
445  errorMessage->clear();
446  }
447  }
448 
449  if ( canceled )
450  return ErrUserCanceled;
451  else if ( errors > 0 )
452  return ErrFeatureWriteFailed;
453 
454  return NoError;
455 }
456 
457 
458 //
459 // QgsVectorLayerExporterTask
460 //
461 
462 QgsVectorLayerExporterTask::QgsVectorLayerExporterTask( QgsVectorLayer *layer, const QString &uri, const QString &providerKey, const QgsCoordinateReferenceSystem &destinationCrs, const QMap<QString, QVariant> &options, bool ownsLayer )
463  : QgsTask( tr( "Exporting %1" ).arg( layer->name() ), QgsTask::CanCancel )
464  , mLayer( layer )
465  , mOwnsLayer( ownsLayer )
466  , mDestUri( uri )
467  , mDestProviderKey( providerKey )
468  , mDestCrs( destinationCrs )
469  , mOptions( options )
470  , mOwnedFeedback( new QgsFeedback() )
471 {
472  if ( mLayer )
473  setDependentLayers( QList< QgsMapLayer * >() << mLayer );
474 }
475 
476 QgsVectorLayerExporterTask *QgsVectorLayerExporterTask::withLayerOwnership( QgsVectorLayer *layer, const QString &uri, const QString &providerKey, const QgsCoordinateReferenceSystem &destinationCrs, const QMap<QString, QVariant> &options )
477 {
478  std::unique_ptr< QgsVectorLayerExporterTask > newTask( new QgsVectorLayerExporterTask( layer, uri, providerKey, destinationCrs, options ) );
479  newTask->mOwnsLayer = true;
480  return newTask.release();
481 }
482 
484 {
485  mOwnedFeedback->cancel();
486  QgsTask::cancel();
487 }
488 
490 {
491  if ( !mLayer )
492  return false;
493 
494  connect( mOwnedFeedback.get(), &QgsFeedback::progressChanged, this, &QgsVectorLayerExporterTask::setProgress );
495 
496 
498  mLayer.data(), mDestUri, mDestProviderKey, mDestCrs, false, &mErrorMessage,
499  mOptions, mOwnedFeedback.get() );
500 
501  return mError == QgsVectorLayerExporter::NoError;
502 }
503 
505 {
506  // QgsMapLayer has QTimer member, which must not be destroyed from another thread
507  if ( mOwnsLayer )
508  delete mLayer;
509 
510  if ( result )
511  emit exportComplete();
512  else
513  emit errorOccurred( mError, mErrorMessage );
514 }
int lookupField(const QString &fieldName) const
Looks up field&#39;s index from the field name.
Definition: qgsfields.cpp:324
QgsFeatureId id
Definition: qgsfeature.h:64
Wrapper for iterator of features from vector data provider or vector layer.
Could not access newly created destination layer.
bool flushBuffer() override
Flushes any internal buffer which may exist in the sink, causing any buffered features to be added to...
Use faster inserts, at the cost of updating the passed features to reflect changes made at the provid...
void setProgress(double progress)
Sets the task&#39;s current progress.
QgsVectorLayerExporter(const QString &uri, const QString &provider, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &crs, bool overwrite=false, const QMap< QString, QVariant > &options=QMap< QString, QVariant >(), QgsFeatureSink::SinkFlags sinkFlags=nullptr)
Constructor for QgsVectorLayerExporter.
virtual QgsVectorDataProvider::Capabilities capabilities() const
Returns flags containing the supported capabilities.
QString name
Definition: qgsfield.h:58
OperationResult transform(const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection direction=QgsCoordinateTransform::ForwardTransform, bool transformZ=false) SIP_THROW(QgsCsException)
Transforms this geometry as described by the coordinate transform ct.
QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
QgsWkbTypes::Type wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
bool addFeatures(QgsFeatureList &flist, QgsFeatureSink::Flags flags=nullptr) override
Adds a list of features to the sink.
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:571
#define FEATURE_BUFFER_SIZE
static ExportError exportLayer(QgsVectorLayer *layer, const QString &uri, const QString &providerKey, const QgsCoordinateReferenceSystem &destCRS, bool onlySelected=false, QString *errorMessage=nullptr, const QMap< QString, QVariant > &options=QMap< QString, QVariant >(), QgsFeedback *feedback=nullptr)
Writes the contents of vector layer to a different datasource.
int selectedFeatureCount() const
Returns the number of features that are selected in this layer.
QString providerType() const
Returns the provider type (provider key) for this layer.
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition: qgsfeedback.h:63
QString errorMessage() const
Returns any error message encountered during the export.
static QgsVectorLayerExporterTask * withLayerOwnership(QgsVectorLayer *layer, const QString &uri, const QString &providerKey, const QgsCoordinateReferenceSystem &destinationCrs, const QMap< QString, QVariant > &options=QMap< QString, QVariant >())
Creates a new QgsVectorLayerExporterTask which has ownership over a source layer. ...
void setDependentLayers(const QList< QgsMapLayer *> &dependentLayers)
Sets a list of layers on which the task depends.
Container of fields for a vector layer.
Definition: qgsfields.h:42
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:121
bool setAttribute(int field, const QVariant &attr)
Set an attribute&#39;s value by field index.
Definition: qgsfeature.cpp:211
QVariantMap decodeUri(const QString &providerKey, const QString &uri)
Breaks a provider data source URI into its component paths (e.g.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
const QgsCoordinateReferenceSystem & crs
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:197
int count() const
Returns number of items.
Definition: qgsfields.cpp:133
QgsVectorLayerExporter::ExportError createEmptyLayer(const QString &providerKey, const QString &uri, const QgsFields &fields, QgsWkbTypes::Type wkbType, const QgsCoordinateReferenceSystem &srs, bool overwrite, QMap< int, int > &oldToNewAttrIdxMap, QString &errorMessage, const QMap< QString, QVariant > *options)
Creates new empty vector layer.
ExportError errorCode() const
Returns any encountered error code, or false if no error was encountered.
bool isValid() const
Returns true if the coordinate transform is valid, ie both the source and destination CRS have been s...
QString what() const
Definition: qgsexception.h:48
QgsField at(int i) const
Gets field at particular index (must be in range 0..N-1)
Definition: qgsfields.cpp:163
QgsDataProvider * createProvider(const QString &providerKey, const QString &dataSource, const QgsDataProvider::ProviderOptions &options=QgsDataProvider::ProviderOptions())
Creates a new instance of a provider.
Base class for feedback objects to be used for cancellation of something running in a worker thread...
Definition: qgsfeedback.h:44
Allows creation of spatial index.
virtual bool createSpatialIndex()
Creates a spatial index on the datasource (if supported by the provider type).
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:68
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
void progressChanged(double progress)
Emitted when the feedback object reports a progress change.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
virtual bool isValid() const =0
Returns true if this is a valid layer.
QgsVectorLayerExporterTask(QgsVectorLayer *layer, const QString &uri, const QString &providerKey, const QgsCoordinateReferenceSystem &destinationCrs, const QMap< QString, QVariant > &options=QMap< QString, QVariant >(), bool ownsLayer=false)
Constructor for QgsVectorLayerExporterTask.
QgsFields fields() const override=0
Returns the fields associated with this data provider.
long featureCount(const QString &legendKey) const
Number of features rendered with specified legend key.
void initAttributes(int fieldCount)
Initialize this feature with the given number of fields.
Definition: qgsfeature.cpp:202
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
Abstract base class for long running background tasks.
QStringList errors() const
Gets recorded errors.
This class wraps a request for features to a vector layer (or directly its vector data provider)...
An error occurred while writing a feature to the destination.
void clearErrors()
Clear recorded errors.
QgsTask task which performs a QgsVectorLayerExporter layer export operation as a background task...
An error occurred while reprojecting features to destination CRS.
QgsCoordinateTransformContext transformContext() const
Returns the layer data provider coordinate transform context or a default transform context if the la...
void errorOccurred(int error, const QString &errorMessage)
Emitted when an error occurs which prevented the layer being exported (or if the task is canceled)...
bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=nullptr) override
Adds a list of features to the sink.
A convenience class for exporting vector layers to a destination data provider.
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=nullptr) override
Adds a single feature to the sink.
A registry / canonical manager of data providers.
virtual void cancel()
Notifies the task that it should terminate.
Setting options for creating vector data providers.
~QgsVectorLayerExporter() override
Finalizes the export and closes the new created layer.
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Sets feature IDs that should be fetched.
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:54
int errorCount() const
Returns the number of error messages encountered during the export.
This class represents a coordinate reference system (CRS).
void setGeometry(const QgsGeometry &geometry)
Set the feature&#39;s geometry.
Definition: qgsfeature.cpp:137
Class for doing transforms between two map coordinate systems.
void cancel() override
Notifies the task that it should terminate.
No errors were encountered.
bool run() override
Performs the task&#39;s operation.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
QgsGeometry geometry
Definition: qgsfeature.h:67
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:65
bool nextFeature(QgsFeature &f)
This is the base class for vector data providers.
Geometry is not required. It may still be returned if e.g. required for a filter condition.
A vector of attributes.
Definition: qgsattributes.h:57
Represents a vector layer which manages a vector based data sets.
void finished(bool result) override
If the task is managed by a QgsTaskManager, this will be called after the task has finished (whether ...
QgsAttributes attributes
Definition: qgsfeature.h:65
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:86
QgsVectorLayerExporter::ExportError createEmptyLayer_t(const QString &uri, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &destCRS, bool overwrite, QMap< int, int > *oldToNewAttrIdx, QString *errorMessage, const QMap< QString, QVariant > *options)
void exportComplete()
Emitted when exporting the layer is successfully completed.
QgsFeatureRequest & setFlags(QgsFeatureRequest::Flags flags)
Sets flags that affect how features will be fetched.
bool isValid() const
Returns whether this CRS is correctly initialized and usable.