QGIS API Documentation  3.4.15-Madeira (e83d02e274)
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 
63 
64  std::unique_ptr< QLibrary > myLib( pReg->createProviderLibrary( providerKey ) );
65  if ( !myLib )
66  {
67  mError = ErrInvalidProvider;
68  mErrorMessage = QObject::tr( "Unable to load %1 provider" ).arg( providerKey );
69  return;
70  }
71 
72  createEmptyLayer_t *pCreateEmpty = reinterpret_cast< createEmptyLayer_t * >( cast_to_fptr( myLib->resolve( "createEmptyLayer" ) ) );
73  if ( !pCreateEmpty )
74  {
76  mErrorMessage = QObject::tr( "Provider %1 has no %2 method" ).arg( providerKey, QStringLiteral( "createEmptyLayer" ) );
77  return;
78  }
79 
80  // create an empty layer
81  QString errMsg;
82  mError = pCreateEmpty( uri, fields, geometryType, crs, overwrite, &mOldToNewAttrIdx, &errMsg, !options.isEmpty() ? &options : nullptr );
83  if ( errorCode() )
84  {
85  mErrorMessage = errMsg;
86  return;
87  }
88 
89  Q_FOREACH ( int idx, mOldToNewAttrIdx )
90  {
91  if ( idx > mAttributeCount )
92  mAttributeCount = idx;
93  }
94 
95  mAttributeCount++;
96 
97  QgsDebugMsg( QStringLiteral( "Created empty layer" ) );
98 
99  QString uriUpdated( uri );
100  // HACK sorry...
101  if ( providerKey == QLatin1String( "ogr" ) )
102  {
103  QString layerName;
104  if ( options.contains( QStringLiteral( "layerName" ) ) )
105  layerName = options.value( QStringLiteral( "layerName" ) ).toString();
106  if ( !layerName.isEmpty() )
107  {
108  uriUpdated += QLatin1String( "|layername=" );
109  uriUpdated += layerName;
110  }
111  }
112 
113  QgsDataProvider::ProviderOptions providerOptions;
114  QgsVectorDataProvider *vectorProvider = dynamic_cast< QgsVectorDataProvider * >( pReg->createProvider( providerKey, uriUpdated, providerOptions ) );
115  if ( !vectorProvider || !vectorProvider->isValid() || ( vectorProvider->capabilities() & QgsVectorDataProvider::AddFeatures ) == 0 )
116  {
117  mError = ErrInvalidLayer;
118  mErrorMessage = QObject::tr( "Loading of layer failed" );
119 
120  delete vectorProvider;
121  return;
122  }
123 
124  // If the result is a geopackage layer and there is already a field name FID requested which
125  // might contain duplicates, make sure to generate a new field with a unique name instead
126  // that will be filled by ogr with unique values.
127 
128  // HACK sorry
129  const QString path = QgsProviderRegistry::instance()->decodeUri( QStringLiteral( "ogr" ), uri ).value( QStringLiteral( "path" ) ).toString();
130  if ( sinkFlags.testFlag( QgsFeatureSink::SinkFlag::RegeneratePrimaryKey ) && path.endsWith( QLatin1String( ".gpkg" ), Qt::CaseInsensitive ) )
131  {
132  QString fidName = options.value( QStringLiteral( "FID" ), QStringLiteral( "FID" ) ).toString();
133  int fidIdx = vectorProvider->fields().lookupField( fidName );
134  if ( fidIdx != -1 )
135  {
136  mOldToNewAttrIdx.remove( fidIdx );
137  }
138  }
139 
140  mProvider = vectorProvider;
141  mError = NoError;
142 }
143 
145 {
146  flushBuffer();
147  delete mProvider;
148 }
149 
151 {
152  return mError;
153 }
154 
156 {
157  return mErrorMessage;
158 }
159 
161 {
162  QgsFeatureList::iterator fIt = features.begin();
163  bool result = true;
164  for ( ; fIt != features.end(); ++fIt )
165  {
166  result = result && addFeature( *fIt, flags );
167  }
168  return result;
169 }
170 
172 {
173  QgsAttributes attrs = feat.attributes();
174 
175  QgsFeature newFeat;
176  if ( feat.hasGeometry() )
177  newFeat.setGeometry( feat.geometry() );
178 
179  newFeat.initAttributes( mAttributeCount );
180 
181  for ( int i = 0; i < attrs.count(); ++i )
182  {
183  // add only mapped attributes (un-mapped ones will not be present in the
184  // destination layer)
185  int dstIdx = mOldToNewAttrIdx.value( i, -1 );
186  if ( dstIdx < 0 )
187  continue;
188 
189  QgsDebugMsgLevel( QStringLiteral( "moving field from pos %1 to %2" ).arg( i ).arg( dstIdx ), 3 );
190  newFeat.setAttribute( dstIdx, attrs.at( i ) );
191  }
192 
193  mFeatureBuffer.append( newFeat );
194 
195  if ( mFeatureBuffer.count() >= FEATURE_BUFFER_SIZE )
196  {
197  return flushBuffer();
198  }
199 
200  return true;
201 }
202 
204 {
205  if ( mFeatureBuffer.count() <= 0 )
206  return true;
207 
208  if ( !mProvider->addFeatures( mFeatureBuffer, QgsFeatureSink::FastInsert ) )
209  {
210  QStringList errors = mProvider->errors();
211  mProvider->clearErrors();
212 
213  mErrorMessage = QObject::tr( "Creation error for features from #%1 to #%2. Provider errors was: \n%3" )
214  .arg( mFeatureBuffer.first().id() )
215  .arg( mFeatureBuffer.last().id() )
216  .arg( errors.join( QStringLiteral( "\n" ) ) );
217 
218  mError = ErrFeatureWriteFailed;
219  mErrorCount += mFeatureBuffer.count();
220 
221  mFeatureBuffer.clear();
222  QgsDebugMsg( mErrorMessage );
223  return false;
224  }
225 
226  mFeatureBuffer.clear();
227  return true;
228 }
229 
230 bool QgsVectorLayerExporter::createSpatialIndex()
231 {
232  if ( mProvider && ( mProvider->capabilities() & QgsVectorDataProvider::CreateSpatialIndex ) != 0 )
233  {
234  return mProvider->createSpatialIndex();
235  }
236  else
237  {
238  return true;
239  }
240 }
241 
244  const QString &uri,
245  const QString &providerKey,
246  const QgsCoordinateReferenceSystem &destCRS,
247  bool onlySelected,
248  QString *errorMessage,
249  const QMap<QString, QVariant> &options,
250  QgsFeedback *feedback )
251 {
254  bool shallTransform = false;
255 
256  if ( !layer )
257  return ErrInvalidLayer;
258 
259  if ( destCRS.isValid() )
260  {
261  // This means we should transform
262  outputCRS = destCRS;
263  shallTransform = true;
264  }
265  else
266  {
267  // This means we shouldn't transform, use source CRS as output (if defined)
268  outputCRS = layer->crs();
269  }
270 
271 
272  bool overwrite = false;
273  bool forceSinglePartGeom = false;
274  QMap<QString, QVariant> providerOptions = options;
275  if ( !options.isEmpty() )
276  {
277  overwrite = providerOptions.take( QStringLiteral( "overwrite" ) ).toBool();
278  forceSinglePartGeom = providerOptions.take( QStringLiteral( "forceSinglePartGeometryType" ) ).toBool();
279  }
280 
281  QgsFields fields = layer->fields();
282  QgsWkbTypes::Type wkbType = layer->wkbType();
283 
284  // Special handling for Shapefiles
285  if ( layer->providerType() == QLatin1String( "ogr" ) && layer->storageType() == QLatin1String( "ESRI Shapefile" ) )
286  {
287  // convert field names to lowercase
288  for ( int fldIdx = 0; fldIdx < fields.count(); ++fldIdx )
289  {
290  fields[fldIdx].setName( fields.at( fldIdx ).name().toLower() );
291  }
292 
293  if ( !forceSinglePartGeom )
294  {
295  // convert wkbtype to multipart (see #5547)
296  switch ( wkbType )
297  {
298  case QgsWkbTypes::Point:
299  wkbType = QgsWkbTypes::MultiPoint;
300  break;
303  break;
305  wkbType = QgsWkbTypes::MultiPolygon;
306  break;
308  wkbType = QgsWkbTypes::MultiPoint25D;
309  break;
312  break;
315  break;
316  default:
317  break;
318  }
319  }
320  }
321 
322  QgsVectorLayerExporter *writer =
323  new QgsVectorLayerExporter( uri, providerKey, fields, wkbType, outputCRS, overwrite, providerOptions );
324 
325  // check whether file creation was successful
326  ExportError err = writer->errorCode();
327  if ( err != NoError )
328  {
329  if ( errorMessage )
330  *errorMessage = writer->errorMessage();
331  delete writer;
332  return err;
333  }
334 
335  if ( errorMessage )
336  {
337  errorMessage->clear();
338  }
339 
340  QgsFeature fet;
341 
342  QgsFeatureRequest req;
343  if ( wkbType == QgsWkbTypes::NoGeometry )
345  if ( onlySelected )
346  req.setFilterFids( layer->selectedFeatureIds() );
347 
348  QgsFeatureIterator fit = layer->getFeatures( req );
349 
350  // Create our transform
351  if ( destCRS.isValid() )
352  {
354  ct = QgsCoordinateTransform( layer->crs(), destCRS );
356  }
357 
358  // Check for failure
359  if ( !ct.isValid() )
360  shallTransform = false;
361 
362  long n = 0;
363  long approxTotal = onlySelected ? layer->selectedFeatureCount() : layer->featureCount();
364 
365  if ( errorMessage )
366  {
367  *errorMessage = QObject::tr( "Feature write errors:" );
368  }
369 
370  bool canceled = false;
371 
372  // write all features
373  while ( fit.nextFeature( fet ) )
374  {
375  if ( feedback && feedback->isCanceled() )
376  {
377  canceled = true;
378  if ( errorMessage )
379  {
380  *errorMessage += '\n' + QObject::tr( "Import was canceled at %1 of %2" ).arg( n ).arg( approxTotal );
381  }
382  break;
383  }
384 
385  if ( writer->errorCount() > 1000 )
386  {
387  if ( errorMessage )
388  {
389  *errorMessage += '\n' + QObject::tr( "Stopping after %1 errors" ).arg( writer->errorCount() );
390  }
391  break;
392  }
393 
394  if ( shallTransform )
395  {
396  try
397  {
398  if ( fet.hasGeometry() )
399  {
400  QgsGeometry g = fet.geometry();
401  g.transform( ct );
402  fet.setGeometry( g );
403  }
404  }
405  catch ( QgsCsException &e )
406  {
407  delete writer;
408 
409  QString msg = QObject::tr( "Failed to transform a point while drawing a feature with ID '%1'. Writing stopped. (Exception: %2)" )
410  .arg( fet.id() ).arg( e.what() );
411  QgsMessageLog::logMessage( msg, QObject::tr( "Vector import" ) );
412  if ( errorMessage )
413  *errorMessage += '\n' + msg;
414 
415  return ErrProjection;
416  }
417  }
418  if ( !writer->addFeature( fet ) )
419  {
420  if ( writer->errorCode() && errorMessage )
421  {
422  *errorMessage += '\n' + writer->errorMessage();
423  }
424  }
425  n++;
426 
427  if ( feedback )
428  {
429  feedback->setProgress( 100.0 * static_cast< double >( n ) / approxTotal );
430  }
431 
432  }
433 
434  // flush the buffer to be sure that all features are written
435  if ( !writer->flushBuffer() )
436  {
437  if ( writer->errorCode() && errorMessage )
438  {
439  *errorMessage += '\n' + writer->errorMessage();
440  }
441  }
442  int errors = writer->errorCount();
443 
444  if ( !writer->createSpatialIndex() )
445  {
446  if ( writer->errorCode() && errorMessage )
447  {
448  *errorMessage += '\n' + writer->errorMessage();
449  }
450  }
451 
452  delete writer;
453 
454  if ( errorMessage )
455  {
456  if ( errors > 0 )
457  {
458  *errorMessage += '\n' + QObject::tr( "Only %1 of %2 features written." ).arg( n - errors ).arg( n );
459  }
460  else
461  {
462  errorMessage->clear();
463  }
464  }
465 
466  if ( canceled )
467  return ErrUserCanceled;
468  else if ( errors > 0 )
469  return ErrFeatureWriteFailed;
470 
471  return NoError;
472 }
473 
474 
475 //
476 // QgsVectorLayerExporterTask
477 //
478 
479 QgsVectorLayerExporterTask::QgsVectorLayerExporterTask( QgsVectorLayer *layer, const QString &uri, const QString &providerKey, const QgsCoordinateReferenceSystem &destinationCrs, const QMap<QString, QVariant> &options, bool ownsLayer )
480  : QgsTask( tr( "Exporting %1" ).arg( layer->name() ), QgsTask::CanCancel )
481  , mLayer( layer )
482  , mOwnsLayer( ownsLayer )
483  , mDestUri( uri )
484  , mDestProviderKey( providerKey )
485  , mDestCrs( destinationCrs )
486  , mOptions( options )
487  , mOwnedFeedback( new QgsFeedback() )
488 {
489  if ( mLayer )
490  setDependentLayers( QList< QgsMapLayer * >() << mLayer );
491 }
492 
493 QgsVectorLayerExporterTask *QgsVectorLayerExporterTask::withLayerOwnership( QgsVectorLayer *layer, const QString &uri, const QString &providerKey, const QgsCoordinateReferenceSystem &destinationCrs, const QMap<QString, QVariant> &options )
494 {
495  std::unique_ptr< QgsVectorLayerExporterTask > newTask( new QgsVectorLayerExporterTask( layer, uri, providerKey, destinationCrs, options ) );
496  newTask->mOwnsLayer = true;
497  return newTask.release();
498 }
499 
501 {
502  mOwnedFeedback->cancel();
503  QgsTask::cancel();
504 }
505 
507 {
508  if ( !mLayer )
509  return false;
510 
511  connect( mOwnedFeedback.get(), &QgsFeedback::progressChanged, this, &QgsVectorLayerExporterTask::setProgress );
512 
513 
515  mLayer.data(), mDestUri, mDestProviderKey, mDestCrs, false, &mErrorMessage,
516  mOptions, mOwnedFeedback.get() );
517 
518  return mError == QgsVectorLayerExporter::NoError;
519 }
520 
522 {
523  // QgsMapLayer has QTimer member, which must not be destroyed from another thread
524  if ( mOwnsLayer )
525  delete mLayer;
526 
527  if ( result )
528  emit exportComplete();
529  else
530  emit errorOccurred( mError, mErrorMessage );
531 }
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 isCanceled() const
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:54
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.
QString name
Definition: qgsfield.h:57
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.
int errorCount() const
Returns the number of error messages encountered during the export.
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.
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition: qgsfeedback.h:63
void setDependentLayers(const QList< QgsMapLayer * > &dependentLayers)
Sets a list of layers on which the task depends.
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:614
int selectedFeatureCount() const
Returns the number of features that are selected in this layer.
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. ...
Container of fields for a vector layer.
Definition: qgsfields.h:42
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:106
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)
Returns the components (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
Could not find a matching provider key.
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.
QString errorMessage() const
Returns any error message encountered during the export.
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.
#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.
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.
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.
long featureCount(const QString &legendKey) const
Number of features rendered with specified legend key.
void clearErrors()
Clear recorded errors.
int count() const
Returns number of items.
Definition: qgsfields.cpp:133
ExportError errorCode() const
Returns any encountered error code, or false if no error was encountered.
QgsTask task which performs a QgsVectorLayerExporter layer export operation as a background task...
An error occurred while reprojecting features to destination CRS.
const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
int lookupField(const QString &fieldName) const
Looks up field&#39;s index from the field name.
Definition: qgsfields.cpp:320
QLibrary * createProviderLibrary(const QString &providerKey) const
Returns a new QLibrary for the specified providerKey.
#define cast_to_fptr(f)
Definition: qgis.h:171
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.
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:615
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
QString providerType() const
Returns the provider type for this layer.
QString what() const
Definition: qgsexception.h:48
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.
virtual QgsVectorDataProvider::Capabilities capabilities() const
Returns flags containing the supported capabilities.
This class represents a coordinate reference system (CRS).
void setGeometry(const QgsGeometry &geometry)
Set the feature&#39;s geometry.
Definition: qgsfeature.cpp:137
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:197
QStringList errors() const
Gets recorded errors.
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
Query 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
Provider does not support creation of empty layers.
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:70
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 true if the coordinate transform is valid, ie both the source and destination CRS have been s...
QString storageType() const
Returns the permanent storage type for this layer as a friendly name.