36#include <QProgressDialog>
40#include "moc_qgsvectorlayerexporter.cpp"
42using namespace Qt::StringLiterals;
50 QMap<int, int> *oldToNewAttrIdx,
51 QString *errorMessage,
52 const QMap<QString, QVariant> *options
62 mTransformContext = context;
67 return mTransformContext;
72 mDestinationCrs = crs;
77 return mDestinationCrs;
92 mFilterExpression = expression;
97 return mFilterExpression;
102 mExpressionContext = context;
107 return mExpressionContext;
112 return mOutputFields;
117 mOutputFields = fields;
126 const QString &providerKey,
131 const QMap<QString, QVariant> &options,
136 QMap<QString, QVariant> modifiedOptions( options );
138 if ( providerKey ==
"ogr"_L1 &&
139 options.contains( u
"driverName"_s ) &&
140 ( options[ u
"driverName"_s ].toString().compare(
"GPKG"_L1, Qt::CaseInsensitive ) == 0 ||
141 options[ u
"driverName"_s ].toString().compare(
"SQLite"_L1, Qt::CaseInsensitive ) == 0 ) )
148 QStringList modifiedLayerOptions;
149 if ( options.contains( u
"layerOptions"_s ) )
151 const QStringList layerOptions = options.value( u
"layerOptions"_s ).toStringList();
152 for (
const QString &layerOption : layerOptions )
154 if ( layerOption.compare(
"SPATIAL_INDEX=YES"_L1, Qt::CaseInsensitive ) == 0 ||
155 layerOption.compare(
"SPATIAL_INDEX=ON"_L1, Qt::CaseInsensitive ) == 0 ||
156 layerOption.compare(
"SPATIAL_INDEX=TRUE"_L1, Qt::CaseInsensitive ) == 0 ||
157 layerOption.compare(
"SPATIAL_INDEX=1"_L1, Qt::CaseInsensitive ) == 0 )
161 else if ( layerOption.compare(
"SPATIAL_INDEX=NO"_L1, Qt::CaseInsensitive ) == 0 ||
162 layerOption.compare(
"SPATIAL_INDEX=OFF"_L1, Qt::CaseInsensitive ) == 0 ||
163 layerOption.compare(
"SPATIAL_INDEX=FALSE"_L1, Qt::CaseInsensitive ) == 0 ||
164 layerOption.compare(
"SPATIAL_INDEX=0"_L1, Qt::CaseInsensitive ) == 0 )
166 mCreateSpatialIndex =
false;
170 modifiedLayerOptions << layerOption;
174 modifiedLayerOptions << u
"SPATIAL_INDEX=FALSE"_s;
175 modifiedOptions[ u
"layerOptions"_s ] = modifiedLayerOptions;
183 mError = pReg->
createEmptyLayer( providerKey, uri, fields, geometryType, crs, overwrite, mOldToNewAttrIdx,
184 errMsg, !modifiedOptions.isEmpty() ? &modifiedOptions :
nullptr, uriUpdated );
188 mErrorMessage = errMsg;
192 const auto constMOldToNewAttrIdx = mOldToNewAttrIdx;
193 for (
const int idx : constMOldToNewAttrIdx )
195 if ( idx > mAttributeCount )
196 mAttributeCount = idx;
205 if ( providerKey ==
"oracle"_L1 )
215 mErrorMessage = QObject::tr(
"Loading of layer failed" );
217 delete vectorProvider;
229 const QString fidName = options.value( u
"FID"_s, u
"FID"_s ).toString();
233 mOldToNewAttrIdx.remove( fidIdx );
237 mProvider = vectorProvider;
245 if ( mCreateSpatialIndex )
247 createSpatialIndex();
260 return mErrorMessage;
270 QgsFeatureList::iterator fIt = features.begin();
272 for ( ; fIt != features.end(); ++fIt )
289 for (
int i = 0; i < attrs.count(); ++i )
293 const int dstIdx = mOldToNewAttrIdx.value( i, -1 );
297 QgsDebugMsgLevel( u
"moving field from pos %1 to %2"_s.arg( i ).arg( dstIdx ), 3 );
301 mFeatureBuffer.append( newFeat );
304 if ( mFeatureBufferMemoryUsage >= 100 * 1000 * 1000 )
314 return mErrorMessage;
319 mFeatureBufferMemoryUsage = 0;
320 if ( mFeatureBuffer.count() <= 0 )
325 const QStringList errors = mProvider->errors();
326 mProvider->clearErrors();
328 mErrorMessage = QObject::tr(
"Creation error for features from #%1 to #%2. Provider errors were: \n%3" )
329 .arg( mFeatureBuffer.first().id() )
330 .arg( mFeatureBuffer.last().id() )
331 .arg( errors.join( QLatin1Char(
'\n' ) ) );
334 mErrorCount += mFeatureBuffer.count();
336 mFeatureBuffer.clear();
341 mFeatureBuffer.clear();
345bool QgsVectorLayerExporter::createSpatialIndex()
347 mCreateSpatialIndex =
false;
360 const QString &providerKey,
364 const QMap<QString, QVariant> &options,
380 bool shallTransform =
false;
389 shallTransform =
true;
394 outputCRS = layer->
crs();
397 QMap<QString, QVariant> providerOptions = _providerOptions;
398 const bool overwrite = providerOptions.take( u
"overwrite"_s ).toBool();
399 const bool forceSinglePartGeom = providerOptions.take( u
"forceSinglePartGeometryType"_s ).toBool();
402 bool useFieldMapping =
false;
403 QList<QgsExpression> expressions;
406 outputFields = layer->
fields();
410 useFieldMapping =
true;
411 const QList<QgsVectorLayerExporter::OutputField> exportFieldDefinitions = exportOptions.
outputFields();
414 outputFields.
append( field.field );
416 expressions.last().prepare( &expressionContext );
417 if ( expressions.last().hasParserError() )
420 *
errorMessage = QObject::tr(
"Parser error for field \"%1\" with expression \"%2\": %3" )
424 expressions.last().parserErrorString()
433 bool convertGeometryToSinglePart =
false;
437 convertGeometryToSinglePart =
true;
440 auto writer = std::make_unique< QgsVectorLayerExporter >(
441 uri, providerKey, outputFields, wkbType, outputCRS, overwrite, providerOptions );
465 shallTransform =
false;
507 bool canceled =
false;
518 *
errorMessage +=
'\n' + QObject::tr(
"Import was canceled at %1 of %2" ).arg( n ).arg( approxTotal );
523 if ( writer->errorCount() > 1000 )
527 *
errorMessage +=
'\n' + QObject::tr(
"Stopping after %n error(s)",
nullptr, writer->errorCount() );
533 outputFeature.
setId( sourceFeature.
id() );
536 if ( shallTransform )
549 const QString msg = QObject::tr(
"Failed to transform feature with ID '%1'. Writing stopped. (Exception: %2)" )
550 .arg( sourceFeature.
id() ).arg( e.
what() );
568 const QString msg = QObject::tr(
"Failed to transform a feature with ID '%1' to single part. Writing stopped." )
569 .arg( sourceFeature.
id() );
579 if ( useFieldMapping )
582 attributes.reserve( expressions.size() );
583 for (
auto it = expressions.begin(); it != expressions.end(); ++it )
587 expressionContext.
setFeature( sourceFeature );
588 const QVariant value = it->evaluate( &expressionContext );
589 if ( it->hasEvalError() )
591 const QString msg = QObject::tr(
"Evaluation error in expression \"%1\": %2" ).arg( it->expression(), it->evalErrorString() );
597 attributes.append( value );
601 attributes.append( QVariant() );
611 if ( !writer->addFeature( outputFeature ) )
622 feedback->
setProgress( 100.0 *
static_cast< double >( n ) /
static_cast< double >( approxTotal ) );
628 if ( !writer->flushBuffer() )
635 const int errors = writer->errorCount();
637 if ( writer->mCreateSpatialIndex && !writer->createSpatialIndex() )
651 *
errorMessage +=
'\n' + QObject::tr(
"Only %1 of %2 features written." ).arg( n - errors ).arg( n );
661 else if ( errors > 0 )
674 , mOwnsLayer( ownsLayer )
676 , mDestProviderKey( providerKey )
677 , mOptions( options )
680 mExportOptions.setDestinationCrs( destinationCrs );
690 , mOwnsLayer( ownsLayer )
692 , mDestProviderKey( providerKey )
693 , mExportOptions( exportOptions )
694 , mOptions( providerOptions )
699 if ( mLayer && mOwnsLayer )
700 mLayer->moveToThread(
nullptr );
705 auto newTask = std::make_unique<QgsVectorLayerExporterTask>( layer, uri, providerKey, destinationCrs, options,
true );
706 return newTask.release();
711 mOwnedFeedback->cancel();
721 mLayer->moveToThread( QThread::currentThread() );
727 mLayer.data(), mDestUri, mDestProviderKey, mExportOptions, &mErrorMessage,
728 mOptions, mOwnedFeedback.get() );
731 mLayer->moveToThread(
nullptr );
738 if ( mOwnsLayer && mLayer )
739 mLayer->moveToThread( QThread::currentThread() );
@ AddFeatures
Allows adding features.
@ CreateSpatialIndex
Allows creation of spatial index.
VectorExportResult
Vector layer export result codes.
@ Success
No errors were encountered.
@ ErrorInvalidLayer
Could not access newly created destination layer.
@ ErrorFeatureWriteFailed
An error occurred while writing a feature to the destination.
@ ErrorAttributeCreationFailed
Destination provider was unable to create an attribute.
@ UserCanceled
User canceled the export.
@ ErrorProjectingFeatures
An error occurred while reprojecting features to destination CRS.
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
QFlags< VectorDataProviderAttributeEditCapability > VectorDataProviderAttributeEditCapabilities
Attribute editing capabilities which may be supported by vector data providers.
WkbType
The WKB type describes the number of dimensions a geometry has.
Represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
Contains information about the context in which a coordinate transform is executed.
Custom exception class for Coordinate Reference System related exceptions.
virtual bool isValid() const =0
Returns true if this is a valid layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
Handles parsing and evaluation of expressions (formerly called "search strings").
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.
Wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFlags(Qgis::FeatureRequestFlags flags)
Sets flags that affect how features will be fetched.
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Sets the feature IDs that should be fetched.
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
QgsFeatureRequest & setExpressionContext(const QgsExpressionContext &context)
Sets the expression context used to evaluate filter expressions.
QgsFeatureRequest & setFilterRect(const QgsRectangle &rectangle)
Sets the rectangle from which features will be taken.
QFlags< SinkFlag > SinkFlags
@ FastInsert
Use faster inserts, at the cost of updating the passed features to reflect changes made at the provid...
@ RegeneratePrimaryKey
This flag indicates, that a primary key field cannot be guaranteed to be unique and the sink should i...
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Q_INVOKABLE 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.
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
void setId(QgsFeatureId id)
Sets the feature id for this feature.
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.
bool isCanceled() const
Tells whether the operation has been canceled already.
void progressChanged(double progress)
Emitted when the feedback object reports a progress change.
void setProgress(double progress)
Sets the current progress for the feedback object.
Container of fields for a vector layer.
bool append(const QgsField &field, Qgis::FieldOrigin origin=Qgis::FieldOrigin::Provider, int originIndex=-1)
Appends a field.
Q_INVOKABLE int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
A geometry is the spatial representation of a feature.
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false)
Transforms this geometry as described by the coordinate transform ct.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
bool convertToSingleType()
Converts multi type geometry into single type geometry e.g.
bool isMultipart() const
Returns true if WKB of the geometry is of WKBMulti* type.
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, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE())
Adds a message to the log instance (and creates it if necessary).
A registry / canonical manager of data providers.
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, Qgis::WkbType wkbType, const QgsCoordinateReferenceSystem &srs, bool overwrite, QMap< int, int > &oldToNewAttrIdxMap, QString &errorMessage, const QMap< QString, QVariant > *options, QString &createdLayerName)
Creates new empty vector layer.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
QgsDataProvider * createProvider(const QString &providerKey, const QString &dataSource, const QgsDataProvider::ProviderOptions &options=QgsDataProvider::ProviderOptions(), Qgis::DataProviderReadFlags flags=Qgis::DataProviderReadFlags())
Creates a new instance of a provider.
A rectangle specified with double values.
QgsCoordinateReferenceSystem crs() const
Returns the associated coordinate reference system, or an invalid CRS if no reference system is set.
A QgsRectangle with associated coordinate reference system.
virtual void cancel()
Notifies the task that it should terminate.
QgsTask(const QString &description=QString(), QgsTask::Flags flags=AllFlags)
Constructor for QgsTask.
@ CanCancel
Task can be canceled.
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.
Base class for vector data providers.
virtual bool createSpatialIndex()
Creates a spatial index on the datasource (if supported by the provider type).
virtual Q_INVOKABLE Qgis::VectorProviderCapabilities capabilities() const
Returns flags containing the supported capabilities.
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.
Encapsulates options for use with QgsVectorLayerExporter.
QgsReferencedRectangle extent() const
Returns the extent filter for the features to export.
void setExtent(const QgsReferencedRectangle &extent)
Sets an extent filter for the features to export.
void setOutputFields(const QList< QgsVectorLayerExporter::OutputField > &fields)
Sets the output field definitions for the destination table.
void setSelectedOnly(bool selected)
Sets whether the export should only include selected features.
QString filterExpression() const
Returns the filter expression for features to export.
void setDestinationCrs(const QgsCoordinateReferenceSystem &crs)
Sets the destination coordinate reference system to use for exported features.
const QgsExpressionContext & expressionContext() const
Returns the expression context used when a filterExpression() is set.
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context used when transforming exported features.
void setFilterExpression(const QString &expression)
Set the filter expression for the features to export.
bool selectedOnly() const
Returns whether the export will only include selected features.
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context to use when a filterExpression() is set.
void setTransformContext(const QgsCoordinateTransformContext &context)
Sets the coordinate transform context to use when transforming exported features.
QgsCoordinateReferenceSystem destinationCrs() const
Returns the destination coordinate reference system used for exported features.
QList< QgsVectorLayerExporter::OutputField > outputFields() const
Returns the output field definitions for the destination table.
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.
QString errorMessage() const
Returns any error message encountered during the export.
Qgis::VectorDataProviderAttributeEditCapabilities attributeEditCapabilities() const
Returns the attribute capabilities of the exporter.
~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.
QgsVectorLayerExporter(const QString &uri, const QString &provider, const QgsFields &fields, Qgis::WkbType geometryType, const QgsCoordinateReferenceSystem &crs, bool overwrite=false, const QMap< QString, QVariant > &options=QMap< QString, QVariant >(), QgsFeatureSink::SinkFlags sinkFlags=QgsFeatureSink::SinkFlags())
Constructor for QgsVectorLayerExporter.
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 dataset.
long long featureCount(const QString &legendKey) const
Number of features rendered with specified legend key.
int selectedFeatureCount() const
Returns the number of features that are selected in this layer.
Q_INVOKABLE Qgis::WkbType wkbType() const final
Returns the WKBType or WKBUnknown in case of error.
Q_INVOKABLE const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const final
Queries the layer for features specified in request.
static Q_INVOKABLE QString displayString(Qgis::WkbType type)
Returns a non-translated display string type for a WKB type, e.g., the geometry name used in WKT geom...
static Qgis::WkbType singleType(Qgis::WkbType type)
Returns the single type for a WKB type.
static Q_INVOKABLE bool isMultiType(Qgis::WkbType type)
Returns true if the WKB type is a multi 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
T qgsgeometry_cast(QgsAbstractGeometry *geom)
QList< QgsFeature > QgsFeatureList
#define QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)
Qgis::VectorExportResult createEmptyLayer_t(const QString &uri, const QgsFields &fields, Qgis::WkbType geometryType, const QgsCoordinateReferenceSystem &destCRS, bool overwrite, QMap< int, int > *oldToNewAttrIdx, QString *errorMessage, const QMap< QString, QVariant > *options)
Setting options for creating vector data providers.
Encapsulates output field definition.