35 #include <QProgressDialog> 
   43   QMap<int, int> *oldToNewAttrIdx,
 
   44   QString *errorMessage,
 
   45   const QMap<QString, QVariant> *options
 
   50     const QString &providerKey,
 
   55     const QMap<QString, QVariant> &options,
 
   56     QgsFeatureSink::SinkFlags sinkFlags )
 
   58   , mAttributeCount( -1 )
 
   63   QMap<QString, QVariant> modifiedOptions( options );
 
   65   if ( providerKey == QLatin1String( 
"ogr" ) &&
 
   66        options.contains( QStringLiteral( 
"driverName" ) ) &&
 
   67        ( options[ QStringLiteral( 
"driverName" ) ].toString().compare( QLatin1String( 
"GPKG" ), Qt::CaseInsensitive ) == 0 ||
 
   68          options[ QStringLiteral( 
"driverName" ) ].toString().compare( QLatin1String( 
"SQLite" ), Qt::CaseInsensitive ) == 0 ) )
 
   75       QStringList modifiedLayerOptions;
 
   76       if ( options.contains( QStringLiteral( 
"layerOptions" ) ) )
 
   78         QStringList layerOptions = options.value( QStringLiteral( 
"layerOptions" ) ).toStringList();
 
   79         for ( 
const QString &layerOption : layerOptions )
 
   81           if ( layerOption.compare( QLatin1String( 
"SPATIAL_INDEX=YES" ), Qt::CaseInsensitive ) == 0 ||
 
   82                layerOption.compare( QLatin1String( 
"SPATIAL_INDEX=ON" ), Qt::CaseInsensitive ) == 0 ||
 
   83                layerOption.compare( QLatin1String( 
"SPATIAL_INDEX=TRUE" ), Qt::CaseInsensitive ) == 0 ||
 
   84                layerOption.compare( QLatin1String( 
"SPATIAL_INDEX=1" ), Qt::CaseInsensitive ) == 0 )
 
   88           else if ( layerOption.compare( QLatin1String( 
"SPATIAL_INDEX=NO" ), Qt::CaseInsensitive ) == 0 ||
 
   89                     layerOption.compare( QLatin1String( 
"SPATIAL_INDEX=OFF" ), Qt::CaseInsensitive ) == 0 ||
 
   90                     layerOption.compare( QLatin1String( 
"SPATIAL_INDEX=FALSE" ), Qt::CaseInsensitive ) == 0 ||
 
   91                     layerOption.compare( QLatin1String( 
"SPATIAL_INDEX=0" ), Qt::CaseInsensitive ) == 0 )
 
   93             mCreateSpatialIndex = 
false;
 
   97             modifiedLayerOptions << layerOption;
 
  101       modifiedLayerOptions << QStringLiteral( 
"SPATIAL_INDEX=FALSE" );
 
  102       modifiedOptions[ QStringLiteral( 
"layerOptions" ) ] = modifiedLayerOptions;
 
  109   mError = pReg->
