24#include <cpl_string.h>
29#include <ogr_srs_api.h>
54#include <QJsonDocument>
57#include <QRegularExpression>
63using namespace Qt::StringLiterals;
84 const QString &vectorFileName,
85 const QString &fileEncoding,
89 const QString &driverName,
90 const QStringList &datasourceOptions,
91 const QStringList &layerOptions,
104 init( vectorFileName, fileEncoding, fields, geometryType, srs, driverName, datasourceOptions, layerOptions, newFilename,
nullptr, QString(),
CreateOrOverwriteFile, newLayer, sinkFlags, transformContext, fieldNameSource,
nullptr );
108 const QString &vectorFileName,
109 const QString &fileEncoding,
113 const QString &driverName,
114 const QStringList &datasourceOptions,
115 const QStringList &layerOptions,
116 QString *newFilename,
119 const QString &layerName,
125 bool includeConstraints,
126 bool setFieldDomains,
136 init( vectorFileName, fileEncoding, fields, geometryType, srs, driverName, datasourceOptions, layerOptions, newFilename, fieldValueConverter, layerName, action, newLayer, sinkFlags, transformContext, fieldNameSource, sourceDatabaseProviderConnection );
140 const QString &fileName,
147 QString *newFilename,
179 if ( driverName ==
"MapInfo MIF"_L1 )
183 GDALDriverH gdalDriver = GDALGetDriverByName( driverName.toLocal8Bit().constData() );
187 CSLConstList
driverMetadata = GDALGetMetadata( gdalDriver,
nullptr );
191#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION( 3, 7, 0 )
192 return CSLFetchBoolean(
driverMetadata, GDAL_DCAP_FEATURE_STYLES_WRITE,
false );
194 return CSLFetchBoolean(
driverMetadata, GDAL_DCAP_FEATURE_STYLES,
false );
198void QgsVectorFileWriter::init(
199 QString vectorFileName,
200 QString fileEncoding,
204 const QString &driverName,
205 QStringList datasourceOptions,
206 QStringList layerOptions,
207 QString *newFilename,
208 FieldValueConverter *fieldValueConverter,
209 const QString &layerNameIn,
210 ActionOnExistingFile action,
214 FieldNameSource fieldNameSource,
218#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION( 3, 5, 0 )
219 ( void ) sourceDatabaseProviderConnection;
224 if ( vectorFileName.isEmpty() )
231 if ( driverName ==
"MapInfo MIF"_L1 )
235 else if ( driverName ==
"SpatiaLite"_L1 )
238 if ( !datasourceOptions.contains( u
"SPATIALITE=YES"_s ) )
240 datasourceOptions.append( u
"SPATIALITE=YES"_s );
243 else if ( driverName ==
"DBF file"_L1 )
246 if ( !layerOptions.contains( u
"SHPT=NULL"_s ) )
248 layerOptions.append( u
"SHPT=NULL"_s );
250 srs = QgsCoordinateReferenceSystem();
257#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION( 3, 3, 1 )
258 QString fidFieldName;
261 for (
const QString &layerOption : layerOptions )
263 if ( layerOption.startsWith(
"FID="_L1 ) )
265 fidFieldName = layerOption.mid( 4 );
269 if ( fidFieldName.isEmpty() )
270 fidFieldName = u
"fid"_s;
275 OGRSFDriverH poDriver;
278 poDriver = OGRGetDriverByName(
mOgrDriverName.toLocal8Bit().constData() );
282 mErrorMessage = QObject::tr(
"OGR driver for '%1' not found (OGR error: %2)" ).arg( driverName, QString::fromUtf8( CPLGetLastErrorMsg() ) );
287 mOgrDriverLongName = QString( GDALGetMetadataItem( poDriver, GDAL_DMD_LONGNAME,
nullptr ) );
294 if ( layerOptions.join( QString() ).toUpper().indexOf(
"ENCODING="_L1 ) == -1 )
299 if ( driverName ==
"ESRI Shapefile"_L1 && !vectorFileName.endsWith(
".shp"_L1, Qt::CaseInsensitive ) )
301 vectorFileName +=
".shp"_L1;
303 else if ( driverName ==
"DBF file"_L1 && !vectorFileName.endsWith(
".dbf"_L1, Qt::CaseInsensitive ) )
305 vectorFileName +=
".dbf"_L1;
315 QStringList allExts = metadata.glob.split(
' ', Qt::SkipEmptyParts );
317 const auto constAllExts = allExts;
318 for (
const QString &ext : constAllExts )
321 if ( vectorFileName.endsWith( ext.mid( 1 ), Qt::CaseInsensitive ) )
330 allExts = metadata.ext.split(
' ', Qt::SkipEmptyParts );
331 vectorFileName +=
'.' + allExts[0];
337 if ( vectorFileName.endsWith(
".gdb"_L1, Qt::CaseInsensitive ) )
339 QDir dir( vectorFileName );
342 QFileInfoList fileList = dir.entryInfoList( QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files, QDir::DirsFirst );
343 const auto constFileList = fileList;
344 for (
const QFileInfo &info : constFileList )
346 QFile::remove( info.absoluteFilePath() );
349 QDir().rmdir( vectorFileName );
353 QFile::remove( vectorFileName );
358 if ( metadataFound && !metadata.compulsoryEncoding.isEmpty() )
360 if ( fileEncoding.compare( metadata.compulsoryEncoding, Qt::CaseInsensitive ) != 0 )
362 QgsDebugMsgLevel( u
"forced %1 encoding for %2"_s.arg( metadata.compulsoryEncoding, driverName ), 2 );
363 fileEncoding = metadata.compulsoryEncoding;
367 char **options =
nullptr;
368 if ( !datasourceOptions.isEmpty() )
370 options =
new char *[datasourceOptions.size() + 1];
371 for (
int i = 0; i < datasourceOptions.size(); i++ )
374 options[i] = CPLStrdup( datasourceOptions[i].toUtf8().constData() );
376 options[datasourceOptions.size()] =
nullptr;
381 mDS.reset( OGR_Dr_CreateDataSource( poDriver, vectorFileName.toUtf8().constData(), options ) );
383 mDS.reset( OGROpen( vectorFileName.toUtf8().constData(), TRUE,
nullptr ) );
387 for (
int i = 0; i < datasourceOptions.size(); i++ )
388 CPLFree( options[i] );
397 mErrorMessage = QObject::tr(
"Creation of data source failed (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
399 mErrorMessage = QObject::tr(
"Opening of data source in update mode failed (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
403 QString layerName( layerNameIn );
404 if ( layerName.isEmpty() )
405 layerName = QFileInfo( vectorFileName ).baseName();
409 const int layer_count = OGR_DS_GetLayerCount(
mDS.get() );
410 for (
int i = 0; i < layer_count; i++ )
412 OGRLayerH hLayer = OGR_DS_GetLayer(
mDS.get(), i );
413 if ( EQUAL( OGR_L_GetName( hLayer ), layerName.toUtf8().constData() ) )
415 if ( OGR_DS_DeleteLayer(
mDS.get(), i ) != OGRERR_NONE )
418 mErrorMessage = QObject::tr(
"Overwriting of existing layer failed (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
436 mCodec = QTextCodec::codecForName( fileEncoding.toLocal8Bit().constData() );
439 QgsDebugError(
"error finding QTextCodec for " + fileEncoding );
442 mCodec = QTextCodec::codecForName( enc.toLocal8Bit().constData() );
446 mCodec = QTextCodec::codecForLocale();
452 if ( driverName ==
"KML"_L1 || driverName ==
"LIBKML"_L1 || driverName ==
"GPX"_L1 )
454 if ( srs.
authid() !=
"EPSG:4326"_L1 )
458 mCoordinateTransform = std::make_unique<QgsCoordinateTransform>( srs, wgs84, transformContext );
475 int optIndex = layerOptions.indexOf(
"FEATURE_DATASET="_L1 );
476 if ( optIndex != -1 )
478 layerOptions.removeAt( optIndex );
481 if ( !layerOptions.isEmpty() )
483 options =
new char *[layerOptions.size() + 1];
484 for (
int i = 0; i < layerOptions.size(); i++ )
487 options[i] = CPLStrdup( layerOptions[i].toUtf8().constData() );
489 options[layerOptions.size()] =
nullptr;
493 CPLSetConfigOption(
"SHAPE_ENCODING",
"" );
497 mLayer = OGR_DS_CreateLayer(
mDS.get(), layerName.toUtf8().constData(),
mOgrRef, wkbType, options );
500 *newLayer = OGR_L_GetName(
mLayer );
501 if ( driverName ==
"GPX"_L1 )
508 if ( !EQUAL( layerName.toUtf8().constData(),
"track_points" ) && !EQUAL( layerName.toUtf8().constData(),
"route_points" ) )
510 *newLayer = u
"waypoints"_s;
517 const char *pszForceGPXTrack = CSLFetchNameValue( options,
"FORCE_GPX_TRACK" );
518 if ( pszForceGPXTrack && CPLTestBool( pszForceGPXTrack ) )
519 *newLayer = u
"tracks"_s;
521 *newLayer = u
"routes"_s;
527 const char *pszForceGPXRoute = CSLFetchNameValue( options,
"FORCE_GPX_ROUTE" );
528 if ( pszForceGPXRoute && CPLTestBool( pszForceGPXRoute ) )
529 *newLayer = u
"routes"_s;
531 *newLayer = u
"tracks"_s;
541 else if ( driverName ==
"DGN"_L1 )
543 mLayer = OGR_DS_GetLayerByName(
mDS.get(),
"elements" );
547 mLayer = OGR_DS_GetLayerByName(
mDS.get(), layerName.toUtf8().constData() );
552 for (
int i = 0; i < layerOptions.size(); i++ )
553 CPLFree( options[i] );
562 QString layerName = vectorFileName.left( vectorFileName.indexOf(
".shp"_L1, Qt::CaseInsensitive ) );
563 QFile prjFile( layerName +
".qpj" );
564 if ( prjFile.exists() )
572 mErrorMessage = QObject::tr(
"Creation of layer failed (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
574 mErrorMessage = QObject::tr(
"Opening of layer failed (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
579 OGRFeatureDefnH defn = OGR_L_GetLayerDefn(
mLayer );
589 QSet<int> existingIdxs;
593#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION( 3, 7, 0 )
594 if (
const char *pszCreateFieldDefnFlags = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATION_FIELD_DEFN_FLAGS,
nullptr ) )
596 char **papszTokens = CSLTokenizeString2( pszCreateFieldDefnFlags,
" ", 0 );
597 if ( CSLFindString( papszTokens,
"AlternativeName" ) >= 0 )
601 if ( CSLFindString( papszTokens,
"Comment" ) >= 0 )
605 CSLDestroy( papszTokens );
615#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION( 3, 5, 0 )
616 QSet<QString> existingDestDomainNames;
617 if ( sourceDatabaseProviderConnection )
619 char **domainNames = GDALDatasetGetFieldDomainNames(
mDS.get(),
nullptr );
620 for (
const char *
const *iterDomainNames = domainNames; iterDomainNames && *iterDomainNames; ++iterDomainNames )
622 existingDestDomainNames.insert( QString::fromUtf8( *iterDomainNames ) );
624 CSLDestroy( domainNames );
627#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION( 3, 6, 0 )
628 QSet< QString > usedAlternativeNames;
631 const QString ogrFidColumnName { OGR_L_GetFIDColumn(
mLayer ) };
632 const int fidNameIndex = OGR_FD_GetFieldIndex( defn, ogrFidColumnName.toUtf8() );
635 const bool promoteFidColumnToAttribute = !ogrFidColumnName.isEmpty() && fidNameIndex < 0 && fields.
lookupField( ogrFidColumnName ) >= 0;
636 int offsetRoomForFid = promoteFidColumnToAttribute ? 1 : 0;
638 for (
int fldIdx = 0; fldIdx < fields.
count(); ++fldIdx )
640 QgsField attrField = fields.
at( fldIdx );
642 if ( fieldValueConverter )
644 attrField = fieldValueConverter->fieldDefinition( fields.
at( fldIdx ) );
649 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( attrField.
name() ) );
659 switch ( fieldNameSource )
662 name = attrField.
name();
666 name = !attrField.
alias().isEmpty() ? attrField.
alias() : attrField.
name();
670 OGRFieldType ogrType = OFTString;
671 OGRFieldSubType ogrSubType = OFSTNone;
672 int ogrWidth = attrField.
length();
673 int ogrPrecision = attrField.
precision();
674 if ( ogrPrecision > 0 )
677 switch ( attrField.
type() )
679 case QMetaType::Type::LongLong:
681 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
682 if ( pszDataTypes && strstr( pszDataTypes,
"Integer64" ) )
683 ogrType = OFTInteger64;
686 ogrWidth = ogrWidth > 0 && ogrWidth <= 20 ? ogrWidth : 20;
690 case QMetaType::Type::QString:
692 if ( ( ogrWidth <= 0 || ogrWidth > 255 ) &&
mOgrDriverName ==
"ESRI Shapefile"_L1 )
696 case QMetaType::Type::Int:
697 ogrType = OFTInteger;
698 ogrWidth = ogrWidth > 0 && ogrWidth <= 10 ? ogrWidth : 10;
702 case QMetaType::Type::Bool:
703 ogrType = OFTInteger;
704 ogrSubType = OFSTBoolean;
709 case QMetaType::Type::Double:
710#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION( 3, 3, 1 )
711 if (
mOgrDriverName ==
"GPKG"_L1 && attrField.
precision() == 0 && attrField.
name().compare( fidFieldName, Qt::CaseInsensitive ) == 0 )
714 ogrType = OFTInteger64;
721 case QMetaType::Type::QDate:
725 case QMetaType::Type::QTime:
737 case QMetaType::Type::QDateTime:
745 ogrType = OFTDateTime;
749 case QMetaType::Type::QByteArray:
753 case QMetaType::Type::QStringList:
759 ogrSubType = OFSTJSON;
763 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
764 if ( pszDataTypes && strstr( pszDataTypes,
"StringList" ) )
766 ogrType = OFTStringList;
767 mSupportedListSubTypes.insert( QMetaType::Type::QString );
777 case QMetaType::Type::QVariantMap:
780 const char *pszDataSubTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATASUBTYPES,
nullptr );
781 if ( pszDataSubTypes && strstr( pszDataSubTypes,
"JSON" ) )
784 ogrSubType = OFSTJSON;
792 case QMetaType::Type::QVariantList:
797 ogrSubType = OFSTJSON;
802 if ( attrField.
subType() == QMetaType::Type::QString )
804 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
805 if ( pszDataTypes && strstr( pszDataTypes,
"StringList" ) )
807 ogrType = OFTStringList;
808 mSupportedListSubTypes.insert( QMetaType::Type::QString );
817 else if ( attrField.
subType() == QMetaType::Type::Int )
819 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
820 if ( pszDataTypes && strstr( pszDataTypes,
"IntegerList" ) )
822 ogrType = OFTIntegerList;
823 mSupportedListSubTypes.insert( QMetaType::Type::Int );
832 else if ( attrField.
subType() == QMetaType::Type::Double )
834 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
835 if ( pszDataTypes && strstr( pszDataTypes,
"RealList" ) )
837 ogrType = OFTRealList;
838 mSupportedListSubTypes.insert( QMetaType::Type::Double );
847 else if ( attrField.
subType() == QMetaType::Type::LongLong )
849 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
850 if ( pszDataTypes && strstr( pszDataTypes,
"Integer64List" ) )
852 ogrType = OFTInteger64List;
853 mSupportedListSubTypes.insert( QMetaType::Type::LongLong );
867 mErrorMessage = QObject::tr(
"Unsupported type for field %1" ).arg( attrField.
name() );
872 if (
mOgrDriverName ==
"SQLite"_L1 && name.compare(
"ogc_fid"_L1, Qt::CaseInsensitive ) == 0 )
875 for ( i = 0; i < 10; i++ )
877 name = u
"ogc_fid%1"_s.arg( i );
880 for ( j = 0; j < fields.
size() && name.compare( fields.
at( j ).
name(), Qt::CaseInsensitive ) != 0; j++ )
883 if ( j == fields.
size() )
889 mErrorMessage = QObject::tr(
"No available replacement for internal fieldname ogc_fid found" ).arg( attrField.
name() );
894 QgsMessageLog::logMessage( QObject::tr(
"Reserved attribute name ogc_fid replaced with %1" ).arg( name ), QObject::tr(
"OGR" ) );
901 OGR_Fld_SetWidth( fld.get(), ogrWidth );
904 if ( ogrPrecision >= 0 )
906 OGR_Fld_SetPrecision( fld.get(), ogrPrecision );
909 if ( ogrSubType != OFSTNone )
910 OGR_Fld_SetSubType( fld.get(), ogrSubType );
912#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION( 3, 6, 0 )
913 if ( !attrField.
alias().isEmpty() )
915 QString alternativeName = attrField.
alias();
917 while ( usedAlternativeNames.contains( alternativeName ) )
920 alternativeName = attrField.
alias() + u
" (%1)"_s.arg( ++counter );
922 OGR_Fld_SetAlternativeName( fld.get(),
mCodec->fromUnicode( alternativeName ).constData() );
923 usedAlternativeNames.insert( alternativeName );
926#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION( 3, 7, 0 )
927 OGR_Fld_SetComment( fld.get(),
mCodec->fromUnicode( attrField.
comment() ).constData() );
934 OGR_Fld_SetNullable( fld.get(),
false );
938 OGR_Fld_SetUnique( fld.get(),
true );
941#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION( 3, 5, 0 )
945 if ( !domainName.isEmpty() )
947 bool canSetFieldDomainName =
false;
948 if ( existingDestDomainNames.contains( domainName ) )
952 canSetFieldDomainName =
true;
954 else if ( GDALDatasetTestCapability(
mDS.get(), ODsCAddFieldDomain ) )
964 std::unique_ptr<QgsFieldDomain> domain( sourceDatabaseProviderConnection->
fieldDomain( domainName ) );
970 char *pszFailureReason =
nullptr;
971 if ( GDALDatasetAddFieldDomain(
mDS.get(), hFieldDomain, &pszFailureReason ) )
973 existingDestDomainNames.insert( domainName );
974 canSetFieldDomainName =
true;
978 QgsDebugError( u
"cannot create field domain: %1"_s.arg( pszFailureReason ) );
980 CPLFree( pszFailureReason );
981 OGR_FldDomain_Destroy( hFieldDomain );
985 catch ( QgsProviderConnectionException & )
987 QgsDebugError( u
"Cannot retrieve field domain: %1"_s.arg( domainName ) );
990 if ( canSetFieldDomainName )
992 OGR_Fld_SetDomainName( fld.get(), domainName.toUtf8().toStdString().c_str() );
999 QgsDebugMsgLevel(
"creating field " + attrField.
name() +
" type " + QString( QVariant::typeToName( attrField.
type() ) ) +
" width " + QString::number( ogrWidth ) +
" precision " + QString::number( ogrPrecision ), 2 );
1000 if ( OGR_L_CreateField(
mLayer, fld.get(),
true ) != OGRERR_NONE )
1003 mErrorMessage = QObject::tr(
"Creation of field %1 (%2) failed (OGR error: %3)" ).arg( attrField.
name(), QVariant::typeToName( attrField.
type() ), QString::fromUtf8( CPLGetLastErrorMsg() ) );
1008 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( name ) );
1009 QgsDebugMsgLevel( u
"returned field index for %1: %2"_s.arg( name ).arg( ogrIdx ), 2 );
1010 if ( ogrIdx < 0 || existingIdxs.contains( ogrIdx ) )
1013 ogrIdx = OGR_FD_GetFieldCount( defn ) - 1;
1018 mErrorMessage = QObject::tr(
"Created field %1 not found (OGR error: %2)" ).arg( attrField.
name(), QString::fromUtf8( CPLGetLastErrorMsg() ) );
1024 existingIdxs.insert( ogrIdx );
1027 if ( promoteFidColumnToAttribute )
1029 if ( ogrFidColumnName.compare( attrField.
name(), Qt::CaseInsensitive ) == 0 )
1032 offsetRoomForFid = 0;
1037 ogrIdx += offsetRoomForFid;
1048 for (
int fldIdx = 0; fldIdx < fields.
count(); ++fldIdx )
1050 QgsField attrField = fields.
at( fldIdx );
1051 QString name( attrField.
name() );
1052 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( name ) );
1081 *newFilename = vectorFileName;
1084 mUsingTransaction =
true;
1085 if ( OGRERR_NONE != OGR_L_StartTransaction(
mLayer ) )
1087 mUsingTransaction =
false;
1097class QgsVectorFileWriterMetadataContainer
1100 QgsVectorFileWriterMetadataContainer()
1102 QMap<QString, QgsVectorFileWriter::Option *> datasetOptions;
1103 QMap<QString, QgsVectorFileWriter::Option *> layerOptions;
1106 datasetOptions.clear();
1107 layerOptions.clear();
1109 layerOptions.insert(
1112 QObject::tr(
"Compression method." ),
1113 QStringList() << u
"UNCOMPRESSED"_s << u
"ZSTD"_s << u
"LZ4"_s,
1119 layerOptions.insert(
1120 u
"GEOMETRY_ENCODING"_s,
1122 QObject::tr(
"Geometry encoding." ),
1123 QStringList() << u
"GEOARROW"_s << u
"WKB"_s << u
"WKT"_s,
1129 layerOptions.insert(
1132 QObject::tr(
"Maximum number of rows per batch." ),
1137 layerOptions.insert(
1140 QObject::tr(
"Name for the feature identifier column" ),
1145 layerOptions.insert(
1148 QObject::tr(
"Name for the geometry column" ),
1153 driverMetadata.insert( u
"Arrow"_s,
QgsVectorFileWriter::MetaData( u
"(Geo)Arrow"_s, QObject::tr(
"(Geo)Arrow" ), u
"*.arrow *.feather *.arrows *.ipc"_s, u
"arrow"_s, datasetOptions, layerOptions, u
"UTF-8"_s ) );
1156 datasetOptions.clear();
1157 layerOptions.clear();
1159 driverMetadata.insert( u
"AVCE00"_s,
QgsVectorFileWriter::MetaData( u
"Arc/Info ASCII Coverage"_s, QObject::tr(
"Arc/Info ASCII Coverage" ), u
"*.e00"_s, u
"e00"_s, datasetOptions, layerOptions ) );
1162 datasetOptions.clear();
1163 layerOptions.clear();
1165 layerOptions.insert(
1169 "By default when creating new .csv files they "
1170 "are created with the line termination conventions "
1171 "of the local platform (CR/LF on Win32 or LF on all other systems). "
1172 "This may be overridden through the use of the LINEFORMAT option."
1174 QStringList() << u
"CRLF"_s << u
"LF"_s,
1180 layerOptions.insert(
1184 "By default, the geometry of a feature written to a .csv file is discarded. "
1185 "It is possible to export the geometry in its WKT representation by "
1186 "specifying GEOMETRY=AS_WKT. It is also possible to export point geometries "
1187 "into their X,Y,Z components by specifying GEOMETRY=AS_XYZ, GEOMETRY=AS_XY "
1188 "or GEOMETRY=AS_YX."
1190 QStringList() << u
"AS_WKT"_s << u
"AS_XYZ"_s << u
"AS_XY"_s << u
"AS_YX"_s,
1196 layerOptions.insert(
1199 QObject::tr(
"Name of geometry column. Only used if GEOMETRY=AS_WKT. Defaults to 'WKT'." ),
1204 layerOptions.insert(
1208 "Create the associated .csvt file to describe the type of each "
1209 "column of the layer and its optional width and precision. "
1210 "This option also creates a .prj file which stores coordinate system information."
1216 layerOptions.insert(
1219 QObject::tr(
"Field separator character." ),
1225#
if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION( 3, 12, 0 )
1233 layerOptions.insert(
1234 u
"STRING_QUOTING"_s,
1236 QObject::tr(
"Double-quote strings. IF_AMBIGUOUS means that string values that look like numbers will be quoted." ),
1237 QStringList() << u
"IF_NEEDED"_s << u
"IF_AMBIGUOUS"_s << u
"ALWAYS"_s,
1242 layerOptions.insert(
1245 QObject::tr(
"Write a UTF-8 Byte Order Mark (BOM) at the start of the file." ),
1250#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION( 3, 12, 0 )
1251 layerOptions.insert(
1254 QObject::tr(
"Whether to write a header line with the field names." ),
1260 driverMetadata.insert( u
"CSV"_s,
QgsVectorFileWriter::MetaData( u
"Comma Separated Value [CSV]"_s, QObject::tr(
"Comma Separated Value [CSV]" ), u
"*.csv"_s, u
"csv"_s, datasetOptions, layerOptions ) );
1263 datasetOptions.clear();
1264 layerOptions.clear();
1266 driverMetadata.insert( u
"FlatGeobuf"_s,
QgsVectorFileWriter::MetaData( u
"FlatGeobuf"_s, QObject::tr(
"FlatGeobuf" ), u
"*.fgb"_s, u
"fgb"_s, datasetOptions, layerOptions, u
"UTF-8"_s ) );
1269 datasetOptions.clear();
1270 layerOptions.clear();
1272 layerOptions.insert(
1276 "Override the type of shapefile created. "
1277 "Can be one of NULL for a simple .dbf file with no .shp file, POINT, "
1278 "ARC, POLYGON or MULTIPOINT for 2D, or POINTZ, ARCZ, POLYGONZ or "
1279 "MULTIPOINTZ for 3D;"
1282 " POINTM, ARCM, POLYGONM or MULTIPOINTM for measured geometries"
1283 " and POINTZM, ARCZM, POLYGONZM or MULTIPOINTZM for 3D measured"
1286 + QObject::tr(
" MULTIPATCH files are supported since GDAL 2.2." )
1305 << u
"MULTIPOINTZM"_s
1317 QObject::tr(
"Set the encoding value in the DBF file. "
1318 "The default value is LDID/87. It is not clear "
1319 "what other values may be appropriate." ),
1326 layerOptions.insert(
1329 QObject::tr(
"Set to YES to resize fields to their optimal size." ),
1334 driverMetadata.insert( u
"ESRI"_s,
QgsVectorFileWriter::MetaData( u
"ESRI Shapefile"_s, QObject::tr(
"ESRI Shapefile" ), u
"*.shp"_s, u
"shp"_s, datasetOptions, layerOptions ) );
1337 datasetOptions.clear();
1338 layerOptions.clear();
1340 driverMetadata.insert( u
"DBF File"_s,
QgsVectorFileWriter::MetaData( u
"DBF File"_s, QObject::tr(
"DBF File" ), u
"*.dbf"_s, u
"dbf"_s, datasetOptions, layerOptions ) );
1343 datasetOptions.clear();
1344 layerOptions.clear();
1346 layerOptions.insert(
1350 "Set to YES to write a bbox property with the bounding box "
1351 "of the geometries at the feature and feature collection level."
1357 layerOptions.insert(
1358 u
"COORDINATE_PRECISION"_s,
1361 "Maximum number of figures after decimal separator to write in coordinates. "
1362 "Defaults to 15. Truncation will occur to remove trailing zeros."
1368 layerOptions.insert(
1372 "Whether to use RFC 7946 standard. "
1373 "If disabled GeoJSON 2008 initial version will be used. "
1374 "Default is NO (thus GeoJSON 2008). See also Documentation (via Help button)"
1380 driverMetadata.insert( u
"GeoJSON"_s,
QgsVectorFileWriter::MetaData( u
"GeoJSON"_s, QObject::tr(
"GeoJSON" ), u
"*.geojson"_s, u
"geojson"_s, datasetOptions, layerOptions, u
"UTF-8"_s ) );
1383 datasetOptions.clear();
1384 layerOptions.clear();
1386 layerOptions.insert(
1387 u
"COORDINATE_PRECISION"_s,
1390 "Maximum number of figures after decimal separator to write in coordinates. "
1391 "Defaults to 15. Truncation will occur to remove trailing zeros."
1397 layerOptions.insert(
1401 "Whether to start records with the RS=0x1E character (RFC 8142 standard). "
1402 "Defaults to NO: Newline Delimited JSON (geojsonl). \n"
1403 "If set to YES: RFC 8142 standard: GeoJSON Text Sequences (geojsons)."
1410 .insert( u
"GeoJSONSeq"_s,
QgsVectorFileWriter::MetaData( u
"GeoJSON - Newline Delimited"_s, QObject::tr(
"GeoJSON - Newline Delimited" ), u
"*.geojsonl *.geojsons *.json"_s, u
"geojsonl geojsons json"_s, datasetOptions, layerOptions, u
"UTF-8"_s ) );
1413 datasetOptions.clear();
1414 layerOptions.clear();
1416 datasetOptions.insert(
1420 "whether the document must be in RSS 2.0 or Atom 1.0 format. "
1421 "Default value : RSS"
1423 QStringList() << u
"RSS"_s << u
"ATOM"_s,
1428 datasetOptions.insert(
1432 "The encoding of location information. Default value : SIMPLE. "
1433 "W3C_GEO only supports point geometries. "
1434 "SIMPLE or W3C_GEO only support geometries in geographic WGS84 coordinates."
1436 QStringList() << u
"SIMPLE"_s << u
"GML"_s << u
"W3C_GEO"_s,
1441 datasetOptions.insert(
1442 u
"USE_EXTENSIONS"_s,
1445 "If defined to YES, extension fields will be written. "
1446 "If the field name not found in the base schema matches "
1447 "the foo_bar pattern, foo will be considered as the namespace "
1448 "of the element, and a <foo:bar> element will be written. "
1449 "Otherwise, elements will be written in the <ogr:> namespace."
1455 datasetOptions.insert(
1456 u
"WRITE_HEADER_AND_FOOTER"_s,
1459 "If defined to NO, only <entry> or <item> elements will be written. "
1460 "The user will have to provide the appropriate header and footer of the document."
1466 datasetOptions.insert(
1470 "XML content that will be put between the <channel> element and the "
1471 "first <item> element for a RSS document, or between the xml tag and "
1472 "the first <entry> element for an Atom document."
1478 datasetOptions.insert(
1482 "Value put inside the <title> element in the header. "
1483 "If not provided, a dummy value will be used as that element is compulsory."
1489 datasetOptions.insert(
1493 "Value put inside the <description> element in the header. "
1494 "If not provided, a dummy value will be used as that element is compulsory."
1500 datasetOptions.insert(
1504 "Value put inside the <link> element in the header. "
1505 "If not provided, a dummy value will be used as that element is compulsory."
1511 datasetOptions.insert(
1515 "Value put inside the <updated> element in the header. "
1516 "Should be formatted as a XML datetime. "
1517 "If not provided, a dummy value will be used as that element is compulsory."
1523 datasetOptions.insert(
1527 "Value put inside the <author><name> element in the header. "
1528 "If not provided, a dummy value will be used as that element is compulsory."
1534 datasetOptions.insert(
1538 "Value put inside the <id> element in the header. "
1539 "If not provided, a dummy value will be used as that element is compulsory."
1545 driverMetadata.insert( u
"GeoRSS"_s,
QgsVectorFileWriter::MetaData( u
"GeoRSS"_s, QObject::tr(
"GeoRSS" ), u
"*.xml"_s, u
"xml"_s, datasetOptions, layerOptions, u
"UTF-8"_s ) );
1548 datasetOptions.clear();
1549 layerOptions.clear();
1551 datasetOptions.insert(
1555 "If provided, this URI will be inserted as the schema location. "
1556 "Note that the schema file isn't actually accessed by OGR, so it "
1557 "is up to the user to ensure it will match the schema of the OGR "
1558 "produced GML data file."
1564 datasetOptions.insert(
1568 "This writes a GML application schema file to a corresponding "
1569 ".xsd file (with the same basename). If INTERNAL is used the "
1570 "schema is written within the GML file, but this is experimental "
1571 "and almost certainly not valid XML. "
1572 "OFF disables schema generation (and is implicit if XSISCHEMAURI is used)."
1574 QStringList() << u
"EXTERNAL"_s << u
"INTERNAL"_s << u
"OFF"_s,
1579 datasetOptions.insert(
1582 QObject::tr(
"This is the prefix for the application target namespace." ),
1587 datasetOptions.insert(
1591 "Can be set to TRUE to avoid writing the prefix of the "
1592 "application target namespace in the GML file."
1598 datasetOptions.insert(
1599 u
"TARGET_NAMESPACE"_s,
1602 "Defaults to 'http://ogr.maptools.org/'. "
1603 "This is the application target namespace."
1605 u
"http://ogr.maptools.org/"_s
1609 datasetOptions.insert(
1612 QObject::tr(
"GML version to use." ),
1613 QStringList() << u
"GML2"_s << u
"GML3"_s << u
"GML3Deegree"_s << u
"GML3.2"_s,
1618 datasetOptions.insert(
1622 "Only valid when FORMAT=GML3/GML3Degree/GML3.2. Default to YES. "
1623 "If YES, SRS with EPSG authority will be written with the "
1624 "'urn:ogc:def:crs:EPSG::' prefix. In the case the SRS is a "
1625 "geographic SRS without explicit AXIS order, but that the same "
1626 "SRS authority code imported with ImportFromEPSGA() should be "
1627 "treated as lat/long, then the function will take care of coordinate "
1628 "order swapping. If set to NO, SRS with EPSG authority will be "
1629 "written with the 'EPSG:' prefix, even if they are in lat/long order."
1635 datasetOptions.insert(
1636 u
"WRITE_FEATURE_BOUNDED_BY"_s,
1639 "only valid when FORMAT=GML3/GML3Degree/GML3.2) Default to YES. "
1640 "If set to NO, the <gml:boundedBy> element will not be written for "
1647 datasetOptions.insert(
1648 u
"SPACE_INDENTATION"_s,
1651 "Default to YES. If YES, the output will be indented with spaces "
1652 "for more readability, but at the expense of file size."
1660 .insert( u
"GML"_s,
QgsVectorFileWriter::MetaData( u
"Geography Markup Language [GML]"_s, QObject::tr(
"Geography Markup Language [GML]" ), u
"*.gml"_s, u
"gml"_s, datasetOptions, layerOptions, u
"UTF-8"_s ) );
1663 datasetOptions.clear();
1664 layerOptions.clear();
1666 layerOptions.insert(
1669 QObject::tr(
"Human-readable identifier (e.g. short name) for the layer content" ),
1674 layerOptions.insert(
1677 QObject::tr(
"Human-readable description for the layer content" ),
1682 layerOptions.insert(
1685 QObject::tr(
"Name for the feature identifier column" ),
1690 layerOptions.insert(
1693 QObject::tr(
"Name for the geometry column" ),
1698 layerOptions.insert(
1701 QObject::tr(
"If a spatial index must be created." ),
1706 driverMetadata.insert(
1710 QObject::tr(
"GeoPackage" ),
1711#
if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION( 3, 7, 0 )
1712 u
"*.gpkg *.gpkg.zip"_s,
1724 datasetOptions.clear();
1725 layerOptions.clear();
1727 driverMetadata.insert( u
"GMT"_s,
QgsVectorFileWriter::MetaData( u
"Generic Mapping Tools [GMT]"_s, QObject::tr(
"Generic Mapping Tools [GMT]" ), u
"*.gmt"_s, u
"gmt"_s, datasetOptions, layerOptions ) );
1730 datasetOptions.clear();
1731 layerOptions.clear();
1733 layerOptions.insert(
1734 u
"FORCE_GPX_TRACK"_s,
1737 "By default when writing a layer whose features are of "
1738 "type wkbLineString, the GPX driver chooses to write "
1739 "them as routes. If FORCE_GPX_TRACK=YES is specified, "
1740 "they will be written as tracks."
1746 layerOptions.insert(
1747 u
"FORCE_GPX_ROUTE"_s,
1750 "By default when writing a layer whose features are of "
1751 "type wkbMultiLineString, the GPX driver chooses to write "
1752 "them as tracks. If FORCE_GPX_ROUTE=YES is specified, "
1753 "they will be written as routes, provided that the multilines "
1754 "are composed of only one single line."
1760 datasetOptions.insert(
1761 u
"GPX_USE_EXTENSIONS"_s,
1764 "If GPX_USE_EXTENSIONS=YES is specified, "
1765 "extra fields will be written inside the <extensions> tag."
1771 datasetOptions.insert(
1772 u
"GPX_EXTENSIONS_NS"_s,
1775 "Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS_URL "
1776 "is set. The namespace value used for extension tags. By default, 'ogr'."
1782 datasetOptions.insert(
1783 u
"GPX_EXTENSIONS_NS_URL"_s,
1786 "Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS "
1787 "is set. The namespace URI. By default, 'http://osgeo.org/gdal'."
1789 u
"http://osgeo.org/gdal"_s
1793 datasetOptions.insert(
1797 "By default files are created with the line termination "
1798 "conventions of the local platform (CR/LF on win32 or LF "
1799 "on all other systems). This may be overridden through use "
1800 "of the LINEFORMAT layer creation option which may have a value "
1801 "of CRLF (DOS format) or LF (Unix format)."
1803 QStringList() << u
"CRLF"_s << u
"LF"_s,
1809 driverMetadata.insert( u
"GPX"_s,
QgsVectorFileWriter::MetaData( u
"GPS eXchange Format [GPX]"_s, QObject::tr(
"GPS eXchange Format [GPX]" ), u
"*.gpx"_s, u
"gpx"_s, datasetOptions, layerOptions, u
"UTF-8"_s ) );
1812 datasetOptions.clear();
1813 layerOptions.clear();
1815 driverMetadata.insert( u
"Interlis 1"_s,
QgsVectorFileWriter::MetaData( u
"INTERLIS 1"_s, QObject::tr(
"INTERLIS 1" ), u
"*.itf *.xml *.ili"_s, u
"ili"_s, datasetOptions, layerOptions ) );
1818 datasetOptions.clear();
1819 layerOptions.clear();
1821 driverMetadata.insert( u
"Interlis 2"_s,
QgsVectorFileWriter::MetaData( u
"INTERLIS 2"_s, QObject::tr(
"INTERLIS 2" ), u
"*.xtf *.xml *.ili"_s, u
"ili"_s, datasetOptions, layerOptions ) );
1824 datasetOptions.clear();
1825 layerOptions.clear();
1827 datasetOptions.insert(
1830 QObject::tr(
"Allows you to specify the field to use for the KML <name> element." ),
1835 datasetOptions.insert(
1836 u
"DescriptionField"_s,
1838 QObject::tr(
"Allows you to specify the field to use for the KML <description> element." ),
1843 datasetOptions.insert(
1847 "Allows you to specify the AltitudeMode to use for KML geometries. "
1848 "This will only affect 3D geometries and must be one of the valid KML options."
1850 QStringList() << u
"clampToGround"_s << u
"relativeToGround"_s << u
"absolute"_s,
1851 u
"relativeToGround"_s
1855 datasetOptions.insert(
1859 "The DOCUMENT_ID datasource creation option can be used to specified "
1860 "the id of the root <Document> node. The default value is root_doc."
1867 .insert( u
"KML"_s,
QgsVectorFileWriter::MetaData( u
"Keyhole Markup Language [KML]"_s, QObject::tr(
"Keyhole Markup Language [KML]" ), u
"*.kml"_s, u
"kml"_s, datasetOptions, layerOptions, u
"UTF-8"_s ) );
1870 datasetOptions.clear();
1871 layerOptions.clear();
1873 auto insertMapInfoOptions = []( QMap<QString, QgsVectorFileWriter::Option *> &datasetOptions, QMap<QString, QgsVectorFileWriter::Option *> &layerOptions ) {
1874 datasetOptions.insert(
1875 u
"SPATIAL_INDEX_MODE"_s,
1878 "Use this to turn on 'quick spatial index mode'. "
1879 "In this mode writing files can be about 5 times faster, "
1880 "but spatial queries can be up to 30 times slower."
1882 QStringList() << u
"QUICK"_s << u
"OPTIMIZED"_s,
1888 datasetOptions.insert(
1892 "(multiples of 512): Block size for .map files. Defaults "
1893 "to 512. MapInfo 15.2 and above creates .tab files with a "
1894 "blocksize of 16384 bytes. Any MapInfo version should be "
1895 "able to handle block sizes from 512 to 32256."
1900 layerOptions.insert(
1904 "xmin,ymin,xmax,ymax: Define custom layer bounds to increase the "
1905 "accuracy of the coordinates. Note: the geometry of written "
1906 "features must be within the defined box."
1912 insertMapInfoOptions( datasetOptions, layerOptions );
1914 driverMetadata.insert( u
"MapInfo File"_s, QgsVectorFileWriter::MetaData( u
"Mapinfo"_s, QObject::tr(
"Mapinfo TAB" ), u
"*.tab"_s, u
"tab"_s, datasetOptions, layerOptions ) );
1915 datasetOptions.clear();
1916 layerOptions.clear();
1917 insertMapInfoOptions( datasetOptions, layerOptions );
1920 driverMetadata.insert( u
"MapInfo MIF"_s, QgsVectorFileWriter::MetaData( u
"Mapinfo"_s, QObject::tr(
"Mapinfo MIF" ), u
"*.mif"_s, u
"mif"_s, datasetOptions, layerOptions ) );
1923 datasetOptions.clear();
1924 layerOptions.clear();
1926 datasetOptions.insert(
1928 new QgsVectorFileWriter::BoolOption(
1930 "Determine whether 2D (seed_2d.dgn) or 3D (seed_3d.dgn) "
1931 "seed file should be used. This option is ignored if the SEED option is provided."
1937 datasetOptions.insert(
1939 new QgsVectorFileWriter::StringOption(
1940 QObject::tr(
"Override the seed file to use." ),
1945 datasetOptions.insert(
1946 u
"COPY_WHOLE_SEED_FILE"_s,
1947 new QgsVectorFileWriter::BoolOption(
1949 "Indicate whether the whole seed file should be copied. "
1950 "If not, only the first three elements will be copied."
1956 datasetOptions.insert(
1957 u
"COPY_SEED_FILE_COLOR_TABLE"_s,
1958 new QgsVectorFileWriter::BoolOption(
1959 QObject::tr(
"Indicates whether the color table should be copied from the seed file." ),
1964 datasetOptions.insert(
1965 u
"MASTER_UNIT_NAME"_s,
1966 new QgsVectorFileWriter::StringOption(
1968 "Override the master unit name from the seed file with "
1969 "the provided one or two character unit name."
1975 datasetOptions.insert(
1977 new QgsVectorFileWriter::StringOption(
1979 "Override the sub unit name from the seed file with the provided "
1980 "one or two character unit name."
1986 datasetOptions.insert(
1987 u
"SUB_UNITS_PER_MASTER_UNIT"_s,
1988 new QgsVectorFileWriter::IntOption(
1990 "Override the number of subunits per master unit. "
1991 "By default the seed file value is used."
1997 datasetOptions.insert(
1998 u
"UOR_PER_SUB_UNIT"_s,
1999 new QgsVectorFileWriter::IntOption(
2001 "Override the number of UORs (Units of Resolution) "
2002 "per sub unit. By default the seed file value is used."
2008 datasetOptions.insert(
2010 new QgsVectorFileWriter::StringOption(
2012 "ORIGIN=x,y,z: Override the origin of the design plane. "
2013 "By default the origin from the seed file is used."
2019 driverMetadata.insert( u
"DGN"_s, QgsVectorFileWriter::MetaData( u
"Microstation DGN"_s, QObject::tr(
"Microstation DGN" ), u
"*.dgn"_s, u
"dgn"_s, datasetOptions, layerOptions ) );
2022 datasetOptions.clear();
2023 layerOptions.clear();
2025 datasetOptions.insert(
2027 new QgsVectorFileWriter::SetOption(
2028 QObject::tr(
"Should update files be incorporated into the base data on the fly." ),
2029 QStringList() << u
"APPLY"_s << u
"IGNORE"_s,
2034 datasetOptions.insert(
2035 u
"SPLIT_MULTIPOINT"_s,
2036 new QgsVectorFileWriter::BoolOption(
2038 "Should multipoint soundings be split into many single point sounding features. "
2039 "Multipoint geometries are not well handled by many formats, "
2040 "so it can be convenient to split single sounding features with many points "
2041 "into many single point features."
2047 datasetOptions.insert(
2048 u
"ADD_SOUNDG_DEPTH"_s,
2049 new QgsVectorFileWriter::BoolOption(
2051 "Should a DEPTH attribute be added on SOUNDG features and assign the depth "
2052 "of the sounding. This should only be enabled when SPLIT_MULTIPOINT is "
2059 datasetOptions.insert(
2060 u
"RETURN_PRIMITIVES"_s,
2061 new QgsVectorFileWriter::BoolOption(
2063 "Should all the low level geometry primitives be returned as special "
2064 "IsolatedNode, ConnectedNode, Edge and Face layers."
2070 datasetOptions.insert(
2071 u
"PRESERVE_EMPTY_NUMBERS"_s,
2072 new QgsVectorFileWriter::BoolOption(
2074 "If enabled, numeric attributes assigned an empty string as a value will "
2075 "be preserved as a special numeric value. This option should not generally "
2076 "be needed, but may be useful when translated S-57 to S-57 losslessly."
2082 datasetOptions.insert(
2084 new QgsVectorFileWriter::BoolOption(
2086 "Should LNAM and LNAM_REFS fields be attached to features capturing "
2087 "the feature to feature relationships in the FFPT group of the S-57 file."
2093 datasetOptions.insert(
2094 u
"RETURN_LINKAGES"_s,
2095 new QgsVectorFileWriter::BoolOption(
2097 "Should additional attributes relating features to their underlying "
2098 "geometric primitives be attached. These are the values of the FSPT group, "
2099 "and are primarily needed when doing S-57 to S-57 translations."
2105 datasetOptions.insert(
2106 u
"RECODE_BY_DSSI"_s,
2107 new QgsVectorFileWriter::BoolOption(
2109 "Should attribute values be recoded to UTF-8 from the character encoding "
2110 "specified in the S57 DSSI record."
2118 driverMetadata.insert( u
"S57"_s, QgsVectorFileWriter::MetaData( u
"S-57 Base file"_s, QObject::tr(
"S-57 Base file" ), u
"*.000"_s, u
"000"_s, datasetOptions, layerOptions ) );
2121 datasetOptions.clear();
2122 layerOptions.clear();
2125 .insert( u
"SDTS"_s, QgsVectorFileWriter::MetaData( u
"Spatial Data Transfer Standard [SDTS]"_s, QObject::tr(
"Spatial Data Transfer Standard [SDTS]" ), u
"*catd.ddf"_s, u
"ddf"_s, datasetOptions, layerOptions ) );
2128 datasetOptions.clear();
2129 layerOptions.clear();
2131 datasetOptions.insert(
2133 new QgsVectorFileWriter::BoolOption(
2135 "Can be used to avoid creating the geometry_columns and spatial_ref_sys "
2136 "tables in a new database. By default these metadata tables are created "
2137 "when a new database is created."
2144 datasetOptions.insert( u
"SPATIALITE"_s,
new QgsVectorFileWriter::HiddenOption( u
"NO"_s ) );
2147 datasetOptions.insert( u
"INIT_WITH_EPSG"_s,
new QgsVectorFileWriter::HiddenOption( u
"NO"_s ) );
2149 layerOptions.insert(
2151 new QgsVectorFileWriter::SetOption(
2153 "Controls the format used for the geometry column. Defaults to WKB. "
2154 "This is generally more space and processing efficient, but harder "
2155 "to inspect or use in simple applications than WKT (Well Known Text)."
2157 QStringList() << u
"WKB"_s << u
"WKT"_s,
2162 layerOptions.insert(
2164 new QgsVectorFileWriter::BoolOption(
2166 "Controls whether layer and field names will be laundered for easier use "
2167 "in SQLite. Laundered names will be converted to lower case and some special "
2168 "characters(' - #) will be changed to underscores."
2174 layerOptions.insert( u
"SPATIAL_INDEX"_s,
new QgsVectorFileWriter::HiddenOption( u
"NO"_s ) );
2176 layerOptions.insert( u
"COMPRESS_GEOM"_s,
new QgsVectorFileWriter::HiddenOption( u
"NO"_s ) );
2178 layerOptions.insert( u
"SRID"_s,
new QgsVectorFileWriter::HiddenOption( QString() ) );
2180 layerOptions.insert(
2181 u
"COMPRESS_COLUMNS"_s,
2182 new QgsVectorFileWriter::StringOption(
2184 "column_name1[,column_name2, …] A list of (String) columns that "
2185 "must be compressed with ZLib DEFLATE algorithm. This might be beneficial "
2186 "for databases that have big string blobs. However, use with care, since "
2187 "the value of such columns will be seen as compressed binary content with "
2188 "other SQLite utilities (or previous OGR versions). With OGR, when inserting, "
2189 "modifying or querying compressed columns, compression/decompression is "
2190 "done transparently. However, such columns cannot be (easily) queried with "
2191 "an attribute filter or WHERE clause. Note: in table definition, such columns "
2192 "have the 'VARCHAR_deflate' declaration type."
2198 driverMetadata.insert( u
"SQLite"_s, QgsVectorFileWriter::MetaData( u
"SQLite"_s, QObject::tr(
"SQLite" ), u
"*.sqlite"_s, u
"sqlite"_s, datasetOptions, layerOptions, u
"UTF-8"_s ) );
2201 datasetOptions.clear();
2202 layerOptions.clear();
2204 datasetOptions.insert(
2206 new QgsVectorFileWriter::BoolOption(
2208 "Can be used to avoid creating the geometry_columns and spatial_ref_sys "
2209 "tables in a new database. By default these metadata tables are created "
2210 "when a new database is created."
2216 datasetOptions.insert( u
"SPATIALITE"_s,
new QgsVectorFileWriter::HiddenOption( u
"YES"_s ) );
2218 datasetOptions.insert(
2219 u
"INIT_WITH_EPSG"_s,
2220 new QgsVectorFileWriter::BoolOption(
2222 "Insert the content of the EPSG CSV files into the spatial_ref_sys table. "
2223 "Set to NO for regular SQLite databases."
2229 layerOptions.insert( u
"FORMAT"_s,
new QgsVectorFileWriter::HiddenOption( u
"SPATIALITE"_s ) );
2231 layerOptions.insert(
2233 new QgsVectorFileWriter::BoolOption(
2235 "Controls whether layer and field names will be laundered for easier use "
2236 "in SQLite. Laundered names will be converted to lower case and some special "
2237 "characters(' - #) will be changed to underscores."
2243 layerOptions.insert(
2245 new QgsVectorFileWriter::BoolOption(
2247 "If the database is of the SpatiaLite flavor, and if OGR is linked "
2248 "against libspatialite, this option can be used to control if a spatial "
2249 "index must be created."
2255 layerOptions.insert(
2257 new QgsVectorFileWriter::BoolOption(
2259 "If the format of the geometry BLOB is of the SpatiaLite flavor, "
2260 "this option can be used to control if the compressed format for "
2261 "geometries (LINESTRINGs, POLYGONs) must be used."
2267 layerOptions.insert(
2269 new QgsVectorFileWriter::StringOption(
2271 "Used to force the SRID number of the SRS associated with the layer. "
2272 "When this option isn't specified and that a SRS is associated with the "
2273 "layer, a search is made in the spatial_ref_sys to find a match for the "
2274 "SRS, and, if there is no match, a new entry is inserted for the SRS in "
2275 "the spatial_ref_sys table. When the SRID option is specified, this "
2276 "search (and the eventual insertion of a new entry) will not be done: "
2277 "the specified SRID is used as such."
2283 layerOptions.insert(
2284 u
"COMPRESS_COLUMNS"_s,
2285 new QgsVectorFileWriter::StringOption(
2287 "column_name1[,column_name2, …] A list of (String) columns that "
2288 "must be compressed with ZLib DEFLATE algorithm. This might be beneficial "
2289 "for databases that have big string blobs. However, use with care, since "
2290 "the value of such columns will be seen as compressed binary content with "
2291 "other SQLite utilities (or previous OGR versions). With OGR, when inserting, "
2292 "modifying or queryings compressed columns, compression/decompression is "
2293 "done transparently. However, such columns cannot be (easily) queried with "
2294 "an attribute filter or WHERE clause. Note: in table definition, such columns "
2295 "have the 'VARCHAR_deflate' declaration type."
2301 driverMetadata.insert( u
"SpatiaLite"_s, QgsVectorFileWriter::MetaData( u
"SpatiaLite"_s, QObject::tr(
"SpatiaLite" ), u
"*.sqlite"_s, u
"sqlite"_s, datasetOptions, layerOptions, u
"UTF-8"_s ) );
2303 datasetOptions.clear();
2304 layerOptions.clear();
2306 datasetOptions.insert(
2308 new QgsVectorFileWriter::StringOption(
2309 QObject::tr(
"Override the header file used - in place of header.dxf." ),
2314 datasetOptions.insert(
2316 new QgsVectorFileWriter::StringOption(
2317 QObject::tr(
"Override the trailer file used - in place of trailer.dxf." ),
2322#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION( 3, 11, 0 )
2323 datasetOptions.insert(
2325 new QgsVectorFileWriter::SetOption(
2326 QObject::tr(
"Drawing units for the model space ($INSUNITS system variable)." ),
2327 QStringList() << u
"AUTO"_s << u
"HEADER_VALUE"_s << u
"UNITLESS"_s << u
"INCHES"_s << u
"FEET"_s << u
"MILLIMETERS"_s << u
"CENTIMETERS"_s << u
"METERS"_s << u
"US_SURVEY_FEET"_s,
2332 datasetOptions.insert(
2334 new QgsVectorFileWriter::SetOption(
2336 "Whether the current drawing uses imperial or metric hatch "
2337 "pattern and linetype ($MEASUREMENT system variable)."
2339 QStringList() << u
"HEADER_VALUE"_s << u
"IMPERIAL"_s << u
"METRIC"_s,
2345 driverMetadata.insert( u
"DXF"_s, QgsVectorFileWriter::MetaData( u
"AutoCAD DXF"_s, QObject::tr(
"AutoCAD DXF" ), u
"*.dxf"_s, u
"dxf"_s, datasetOptions, layerOptions ) );
2348 datasetOptions.clear();
2349 layerOptions.clear();
2351 datasetOptions.insert(
2353 new QgsVectorFileWriter::SetOption(
2355 "Indicates the GeoConcept export file extension. "
2356 "TXT was used by earlier releases of GeoConcept. GXT is currently used."
2358 QStringList() << u
"GXT"_s << u
"TXT"_s,
2363 datasetOptions.insert(
2365 new QgsVectorFileWriter::StringOption(
2367 "Path to the GCT: the GCT file describes the GeoConcept types definitions: "
2368 "In this file, every line must start with //# followed by a keyword. "
2369 "Lines starting with // are comments."
2375 datasetOptions.insert(
2377 new QgsVectorFileWriter::StringOption(
2379 "Defines the feature to be created. The TYPE corresponds to one of the Name "
2380 "found in the GCT file for a type section. The SUBTYPE corresponds to one of "
2381 "the Name found in the GCT file for a sub-type section within the previous "
2388 driverMetadata.insert( u
"Geoconcept"_s, QgsVectorFileWriter::MetaData( u
"Geoconcept"_s, QObject::tr(
"Geoconcept" ), u
"*.gxt *.txt"_s, u
"gxt"_s, datasetOptions, layerOptions ) );
2391 datasetOptions.clear();
2392 layerOptions.clear();
2394#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION( 3, 9, 0 )
2395 layerOptions.insert(
2396 u
"TARGET_ARCGIS_VERSION"_s,
2397 new QgsVectorFileWriter::SetOption(
2399 "Selects which ArcGIS version this dataset should be compatible with. ALL is used by default and means any ArcGIS 10.x or ArcGIS Pro version. Using ARCGIS_PRO_3_2_OR_LATER is required to "
2400 "export 64-bit integer fields as such, otherwise they will be converted as Real fields. ARCGIS_PRO_3_2_OR_LATER also supports proper Date and Time field types."
2402 QStringList() << u
"ALL"_s << u
"ARCGIS_PRO_3_2_OR_LATER"_s,
2408 layerOptions.insert(
2409 u
"FEATURE_DATASET"_s,
2410 new QgsVectorFileWriter::StringOption(
2412 "When this option is set, the new layer will be created inside the named "
2413 "FeatureDataset folder. If the folder does not already exist, it will be created."
2419 layerOptions.insert(
2421 new QgsVectorFileWriter::StringOption(
2422 QObject::tr(
"Set layer name alias." ),
2427 layerOptions.insert(
2429 new QgsVectorFileWriter::StringOption(
2430 QObject::tr(
"Set name of geometry column in new layer. Defaults to 'SHAPE'." ),
2435 layerOptions.insert(
2436 u
"GEOMETRY_NULLABLE"_s,
2437 new QgsVectorFileWriter::BoolOption(
2438 QObject::tr(
"Whether the values of the geometry column can be NULL. Can be set to NO so that geometry is required. Default to 'YES'." ),
2443 layerOptions.insert(
2445 new QgsVectorFileWriter::StringOption(
2446 QObject::tr(
"Name of the OID column to create. Defaults to 'OBJECTID'." ),
2463 layerOptions.insert(
2465 new QgsVectorFileWriter::StringOption(
2466 QObject::tr(
"A list of strings of format field_name=fgdb_field_type (separated by comma) to force the FileGDB column type of fields to be created." ),
2471 layerOptions.insert(
2473 new QgsVectorFileWriter::StringOption(
2474 QObject::tr(
"XML documentation for the layer." ),
2478 layerOptions.insert(
2479 u
"CONFIGURATION_KEYWORD"_s,
2480 new QgsVectorFileWriter::SetOption(
2481 QObject::tr(
"Customize how data is stored. By default text in UTF-8 and data up to 1TB." ),
2482 { u
"DEFAULTS"_s, u
"MAX_FILE_SIZE_4GB"_s, u
"MAX_FILE_SIZE_256TB"_s },
2488 layerOptions.insert(
2489 u
"CREATE_SHAPE_AREA_AND_LENGTH_FIELDS"_s,
2490 new QgsVectorFileWriter::BoolOption(
2492 " Defaults to NO (through CreateLayer() API). When this option is set, a Shape_Area and Shape_Length special fields will be created for polygonal layers (Shape_Length only for linear "
2493 "layers). These fields will automatically be populated with the feature’s area or length whenever a new feature is added to the dataset or an existing feature is amended. When using "
2494 "ogr2ogr with a source layer that has Shape_Area/Shape_Length special fields, and this option is not explicitly specified, it will be automatically set, so that the resulting "
2495 "FileGeodatabase has those fields properly tagged."
2501 driverMetadata.insert( u
"OpenFileGDB"_s, QgsVectorFileWriter::MetaData( u
"ESRI File Geodatabase"_s, QObject::tr(
"ESRI File Geodatabase" ), u
"*.gdb"_s, u
"gdb"_s, datasetOptions, layerOptions, u
"UTF-8"_s ) );
2503#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION( 3, 11, 0 )
2505 datasetOptions.clear();
2506 layerOptions.clear();
2508 layerOptions.insert(
2509 u
"FEATURE_DATASET"_s,
2510 new QgsVectorFileWriter::StringOption(
2512 "When this option is set, the new layer will be created inside the named "
2513 "FeatureDataset folder. If the folder does not already exist, it will be created."
2519 layerOptions.insert(
2521 new QgsVectorFileWriter::StringOption(
2522 QObject::tr(
"Set name of geometry column in new layer. Defaults to 'SHAPE'." ),
2527 layerOptions.insert(
2529 new QgsVectorFileWriter::StringOption(
2530 QObject::tr(
"Name of the OID column to create. Defaults to 'OBJECTID'." ),
2535 driverMetadata.insert( u
"FileGDB"_s, QgsVectorFileWriter::MetaData( u
"ESRI FileGDB"_s, QObject::tr(
"ESRI FileGDB" ), u
"*.gdb"_s, u
"gdb"_s, datasetOptions, layerOptions, u
"UTF-8"_s ) );
2539 datasetOptions.clear();
2540 layerOptions.clear();
2542 layerOptions.insert(
2543 u
"OGR_XLSX_FIELD_TYPES"_s,
2544 new QgsVectorFileWriter::SetOption(
2546 "By default, the driver will try to detect the data type of fields. If set "
2547 "to STRING, all fields will be of String type."
2549 QStringList() << u
"AUTO"_s << u
"STRING"_s,
2555 layerOptions.insert(
2556 u
"OGR_XLSX_HEADERS"_s,
2557 new QgsVectorFileWriter::SetOption(
2559 "By default, the driver will read the first lines of each sheet to detect "
2560 "if the first line might be the name of columns. If set to FORCE, the driver "
2561 "will consider the first line as the header line. If set to "
2562 "DISABLE, it will be considered as the first feature. Otherwise "
2563 "auto-detection will occur."
2565 QStringList() << u
"FORCE"_s << u
"DISABLE"_s << u
"AUTO"_s,
2572 .insert( u
"XLSX"_s, QgsVectorFileWriter::MetaData( u
"MS Office Open XML spreadsheet"_s, QObject::tr(
"MS Office Open XML spreadsheet [XLSX]" ), u
"*.xlsx"_s, u
"xlsx"_s, datasetOptions, layerOptions, u
"UTF-8"_s ) );
2575 datasetOptions.clear();
2576 layerOptions.clear();
2578 layerOptions.insert(
2579 u
"OGR_ODS_FIELD_TYPES"_s,
2580 new QgsVectorFileWriter::SetOption(
2582 "By default, the driver will try to detect the data type of fields. If set "
2583 "to STRING, all fields will be of String type."
2585 QStringList() << u
"AUTO"_s << u
"STRING"_s,
2591 layerOptions.insert(
2592 u
"OGR_ODS_HEADERS"_s,
2593 new QgsVectorFileWriter::SetOption(
2595 "By default, the driver will read the first lines of each sheet to detect "
2596 "if the first line might be the name of columns. If set to FORCE, the driver "
2597 "will consider the first line as the header line. If set to "
2598 "DISABLE, it will be considered as the first feature. Otherwise "
2599 "auto-detection will occur."
2601 QStringList() << u
"FORCE"_s << u
"DISABLE"_s << u
"AUTO"_s,
2607 driverMetadata.insert( u
"ODS"_s, QgsVectorFileWriter::MetaData( u
"Open Document Spreadsheet"_s, QObject::tr(
"Open Document Spreadsheet [ODS]" ), u
"*.ods"_s, u
"ods"_s, datasetOptions, layerOptions, u
"UTF-8"_s ) );
2610 datasetOptions.clear();
2611 layerOptions.clear();
2613 QStringList compressionMethods;
2614 const QStringList searchCompressions = { u
"NONE"_s, u
"SNAPPY"_s, u
"BROTLI"_s, u
"ZSTD"_s };
2616 if ( GDALDriverH hParquetDrv = GDALGetDriverByName(
"PARQUET" ) )
2618 if (
const char *xml = GDALGetMetadataItem( hParquetDrv, GDAL_DS_LAYER_CREATIONOPTIONLIST,
nullptr ) )
2620 for (
const QString &comp : searchCompressions )
2622 QRegularExpression re(
"<Value[^>]*>\\s*" + comp +
"\\s*</Value>" );
2623 if ( re.match( QString::fromUtf8( xml ) ).hasMatch() )
2625 compressionMethods << comp;
2631 layerOptions.insert(
2633 new QgsVectorFileWriter::SetOption(
2634 QObject::tr(
"Compression method." ),
2641#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION( 3, 12, 0 )
2642 layerOptions.insert(
2643 u
"COMPRESSION_LEVEL"_s,
2644 new QgsVectorFileWriter::IntOption(
2645 QObject::tr(
"Compression level." ),
2651#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION( 3, 9, 0 )
2652 layerOptions.insert(
2654 new QgsVectorFileWriter::BoolOption(
2655 QObject::tr(
"Whether to sort by spatial location. Enables faster spatial filtering on reading." ),
2660 layerOptions.insert(
2661 u
"WRITE_COVERING_BBOX"_s,
2662 new QgsVectorFileWriter::BoolOption(
2663 QObject::tr(
"Whether to write the bounding box of geometries into columns." ),
2669 layerOptions.insert(
2670 u
"GEOMETRY_ENCODING"_s,
2671 new QgsVectorFileWriter::SetOption(
2672 QObject::tr(
"Geometry encoding." ),
2673 QStringList() << u
"WKB"_s << u
"WKT"_s << u
"GEOARROW"_s,
2679 layerOptions.insert(
2680 u
"ROW_GROUP_SIZE"_s,
2681 new QgsVectorFileWriter::IntOption(
2682 QObject::tr(
"Maximum number of rows per group." ),
2687 layerOptions.insert(
2689 new QgsVectorFileWriter::StringOption(
2690 QObject::tr(
"Name for the feature identifier column" ),
2695 layerOptions.insert(
2697 new QgsVectorFileWriter::StringOption(
2698 QObject::tr(
"Name for the geometry column" ),
2703 layerOptions.insert(
2705 new QgsVectorFileWriter::SetOption(
2706 QObject::tr(
"Name of the coordinate system for the edges." ),
2707 QStringList() << u
"PLANAR"_s << u
"SPHERICAL"_s,
2713 driverMetadata.insert( u
"Parquet"_s, QgsVectorFileWriter::MetaData( u
"(Geo)Parquet"_s, QObject::tr(
"(Geo)Parquet" ), u
"*.parquet"_s, u
"parquet"_s, datasetOptions, layerOptions, u
"UTF-8"_s ) );
2716 datasetOptions.clear();
2717 layerOptions.clear();
2719 datasetOptions.insert(
2721 new QgsVectorFileWriter::SetOption(
2722 QObject::tr(
"Line termination character sequence." ),
2723 QStringList() << u
"CRLF"_s << u
"LF"_s,
2730 layerOptions.insert(
2732 new QgsVectorFileWriter::SetOption(
2733 QObject::tr(
"Format of geometry columns." ),
2734 QStringList() << u
"geometry"_s << u
"geography"_s,
2740 layerOptions.insert(
2742 new QgsVectorFileWriter::BoolOption(
2744 "Controls whether layer and field names will be laundered for easier use. "
2745 "Laundered names will be converted to lower case and some special "
2746 "characters(' - #) will be changed to underscores."
2752 layerOptions.insert(
2754 new QgsVectorFileWriter::StringOption(
2756 "Name for the geometry column. Defaults to wkb_geometry "
2757 "for GEOM_TYPE=geometry or the_geog for GEOM_TYPE=geography"
2762 layerOptions.insert( u
"SCHEMA"_s,
new QgsVectorFileWriter::StringOption( QObject::tr(
"Name of schema into which to create the new table" ) ) );
2764 layerOptions.insert(
2766 new QgsVectorFileWriter::BoolOption(
2767 QObject::tr(
"Whether to explicitly emit the CREATE SCHEMA statement to create the specified schema." ),
2772 layerOptions.insert(
2774 new QgsVectorFileWriter::BoolOption(
2775 QObject::tr(
"Whether to explicitly recreate the table if necessary." ),
2780 layerOptions.insert(
2782 new QgsVectorFileWriter::SetOption(
2783 QObject::tr(
"Whether to explicitly destroy tables before recreating them." ),
2784 QStringList() << u
"YES"_s << u
"NO"_s << u
"IF_EXISTS"_s,
2790 layerOptions.insert(
2792 new QgsVectorFileWriter::StringOption(
2794 "Used to force the SRID number of the SRS associated with the layer. "
2795 "When this option isn't specified and that a SRS is associated with the "
2796 "layer, a search is made in the spatial_ref_sys to find a match for the "
2797 "SRS, and, if there is no match, a new entry is inserted for the SRS in "
2798 "the spatial_ref_sys table. When the SRID option is specified, this "
2799 "search (and the eventual insertion of a new entry) will not be done: "
2800 "the specified SRID is used as such."
2806 layerOptions.insert(
2807 u
"POSTGIS_VERSION"_s,
2808 new QgsVectorFileWriter::StringOption(
2810 "Can be set to 2.0 or 2.2 for PostGIS 2.0/2.2 compatibility. "
2811 "Important to set it correctly if using non-linear geometry types"
2817 driverMetadata.insert( u
"PGDUMP"_s, QgsVectorFileWriter::MetaData( u
"PostgreSQL SQL dump"_s, QObject::tr(
"PostgreSQL SQL dump" ), u
"*.sql"_s, u
"sql"_s, datasetOptions, layerOptions, u
"UTF-8"_s ) );
2820 QgsVectorFileWriterMetadataContainer(
const QgsVectorFileWriterMetadataContainer &other ) =
delete;
2821 QgsVectorFileWriterMetadataContainer &operator=(
const QgsVectorFileWriterMetadataContainer &other ) =
delete;
2822 ~QgsVectorFileWriterMetadataContainer()
2824 for (
auto it = driverMetadata.constBegin(); it != driverMetadata.constEnd(); ++it )
2826 for (
auto optionIt = it.value().driverOptions.constBegin(); optionIt != it.value().driverOptions.constEnd(); ++optionIt )
2827 delete optionIt.value();
2828 for (
auto optionIt = it.value().layerOptions.constBegin(); optionIt != it.value().layerOptions.constEnd(); ++optionIt )
2829 delete optionIt.value();
2833 QMap<QString, QgsVectorFileWriter::MetaData> driverMetadata;
2839 static QgsVectorFileWriterMetadataContainer sDriverMetadata;
2840 QMap<QString, MetaData>::ConstIterator it = sDriverMetadata.driverMetadata.constBegin();
2842 for ( ; it != sDriverMetadata.driverMetadata.constEnd(); ++it )
2844 if ( it.key() ==
"PGDUMP"_L1 && driverName !=
"PGDUMP"_L1 && driverName !=
"PostgreSQL SQL dump"_L1 )
2849 if ( it.key().startsWith( driverName ) || it.value().longName.startsWith( driverName ) )
2864 return QStringList();
2873 return QStringList();
2904 return mCapabilities;
2914 QgsFeatureList::iterator fIt = features.begin();
2916 for ( ; fIt != features.end(); ++fIt )
2938 mRenderContext.expressionContext().setFeature( feature );
2941 QString styleString;
2942 QString currentStyle;
2944 QgsSymbolList::const_iterator symbolIt = symbols.constBegin();
2945 for ( ; symbolIt != symbols.constEnd(); ++symbolIt )
2947 int nSymbolLayers = ( *symbolIt )->symbolLayerCount();
2948 for (
int i = 0; i < nSymbolLayers; ++i )
2951 QMap< QgsSymbolLayer *, QString >::const_iterator it =
mSymbolLayerTable.find( ( *symbolIt )->symbolLayer( i ) );
2957 double mmsf = mmScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
2958 double musf = mapUnitScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
2960 currentStyle = ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf );
2966 if ( symbolIt != symbols.constBegin() || i != 0 )
2968 styleString.append(
';' );
2970 styleString.append( currentStyle );
2975 OGR_F_SetStyleString( poFeature.get(), currentStyle.toLocal8Bit().constData() );
2976 if ( !writeFeature(
mLayer, poFeature.get() ) )
2988 OGR_F_SetStyleString( poFeature.get(), styleString.toLocal8Bit().constData() );
2996 if ( !writeFeature(
mLayer, poFeature.get() ) )
3020 int fldIdx = it.key();
3021 int ogrField = it.value();
3023 QVariant attrValue = feature.
attribute( fldIdx );
3028 OGR_F_UnsetField( poFeature.get(), ogrField );
3041 OGR_F_SetFieldNull( poFeature.get(), ogrField );
3062 switch ( field.
type() )
3064 case QMetaType::Type::Int:
3065 OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
3067 case QMetaType::Type::LongLong:
3068 OGR_F_SetFieldInteger64( poFeature.get(), ogrField, attrValue.toLongLong() );
3070 case QMetaType::Type::Bool:
3071 OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
3073 case QMetaType::Type::QString:
3074 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toString() ).constData() );
3076 case QMetaType::Type::Double:
3077 OGR_F_SetFieldDouble( poFeature.get(), ogrField, attrValue.toDouble() );
3079 case QMetaType::Type::QDate:
3080 OGR_F_SetFieldDateTime( poFeature.get(), ogrField, attrValue.toDate().year(), attrValue.toDate().month(), attrValue.toDate().day(), 0, 0, 0, 0 );
3082 case QMetaType::Type::QDateTime:
3085 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toDateTime().toString( u
"yyyy/MM/dd hh:mm:ss.zzz"_s ) ).constData() );
3089 const QDateTime dt = attrValue.toDateTime();
3090 const QDate date = dt.date();
3091 const QTime time = dt.time();
3092 OGR_F_SetFieldDateTimeEx( poFeature.get(), ogrField, date.year(), date.month(), date.day(), time.hour(), time.minute(),
static_cast<float>( time.second() +
static_cast< double >( time.msec() ) / 1000 ),
QgsOgrUtils::OGRTZFlagFromQt( dt ) );
3095 case QMetaType::Type::QTime:
3098 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toString() ).constData() );
3102 const QTime time = attrValue.toTime();
3103 OGR_F_SetFieldDateTimeEx( poFeature.get(), ogrField, 0, 0, 0, time.hour(), time.minute(),
static_cast<float>( time.second() +
static_cast< double >( time.msec() ) / 1000 ), 0 );
3107 case QMetaType::Type::QByteArray:
3109 const QByteArray ba = attrValue.toByteArray();
3110 OGR_F_SetFieldBinary( poFeature.get(), ogrField, ba.size(),
const_cast< GByte *
>(
reinterpret_cast< const GByte *
>( ba.data() ) ) );
3114 case QMetaType::Type::UnknownType:
3117 case QMetaType::Type::QStringList:
3122 const QJsonDocument doc = QJsonDocument::fromVariant( attrValue );
3124 if ( !doc.isNull() )
3126 jsonString = QString::fromUtf8( doc.toJson( QJsonDocument::Compact ).constData() );
3128 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( jsonString.constData() ) );
3132 QStringList list = attrValue.toStringList();
3133 if ( mSupportedListSubTypes.contains( QMetaType::Type::QString ) )
3135 int count = list.count();
3136 char **lst =
new char *[count + 1];
3140 for (
const QString &
string : list )
3142 lst[pos] = CPLStrdup(
mCodec->fromUnicode(
string ).data() );
3146 lst[count] =
nullptr;
3147 OGR_F_SetFieldStringList( poFeature.get(), ogrField, lst );
3152 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( list.join(
',' ) ).constData() );
3157 case QMetaType::Type::QVariantList:
3161 const QJsonDocument doc = QJsonDocument::fromVariant( attrValue );
3163 if ( !doc.isNull() )
3165 jsonString = QString::fromUtf8( doc.toJson( QJsonDocument::Compact ).data() );
3167 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( jsonString.constData() ) );
3172 if ( field.
subType() == QMetaType::Type::QString )
3174 QStringList list = attrValue.toStringList();
3175 if ( mSupportedListSubTypes.contains( QMetaType::Type::QString ) )
3177 int count = list.count();
3178 char **lst =
new char *[count + 1];
3182 for (
const QString &
string : list )
3184 lst[pos] = CPLStrdup(
mCodec->fromUnicode(
string ).data() );
3188 lst[count] =
nullptr;
3189 OGR_F_SetFieldStringList( poFeature.get(), ogrField, lst );
3194 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( list.join(
',' ) ).constData() );
3198 else if ( field.
subType() == QMetaType::Type::Int )
3200 const QVariantList list = attrValue.toList();
3201 if ( mSupportedListSubTypes.contains( QMetaType::Type::Int ) )
3203 const int count = list.count();
3204 int *lst =
new int[count];
3208 for (
const QVariant &value : list )
3210 lst[pos] = value.toInt();
3214 OGR_F_SetFieldIntegerList( poFeature.get(), ogrField, count, lst );
3219 QStringList strings;
3220 strings.reserve( list.size() );
3221 for (
const QVariant &value : list )
3223 strings << QString::number( value.toInt() );
3225 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
3229 else if ( field.
subType() == QMetaType::Type::Double )
3231 const QVariantList list = attrValue.toList();
3232 if ( mSupportedListSubTypes.contains( QMetaType::Type::Double ) )
3234 const int count = list.count();
3235 double *lst =
new double[count];
3239 for (
const QVariant &value : list )
3241 lst[pos] = value.toDouble();
3245 OGR_F_SetFieldDoubleList( poFeature.get(), ogrField, count, lst );
3250 QStringList strings;
3251 strings.reserve( list.size() );
3252 for (
const QVariant &value : list )
3254 strings << QString::number( value.toDouble() );
3256 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
3260 else if ( field.
subType() == QMetaType::Type::LongLong )
3262 const QVariantList list = attrValue.toList();
3263 if ( mSupportedListSubTypes.contains( QMetaType::Type::LongLong ) )
3265 const int count = list.count();
3266 long long *lst =
new long long[count];
3270 for (
const QVariant &value : list )
3272 lst[pos] = value.toLongLong();
3276 OGR_F_SetFieldInteger64List( poFeature.get(), ogrField, count, lst );
3281 QStringList strings;
3282 strings.reserve( list.size() );
3283 for (
const QVariant &value : list )
3285 strings << QString::number( value.toLongLong() );
3287 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
3294 case QMetaType::Type::QVariantMap:
3297 const char *pszDataSubTypes = GDALGetMetadataItem( OGRGetDriverByName(
mOgrDriverName.toLocal8Bit().constData() ), GDAL_DMD_CREATIONFIELDDATASUBTYPES,
nullptr );
3298 if ( pszDataSubTypes && strstr( pszDataSubTypes,
"JSON" ) )
3300 const QJsonDocument doc = QJsonDocument::fromVariant( attrValue );
3302 if ( !doc.isNull() )
3304 const QByteArray json { doc.toJson( QJsonDocument::Compact ) };
3305 jsonString = QString::fromUtf8( json.data() );
3307 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( jsonString.constData() ) );
3317 mErrorMessage = QObject::tr(
"Invalid variant type for field %1[%2]: received %3 with type %4" ).arg(
mFields.at( fldIdx ).name() ).arg( ogrField ).arg( attrValue.typeName(), attrValue.toString() );
3329 QgsGeometry geom = feature.
geometry();
3330 if ( mCoordinateTransform )
3335 geom.
transform( *mCoordinateTransform );
3337 catch ( QgsCsException & )
3371 QVector<QgsGeometry> geoms = geom.
coerceToType( coercedType );
3372 if ( geoms.size() == 1 )
3376 OGRGeometryH ogrGeom =
nullptr;
3409 geom.
get()->
addZValue( std::numeric_limits<double>::quiet_NaN() );
3416 geom.
get()->
addMValue( std::numeric_limits<double>::quiet_NaN() );
3436 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
3459 QByteArray wkb( geom.
asWkb( wkbFlags ) );
3460 if ( wkb.length() > std::numeric_limits<int>::max() )
3462 mErrorMessage = QObject::tr(
"Feature geometry not imported (too large geometry)" );
3465 OGR_G_DestroyGeometry( ogrGeom );
3468 OGRErr err = OGR_G_ImportFromWkb( ogrGeom,
reinterpret_cast<unsigned char *
>(
const_cast<char *
>( wkb.constData() ) ),
static_cast<int>( wkb.length() ) );
3469 if ( err != OGRERR_NONE )
3471 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
3474 OGR_G_DestroyGeometry( ogrGeom );
3479 OGR_F_SetGeometryDirectly( poFeature.get(), ogrGeom );
3493 for (
int i = 0; i < attributes.size(); i++ )
3495 if ( omap.find( i ) != omap.end() )
3500bool QgsVectorFileWriter::writeFeature( OGRLayerH layer, OGRFeatureH feature )
3502 if ( OGR_L_CreateFeature( layer, feature ) != OGRERR_NONE )
3504 mErrorMessage = QObject::tr(
"Feature creation error (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
3514 if ( mUsingTransaction )
3516 if ( OGRERR_NONE != OGR_L_CommitTransaction(
mLayer ) )
3518 QgsDebugError( u
"Error while committing transaction on OGRLayer."_s );
3531 const QString &fileName,
3532 const QString &fileEncoding,
3534 const QString &driverName,
3537 const QStringList &datasourceOptions,
3538 const QStringList &layerOptions,
3539 bool skipAttributeCreation,
3540 QString *newFilename,
3585 const QString &fileName,
3586 const QString &fileEncoding,
3588 const QString &driverName,
3591 const QStringList &datasourceOptions,
3592 const QStringList &layerOptions,
3593 bool skipAttributeCreation,
3594 QString *newFilename,
3636 if ( !layer || !layer->
isValid() )
3643 details.sourceCrs = layer->
crs();
3644 details.sourceWkbType = layer->
wkbType();
3645 details.sourceFields = layer->
fields();
3654 if ( details.storageType ==
"ESRI Shapefile"_L1 )
3662 details.geometryTypeScanIterator = layer->
getFeatures( req );
3669 details.shallTransform =
false;
3674 details.shallTransform =
true;
3679 details.outputCrs = details.sourceCrs;
3682 details.destWkbType = details.sourceWkbType;
3696 details.attributes.clear();
3697 else if ( details.attributes.isEmpty() )
3700 for (
int idx : allAttributes )
3702 QgsField fld = details.sourceFields.
at( idx );
3703 if ( details.providerType ==
"oracle"_L1 && fld.
typeName().contains(
"SDO_GEOMETRY"_L1 ) )
3705 details.attributes.append( idx );
3709 if ( !details.attributes.isEmpty() )
3711 for (
int attrIdx : std::as_const( details.attributes ) )
3713 if ( details.sourceFields.
exists( attrIdx ) )
3715 QgsField field = details.sourceFields.
at( attrIdx );
3717 details.outputFields.
append( field );
3721 QgsDebugError( u
"No such source field with index '%1' available."_s.arg( attrIdx ) );
3728 if ( details.providerType ==
"spatialite"_L1 )
3730 for (
int i = 0; i < details.outputFields.
size(); i++ )
3732 if ( details.outputFields.
at( i ).
type() == QMetaType::Type::LongLong )
3737 if ( std::max( std::llabs( min.toLongLong() ), std::llabs( max.toLongLong() ) ) < std::numeric_limits<int>::max() )
3739 details.outputFields[i].setType( QMetaType::Type::Int );
3747 addRendererAttributes( details.renderer.get(), details.renderContext, details.sourceFields, details.attributes );
3749 QgsFeatureRequest req;
3757 bool useFilterRect =
true;
3758 if ( details.shallTransform )
3763 QgsCoordinateTransform extentTransform = options.
ct;
3767 catch ( QgsCsException & )
3769 useFilterRect =
false;
3772 if ( useFilterRect )
3778 details.filterRectEngine->prepareGeometry();
3780 details.sourceFeatureIterator = layer->
getFeatures( req );
3791 PreparedWriterDetails &details,
const QString &fileName,
const QgsVectorFileWriter::SaveVectorOptions &options, QString *newFilename, QString *
errorMessage, QString *newLayer
3798 PreparedWriterDetails &details,
3799 const QString &fileName,
3800 const QgsCoordinateTransformContext &transformContext,
3801 const QgsVectorFileWriter::SaveVectorOptions &options,
3802 QString *newFilename,
3810 int lastProgressReport = 0;
3811 long long total = details.featureCount;
3814 if ( details.providerType ==
"ogr"_L1 && !details.dataSourceUri.isEmpty() )
3816 QString srcFileName( details.providerUriParams.value( u
"path"_s ).toString() );
3817 if ( QFile::exists( srcFileName ) && QFileInfo( fileName ).canonicalFilePath() == QFileInfo( srcFileName ).canonicalFilePath() )
3820 QgsDataSourceUri uri( details.dataSourceUri );
3822 && options.
layerName != details.providerUriParams.value( u
"layerName"_s ) ) )
3825 *
errorMessage = QObject::tr(
"Cannot overwrite an OGR layer in place" );
3833 QgsFeatureIterator fit = details.geometryTypeScanIterator;
3845 int newProgress =
static_cast<int>( ( 5.0 * scanned ) / total );
3846 if ( newProgress != lastProgressReport )
3848 lastProgressReport = newProgress;
3863 QString tempNewFilename;
3864 QString tempNewLayer;
3866 QgsVectorFileWriter::SaveVectorOptions newOptions = options;
3872 std::unique_ptr< QgsVectorFileWriter > writer(
create( fileName, details.outputFields, destWkbType, details.outputCrs, transformContext, newOptions, sinkFlags, &tempNewFilename, &tempNewLayer ) );
3876 *newFilename = tempNewFilename;
3879 *newLayer = tempNewLayer;
3908 switch ( writer->symbologyExport() )
3912 QgsFeatureRenderer *r = details.renderer.get();
3925 int n = 0, errors = 0;
3934 writer->startRender( details.renderer.get(), details.sourceFields );
3936 writer->resetMap( details.attributes );
3938 writer->mFields = details.sourceFields;
3942 int initialProgress = lastProgressReport;
3943 while ( details.sourceFeatureIterator.nextFeature( fet ) )
3954 int newProgress =
static_cast<int>( initialProgress + ( ( 100.0 - initialProgress ) * saved ) / total );
3955 if ( newProgress < 100 && newProgress != lastProgressReport )
3957 lastProgressReport = newProgress;
3962 if ( details.shallTransform )
3973 catch ( QgsCsException &e )
3975 const QString msg = QObject::tr(
"Failed to transform feature with ID '%1'. Writing stopped. (Exception: %2)" ).arg( fet.
id() ).arg( e.
what() );
3992 if ( !writer->addFeatureWithStyle( fet, writer->mRenderer.get(), mapUnits ) )
3999 *
errorMessage = QObject::tr(
"Feature write errors:" );
4005 if ( errors > 1000 )
4009 *
errorMessage += QObject::tr(
"Stopping after %n error(s)",
nullptr, errors );
4019 writer->stopRender();
4023 *
errorMessage += QObject::tr(
"\nOnly %1 of %2 features written." ).arg( n - errors ).arg( n );
4028 bool metadataFailure =
false;
4044 metadataFailure =
true;
4047 catch ( QgsNotSupportedException &e )
4055 metadataFailure =
true;
4066 QgsVectorFileWriter::PreparedWriterDetails details;
4067 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
4078 QgsVectorFileWriter::PreparedWriterDetails details;
4079 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
4088 const QString &fileName,
4092 QString *newFilename,
4096 QgsVectorFileWriter::PreparedWriterDetails details;
4097 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
4106 QFileInfo fi( fileName );
4107 QDir dir = fi.dir();
4110 for (
const char *suffix : {
".shp",
".shx",
".dbf",
".prj",
".qix",
".qpj",
".cpg",
".sbn",
".sbx",
".idm",
".ind" } )
4112 filter << fi.completeBaseName() + suffix;
4116 const auto constEntryList = dir.entryList( filter );
4117 for (
const QString &file : constEntryList )
4119 QFile f( dir.canonicalPath() +
'/' + file );
4122 QgsDebugError( u
"Removing file %1 failed: %2"_s.arg( file, f.errorString() ) );
4138 QStringList driverNames;
4141 for (
int i = 0; i < GDALGetDriverCount(); ++i )
4143 GDALDriverH
driver = GDALGetDriver( i );
4150 const QString driverExtensions = GDALGetMetadataItem(
driver, GDAL_DMD_EXTENSIONS,
"" );
4151 if ( driverExtensions.isEmpty() )
4154 const QSet< QString > splitExtensions = qgis::listToSet( driverExtensions.split(
' ', Qt::SkipEmptyParts ) );
4155 if ( splitExtensions.intersects( multiLayerExtensions ) )
4157 driverNames << GDALGetDescription(
driver );
4165 static QReadWriteLock sFilterLock;
4166 static QMap< VectorFormatOptions, QList< QgsVectorFileWriter::FilterFormatDetails > > sFilters;
4170 const auto it = sFilters.constFind( options );
4171 if ( it != sFilters.constEnd() )
4175 QList< QgsVectorFileWriter::FilterFormatDetails > results;
4178 int const drvCount = OGRGetDriverCount();
4182 for (
int i = 0; i < drvCount; ++i )
4184 OGRSFDriverH drv = OGRGetDriver( i );
4187 const QString drvName = GDALGetDescription( drv );
4191 if ( !multiLayerDrivers.contains( drvName ) )
4195 GDALDriverH gdalDriver = GDALGetDriverByName( drvName.toLocal8Bit().constData() );
4196 bool nonSpatialFormat =
false;
4199 nonSpatialFormat = GDALGetMetadataItem( gdalDriver, GDAL_DCAP_NONSPATIAL,
nullptr );
4202 if ( OGR_Dr_TestCapability( drv,
"CreateDataSource" ) != 0 )
4207 if ( nonSpatialFormat )
4212 if ( filterString.isEmpty() )
4219 globs = metadata.
glob.toLower().split(
' ' );
4225 details.
globs = globs;
4233 if ( options & SortRecommended )
4235 if ( a.driverName ==
"GPKG"_L1 )
4237 else if ( b.driverName ==
"GPKG"_L1 )
4239 else if ( a.driverName ==
"ESRI Shapefile"_L1 )
4241 else if ( b.driverName ==
"ESRI Shapefile"_L1 )
4248 sFilters.insert( options, results );
4255 QSet< QString > extensions;
4257 const thread_local QRegularExpression rx( u
"\\*\\.(.*)$"_s );
4261 for (
const QString &glob : format.globs )
4263 const QRegularExpressionMatch match = rx.match( glob );
4264 if ( !match.hasMatch() )
4267 const QString matched = match.captured( 1 );
4268 extensions.insert( matched );
4272 QStringList extensionList( extensions.constBegin(), extensions.constEnd() );
4274 std::sort( extensionList.begin(), extensionList.end(), [options](
const QString &a,
const QString &b ) ->
bool {
4275 if ( options & SortRecommended )
4277 if ( a ==
"gpkg"_L1 )
4279 else if ( b ==
"gpkg"_L1 )
4281 else if ( a ==
"shp"_L1 )
4283 else if ( b ==
"shp"_L1 )
4287 return a.toLower().localeAwareCompare( b.toLower() ) < 0;
4290 return extensionList;
4295 QList< QgsVectorFileWriter::DriverDetails > results;
4298 const int drvCount = OGRGetDriverCount();
4302 QStringList writableDrivers;
4303 for (
int i = 0; i < drvCount; ++i )
4305 OGRSFDriverH drv = OGRGetDriver( i );
4308 const QString drvName = GDALGetDescription( drv );
4312 if ( !multiLayerDrivers.contains( drvName ) )
4320 if ( drvName ==
"ODS"_L1 || drvName ==
"XLSX"_L1 || drvName ==
"XLS"_L1 )
4324 if ( drvName ==
"ESRI Shapefile"_L1 )
4326 writableDrivers << u
"DBF file"_s;
4328 if ( OGR_Dr_TestCapability( drv,
"CreateDataSource" ) != 0 )
4331 if ( drvName ==
"MapInfo File"_L1 )
4333 writableDrivers << u
"MapInfo MIF"_s;
4335 else if ( drvName ==
"SQLite"_L1 )
4342 QString option = u
"SPATIALITE=YES"_s;
4343 char *options[2] = { CPLStrdup( option.toLocal8Bit().constData() ),
nullptr };
4344 OGRSFDriverH poDriver;
4346 poDriver = OGRGetDriverByName( drvName.toLocal8Bit().constData() );
4352 writableDrivers << u
"SpatiaLite"_s;
4353 OGR_Dr_DeleteDataSource( poDriver, u
"/vsimem/spatialitetest.sqlite"_s.toUtf8().constData() );
4356 CPLFree( options[0] );
4358 writableDrivers << drvName;
4363 results.reserve( writableDrivers.count() );
4364 for (
const QString &drvName : std::as_const( writableDrivers ) )
4377 if ( options & SortRecommended )
4379 if ( a.driverName ==
"GPKG"_L1 )
4381 else if ( b.driverName ==
"GPKG"_L1 )
4383 else if ( a.driverName ==
"ESRI Shapefile"_L1 )
4385 else if ( b.driverName ==
"ESRI Shapefile"_L1 )
4389 return a.
longName.toLower().localeAwareCompare( b.
longName.toLower() ) < 0;
4396 QString ext = extension.trimmed();
4397 if ( ext.isEmpty() )
4400 if ( ext.startsWith(
'.' ) )
4404 int const drvCount = GDALGetDriverCount();
4406 for (
int i = 0; i < drvCount; ++i )
4408 GDALDriverH drv = GDALGetDriver( i );
4414 QString drvName = GDALGetDriverShortName( drv );
4415 QStringList driverExtensions = QString( GDALGetMetadataItem( drv, GDAL_DMD_EXTENSIONS,
nullptr ) ).split(
' ' );
4417 const auto constDriverExtensions = driverExtensions;
4418 for (
const QString &
driver : constDriverExtensions )
4420 if (
driver.compare( ext, Qt::CaseInsensitive ) == 0 )
4431 QString filterString;
4435 if ( !filterString.isEmpty() )
4436 filterString +=
";;"_L1;
4438 filterString += details.filterString;
4440 return filterString;
4449 return u
"%1 (%2 %3)"_s.arg( metadata.
trLongName, metadata.
glob.toLower(), metadata.
glob.toUpper() );
4454 if ( codecName ==
"System"_L1 )
4457 const thread_local QRegularExpression re( QRegularExpression::anchoredPattern( QString(
"(CP|windows-|ISO[ -])(.+)" ) ), QRegularExpression::CaseInsensitiveOption );
4458 const QRegularExpressionMatch match = re.match( codecName );
4459 if ( match.hasMatch() )
4461 QString
c = match.captured( 2 ).remove(
'-' );
4463 ( void )
c.toInt( &isNumber );
4477 QgsFeatureRenderer *renderer = vl->
renderer();
4491 OGRStyleTableH ogrStyleTable = OGR_STBL_Create();
4492 OGRStyleMgrH styleManager = OGR_SM_Create( ogrStyleTable );
4495 int nTotalLevels = 0;
4497 QgsSymbolList::iterator symbolIt = symbolList.begin();
4498 for ( ; symbolIt != symbolList.end(); ++symbolIt )
4500 double mmsf = mmScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
4501 double musf = mapUnitScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
4503 int nLevels = ( *symbolIt )->symbolLayerCount();
4504 for (
int i = 0; i < nLevels; ++i )
4506 mSymbolLayerTable.insert( ( *symbolIt )->symbolLayer( i ), QString::number( nTotalLevels ) );
4507 OGR_SM_AddStyle( styleManager, QString::number( nTotalLevels ).toLocal8Bit(), ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf ).toLocal8Bit() );
4511 OGR_DS_SetStyleTableDirectly( ds, ogrStyleTable );
4516 if ( !details.renderer )
4519 mRenderContext.expressionContext() = details.expressionContext;
4521 QHash< QgsSymbol *, QList<QgsFeature> > features;
4530 startRender( details.renderer.get(), details.sourceFields );
4534 QgsSymbol *featureSymbol =
nullptr;
4548 catch ( QgsCsException &e )
4550 QString msg = QObject::tr(
"Failed to transform, writing stopped. (Exception: %1)" ).arg( e.
what() );
4558 mRenderContext.expressionContext().setFeature( fet );
4560 featureSymbol = mRenderer->symbolForFeature( fet, mRenderContext );
4561 if ( !featureSymbol )
4566 QHash< QgsSymbol *, QList<QgsFeature> >::iterator it = features.find( featureSymbol );
4567 if ( it == features.end() )
4569 it = features.insert( featureSymbol, QList<QgsFeature>() );
4571 it.value().append( fet );
4576 QgsSymbolList symbols = mRenderer->symbols( mRenderContext );
4577 for (
int i = 0; i < symbols.count(); i++ )
4579 QgsSymbol *sym = symbols[i];
4583 if ( level < 0 || level >= 1000 )
4585 QgsSymbolLevelItem item( sym, j );
4586 while ( level >= levels.count() )
4588 levels[level].append( item );
4593 int nTotalFeatures = 0;
4596 for (
int l = 0; l < levels.count(); l++ )
4599 for (
int i = 0; i < level.count(); i++ )
4601 QgsSymbolLevelItem &item = level[i];
4602 QHash< QgsSymbol *, QList<QgsFeature> >::iterator levelIt = features.find( item.
symbol() );
4603 if ( levelIt == features.end() )
4609 double mmsf = mmScaleFactor(
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
4610 double musf = mapUnitScaleFactor(
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
4612 int llayer = item.
layer();
4613 QList<QgsFeature> &featureList = levelIt.value();
4614 QList<QgsFeature>::iterator featureIt = featureList.begin();
4615 for ( ; featureIt != featureList.end(); ++featureIt )
4625 QString styleString = levelIt.key()->symbolLayer( llayer )->ogrFeatureStyle( mmsf, musf );
4626 if ( !styleString.isEmpty() )
4628 OGR_F_SetStyleString( ogrFeature.get(), styleString.toLocal8Bit().constData() );
4629 if ( !writeFeature(
mLayer, ogrFeature.get() ) )
4642 *
errorMessage += QObject::tr(
"\nOnly %1 of %2 features written." ).arg( nTotalFeatures - nErrors ).arg( nTotalFeatures );
4659 return 1000 / scale;
4675 return scale / 1000;
4681void QgsVectorFileWriter::startRender( QgsFeatureRenderer *sourceRenderer,
const QgsFields &fields )
4683 mRenderer = createSymbologyRenderer( sourceRenderer );
4689 mRenderer->startRender( mRenderContext, fields );
4692void QgsVectorFileWriter::stopRender()
4699 mRenderer->stopRender( mRenderContext );
4702std::unique_ptr<QgsFeatureRenderer> QgsVectorFileWriter::createSymbologyRenderer( QgsFeatureRenderer *sourceRenderer )
const
4715 if ( !sourceRenderer )
4720 return std::unique_ptr< QgsFeatureRenderer >( sourceRenderer->
clone() );
4723void QgsVectorFileWriter::addRendererAttributes( QgsFeatureRenderer *renderer, QgsRenderContext &context,
const QgsFields &fields,
QgsAttributeList &attList )
4727 const QSet<QString> rendererAttributes = renderer->
usedAttributes( context );
4728 for (
const QString &attr : rendererAttributes )
4733 attList.append( index );
4739QStringList QgsVectorFileWriter::concatenateOptions(
const QMap<QString, QgsVectorFileWriter::Option *> &options )
4742 QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
4744 for ( it = options.constBegin(); it != options.constEnd(); ++it )
4746 QgsVectorFileWriter::Option *option = it.value();
4747 switch ( option->
type )
4751 QgsVectorFileWriter::IntOption *opt =
dynamic_cast<QgsVectorFileWriter::IntOption *
>( option );
4754 list.append( u
"%1=%2"_s.arg( it.key() ).arg( opt->
defaultValue ) );
4761 QgsVectorFileWriter::SetOption *opt =
dynamic_cast<QgsVectorFileWriter::SetOption *
>( option );
4764 list.append( u
"%1=%2"_s.arg( it.key(), opt->
defaultValue ) );
4771 QgsVectorFileWriter::StringOption *opt =
dynamic_cast<QgsVectorFileWriter::StringOption *
>( option );
4774 list.append( u
"%1=%2"_s.arg( it.key(), opt->
defaultValue ) );
4780 QgsVectorFileWriter::HiddenOption *opt =
dynamic_cast<QgsVectorFileWriter::HiddenOption *
>( option );
4781 if ( opt && !opt->
mValue.isEmpty() )
4783 list.append( u
"%1=%2"_s.arg( it.key(), opt->
mValue ) );
4794 OGRSFDriverH hDriver =
nullptr;
4798 const QString drvName = GDALGetDescription( hDriver );
4800 if ( OGR_DS_TestCapability( hDS.get(), ODsCCreateLayer ) )
4805 if ( !( drvName ==
"ESRI Shapefile"_L1 && QFile::exists( datasetName ) ) )
4808 if ( OGR_DS_TestCapability( hDS.get(), ODsCDeleteLayer ) )
4812 int layer_count = OGR_DS_GetLayerCount( hDS.get() );
4815 OGRLayerH hLayer = OGR_DS_GetLayer( hDS.get(), 0 );
4818 if ( OGR_L_TestCapability( hLayer, OLCSequentialWrite ) )
4821 if ( OGR_L_TestCapability( hLayer, OLCCreateField ) )
4833 OGRSFDriverH hDriver =
nullptr;
4838 QString layerName( layerNameIn );
4839 if ( layerName.isEmpty() )
4840 layerName = QFileInfo( datasetName ).baseName();
4842 return OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
4848 OGRSFDriverH hDriver =
nullptr;
4852 OGRLayerH hLayer = OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
4858 OGRFeatureDefnH defn = OGR_L_GetLayerDefn( hLayer );
4859 const auto constAttributes = attributes;
4860 for (
int idx : constAttributes )
4863 if ( OGR_FD_GetFieldIndex( defn, fld.
name().toUtf8().constData() ) < 0 )
@ FieldComments
Writer can support field comments.
@ FieldAliases
Writer can support field aliases.
DistanceUnit
Units of distance.
QFlags< VectorFileWriterCapability > VectorFileWriterCapabilities
Capabilities supported by a QgsVectorFileWriter object.
RenderUnit
Rendering size units.
@ Millimeters
Millimeters.
WkbType
The WKB type describes the number of dimensions a geometry has.
@ LineStringM
LineStringM.
@ NurbsCurveM
NurbsCurveM.
@ MultiPolygon25D
MultiPolygon25D.
@ LineStringZM
LineStringZM.
@ MultiLineString
MultiLineString.
@ NurbsCurveZ
NurbsCurveZ.
@ NurbsCurveZM
NurbsCurveZM.
@ MultiPolygonZ
MultiPolygonZ.
@ LineStringZ
LineStringZ.
FeatureSymbologyExport
Options for exporting features considering their symbology.
@ PerFeature
Keeps the number of features and export symbology per feature.
@ PerSymbolLayer
Exports one feature per symbol layer (considering symbol levels).
@ NoSymbology
Export only data.
@ Reverse
Reverse/inverse transform (from destination to source).
Provides common functionality for database based connections.
virtual QgsFieldDomain * fieldDomain(const QString &name) const
Returns the field domain with the specified name from the provider.
virtual bool addZValue(double zValue=0)=0
Adds a z-dimension to the geometry, initialized to a preset value.
virtual bool dropMValue()=0
Drops any measure values which exist in the geometry.
QFlags< WkbFlag > WkbFlags
virtual bool addMValue(double mValue=0)=0
Adds a measure to the geometry, initialized to a preset value.
virtual bool dropZValue()=0
Drops any z-dimensions which exist in the geometry.
@ FlagExportTrianglesAsPolygons
Triangles should be exported as polygon geometries.
@ FlagExportNanAsDoubleMin
Use -DOUBLE_MAX to represent NaN.
static void registerOgrDrivers()
Register OGR drivers ensuring this only happens once.
Represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
static Q_INVOKABLE QgsCoordinateReferenceSystem fromEpsgId(long epsg)
Creates a CRS from a given EPSG ID.
Qgis::DistanceUnit mapUnits
Contains information about the context in which a coordinate transform is executed.
virtual QString dataSourceUri(bool expandAuthConfig=false) const
Gets the data source specification.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
Abstract base class for all 2D vector feature renderers.
virtual QgsSymbolList symbolsForFeature(const QgsFeature &feature, QgsRenderContext &context) const
Returns list of symbols used for rendering the feature.
virtual QgsSymbolList symbols(QgsRenderContext &context) const
Returns list of symbols used by the renderer.
bool usingSymbolLevels() const
virtual QgsFeatureRenderer::Capabilities capabilities()
Returns details about internals of this renderer.
virtual QSet< QString > usedAttributes(const QgsRenderContext &context) const =0
Returns a list of attributes required by this renderer.
@ SymbolLevels
Rendering with symbol levels (i.e. implements symbols(), symbolForFeature()).
virtual QgsFeatureRenderer * clone() const =0
Create a deep copy of this renderer.
Wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Sets the feature IDs that should be fetched.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
QgsFeatureRequest & setFilterRect(const QgsRectangle &rectangle)
Sets the rectangle from which features will be taken.
QFlags< SinkFlag > SinkFlags
@ 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...
void initAttributes(int fieldCount)
Initialize this feature with the given number of fields.
bool hasGeometry() const
Returns true if the feature has an associated geometry.
bool isUnsetValue(int fieldIdx) const
Returns true if the attribute at the specified index is an unset value.
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
bool isCanceled() const
Tells whether the operation has been canceled already.
void setProgress(double progress)
Sets the current progress for the feedback object.
QString domainName() const
Returns the associated field domain name, for providers which support field domains.
@ ConstraintNotNull
Field may not be null.
@ ConstraintUnique
Field must have a unique value.
Encapsulate a field in an attribute table or data source.
QString typeName() const
Gets the field type.
bool convertCompatible(QVariant &v, QString *errorMessage=nullptr) const
Converts the provided variant to a compatible format.
void setName(const QString &name)
Set the field name.
QMetaType::Type subType() const
If the field is a collection, gets its element's type.
QgsFieldConstraints constraints
Container of fields for a vector layer.
bool append(const QgsField &field, Qgis::FieldOrigin origin=Qgis::FieldOrigin::Provider, int originIndex=-1)
Appends a field.
QgsAttributeList allAttributesList() const
Utility function to get list of attribute indexes.
Q_INVOKABLE bool exists(int i) const
Returns if a field index is valid.
int size() const
Returns number of items.
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
Q_INVOKABLE int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
static QStringList multiLayerFileExtensions()
Returns a list of file extensions which potentially contain multiple layers representing GDAL raster ...
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
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.
QgsAbstractGeometry * get()
Returns a modifiable (non-const) reference to the underlying abstract geometry primitive.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
QVector< QgsGeometry > coerceToType(Qgis::WkbType type, double defaultZ=0, double defaultM=0, bool avoidDuplicates=true) const
Attempts to coerce this geometry into the specified destination type.
bool convertToMultiType()
Converts single type geometry into multitype geometry e.g.
QByteArray asWkb(QgsAbstractGeometry::WkbFlags flags=QgsAbstractGeometry::WkbFlags()) const
Export the geometry to WKB.
Qgis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.).
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry, double precision=0.0, Qgis::GeosCreationFlags flags=Qgis::GeosCreationFlag::SkipEmptyInteriorRings)
Creates and returns a new geometry engine representing the specified geometry using precision on a gr...
Sets the current locale to the c locale for the lifetime of the object.
static void warning(const QString &msg)
Goes to qWarning.
static QgsAbstractDatabaseProviderConnection * databaseConnection(const QgsMapLayer *layer)
Creates and returns the (possibly nullptr) database connection for a layer.
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, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE(), Qgis::StringFormat format=Qgis::StringFormat::PlainText)
Adds a message to the log instance (and creates it if necessary).
static OGRSpatialReferenceH crsToOGRSpatialReference(const QgsCoordinateReferenceSystem &crs)
Returns a OGRSpatialReferenceH corresponding to the specified crs object.
static std::unique_ptr< QgsFieldDomain > convertFieldDomain(OGRFieldDomainH domain)
Converts an OGR field domain definition to a QgsFieldDomain equivalent.
static OGRwkbGeometryType qgsWkbTypeToOgrGeometryType(Qgis::WkbType wkbType, bool approx=false)
Converts a QgsWkbTypes::Type to a OGRwkbGeometryType.
static int OGRTZFlagFromQt(const QDateTime &datetime)
Gets the value of OGRField::Date::TZFlag from the timezone of a QDateTime.
QVariantMap decodeUri(const QString &providerKey, const QString &uri)
Breaks a provider data source URI into its component paths (e.g.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
QString encodeUri(const QString &providerKey, const QVariantMap &parts)
Reassembles a provider data source URI from its component paths (e.g.
A convenience class that simplifies locking and unlocking QReadWriteLocks.
void changeMode(Mode mode)
Change the mode of the lock to mode.
A rectangle specified with double values.
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
void setRendererScale(double scale)
Sets the renderer map scale.
static QgsSettingsTreeNode * sTreeQgis
int renderingPass() const
Specifies the rendering pass in which this symbol layer should be rendered.
int layer() const
The layer of this symbol level.
QgsSymbol * symbol() const
The symbol of this symbol level.
QgsSymbolLayer * symbolLayer(int layer)
Returns the symbol layer at the specified index.
int symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
An available option for configuring file writing for a particular output format, presenting an boolea...
Interface to convert raw field values to their user-friendly values.
FieldValueConverter()=default
virtual QVariant convert(int fieldIdxInLayer, const QVariant &value)
Convert the provided value, for field fieldIdxInLayer.
virtual QgsVectorFileWriter::FieldValueConverter * clone() const
Creates a clone of the FieldValueConverter.
virtual QgsField fieldDefinition(const QgsField &field)
Returns a possibly modified field definition.
An available option for configuring file writing for a particular output format, presenting an intege...
QgsVectorFileWriter::OptionType type
Options to pass to QgsVectorFileWriter::writeAsVectorFormat().
QString fileEncoding
Encoding to use.
bool forceMulti
Sets to true to force creation of multipart geometries.
QString driverName
OGR driver to use.
QgsCoordinateTransform ct
Transform to reproject exported geometries with, or invalid transform for no transformation.
QStringList attributesExportNames
Attributes export names.
QgsLayerMetadata layerMetadata
Layer metadata to save for the exported vector file.
QString layerName
Layer name. If let empty, it will be derived from the filename.
QgsRectangle filterExtent
If not empty, only features intersecting the extent will be saved.
bool includeConstraints
Set to true to transfer field constraints to the exported vector file.
const QgsAbstractDatabaseProviderConnection * sourceDatabaseProviderConnection
Source database provider connection, for field domains.
QgsVectorFileWriter::FieldValueConverter * fieldValueConverter
Field value converter.
QStringList layerOptions
List of OGR layer creation options.
Qgis::WkbType overrideGeometryType
Set to a valid geometry type to override the default geometry type for the layer.
bool includeZ
Sets to true to include z dimension in output. This option is only valid if overrideGeometryType is s...
Qgis::FeatureSymbologyExport symbologyExport
Symbology to export.
bool saveMetadata
Set to true to save layer metadata for the exported vector file.
QgsVectorFileWriter::ActionOnExistingFile actionOnExistingFile
Action on existing file.
QgsAttributeList attributes
Attributes to export (empty means all unless skipAttributeCreation is set).
bool onlySelectedFeatures
Write only selected features of layer.
QgsVectorFileWriter::FieldNameSource fieldNameSource
Source for exported field names.
bool skipAttributeCreation
Only write geometries.
bool setFieldDomains
Set to true to transfer field domains to the exported vector file.
double symbologyScale
Scale of symbology.
QStringList datasourceOptions
List of OGR data source creation options.
QgsFeedback * feedback
Optional feedback object allowing cancellation of layer save.
An available option for configuring file writing for a particular output format, presenting a choice ...
An available option for configuring file writing for a particular output format, presenting a freefor...
static QgsVectorFileWriter::WriterError writeAsVectorFormatV3(QgsVectorLayer *layer, const QString &fileName, const QgsCoordinateTransformContext &transformContext, const QgsVectorFileWriter::SaveVectorOptions &options, QString *errorMessage=nullptr, QString *newFilename=nullptr, QString *newLayer=nullptr)
Writes a layer out to a vector file.
Qgis::FeatureSymbologyExport mSymbologyExport
QString lastError() const override
Returns the most recent error encountered by the sink, e.g.
@ CanAddNewFieldsToExistingLayer
Flag to indicate that new fields can be added to an existing layer. Imply CanAppendToExistingLayer.
@ CanAppendToExistingLayer
Flag to indicate that new features can be added to an existing layer.
@ CanAddNewLayer
Flag to indicate that a new layer can be added to the dataset.
@ CanDeleteLayer
Flag to indicate that an existing layer can be deleted.
static QgsVectorFileWriter::EditionCapabilities editionCapabilities(const QString &datasetName)
Returns edition capabilities for an existing dataset name.
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a single feature to the sink.
static bool supportsFeatureStyles(const QString &driverName)
Returns true if the specified driverName supports feature styles.
Qgis::WkbType mWkbType
Geometry type which is being used.
bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a list of features to the sink.
double mSymbologyScale
Scale for symbology export (e.g. for symbols units in map units).
@ ErrAttributeTypeUnsupported
@ Canceled
Writing was interrupted by manual cancellation.
@ ErrAttributeCreationFailed
@ ErrSavingMetadata
Metadata saving failed.
gdal::ogr_datasource_unique_ptr mDS
static Q_DECL_DEPRECATED QgsVectorFileWriter::WriterError writeAsVectorFormatV2(QgsVectorLayer *layer, const QString &fileName, const QgsCoordinateTransformContext &transformContext, const QgsVectorFileWriter::SaveVectorOptions &options, QString *newFilename=nullptr, QString *newLayer=nullptr, QString *errorMessage=nullptr)
Writes a layer out to a vector file.
OGRGeometryH createEmptyGeometry(Qgis::WkbType wkbType)
QString mOgrDriverLongName
QFlags< EditionCapability > EditionCapabilities
Combination of CanAddNewLayer, CanAppendToExistingLayer, CanAddNewFieldsToExistingLayer or CanDeleteL...
~QgsVectorFileWriter() override
Close opened shapefile for writing.
static bool targetLayerExists(const QString &datasetName, const QString &layerName)
Returns whether the target layer already exists.
double symbologyScale() const
Returns the reference scale for output.
static QStringList defaultLayerOptions(const QString &driverName)
Returns a list of the default layer options for a specified driver.
static QString driverForExtension(const QString &extension)
Returns the OGR driver name for a specified file extension.
Qgis::VectorFileWriterCapabilities capabilities() const
Returns the capabilities supported by the writer.
static QList< QgsVectorFileWriter::FilterFormatDetails > supportedFiltersAndFormats(VectorFormatOptions options=SortRecommended)
Returns a list or pairs, with format filter string as first element and OGR format key as second elem...
OGRSpatialReferenceH mOgrRef
static bool driverMetadata(const QString &driverName, MetaData &driverMetadata)
static QgsVectorFileWriter * create(const QString &fileName, const QgsFields &fields, Qgis::WkbType geometryType, const QgsCoordinateReferenceSystem &srs, const QgsCoordinateTransformContext &transformContext, const QgsVectorFileWriter::SaveVectorOptions &options, QgsFeatureSink::SinkFlags sinkFlags=QgsFeatureSink::SinkFlags(), QString *newFilename=nullptr, QString *newLayer=nullptr)
Create a new vector file writer.
static const QgsSettingsEntryString * settingsDefaultEncoding
QString driver() const
Returns the GDAL (short) driver name associated with the output file.
static bool deleteShapeFile(const QString &fileName)
Delete a shapefile (and its accompanying shx / dbf / prj / qix / qpj / cpg / sbn / sbx / idm / ind).
Q_DECL_DEPRECATED QgsVectorFileWriter(const QString &vectorFileName, const QString &fileEncoding, const QgsFields &fields, Qgis::WkbType geometryType, const QgsCoordinateReferenceSystem &srs=QgsCoordinateReferenceSystem(), const QString &driverName="GPKG", const QStringList &datasourceOptions=QStringList(), const QStringList &layerOptions=QStringList(), QString *newFilename=nullptr, Qgis::FeatureSymbologyExport symbologyExport=Qgis::FeatureSymbologyExport::NoSymbology, QgsFeatureSink::SinkFlags sinkFlags=QgsFeatureSink::SinkFlags(), QString *newLayer=nullptr, const QgsCoordinateTransformContext &transformContext=QgsCoordinateTransformContext(), FieldNameSource fieldNameSource=Original)
Create a new vector file writer.
QMap< int, int > mAttrIdxToProviderIdx
Map attribute indices to OGR provider field indexes such as they are after the OGR provider has been ...
static Q_DECL_DEPRECATED QgsVectorFileWriter::WriterError writeAsVectorFormat(QgsVectorLayer *layer, const QString &fileName, const QString &fileEncoding, const QgsCoordinateReferenceSystem &destCRS=QgsCoordinateReferenceSystem(), const QString &driverName="GPKG", bool onlySelected=false, QString *errorMessage=nullptr, const QStringList &datasourceOptions=QStringList(), const QStringList &layerOptions=QStringList(), bool skipAttributeCreation=false, QString *newFilename=nullptr, Qgis::FeatureSymbologyExport symbologyExport=Qgis::FeatureSymbologyExport::NoSymbology, double symbologyScale=1.0, const QgsRectangle *filterExtent=nullptr, Qgis::WkbType overrideGeometryType=Qgis::WkbType::Unknown, bool forceMulti=false, bool includeZ=false, const QgsAttributeList &attributes=QgsAttributeList(), QgsVectorFileWriter::FieldValueConverter *fieldValueConverter=nullptr, QString *newLayer=nullptr)
Write contents of vector layer to an (OGR supported) vector format.
static QString filterForDriver(const QString &driverName)
Creates a filter for an OGR driver key.
QgsVectorFileWriter::WriterError hasError() const
Checks whether there were any errors in constructor.
@ SupportsMultipleLayers
Filter to only formats which support multiple layers.
@ SkipNonSpatialFormats
Filter out any formats which do not have spatial support (e.g. those which cannot save geometries).
static bool areThereNewFieldsToCreate(const QString &datasetName, const QString &layerName, QgsVectorLayer *layer, const QgsAttributeList &attributes)
Returns whether there are among the attributes specified some that do not exist yet in the layer.
static QList< QgsVectorFileWriter::DriverDetails > ogrDriverList(VectorFormatOptions options=SortRecommended)
Returns the driver list that can be used for dialogs.
QString driverLongName() const
Returns the GDAL long driver name associated with the output file.
QFlags< VectorFormatOption > VectorFormatOptions
WriterError mError
Contains error value if construction was not successful.
Qgis::FeatureSymbologyExport symbologyExport() const
Returns the feature symbology export handling for the writer.
FieldNameSource
Source for exported field names.
@ PreferAlias
Use the field alias as the exported field name, wherever one is set. Otherwise use the original field...
@ Original
Use original field names.
bool mIncludeConstraints
Whether to transfer field constraints to output.
static QStringList defaultDatasetOptions(const QString &driverName)
Returns a list of the default dataset options for a specified driver.
bool addFeatureWithStyle(QgsFeature &feature, QgsFeatureRenderer *renderer, Qgis::DistanceUnit outputUnit=Qgis::DistanceUnit::Meters)
Adds a feature to the currently opened data source, using the style from a specified renderer.
static QStringList supportedFormatExtensions(VectorFormatOptions options=SortRecommended)
Returns a list of file extensions for supported formats, e.g "shp", "gpkg".
bool mSetFieldDomains
Whether to set field domains to output.
static QString convertCodecNameForEncodingOption(const QString &codecName)
Converts codec name to string passed to ENCODING layer creation option of OGR Shapefile.
FieldValueConverter * mFieldValueConverter
Field value converter.
QString errorMessage() const
Retrieves error message.
void setSymbologyScale(double scale)
Set reference scale for output.
QMap< int, int > mAttrIdxToOgrLayerIdx
Map attribute indices to OGR layer field indexes such as they are on the current mLayer instance.
static OGRwkbGeometryType ogrTypeFromWkbType(Qgis::WkbType type)
Gets the ogr geometry type from an internal QGIS wkb type enum.
QMap< QgsSymbolLayer *, QString > mSymbolLayerTable
static QString fileFilterString(VectorFormatOptions options=SortRecommended)
Returns filter string that can be used for dialogs.
ActionOnExistingFile
Enumeration to describe how to handle existing files.
@ CreateOrOverwriteLayer
Create or overwrite layer.
@ CreateOrOverwriteFile
Create or overwrite file.
@ AppendToLayerNoNewFields
Append features to existing layer, but do not create new fields.
@ AppendToLayerAddFields
Append features to existing layer, and create new fields if needed.
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.
QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
QgsFeatureRenderer * renderer()
Returns the feature renderer used for rendering the features in the layer in 2D map views.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const final
Queries the layer for features specified in request.
void minimumAndMaximumValue(int index, QVariant &minimum, QVariant &maximum) const
Calculates both the minimum and maximum value for an attribute column.
QgsVectorDataProvider * dataProvider() final
Returns the layer's data provider, it may be nullptr.
static Q_INVOKABLE QString translatedDisplayString(Qgis::WkbType type)
Returns a translated display string type for a WKB type, e.g., the geometry name used in WKT geometry...
static Qgis::WkbType addZ(Qgis::WkbType type)
Adds the z dimension to a WKB type and returns the new type.
static Q_INVOKABLE bool hasZ(Qgis::WkbType type)
Tests whether a WKB type contains the z-dimension.
static Qgis::WkbType singleType(Qgis::WkbType type)
Returns the single type for a WKB type.
static Q_INVOKABLE bool hasM(Qgis::WkbType type)
Tests whether a WKB type contains m values.
static Qgis::WkbType multiType(Qgis::WkbType type)
Returns the multi type for a WKB type.
static Qgis::WkbType flatType(Qgis::WkbType type)
Returns the flat type for a WKB type.
static Q_INVOKABLE bool isMultiType(Qgis::WkbType type)
Returns true if the WKB type is a multi type.
std::unique_ptr< std::remove_pointer< OGRFeatureH >::type, OGRFeatureDeleter > ogr_feature_unique_ptr
Scoped OGR feature.
std::unique_ptr< std::remove_pointer< OGRDataSourceH >::type, OGRDataSourceDeleter > ogr_datasource_unique_ptr
Scoped OGR data source.
std::unique_ptr< std::remove_pointer< OGRFieldDefnH >::type, OGRFldDeleter > ogr_field_def_unique_ptr
Scoped OGR field definition.
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
#define Q_NOWARN_DEPRECATED_POP
#define Q_NOWARN_DEPRECATED_PUSH
QList< QgsFeature > QgsFeatureList
QList< int > QgsAttributeList
#define QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)
QList< QgsSymbolLevel > QgsSymbolLevelOrder
QList< QgsSymbolLevelItem > QgsSymbolLevel
QList< QgsSymbol * > QgsSymbolList
QStringList multiLayerFormats()
Details of available driver formats.
QString longName
Descriptive, user friendly name for the driver.
QString driverName
Unique driver name.