Skip to content

Commit 55ac5e8

Browse files
committed
Add a new LayerUtils invokable function to save a vector layer as an on-disk dataset
1 parent 0d5345b commit 55ac5e8

File tree

2 files changed

+87
-0
lines changed

2 files changed

+87
-0
lines changed

src/core/utils/layerutils.cpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include <qgssymbol.h>
4343
#include <qgssymbollayer.h>
4444
#include <qgstextbuffersettings.h>
45+
#include <qgsvectorfilewriter.h>
4546
#include <qgsvectorlayer.h>
4647
#include <qgsvectorlayerlabeling.h>
4748
#include <qgsvectorlayerutils.h>
@@ -545,6 +546,16 @@ bool LayerUtils::hasMValue( QgsVectorLayer *layer )
545546
return QgsWkbTypes::hasM( layer->wkbType() );
546547
}
547548

549+
QSet<QVariant> LayerUtils::uniqueValuesForVectorLayerFieldIndex( QgsVectorLayer *layer, int fieldIndex )
550+
{
551+
if ( !layer )
552+
{
553+
return QSet<QVariant>();
554+
}
555+
556+
return layer->uniqueValues( fieldIndex );
557+
}
558+
548559
QgsVectorLayer *LayerUtils::loadVectorLayer( const QString &uri, const QString &name, const QString &provider )
549560
{
550561
QgsVectorLayer *layer = new QgsVectorLayer( uri, name, provider );
@@ -595,3 +606,64 @@ FeatureIterator LayerUtils::createFeatureIteratorFromRectangle( QgsVectorLayer *
595606
const QgsFeatureRequest request = QgsFeatureRequest( rectangle );
596607
return FeatureIterator( layer, request );
597608
}
609+
610+
QString LayerUtils::saveVectorLayerAs( QgsVectorLayer *layer, const QString &filePath, const QString &driverName, const QString &filterExpression )
611+
{
612+
if ( !layer || filePath.isEmpty() )
613+
{
614+
return QString();
615+
}
616+
617+
QFileInfo fileInfo( filePath );
618+
const QString finalDriverName = driverName.isEmpty() ? QgsVectorFileWriter::driverForExtension( fileInfo.suffix() ) : driverName;
619+
if ( finalDriverName.isEmpty() )
620+
{
621+
return QString();
622+
}
623+
QDir dir;
624+
if ( !dir.mkpath( fileInfo.absolutePath() ) )
625+
{
626+
return QString();
627+
}
628+
629+
QStringList datasetOptions = QgsVectorFileWriter::defaultDatasetOptions( finalDriverName );
630+
if ( finalDriverName == QStringLiteral( "GPX" ) )
631+
{
632+
datasetOptions.removeAll( QStringLiteral( "GPX_USE_EXTENSIONS=NO" ) );
633+
datasetOptions << QStringLiteral( "GPX_USE_EXTENSIONS=YES" );
634+
}
635+
636+
QString finalFileName;
637+
QString finalLayerName;
638+
QgsVectorFileWriter::SaveVectorOptions saveOptions;
639+
saveOptions.fileEncoding = QStringLiteral( "UTF8" );
640+
saveOptions.layerName = fileInfo.completeBaseName();
641+
saveOptions.driverName = finalDriverName;
642+
saveOptions.datasourceOptions = datasetOptions;
643+
saveOptions.layerOptions = QgsVectorFileWriter::defaultLayerOptions( finalDriverName );
644+
saveOptions.symbologyExport = Qgis::FeatureSymbologyExport::NoSymbology;
645+
saveOptions.actionOnExistingFile = QgsVectorFileWriter::CreateOrOverwriteFile;
646+
647+
std::unique_ptr<QgsVectorFileWriter> writer( QgsVectorFileWriter::create( filePath, layer->fields(), layer->wkbType(), layer->crs(), QgsProject::instance()->transformContext(), saveOptions, QgsFeatureSink::RegeneratePrimaryKey, &finalFileName, &finalLayerName ) );
648+
if ( writer->hasError() )
649+
{
650+
qInfo() << QStringLiteral( "Vector layer file writer error: %1" ).arg( writer->errorMessage() );
651+
return QString();
652+
}
653+
654+
QgsFeatureRequest request;
655+
if ( !filterExpression.isEmpty() )
656+
{
657+
request.setFilterExpression( filterExpression );
658+
request.setExpressionContext( layer->createExpressionContext() );
659+
}
660+
661+
QgsFeatureIterator it = layer->getFeatures( request );
662+
QgsFeature feature;
663+
while ( it.nextFeature( feature ) )
664+
{
665+
writer->addFeature( feature, QgsFeatureSink::FastInsert );
666+
}
667+
668+
return finalFileName;
669+
}

src/core/utils/layerutils.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,11 @@ class LayerUtils : public QObject
180180
*/
181181
Q_INVOKABLE static bool hasMValue( QgsVectorLayer *layer );
182182

183+
/**
184+
* Returns a list of unique values for a given \a fieldIndex from the \a layer.
185+
*/
186+
Q_INVOKABLE QSet<QVariant> uniqueValuesForVectorLayerFieldIndex( QgsVectorLayer *layer, int fieldIndex );
187+
183188
/**
184189
* Loads a vector layer.
185190
* \param uri the data source uri
@@ -226,6 +231,16 @@ class LayerUtils : public QObject
226231
* Returns a feature iterator to get features overlapping a given \a rectangle within the provided \a layer.
227232
*/
228233
Q_INVOKABLE static FeatureIterator createFeatureIteratorFromRectangle( QgsVectorLayer *layer, const QgsRectangle &rectangle );
234+
235+
/**
236+
* Saves a vector layer into an on-disk dataset a given path using the OGR provider.
237+
* \param layer the vector layer to save features from
238+
* \param filePath the file path where the dataset will be writen
239+
* \param driverName an optional OGR driver name (if left empty, the file path extension will drive the OGR driver)
240+
* \param filterExpression an optional filter expression used to save a subset of features from the layer (note that only the global, project, and layer expression context scopes are used)
241+
* \returns If successful, finalized file path will be returned, otherwise an empty string will be returned
242+
*/
243+
Q_INVOKABLE static QString saveVectorLayerAs( QgsVectorLayer *layer, const QString &filePath, const QString &driverName = QString(), const QString &filterExpression = QString() );
229244
};
230245

231246
#endif // LAYERUTILS_H

0 commit comments

Comments
 (0)