createEmptyLayer( providerKey, uri, fields, geometryType, 
crs, overwrite, mOldToNewAttrIdx,
 
  110                                    errMsg, !modifiedOptions.isEmpty() ? &modifiedOptions : 
nullptr );
 
  112   if ( 
errorCode() != Qgis::VectorExportResult::Success )
 
  114     mErrorMessage = errMsg;
 
  118   const auto constMOldToNewAttrIdx = mOldToNewAttrIdx;
 
  119   for ( 
int idx : constMOldToNewAttrIdx )
 
  121     if ( idx > mAttributeCount )
 
  122       mAttributeCount = idx;
 
  129   QString uriUpdated( uri );
 
  131   if ( providerKey == QLatin1String( 
"ogr" ) )
 
  134     if ( options.contains( QStringLiteral( 
"layerName" ) ) )
 
  135       layerName = options.value( QStringLiteral( 
"layerName" ) ).toString();
 
  136     if ( !layerName.isEmpty() )
 
  138       uriUpdated += QLatin1String( 
"|layername=" );
 
  139       uriUpdated += layerName;
 
  145   if ( providerKey == QLatin1String( 
"oracle" ) )
 
  154     mError = Qgis::VectorExportResult::ErrorInvalidLayer;
 
  155     mErrorMessage = QObject::tr( 
"Loading of layer failed" );
 
  157     delete vectorProvider;
 
  167   if ( sinkFlags.testFlag( QgsFeatureSink::SinkFlag::RegeneratePrimaryKey ) && path.endsWith( QLatin1String( 
".gpkg" ), Qt::CaseInsensitive ) )
 
  169     QString fidName = options.value( QStringLiteral( 
"FID" ), QStringLiteral( 
"FID" ) ).toString();
 
  173       mOldToNewAttrIdx.remove( fidIdx );
 
  177   mProvider = vectorProvider;
 
  178   mError = Qgis::VectorExportResult::Success;
 
  185   if ( mCreateSpatialIndex )
 
  187     createSpatialIndex();
 
  200   return mErrorMessage;
 
  205   QgsFeatureList::iterator fIt = features.begin();
 
  207   for ( ; fIt != features.end(); ++fIt )
 
  224   for ( 
int i = 0; i < attrs.count(); ++i )
 
  228     int dstIdx = mOldToNewAttrIdx.value( i, -1 );
 
  232     QgsDebugMsgLevel( QStringLiteral( 
"moving field from pos %1 to %2" ).arg( i ).arg( dstIdx ), 3 );
 
  236   mFeatureBuffer.append( newFeat );
 
  239   if ( mFeatureBufferMemoryUsage >= 100 * 1000 * 1000 )
 
  249   return mErrorMessage;
 
  254   mFeatureBufferMemoryUsage = 0;
 
  255   if ( mFeatureBuffer.count() <= 0 )
 
  260     QStringList errors = mProvider->
errors();
 
  263     mErrorMessage = QObject::tr( 
"Creation error for features from #%1 to #%2. Provider errors was: \n%3" )
 
  264                     .arg( mFeatureBuffer.first().id() )
 
  265                     .arg( mFeatureBuffer.last().id() )
 
  266                     .arg( errors.join( QLatin1Char( 
'\n' ) ) );
 
  268     mError = Qgis::VectorExportResult::ErrorFeatureWriteFailed;
 
  269     mErrorCount += mFeatureBuffer.count();
 
  271     mFeatureBuffer.clear();
 
  276   mFeatureBuffer.clear();
 
  280 bool QgsVectorLayerExporter::createSpatialIndex()
 
  282   mCreateSpatialIndex = 
false;
 
  295     const QString &providerKey,
 
  298     QString *errorMessage,
 
  299     const QMap<QString, QVariant> &options,
 
  304   bool shallTransform = 
false;
 
  307     return Qgis::VectorExportResult::ErrorInvalidLayer;
 
  313     shallTransform = 
true;
 
  318     outputCRS = layer->
crs();
 
  322   bool overwrite = 
false;
 
  323   bool forceSinglePartGeom = 
false;
 
  324   QMap<QString, QVariant> providerOptions = options;
 
  325   if ( !options.isEmpty() )
 
  327     overwrite = providerOptions.take( QStringLiteral( 
"overwrite" ) ).toBool();
 
  328     forceSinglePartGeom = providerOptions.take( QStringLiteral( 
"forceSinglePartGeometryType" ) ).toBool();
 
  336   if ( layer->
providerType() == QLatin1String( 
"ogr" ) && layer->
storageType() == QLatin1String( 
"ESRI Shapefile" ) )
 
  339     for ( 
int fldIdx = 0; fldIdx < fields.
count(); ++fldIdx )
 
  341       fields.
rename( fldIdx, fields.
at( fldIdx ).
name().toLower() );
 
  345   bool convertGeometryToSinglePart = 
false;
 
  349     convertGeometryToSinglePart = 
true;
 
  357   if ( err != Qgis::VectorExportResult::Success )
 
  388     shallTransform = 
false;
 
  398   bool canceled = 
false;
 
  408         *
errorMessage += 
'\n' + QObject::tr( 
"Import was canceled at %1 of %2" ).arg( n ).arg( approxTotal );
 
  422     if ( shallTransform )
 
  437         QString msg = QObject::tr( 
"Failed to transform a point while drawing a feature with ID '%1'. Writing stopped. (Exception: %2)" )
 
  438                       .arg( fet.
id() ).arg( e.
what() );
 
  443         return Qgis::VectorExportResult::ErrorProjectingFeatures;
 
  453       const QgsGeometryCollection *
c = qgsgeometry_cast<const QgsGeometryCollection *>( singlePartGeometry.constGet() );
 
  454       if ( ( 
c && 
c->partCount() > 1 ) || ! singlePartGeometry.convertToSingleType() )
 
  457         QString msg = QObject::tr( 
"Failed to transform a feature with ID '%1' to single part. Writing stopped." )
 
  462         return Qgis::VectorExportResult::ErrorFeatureWriteFailed;
 
  478       feedback->
setProgress( 100.0 * 
static_cast< double >( n ) / approxTotal );
 
  493   if ( writer->mCreateSpatialIndex && !writer->createSpatialIndex() )
 
  507       *
errorMessage += 
'\n' + QObject::tr( 
"Only %1 of %2 features written." ).arg( n - errors ).arg( n );
 
  516     return Qgis::VectorExportResult::UserCanceled;
 
  517   else if ( errors > 0 )
 
  518     return Qgis::VectorExportResult::ErrorFeatureWriteFailed;
 
  520   return Qgis::VectorExportResult::Success;
 
  529   : 
QgsTask( tr( 
"Exporting %1" ).arg( layer->name() ), 
QgsTask::CanCancel )
 
  531   , mOwnsLayer( ownsLayer )
 
  533   , mDestProviderKey( providerKey )
 
  534   , mDestCrs( destinationCrs )
 
  535   , mOptions( options )
 
  544   std::unique_ptr< QgsVectorLayerExporterTask > newTask( 
new QgsVectorLayerExporterTask( layer, uri, providerKey, destinationCrs, options ) );
 
  545   newTask->mOwnsLayer = 
true;
 
  546   return newTask.release();
 
  551   mOwnedFeedback->cancel();
 
  564              mLayer.data(), mDestUri, mDestProviderKey, mDestCrs, 
false, &mErrorMessage,
 
  565              mOptions, mOwnedFeedback.get() );
 
  567   return mError == Qgis::VectorExportResult::Success;
 
VectorExportResult
Vector layer export result codes.
This class represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
Custom exception class for Coordinate Reference System related exceptions.
virtual bool isValid() const =0
Returns true if this is a valid layer.
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Sets feature IDs that should be fetched.
QgsFeatureRequest & setFlags(QgsFeatureRequest::Flags flags)
Sets flags that affect how features will be fetched.
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
@ FastInsert
Use faster inserts, at the cost of updating the passed features to reflect changes made at the provid...
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
bool setAttribute(int field, const QVariant &attr)
Sets an attribute's value by field index.
void initAttributes(int fieldCount)
Initialize this feature with the given number of fields.
int approximateMemoryUsage() const
Returns the approximate RAM usage of the feature, in bytes.
bool hasGeometry() const
Returns true if the feature has an associated geometry.
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Base class for feedback objects to be used for cancellation of something running in a worker thread.
void progressChanged(double progress)
Emitted when the feedback object reports a progress change.
bool isCanceled() const SIP_HOLDGIL
Tells whether the operation has been canceled already.
void setProgress(double progress)
Sets the current progress for the feedback object.
Container of fields for a vector layer.
int count() const
Returns number of items.
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
bool rename(int fieldIdx, const QString &name)
Renames a name of field.
A geometry is the spatial representation of a feature.
bool isMultipart() const SIP_HOLDGIL
Returns true if WKB of the geometry is of WKBMulti* type.
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 providerType() const
Returns the provider type (provider key) for this layer.
QgsCoordinateReferenceSystem crs
QgsCoordinateTransformContext transformContext() const
Returns the layer data provider coordinate transform context or a default transform context if the la...
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
A registry / canonical manager of data providers.
QgsDataProvider * createProvider(const QString &providerKey, const QString &dataSource, const QgsDataProvider::ProviderOptions &options=QgsDataProvider::ProviderOptions(), QgsDataProvider::ReadFlags flags=QgsDataProvider::ReadFlags())
Creates a new instance of a provider.
QVariantMap decodeUri(const QString &providerKey, const QString &uri)
Breaks a provider data source URI into its component paths (e.g.
Qgis::VectorExportResult 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.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
Abstract base class for long running background tasks.
virtual void cancel()
Notifies the task that it should terminate.
void setDependentLayers(const QList< QgsMapLayer * > &dependentLayers)
Sets a list of layers on which the task depends.
void setProgress(double progress)
Sets the task's current progress.
This is the base class for vector data providers.
@ CreateSpatialIndex
Allows creation of spatial index.
@ AddFeatures
Allows adding features.
virtual bool createSpatialIndex()
Creates a spatial index on the datasource (if supported by the provider type).
void clearErrors()
Clear recorded errors.
QStringList errors() const
Gets recorded errors.
bool addFeatures(QgsFeatureList &flist, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a list of features to the sink.
virtual Q_INVOKABLE QgsVectorDataProvider::Capabilities capabilities() const
Returns flags containing the supported capabilities.
QgsTask task which performs a QgsVectorLayerExporter layer export operation as a background task.
void finished(bool result) override
If the task is managed by a QgsTaskManager, this will be called after the task has finished (whether ...
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.
void exportComplete()
Emitted when exporting the layer is successfully completed.
void errorOccurred(Qgis::VectorExportResult error, const QString &errorMessage)
Emitted when an error occurs which prevented the layer being exported (or if the task is canceled).
void cancel() override
Notifies the task that it should terminate.
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.
bool run() override
Performs the task's operation.
A convenience class for exporting vector layers to a destination data provider.
bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a list of features to the sink.
static Qgis::VectorExportResult 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 errorCount() const
Returns the number of error messages encountered during the export.
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=QgsFeatureSink::SinkFlags())
Constructor for QgsVectorLayerExporter.
QString errorMessage() const
Returns any error message encountered during the export.
~QgsVectorLayerExporter() override
Finalizes the export and closes the new created layer.
QString lastError() const override
Returns the most recent error encountered by the sink, e.g.
bool flushBuffer() override
Flushes any internal buffer which may exist in the sink, causing any buffered features to be added to...
Qgis::VectorExportResult errorCode() const
Returns any encountered error code, or false if no error was encountered.
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a single feature to the sink.
Represents a vector layer which manages a vector based data sets.
Q_INVOKABLE QgsWkbTypes::Type wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
long long featureCount(const QString &legendKey) const
Number of features rendered with specified legend key.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
int selectedFeatureCount() const
Returns the number of features that are selected in this layer.
Q_INVOKABLE const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
static bool isMultiType(Type type) SIP_HOLDGIL
Returns true if the WKB type is a multi type.
Type
The WKB type describes the number of dimensions a geometry has.
static QString displayString(Type type) SIP_HOLDGIL
Returns a non-translated display string type for a WKB type, e.g., the geometry name used in WKT geom...
static Type singleType(Type type) SIP_HOLDGIL
Returns the single type for a WKB type.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
QList< QgsFeature > QgsFeatureList
#define QgsDebugMsgLevel(str, level)
Qgis::VectorExportResult 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)
const QgsCoordinateReferenceSystem & crs
Setting options for creating vector data providers.