50#include <QRegularExpression>
51#include <QJsonDocument>
57#include <ogr_srs_api.h>
60#include <cpl_string.h>
79 const QString &vectorFileName,
80 const QString &fileEncoding,
84 const QString &driverName,
85 const QStringList &datasourceOptions,
86 const QStringList &layerOptions,
89 QgsFeatureSink::SinkFlags sinkFlags,
99 init( vectorFileName, fileEncoding, fields, geometryType,
100 srs, driverName, datasourceOptions, layerOptions, newFilename,
nullptr,
105 const QString &vectorFileName,
106 const QString &fileEncoding,
110 const QString &driverName,
111 const QStringList &datasourceOptions,
112 const QStringList &layerOptions,
113 QString *newFilename,
116 const QString &layerName,
120 QgsFeatureSink::SinkFlags sinkFlags,
124 , mWkbType( geometryType )
125 , mSymbologyExport( symbologyExport )
126 , mSymbologyScale( 1.0 )
128 init( vectorFileName, fileEncoding, fields, geometryType, srs, driverName,
129 datasourceOptions, layerOptions, newFilename, fieldValueConverter,
130 layerName, action, newLayer, sinkFlags, transformContext, fieldNameSource );
134 const QString &fileName,
140 QgsFeatureSink::SinkFlags sinkFlags,
141 QString *newFilename,
155 if ( driverName == QLatin1String(
"MapInfo MIF" ) )
159 GDALDriverH gdalDriver = GDALGetDriverByName( driverName.toLocal8Bit().constData() );
167 return CSLFetchBoolean(
driverMetadata, GDAL_DCAP_FEATURE_STYLES,
false );
170void QgsVectorFileWriter::init( QString vectorFileName,
171 QString fileEncoding,
175 const QString &driverName,
176 QStringList datasourceOptions,
177 QStringList layerOptions,
178 QString *newFilename,
179 FieldValueConverter *fieldValueConverter,
180 const QString &layerNameIn,
181 ActionOnExistingFile action,
182 QString *newLayer, SinkFlags sinkFlags,
187 if ( vectorFileName.isEmpty() )
194 if ( driverName == QLatin1String(
"MapInfo MIF" ) )
198 else if ( driverName == QLatin1String(
"SpatiaLite" ) )
201 if ( !datasourceOptions.contains( QStringLiteral(
"SPATIALITE=YES" ) ) )
203 datasourceOptions.append( QStringLiteral(
"SPATIALITE=YES" ) );
206 else if ( driverName == QLatin1String(
"DBF file" ) )
209 if ( !layerOptions.contains( QStringLiteral(
"SHPT=NULL" ) ) )
211 layerOptions.append( QStringLiteral(
"SHPT=NULL" ) );
220#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,3,1)
221 QString fidFieldName;
224 for (
const QString &layerOption : layerOptions )
226 if ( layerOption.startsWith( QLatin1String(
"FID=" ) ) )
228 fidFieldName = layerOption.mid( 4 );
232 if ( fidFieldName.isEmpty() )
233 fidFieldName = QStringLiteral(
"fid" );
238 OGRSFDriverH poDriver;
241 poDriver = OGRGetDriverByName(
mOgrDriverName.toLocal8Bit().constData() );
245 mErrorMessage = QObject::tr(
"OGR driver for '%1' not found (OGR error: %2)" )
247 QString::fromUtf8( CPLGetLastErrorMsg() ) );
257 if ( layerOptions.join( QString() ).toUpper().indexOf( QLatin1String(
"ENCODING=" ) ) == -1 )
262 if ( driverName == QLatin1String(
"ESRI Shapefile" ) && !vectorFileName.endsWith( QLatin1String(
".shp" ), Qt::CaseInsensitive ) )
264 vectorFileName += QLatin1String(
".shp" );
266 else if ( driverName == QLatin1String(
"DBF file" ) && !vectorFileName.endsWith( QLatin1String(
".dbf" ), Qt::CaseInsensitive ) )
268 vectorFileName += QLatin1String(
".dbf" );
278#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
279 QStringList allExts = metadata.ext.split(
' ', QString::SkipEmptyParts );
281 QStringList allExts = metadata.ext.split(
' ', Qt::SkipEmptyParts );
284 const auto constAllExts = allExts;
285 for (
const QString &ext : constAllExts )
287 if ( vectorFileName.endsWith(
'.' + ext, Qt::CaseInsensitive ) )
296 vectorFileName +=
'.' + allExts[0];
302 if ( vectorFileName.endsWith( QLatin1String(
".gdb" ), Qt::CaseInsensitive ) )
304 QDir dir( vectorFileName );
307 QFileInfoList fileList = dir.entryInfoList(
308 QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files, QDir::DirsFirst );
309 const auto constFileList = fileList;
310 for (
const QFileInfo &info : constFileList )
312 QFile::remove( info.absoluteFilePath() );
315 QDir().rmdir( vectorFileName );
319 QFile::remove( vectorFileName );
324 if ( metadataFound && !metadata.compulsoryEncoding.isEmpty() )
326 if ( fileEncoding.compare( metadata.compulsoryEncoding, Qt::CaseInsensitive ) != 0 )
328 QgsDebugMsgLevel( QStringLiteral(
"forced %1 encoding for %2" ).arg( metadata.compulsoryEncoding, driverName ), 2 );
329 fileEncoding = metadata.compulsoryEncoding;
334 char **options =
nullptr;
335 if ( !datasourceOptions.isEmpty() )
337 options =
new char *[ datasourceOptions.size() + 1 ];
338 for (
int i = 0; i < datasourceOptions.size(); i++ )
340 QgsDebugMsgLevel( QStringLiteral(
"-dsco=%1" ).arg( datasourceOptions[i] ), 2 );
341 options[i] = CPLStrdup( datasourceOptions[i].toLocal8Bit().constData() );
343 options[ datasourceOptions.size()] =
nullptr;
350 mDS.reset( OGR_Dr_CreateDataSource( poDriver, vectorFileName.toUtf8().constData(), options ) );
352 mDS.reset( OGROpen( vectorFileName.toUtf8().constData(), TRUE,
nullptr ) );
356 for (
int i = 0; i < datasourceOptions.size(); i++ )
357 CPLFree( options[i] );
366 mErrorMessage = QObject::tr(
"Creation of data source failed (OGR error: %1)" )
367 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
369 mErrorMessage = QObject::tr(
"Opening of data source in update mode failed (OGR error: %1)" )
370 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
374 QString layerName( layerNameIn );
375 if ( layerName.isEmpty() )
376 layerName = QFileInfo( vectorFileName ).baseName();
380 const int layer_count = OGR_DS_GetLayerCount(
mDS.get() );
381 for (
int i = 0; i < layer_count; i++ )
383 OGRLayerH hLayer = OGR_DS_GetLayer(
mDS.get(), i );
384 if ( EQUAL( OGR_L_GetName( hLayer ), layerName.toUtf8().constData() ) )
386 if ( OGR_DS_DeleteLayer(
mDS.get(), i ) != OGRERR_NONE )
389 mErrorMessage = QObject::tr(
"Overwriting of existing layer failed (OGR error: %1)" )
390 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
404 QgsDebugMsgLevel( QStringLiteral(
"Opened data source in update mode" ), 2 );
408 mCodec = QTextCodec::codecForName( fileEncoding.toLocal8Bit().constData() );
411 QgsDebugMsg(
"error finding QTextCodec for " + fileEncoding );
414 QString enc = settings.
value( QStringLiteral(
"UI/encoding" ),
"System" ).toString();
415 mCodec = QTextCodec::codecForName( enc.toLocal8Bit().constData() );
418 QgsDebugMsg(
"error finding QTextCodec for " + enc );
419 mCodec = QTextCodec::codecForLocale();
425 if ( driverName == QLatin1String(
"KML" ) || driverName == QLatin1String(
"LIBKML" ) || driverName == QLatin1String(
"GPX" ) )
427 if ( srs.
authid() != QLatin1String(
"EPSG:4326" ) )
442 int optIndex = layerOptions.indexOf( QLatin1String(
"FEATURE_DATASET=" ) );
443 if ( optIndex != -1 )
445 layerOptions.removeAt( optIndex );
448 if ( !layerOptions.isEmpty() )
450 options =
new char *[ layerOptions.size() + 1 ];
451 for (
int i = 0; i < layerOptions.size(); i++ )
454 options[i] = CPLStrdup( layerOptions[i].toLocal8Bit().constData() );
456 options[ layerOptions.size()] =
nullptr;
460 CPLSetConfigOption(
"SHAPE_ENCODING",
"" );
464 mLayer = OGR_DS_CreateLayer(
mDS.get(), layerName.toUtf8().constData(),
mOgrRef, wkbType, options );
467 *newLayer = OGR_L_GetName(
mLayer );
468 if ( driverName == QLatin1String(
"GPX" ) )
475 if ( !EQUAL( layerName.toUtf8().constData(),
"track_points" ) &&
476 !EQUAL( layerName.toUtf8().constData(),
"route_points" ) )
478 *newLayer = QStringLiteral(
"waypoints" );
485 const char *pszForceGPXTrack
486 = CSLFetchNameValue( options,
"FORCE_GPX_TRACK" );
487 if ( pszForceGPXTrack && CPLTestBool( pszForceGPXTrack ) )
488 *newLayer = QStringLiteral(
"tracks" );
490 *newLayer = QStringLiteral(
"routes" );
497 const char *pszForceGPXRoute
498 = CSLFetchNameValue( options,
"FORCE_GPX_ROUTE" );
499 if ( pszForceGPXRoute && CPLTestBool( pszForceGPXRoute ) )
500 *newLayer = QStringLiteral(
"routes" );
502 *newLayer = QStringLiteral(
"tracks" );
512 else if ( driverName == QLatin1String(
"DGN" ) )
514 mLayer = OGR_DS_GetLayerByName(
mDS.get(),
"elements" );
518 mLayer = OGR_DS_GetLayerByName(
mDS.get(), layerName.toUtf8().constData() );
523 for (
int i = 0; i < layerOptions.size(); i++ )
524 CPLFree( options[i] );
533 QString layerName = vectorFileName.left( vectorFileName.indexOf( QLatin1String(
".shp" ), Qt::CaseInsensitive ) );
534 QFile prjFile( layerName +
".qpj" );
535 if ( prjFile.exists() )
543 mErrorMessage = QObject::tr(
"Creation of layer failed (OGR error: %1)" )
544 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
546 mErrorMessage = QObject::tr(
"Opening of layer failed (OGR error: %1)" )
547 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
552 OGRFeatureDefnH defn = OGR_L_GetLayerDefn(
mLayer );
561 QSet<int> existingIdxs;
571 for (
int fldIdx = 0; fldIdx < fields.
count(); ++fldIdx )
575 if ( fieldValueConverter )
577 attrField = fieldValueConverter->fieldDefinition( fields.
at( fldIdx ) );
582 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( attrField.
name() ) );
591 switch ( fieldNameSource )
594 name = attrField.
name();
598 name = !attrField.
alias().isEmpty() ? attrField.
alias() : attrField.
name();
602 OGRFieldType ogrType = OFTString;
603 OGRFieldSubType ogrSubType = OFSTNone;
604 int ogrWidth = attrField.
length();
605 int ogrPrecision = attrField.
precision();
606 if ( ogrPrecision > 0 )
609 switch ( attrField.
type() )
611 case QVariant::LongLong:
613 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
614 if ( pszDataTypes && strstr( pszDataTypes,
"Integer64" ) )
615 ogrType = OFTInteger64;
618 ogrWidth = ogrWidth > 0 && ogrWidth <= 20 ? ogrWidth : 20;
622 case QVariant::String:
624 if ( ( ogrWidth <= 0 || ogrWidth > 255 ) &&
mOgrDriverName == QLatin1String(
"ESRI Shapefile" ) )
629 ogrType = OFTInteger;
630 ogrWidth = ogrWidth > 0 && ogrWidth <= 10 ? ogrWidth : 10;
635 ogrType = OFTInteger;
636 ogrSubType = OFSTBoolean;
641 case QVariant::Double:
642#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,3,1)
643 if (
mOgrDriverName == QLatin1String(
"GPKG" ) && attrField.
precision() == 0 && attrField.
name().compare( fidFieldName, Qt::CaseInsensitive ) == 0 )
646 ogrType = OFTInteger64;
669 case QVariant::DateTime:
677 ogrType = OFTDateTime;
681 case QVariant::ByteArray:
685 case QVariant::StringList:
691 ogrSubType = OFSTJSON;
695 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
696 if ( pszDataTypes && strstr( pszDataTypes,
"StringList" ) )
698 ogrType = OFTStringList;
699 mSupportedListSubTypes.insert( QVariant::String );
712 const char *pszDataSubTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATASUBTYPES,
nullptr );
713 if ( pszDataSubTypes && strstr( pszDataSubTypes,
"JSON" ) )
716 ogrSubType = OFSTJSON;
729 ogrSubType = OFSTJSON;
734 if ( attrField.
subType() == QVariant::String )
736 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
737 if ( pszDataTypes && strstr( pszDataTypes,
"StringList" ) )
739 ogrType = OFTStringList;
740 mSupportedListSubTypes.insert( QVariant::String );
749 else if ( attrField.
subType() == QVariant::Int )
751 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
752 if ( pszDataTypes && strstr( pszDataTypes,
"IntegerList" ) )
754 ogrType = OFTIntegerList;
755 mSupportedListSubTypes.insert( QVariant::Int );
764 else if ( attrField.
subType() == QVariant::Double )
766 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
767 if ( pszDataTypes && strstr( pszDataTypes,
"RealList" ) )
769 ogrType = OFTRealList;
770 mSupportedListSubTypes.insert( QVariant::Double );
779 else if ( attrField.
subType() == QVariant::LongLong )
781 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
782 if ( pszDataTypes && strstr( pszDataTypes,
"Integer64List" ) )
784 ogrType = OFTInteger64List;
785 mSupportedListSubTypes.insert( QVariant::LongLong );
799 mErrorMessage = QObject::tr(
"Unsupported type for field %1" )
800 .arg( attrField.
name() );
805 if (
mOgrDriverName == QLatin1String(
"SQLite" ) && name.compare( QLatin1String(
"ogc_fid" ), Qt::CaseInsensitive ) == 0 )
808 for ( i = 0; i < 10; i++ )
810 name = QStringLiteral(
"ogc_fid%1" ).arg( i );
813 for ( j = 0; j < fields.
size() && name.compare( fields.
at( j ).
name(), Qt::CaseInsensitive ) != 0; j++ )
816 if ( j == fields.
size() )
822 mErrorMessage = QObject::tr(
"No available replacement for internal fieldname ogc_fid found" ).arg( attrField.
name() );
827 QgsMessageLog::logMessage( QObject::tr(
"Reserved attribute name ogc_fid replaced with %1" ).arg( name ), QObject::tr(
"OGR" ) );
834 OGR_Fld_SetWidth( fld.get(), ogrWidth );
837 if ( ogrPrecision >= 0 )
839 OGR_Fld_SetPrecision( fld.get(), ogrPrecision );
842 if ( ogrSubType != OFSTNone )
843 OGR_Fld_SetSubType( fld.get(), ogrSubType );
847 " type " + QString( QVariant::typeToName( attrField.
type() ) ) +
848 " width " + QString::number( ogrWidth ) +
849 " precision " + QString::number( ogrPrecision ), 2 );
850 if ( OGR_L_CreateField(
mLayer, fld.get(),
true ) != OGRERR_NONE )
853 mErrorMessage = QObject::tr(
"Creation of field %1 failed (OGR error: %2)" )
854 .arg( attrField.
name(),
855 QString::fromUtf8( CPLGetLastErrorMsg() ) );
860 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( name ) );
861 QgsDebugMsgLevel( QStringLiteral(
"returned field index for %1: %2" ).arg( name ).arg( ogrIdx ), 2 );
862 if ( ogrIdx < 0 || existingIdxs.contains( ogrIdx ) )
865 ogrIdx = OGR_FD_GetFieldCount( defn ) - 1;
870 mErrorMessage = QObject::tr(
"Created field %1 not found (OGR error: %2)" )
871 .arg( attrField.
name(),
872 QString::fromUtf8( CPLGetLastErrorMsg() ) );
878 existingIdxs.insert( ogrIdx );
886 for (
int fldIdx = 0; fldIdx < fields.
count(); ++fldIdx )
889 QString name( attrField.
name() );
890 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( name ) );
902 int fidIdx = fields.
lookupField( QStringLiteral(
"FID" ) );
913 *newFilename = vectorFileName;
916 mUsingTransaction =
true;
917 if ( OGRERR_NONE != OGR_L_StartTransaction(
mLayer ) )
919 mUsingTransaction =
false;
929class QgsVectorFileWriterMetadataContainer
933 QgsVectorFileWriterMetadataContainer()
935 QMap<QString, QgsVectorFileWriter::Option *> datasetOptions;
936 QMap<QString, QgsVectorFileWriter::Option *> layerOptions;
939 datasetOptions.clear();
940 layerOptions.clear();
943 QObject::tr(
"Compression method." ),
945 << QStringLiteral(
"UNCOMPRESSED" )
946 << QStringLiteral(
"ZSTD" )
947 << QStringLiteral(
"LZ4" ),
948 QStringLiteral(
"LZ4" ),
953 QObject::tr(
"Geometry encoding." ),
955 << QStringLiteral(
"GEOARROW" )
956 << QStringLiteral(
"WKB" )
957 << QStringLiteral(
"WKT" ),
958 QStringLiteral(
"GEOARROW" ),
963 QObject::tr(
"Maximum number of rows per batch." ),
968 QObject::tr(
"Name for the feature identifier column" ),
973 QObject::tr(
"Name for the geometry column" ),
974 QStringLiteral(
"geometry" )
977 driverMetadata.insert( QStringLiteral(
"Arrow" ),
979 QStringLiteral(
"(Geo)Arrow" ),
980 QObject::tr(
"(Geo)Arrow" ),
981 QStringLiteral(
"*.arrow *.feather *.arrows *.ipc" ),
982 QStringLiteral(
"arrow" ),
985 QStringLiteral(
"UTF-8" )
990 datasetOptions.clear();
991 layerOptions.clear();
993 driverMetadata.insert( QStringLiteral(
"AVCE00" ),
995 QStringLiteral(
"Arc/Info ASCII Coverage" ),
996 QObject::tr(
"Arc/Info ASCII Coverage" ),
997 QStringLiteral(
"*.e00" ),
998 QStringLiteral(
"e00" ),
1005#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,3,0)
1009 datasetOptions.clear();
1010 layerOptions.clear();
1013 QObject::tr(
"New BNA files are created by the "
1014 "systems default line termination conventions. "
1015 "This may be overridden here." ),
1017 << QStringLiteral(
"CRLF" )
1018 << QStringLiteral(
"LF" ),
1024 QObject::tr(
"By default, BNA files are created in multi-line format. "
1025 "For each record, the first line contains the identifiers and the "
1026 "type/number of coordinates to follow. Each following line contains "
1027 "a pair of coordinates." ),
1032 QObject::tr(
"BNA records may contain from 2 to 4 identifiers per record. "
1033 "Some software packages only support a precise number of identifiers. "
1034 "You can override the default value (2) by a precise value." ),
1036 << QStringLiteral(
"2" )
1037 << QStringLiteral(
"3" )
1038 << QStringLiteral(
"4" )
1039 << QStringLiteral(
"NB_SOURCE_FIELDS" ),
1040 QStringLiteral(
"2" )
1044 QObject::tr(
"The BNA writer will try to recognize ellipses and circles when writing a polygon. "
1045 "This will only work if the feature has previously been read from a BNA file. "
1046 "As some software packages do not support ellipses/circles in BNA data file, "
1047 "it may be useful to tell the writer by specifying ELLIPSES_AS_ELLIPSES=NO not "
1048 "to export them as such, but keep them as polygons." ),
1053 QObject::tr(
"Limit the number of coordinate pairs per line in multiline format." ),
1058 QObject::tr(
"Set the number of decimal for coordinates. Default value is 10." ),
1062 driverMetadata.insert( QStringLiteral(
"BNA" ),
1064 QStringLiteral(
"Atlas BNA" ),
1065 QObject::tr(
"Atlas BNA" ),
1066 QStringLiteral(
"*.bna" ),
1067 QStringLiteral(
"bna" ),
1075 datasetOptions.clear();
1076 layerOptions.clear();
1079 QObject::tr(
"By default when creating new .csv files they "
1080 "are created with the line termination conventions "
1081 "of the local platform (CR/LF on Win32 or LF on all other systems). "
1082 "This may be overridden through the use of the LINEFORMAT option." ),
1084 << QStringLiteral(
"CRLF" )
1085 << QStringLiteral(
"LF" ),
1091 QObject::tr(
"By default, the geometry of a feature written to a .csv file is discarded. "
1092 "It is possible to export the geometry in its WKT representation by "
1093 "specifying GEOMETRY=AS_WKT. It is also possible to export point geometries "
1094 "into their X,Y,Z components by specifying GEOMETRY=AS_XYZ, GEOMETRY=AS_XY "
1095 "or GEOMETRY=AS_YX." ),
1097 << QStringLiteral(
"AS_WKT" )
1098 << QStringLiteral(
"AS_XYZ" )
1099 << QStringLiteral(
"AS_XY" )
1100 << QStringLiteral(
"AS_YX" ),
1106 QObject::tr(
"Create the associated .csvt file to describe the type of each "
1107 "column of the layer and its optional width and precision." ),
1112 QObject::tr(
"Field separator character." ),
1114 << QStringLiteral(
"COMMA" )
1115 << QStringLiteral(
"SEMICOLON" )
1116 << QStringLiteral(
"TAB" ),
1117 QStringLiteral(
"COMMA" )
1121 QObject::tr(
"Double-quote strings. IF_AMBIGUOUS means that string values that look like numbers will be quoted." ),
1123 << QStringLiteral(
"IF_NEEDED" )
1124 << QStringLiteral(
"IF_AMBIGUOUS" )
1125 << QStringLiteral(
"ALWAYS" ),
1126 QStringLiteral(
"IF_AMBIGUOUS" )
1130 QObject::tr(
"Write a UTF-8 Byte Order Mark (BOM) at the start of the file." ),
1134 driverMetadata.insert( QStringLiteral(
"CSV" ),
1136 QStringLiteral(
"Comma Separated Value [CSV]" ),
1137 QObject::tr(
"Comma Separated Value [CSV]" ),
1138 QStringLiteral(
"*.csv" ),
1139 QStringLiteral(
"csv" ),
1146 datasetOptions.clear();
1147 layerOptions.clear();
1149 driverMetadata.insert( QStringLiteral(
"FlatGeobuf" ),
1151 QStringLiteral(
"FlatGeobuf" ),
1152 QObject::tr(
"FlatGeobuf" ),
1153 QStringLiteral(
"*.fgb" ),
1154 QStringLiteral(
"fgb" ),
1157 QStringLiteral(
"UTF-8" )
1162 datasetOptions.clear();
1163 layerOptions.clear();
1166 QObject::tr(
"Override the type of shapefile created. "
1167 "Can be one of NULL for a simple .dbf file with no .shp file, POINT, "
1168 "ARC, POLYGON or MULTIPOINT for 2D, or POINTZ, ARCZ, POLYGONZ or "
1169 "MULTIPOINTZ for 3D;" ) +
1170 QObject::tr(
" POINTM, ARCM, POLYGONM or MULTIPOINTM for measured geometries"
1171 " and POINTZM, ARCZM, POLYGONZM or MULTIPOINTZM for 3D measured"
1173 QObject::tr(
" MULTIPATCH files are supported since GDAL 2.2." ) +
1176 << QStringLiteral(
"NULL" )
1177 << QStringLiteral(
"POINT" )
1178 << QStringLiteral(
"ARC" )
1179 << QStringLiteral(
"POLYGON" )
1180 << QStringLiteral(
"MULTIPOINT" )
1181 << QStringLiteral(
"POINTZ" )
1182 << QStringLiteral(
"ARCZ" )
1183 << QStringLiteral(
"POLYGONZ" )
1184 << QStringLiteral(
"MULTIPOINTZ" )
1185 << QStringLiteral(
"POINTM" )
1186 << QStringLiteral(
"ARCM" )
1187 << QStringLiteral(
"POLYGONM" )
1188 << QStringLiteral(
"MULTIPOINTM" )
1189 << QStringLiteral(
"POINTZM" )
1190 << QStringLiteral(
"ARCZM" )
1191 << QStringLiteral(
"POLYGONZM" )
1192 << QStringLiteral(
"MULTIPOINTZM" )
1193 << QStringLiteral(
"MULTIPATCH" )
1203 QObject::tr(
"Set the encoding value in the DBF file. "
1204 "The default value is LDID/87. It is not clear "
1205 "what other values may be appropriate." ),
1213 QObject::tr(
"Set to YES to resize fields to their optimal size." ),
1217 driverMetadata.insert( QStringLiteral(
"ESRI" ),
1219 QStringLiteral(
"ESRI Shapefile" ),
1220 QObject::tr(
"ESRI Shapefile" ),
1221 QStringLiteral(
"*.shp" ),
1222 QStringLiteral(
"shp" ),
1229 datasetOptions.clear();
1230 layerOptions.clear();
1232 driverMetadata.insert( QStringLiteral(
"DBF File" ),
1234 QStringLiteral(
"DBF File" ),
1235 QObject::tr(
"DBF File" ),
1236 QStringLiteral(
"*.dbf" ),
1237 QStringLiteral(
"dbf" ),
1244 datasetOptions.clear();
1245 layerOptions.clear();
1247 driverMetadata.insert( QStringLiteral(
"FMEObjects Gateway" ),
1249 QStringLiteral(
"FMEObjects Gateway" ),
1250 QObject::tr(
"FMEObjects Gateway" ),
1251 QStringLiteral(
"*.fdd" ),
1252 QStringLiteral(
"fdd" ),
1259 datasetOptions.clear();
1260 layerOptions.clear();
1263 QObject::tr(
"Set to YES to write a bbox property with the bounding box "
1264 "of the geometries at the feature and feature collection level." ),
1269 QObject::tr(
"Maximum number of figures after decimal separator to write in coordinates. "
1270 "Defaults to 15. Truncation will occur to remove trailing zeros." ),
1275 QObject::tr(
"Whether to use RFC 7946 standard. "
1276 "If disabled GeoJSON 2008 initial version will be used. "
1277 "Default is NO (thus GeoJSON 2008). See also Documentation (via Help button)" ),
1281 driverMetadata.insert( QStringLiteral(
"GeoJSON" ),
1283 QStringLiteral(
"GeoJSON" ),
1284 QObject::tr(
"GeoJSON" ),
1285 QStringLiteral(
"*.geojson" ),
1286 QStringLiteral(
"geojson" ),
1289 QStringLiteral(
"UTF-8" )
1294 datasetOptions.clear();
1295 layerOptions.clear();
1298 QObject::tr(
"Maximum number of figures after decimal separator to write in coordinates. "
1299 "Defaults to 15. Truncation will occur to remove trailing zeros." ),
1304 QObject::tr(
"Whether to start records with the RS=0x1E character (RFC 8142 standard). "
1305 "Defaults to NO: Newline Delimited JSON (geojsonl). \n"
1306 "If set to YES: RFC 8142 standard: GeoJSON Text Sequences (geojsons)." ),
1310 driverMetadata.insert( QStringLiteral(
"GeoJSONSeq" ),
1312 QStringLiteral(
"GeoJSON - Newline Delimited" ),
1313 QObject::tr(
"GeoJSON - Newline Delimited" ),
1314 QStringLiteral(
"*.geojsonl *.geojsons *.json" ),
1315 QStringLiteral(
"json" ),
1318 QStringLiteral(
"UTF-8" )
1323 datasetOptions.clear();
1324 layerOptions.clear();
1327 QObject::tr(
"whether the document must be in RSS 2.0 or Atom 1.0 format. "
1328 "Default value : RSS" ),
1330 << QStringLiteral(
"RSS" )
1331 << QStringLiteral(
"ATOM" ),
1332 QStringLiteral(
"RSS" )
1336 QObject::tr(
"The encoding of location information. Default value : SIMPLE. "
1337 "W3C_GEO only supports point geometries. "
1338 "SIMPLE or W3C_GEO only support geometries in geographic WGS84 coordinates." ),
1340 << QStringLiteral(
"SIMPLE" )
1341 << QStringLiteral(
"GML" )
1342 << QStringLiteral(
"W3C_GEO" ),
1343 QStringLiteral(
"SIMPLE" )
1347 QObject::tr(
"If defined to YES, extension fields will be written. "
1348 "If the field name not found in the base schema matches "
1349 "the foo_bar pattern, foo will be considered as the namespace "
1350 "of the element, and a <foo:bar> element will be written. "
1351 "Otherwise, elements will be written in the <ogr:> namespace." ),
1356 QObject::tr(
"If defined to NO, only <entry> or <item> elements will be written. "
1357 "The user will have to provide the appropriate header and footer of the document." ),
1362 QObject::tr(
"XML content that will be put between the <channel> element and the "
1363 "first <item> element for a RSS document, or between the xml tag and "
1364 "the first <entry> element for an Atom document." ),
1369 QObject::tr(
"Value put inside the <title> element in the header. "
1370 "If not provided, a dummy value will be used as that element is compulsory." ),
1375 QObject::tr(
"Value put inside the <description> element in the header. "
1376 "If not provided, a dummy value will be used as that element is compulsory." ),
1381 QObject::tr(
"Value put inside the <link> element in the header. "
1382 "If not provided, a dummy value will be used as that element is compulsory." ),
1387 QObject::tr(
"Value put inside the <updated> element in the header. "
1388 "Should be formatted as a XML datetime. "
1389 "If not provided, a dummy value will be used as that element is compulsory." ),
1394 QObject::tr(
"Value put inside the <author><name> element in the header. "
1395 "If not provided, a dummy value will be used as that element is compulsory." ),
1400 QObject::tr(
"Value put inside the <id> element in the header. "
1401 "If not provided, a dummy value will be used as that element is compulsory." ),
1405 driverMetadata.insert( QStringLiteral(
"GeoRSS" ),
1407 QStringLiteral(
"GeoRSS" ),
1408 QObject::tr(
"GeoRSS" ),
1409 QStringLiteral(
"*.xml" ),
1410 QStringLiteral(
"xml" ),
1413 QStringLiteral(
"UTF-8" )
1418 datasetOptions.clear();
1419 layerOptions.clear();
1422 QObject::tr(
"If provided, this URI will be inserted as the schema location. "
1423 "Note that the schema file isn't actually accessed by OGR, so it "
1424 "is up to the user to ensure it will match the schema of the OGR "
1425 "produced GML data file." ),
1430 QObject::tr(
"This writes a GML application schema file to a corresponding "
1431 ".xsd file (with the same basename). If INTERNAL is used the "
1432 "schema is written within the GML file, but this is experimental "
1433 "and almost certainly not valid XML. "
1434 "OFF disables schema generation (and is implicit if XSISCHEMAURI is used)." ),
1436 << QStringLiteral(
"EXTERNAL" )
1437 << QStringLiteral(
"INTERNAL" )
1438 << QStringLiteral(
"OFF" ),
1439 QStringLiteral(
"EXTERNAL" )
1443 QObject::tr(
"This is the prefix for the application target namespace." ),
1444 QStringLiteral(
"ogr" )
1448 QObject::tr(
"Can be set to TRUE to avoid writing the prefix of the "
1449 "application target namespace in the GML file." ),
1454 QObject::tr(
"Defaults to 'http://ogr.maptools.org/'. "
1455 "This is the application target namespace." ),
1456 QStringLiteral(
"http://ogr.maptools.org/" )
1460 QObject::tr(
"GML version to use." ),
1462 << QStringLiteral(
"GML2" )
1463 << QStringLiteral(
"GML3" )
1464 << QStringLiteral(
"GML3Deegree" )
1465 << QStringLiteral(
"GML3.2" ),
1466 QStringLiteral(
"GML3.2" )
1470 QObject::tr(
"Only valid when FORMAT=GML3/GML3Degree/GML3.2. Default to YES. "
1471 "If YES, SRS with EPSG authority will be written with the "
1472 "'urn:ogc:def:crs:EPSG::' prefix. In the case the SRS is a "
1473 "geographic SRS without explicit AXIS order, but that the same "
1474 "SRS authority code imported with ImportFromEPSGA() should be "
1475 "treated as lat/long, then the function will take care of coordinate "
1476 "order swapping. If set to NO, SRS with EPSG authority will be "
1477 "written with the 'EPSG:' prefix, even if they are in lat/long order." ),
1482 QObject::tr(
"only valid when FORMAT=GML3/GML3Degree/GML3.2) Default to YES. "
1483 "If set to NO, the <gml:boundedBy> element will not be written for "
1489 QObject::tr(
"Default to YES. If YES, the output will be indented with spaces "
1490 "for more readability, but at the expense of file size." ),
1495 driverMetadata.insert( QStringLiteral(
"GML" ),
1497 QStringLiteral(
"Geography Markup Language [GML]" ),
1498 QObject::tr(
"Geography Markup Language [GML]" ),
1499 QStringLiteral(
"*.gml" ),
1500 QStringLiteral(
"gml" ),
1503 QStringLiteral(
"UTF-8" )
1508 datasetOptions.clear();
1509 layerOptions.clear();
1512 QObject::tr(
"Human-readable identifier (e.g. short name) for the layer content" ),
1517 QObject::tr(
"Human-readable description for the layer content" ),
1522 QObject::tr(
"Name for the feature identifier column" ),
1523 QStringLiteral(
"fid" )
1527 QObject::tr(
"Name for the geometry column" ),
1528 QStringLiteral(
"geom" )
1532 QObject::tr(
"If a spatial index must be created." ),
1536 driverMetadata.insert( QStringLiteral(
"GPKG" ),
1538 QStringLiteral(
"GeoPackage" ),
1539 QObject::tr(
"GeoPackage" ),
1540 QStringLiteral(
"*.gpkg" ),
1541 QStringLiteral(
"gpkg" ),
1544 QStringLiteral(
"UTF-8" )
1549 datasetOptions.clear();
1550 layerOptions.clear();
1552 driverMetadata.insert( QStringLiteral(
"GMT" ),
1554 QStringLiteral(
"Generic Mapping Tools [GMT]" ),
1555 QObject::tr(
"Generic Mapping Tools [GMT]" ),
1556 QStringLiteral(
"*.gmt" ),
1557 QStringLiteral(
"gmt" ),
1564 datasetOptions.clear();
1565 layerOptions.clear();
1568 QObject::tr(
"By default when writing a layer whose features are of "
1569 "type wkbLineString, the GPX driver chooses to write "
1570 "them as routes. If FORCE_GPX_TRACK=YES is specified, "
1571 "they will be written as tracks." ),
1576 QObject::tr(
"By default when writing a layer whose features are of "
1577 "type wkbMultiLineString, the GPX driver chooses to write "
1578 "them as tracks. If FORCE_GPX_ROUTE=YES is specified, "
1579 "they will be written as routes, provided that the multilines "
1580 "are composed of only one single line." ),
1585 QObject::tr(
"If GPX_USE_EXTENSIONS=YES is specified, "
1586 "extra fields will be written inside the <extensions> tag." ),
1591 QObject::tr(
"Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS_URL "
1592 "is set. The namespace value used for extension tags. By default, 'ogr'." ),
1593 QStringLiteral(
"ogr" )
1597 QObject::tr(
"Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS "
1598 "is set. The namespace URI. By default, 'http://osgeo.org/gdal'." ),
1599 QStringLiteral(
"http://osgeo.org/gdal" )
1603 QObject::tr(
"By default files are created with the line termination "
1604 "conventions of the local platform (CR/LF on win32 or LF "
1605 "on all other systems). This may be overridden through use "
1606 "of the LINEFORMAT layer creation option which may have a value "
1607 "of CRLF (DOS format) or LF (Unix format)." ),
1609 << QStringLiteral(
"CRLF" )
1610 << QStringLiteral(
"LF" ),
1615 driverMetadata.insert( QStringLiteral(
"GPX" ),
1617 QStringLiteral(
"GPS eXchange Format [GPX]" ),
1618 QObject::tr(
"GPS eXchange Format [GPX]" ),
1619 QStringLiteral(
"*.gpx" ),
1620 QStringLiteral(
"gpx" ),
1623 QStringLiteral(
"UTF-8" )
1628 datasetOptions.clear();
1629 layerOptions.clear();
1631 driverMetadata.insert( QStringLiteral(
"Interlis 1" ),
1633 QStringLiteral(
"INTERLIS 1" ),
1634 QObject::tr(
"INTERLIS 1" ),
1635 QStringLiteral(
"*.itf *.xml *.ili" ),
1636 QStringLiteral(
"ili" ),
1643 datasetOptions.clear();
1644 layerOptions.clear();
1646 driverMetadata.insert( QStringLiteral(
"Interlis 2" ),
1648 QStringLiteral(
"INTERLIS 2" ),
1649 QObject::tr(
"INTERLIS 2" ),
1650 QStringLiteral(
"*.xtf *.xml *.ili" ),
1651 QStringLiteral(
"ili" ),
1658 datasetOptions.clear();
1659 layerOptions.clear();
1662 QObject::tr(
"Allows you to specify the field to use for the KML <name> element." ),
1663 QStringLiteral(
"Name" )
1667 QObject::tr(
"Allows you to specify the field to use for the KML <description> element." ),
1668 QStringLiteral(
"Description" )
1672 QObject::tr(
"Allows you to specify the AltitudeMode to use for KML geometries. "
1673 "This will only affect 3D geometries and must be one of the valid KML options." ),
1675 << QStringLiteral(
"clampToGround" )
1676 << QStringLiteral(
"relativeToGround" )
1677 << QStringLiteral(
"absolute" ),
1678 QStringLiteral(
"relativeToGround" )
1682 QObject::tr(
"The DOCUMENT_ID datasource creation option can be used to specified "
1683 "the id of the root <Document> node. The default value is root_doc." ),
1684 QStringLiteral(
"root_doc" )
1687 driverMetadata.insert( QStringLiteral(
"KML" ),
1689 QStringLiteral(
"Keyhole Markup Language [KML]" ),
1690 QObject::tr(
"Keyhole Markup Language [KML]" ),
1691 QStringLiteral(
"*.kml" ),
1692 QStringLiteral(
"kml" ),
1695 QStringLiteral(
"UTF-8" )
1700 datasetOptions.clear();
1701 layerOptions.clear();
1703 auto insertMapInfoOptions = []( QMap<QString, QgsVectorFileWriter::Option *> &datasetOptions, QMap<QString, QgsVectorFileWriter::Option *> &layerOptions )
1706 QObject::tr(
"Use this to turn on 'quick spatial index mode'. "
1707 "In this mode writing files can be about 5 times faster, "
1708 "but spatial queries can be up to 30 times slower." ),
1710 << QStringLiteral(
"QUICK" )
1711 << QStringLiteral(
"OPTIMIZED" ),
1712 QStringLiteral(
"QUICK" ),
1717 QObject::tr(
"(multiples of 512): Block size for .map files. Defaults "
1718 "to 512. MapInfo 15.2 and above creates .tab files with a "
1719 "blocksize of 16384 bytes. Any MapInfo version should be "
1720 "able to handle block sizes from 512 to 32256." ),
1724 QObject::tr(
"xmin,ymin,xmax,ymax: Define custom layer bounds to increase the "
1725 "accuracy of the coordinates. Note: the geometry of written "
1726 "features must be within the defined box." ),
1730 insertMapInfoOptions( datasetOptions, layerOptions );
1732 driverMetadata.insert( QStringLiteral(
"MapInfo File" ),
1734 QStringLiteral(
"Mapinfo" ),
1735 QObject::tr(
"Mapinfo TAB" ),
1736 QStringLiteral(
"*.tab" ),
1737 QStringLiteral(
"tab" ),
1742 datasetOptions.clear();
1743 layerOptions.clear();
1744 insertMapInfoOptions( datasetOptions, layerOptions );
1747 driverMetadata.insert( QStringLiteral(
"MapInfo MIF" ),
1749 QStringLiteral(
"Mapinfo" ),
1750 QObject::tr(
"Mapinfo MIF" ),
1751 QStringLiteral(
"*.mif" ),
1752 QStringLiteral(
"mif" ),
1759 datasetOptions.clear();
1760 layerOptions.clear();
1763 QObject::tr(
"Determine whether 2D (seed_2d.dgn) or 3D (seed_3d.dgn) "
1764 "seed file should be used. This option is ignored if the SEED option is provided." ),
1769 QObject::tr(
"Override the seed file to use." ),
1774 QObject::tr(
"Indicate whether the whole seed file should be copied. "
1775 "If not, only the first three elements will be copied." ),
1780 QObject::tr(
"Indicates whether the color table should be copied from the seed file." ),
1785 QObject::tr(
"Override the master unit name from the seed file with "
1786 "the provided one or two character unit name." ),
1791 QObject::tr(
"Override the sub unit name from the seed file with the provided "
1792 "one or two character unit name." ),
1797 QObject::tr(
"Override the number of subunits per master unit. "
1798 "By default the seed file value is used." ),
1803 QObject::tr(
"Override the number of UORs (Units of Resolution) "
1804 "per sub unit. By default the seed file value is used." ),
1809 QObject::tr(
"ORIGIN=x,y,z: Override the origin of the design plane. "
1810 "By default the origin from the seed file is used." ),
1814 driverMetadata.insert( QStringLiteral(
"DGN" ),
1816 QStringLiteral(
"Microstation DGN" ),
1817 QObject::tr(
"Microstation DGN" ),
1818 QStringLiteral(
"*.dgn" ),
1819 QStringLiteral(
"dgn" ),
1826 datasetOptions.clear();
1827 layerOptions.clear();
1830 QObject::tr(
"Should update files be incorporated into the base data on the fly." ),
1832 << QStringLiteral(
"APPLY" )
1833 << QStringLiteral(
"IGNORE" ),
1834 QStringLiteral(
"APPLY" )
1838 QObject::tr(
"Should multipoint soundings be split into many single point sounding features. "
1839 "Multipoint geometries are not well handled by many formats, "
1840 "so it can be convenient to split single sounding features with many points "
1841 "into many single point features." ),
1846 QObject::tr(
"Should a DEPTH attribute be added on SOUNDG features and assign the depth "
1847 "of the sounding. This should only be enabled when SPLIT_MULTIPOINT is "
1853 QObject::tr(
"Should all the low level geometry primitives be returned as special "
1854 "IsolatedNode, ConnectedNode, Edge and Face layers." ),
1859 QObject::tr(
"If enabled, numeric attributes assigned an empty string as a value will "
1860 "be preserved as a special numeric value. This option should not generally "
1861 "be needed, but may be useful when translated S-57 to S-57 losslessly." ),
1866 QObject::tr(
"Should LNAM and LNAM_REFS fields be attached to features capturing "
1867 "the feature to feature relationships in the FFPT group of the S-57 file." ),
1872 QObject::tr(
"Should additional attributes relating features to their underlying "
1873 "geometric primitives be attached. These are the values of the FSPT group, "
1874 "and are primarily needed when doing S-57 to S-57 translations." ),
1879 QObject::tr(
"Should attribute values be recoded to UTF-8 from the character encoding "
1880 "specified in the S57 DSSI record." ),
1886 driverMetadata.insert( QStringLiteral(
"S57" ),
1888 QStringLiteral(
"S-57 Base file" ),
1889 QObject::tr(
"S-57 Base file" ),
1890 QStringLiteral(
"*.000" ),
1891 QStringLiteral(
"000" ),
1898 datasetOptions.clear();
1899 layerOptions.clear();
1901 driverMetadata.insert( QStringLiteral(
"SDTS" ),
1903 QStringLiteral(
"Spatial Data Transfer Standard [SDTS]" ),
1904 QObject::tr(
"Spatial Data Transfer Standard [SDTS]" ),
1905 QStringLiteral(
"*catd.ddf" ),
1906 QStringLiteral(
"ddf" ),
1913 datasetOptions.clear();
1914 layerOptions.clear();
1917 QObject::tr(
"Can be used to avoid creating the geometry_columns and spatial_ref_sys "
1918 "tables in a new database. By default these metadata tables are created "
1919 "when a new database is created." ),
1925 QStringLiteral(
"NO" )
1930 QStringLiteral(
"NO" )
1934 QObject::tr(
"Controls the format used for the geometry column. Defaults to WKB. "
1935 "This is generally more space and processing efficient, but harder "
1936 "to inspect or use in simple applications than WKT (Well Known Text)." ),
1938 << QStringLiteral(
"WKB" )
1939 << QStringLiteral(
"WKT" ),
1940 QStringLiteral(
"WKB" )
1944 QObject::tr(
"Controls whether layer and field names will be laundered for easier use "
1945 "in SQLite. Laundered names will be converted to lower case and some special "
1946 "characters(' - #) will be changed to underscores." ),
1951 QStringLiteral(
"NO" )
1955 QStringLiteral(
"NO" )
1963 QObject::tr(
"column_name1[,column_name2, …] A list of (String) columns that "
1964 "must be compressed with ZLib DEFLATE algorithm. This might be beneficial "
1965 "for databases that have big string blobs. However, use with care, since "
1966 "the value of such columns will be seen as compressed binary content with "
1967 "other SQLite utilities (or previous OGR versions). With OGR, when inserting, "
1968 "modifying or querying compressed columns, compression/decompression is "
1969 "done transparently. However, such columns cannot be (easily) queried with "
1970 "an attribute filter or WHERE clause. Note: in table definition, such columns "
1971 "have the 'VARCHAR_deflate' declaration type." ),
1975 driverMetadata.insert( QStringLiteral(
"SQLite" ),
1977 QStringLiteral(
"SQLite" ),
1978 QObject::tr(
"SQLite" ),
1979 QStringLiteral(
"*.sqlite" ),
1980 QStringLiteral(
"sqlite" ),
1983 QStringLiteral(
"UTF-8" )
1988 datasetOptions.clear();
1989 layerOptions.clear();
1992 QObject::tr(
"Can be used to avoid creating the geometry_columns and spatial_ref_sys "
1993 "tables in a new database. By default these metadata tables are created "
1994 "when a new database is created." ),
1999 QStringLiteral(
"YES" )
2003 QObject::tr(
"Insert the content of the EPSG CSV files into the spatial_ref_sys table. "
2004 "Set to NO for regular SQLite databases." ),
2009 QStringLiteral(
"SPATIALITE" )
2013 QObject::tr(
"Controls whether layer and field names will be laundered for easier use "
2014 "in SQLite. Laundered names will be converted to lower case and some special "
2015 "characters(' - #) will be changed to underscores." ),
2020 QObject::tr(
"If the database is of the SpatiaLite flavor, and if OGR is linked "
2021 "against libspatialite, this option can be used to control if a spatial "
2022 "index must be created." ),
2027 QObject::tr(
"If the format of the geometry BLOB is of the SpatiaLite flavor, "
2028 "this option can be used to control if the compressed format for "
2029 "geometries (LINESTRINGs, POLYGONs) must be used." ),
2034 QObject::tr(
"Used to force the SRID number of the SRS associated with the layer. "
2035 "When this option isn't specified and that a SRS is associated with the "
2036 "layer, a search is made in the spatial_ref_sys to find a match for the "
2037 "SRS, and, if there is no match, a new entry is inserted for the SRS in "
2038 "the spatial_ref_sys table. When the SRID option is specified, this "
2039 "search (and the eventual insertion of a new entry) will not be done: "
2040 "the specified SRID is used as such." ),
2045 QObject::tr(
"column_name1[,column_name2, …] A list of (String) columns that "
2046 "must be compressed with ZLib DEFLATE algorithm. This might be beneficial "
2047 "for databases that have big string blobs. However, use with care, since "
2048 "the value of such columns will be seen as compressed binary content with "
2049 "other SQLite utilities (or previous OGR versions). With OGR, when inserting, "
2050 "modifying or queryings compressed columns, compression/decompression is "
2051 "done transparently. However, such columns cannot be (easily) queried with "
2052 "an attribute filter or WHERE clause. Note: in table definition, such columns "
2053 "have the 'VARCHAR_deflate' declaration type." ),
2057 driverMetadata.insert( QStringLiteral(
"SpatiaLite" ),
2059 QStringLiteral(
"SpatiaLite" ),
2060 QObject::tr(
"SpatiaLite" ),
2061 QStringLiteral(
"*.sqlite" ),
2062 QStringLiteral(
"sqlite" ),
2065 QStringLiteral(
"UTF-8" )
2069 datasetOptions.clear();
2070 layerOptions.clear();
2073 QObject::tr(
"Override the header file used - in place of header.dxf." ),
2078 QObject::tr(
"Override the trailer file used - in place of trailer.dxf." ),
2082 driverMetadata.insert( QStringLiteral(
"DXF" ),
2084 QStringLiteral(
"AutoCAD DXF" ),
2085 QObject::tr(
"AutoCAD DXF" ),
2086 QStringLiteral(
"*.dxf" ),
2087 QStringLiteral(
"dxf" ),
2094 datasetOptions.clear();
2095 layerOptions.clear();
2098 QObject::tr(
"Indicates the GeoConcept export file extension. "
2099 "TXT was used by earlier releases of GeoConcept. GXT is currently used." ),
2101 << QStringLiteral(
"GXT" )
2102 << QStringLiteral(
"TXT" ),
2103 QStringLiteral(
"GXT" )
2107 QObject::tr(
"Path to the GCT: the GCT file describes the GeoConcept types definitions: "
2108 "In this file, every line must start with //# followed by a keyword. "
2109 "Lines starting with // are comments." ),
2114 QObject::tr(
"Defines the feature to be created. The TYPE corresponds to one of the Name "
2115 "found in the GCT file for a type section. The SUBTYPE corresponds to one of "
2116 "the Name found in the GCT file for a sub-type section within the previous "
2121 driverMetadata.insert( QStringLiteral(
"Geoconcept" ),
2123 QStringLiteral(
"Geoconcept" ),
2124 QObject::tr(
"Geoconcept" ),
2125 QStringLiteral(
"*.gxt *.txt" ),
2126 QStringLiteral(
"gxt" ),
2133 datasetOptions.clear();
2134 layerOptions.clear();
2137 QObject::tr(
"When this option is set, the new layer will be created inside the named "
2138 "FeatureDataset folder. If the folder does not already exist, it will be created." ),
2143 QObject::tr(
"Set layer name alias." ),
2148 QObject::tr(
"Set name of geometry column in new layer. Defaults to 'SHAPE'." ),
2149 QStringLiteral(
"SHAPE" )
2153 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'." ),
2158 QObject::tr(
"Name of the OID column to create. Defaults to 'OBJECTID'." ),
2159 QStringLiteral(
"OBJECTID" )
2175 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." ),
2180 QObject::tr(
"XML documentation for the layer." ),
2184 QObject::tr(
"Customize how data is stored. By default text in UTF-8 and data up to 1TB." ),
2185 {QStringLiteral(
"DEFAULTS" ), QStringLiteral(
"MAX_FILE_SIZE_4GB" ), QStringLiteral(
"MAX_FILE_SIZE_256TB" )},
2186 QStringLiteral(
"DEFAULTS" ),
2191 QObject::tr(
" 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 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 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 FileGeodatabase has those fields properly tagged." ),
2195 driverMetadata.insert( QStringLiteral(
"OpenFileGDB" ),
2197 QStringLiteral(
"ESRI File Geodatabase" ),
2198 QObject::tr(
"ESRI File Geodatabase" ),
2199 QStringLiteral(
"*.gdb" ),
2200 QStringLiteral(
"gdb" ),
2203 QStringLiteral(
"UTF-8" )
2208 datasetOptions.clear();
2209 layerOptions.clear();
2212 QObject::tr(
"When this option is set, the new layer will be created inside the named "
2213 "FeatureDataset folder. If the folder does not already exist, it will be created." ),
2218 QObject::tr(
"Set name of geometry column in new layer. Defaults to 'SHAPE'." ),
2219 QStringLiteral(
"SHAPE" )
2223 QObject::tr(
"Name of the OID column to create. Defaults to 'OBJECTID'." ),
2224 QStringLiteral(
"OBJECTID" )
2227 driverMetadata.insert( QStringLiteral(
"FileGDB" ),
2229 QStringLiteral(
"ESRI FileGDB" ),
2230 QObject::tr(
"ESRI FileGDB" ),
2231 QStringLiteral(
"*.gdb" ),
2232 QStringLiteral(
"gdb" ),
2235 QStringLiteral(
"UTF-8" )
2240 datasetOptions.clear();
2241 layerOptions.clear();
2244 QObject::tr(
"By default, the driver will try to detect the data type of fields. If set "
2245 "to STRING, all fields will be of String type." ),
2247 << QStringLiteral(
"AUTO" )
2248 << QStringLiteral(
"STRING" ),
2249 QStringLiteral(
"AUTO" ),
2254 QObject::tr(
"By default, the driver will read the first lines of each sheet to detect "
2255 "if the first line might be the name of columns. If set to FORCE, the driver "
2256 "will consider the first line as the header line. If set to "
2257 "DISABLE, it will be considered as the first feature. Otherwise "
2258 "auto-detection will occur." ),
2260 << QStringLiteral(
"FORCE" )
2261 << QStringLiteral(
"DISABLE" )
2262 << QStringLiteral(
"AUTO" ),
2263 QStringLiteral(
"AUTO" ),
2267 driverMetadata.insert( QStringLiteral(
"XLSX" ),
2269 QStringLiteral(
"MS Office Open XML spreadsheet" ),
2270 QObject::tr(
"MS Office Open XML spreadsheet [XLSX]" ),
2271 QStringLiteral(
"*.xlsx" ),
2272 QStringLiteral(
"xlsx" ),
2275 QStringLiteral(
"UTF-8" )
2280 datasetOptions.clear();
2281 layerOptions.clear();
2284 QObject::tr(
"By default, the driver will try to detect the data type of fields. If set "
2285 "to STRING, all fields will be of String type." ),
2287 << QStringLiteral(
"AUTO" )
2288 << QStringLiteral(
"STRING" ),
2289 QStringLiteral(
"AUTO" ),
2294 QObject::tr(
"By default, the driver will read the first lines of each sheet to detect "
2295 "if the first line might be the name of columns. If set to FORCE, the driver "
2296 "will consider the first line as the header line. If set to "
2297 "DISABLE, it will be considered as the first feature. Otherwise "
2298 "auto-detection will occur." ),
2300 << QStringLiteral(
"FORCE" )
2301 << QStringLiteral(
"DISABLE" )
2302 << QStringLiteral(
"AUTO" ),
2303 QStringLiteral(
"AUTO" ),
2307 driverMetadata.insert( QStringLiteral(
"ODS" ),
2309 QStringLiteral(
"Open Document Spreadsheet" ),
2310 QObject::tr(
"Open Document Spreadsheet [ODS]" ),
2311 QStringLiteral(
"*.ods" ),
2312 QStringLiteral(
"ods" ),
2315 QStringLiteral(
"UTF-8" )
2320 datasetOptions.clear();
2321 layerOptions.clear();
2324 QObject::tr(
"Compression method." ),
2326 << QStringLiteral(
"UNCOMPRESSED" )
2327 << QStringLiteral(
"SNAPPY" ),
2328 QStringLiteral(
"SNAPPY" ),
2333 QObject::tr(
"Geometry encoding." ),
2335 << QStringLiteral(
"WKB" )
2336 << QStringLiteral(
"WKT" )
2337 << QStringLiteral(
"GEOARROW" ),
2338 QStringLiteral(
"WKB" ),
2343 QObject::tr(
"Maximum number of rows per group." ),
2348 QObject::tr(
"Name for the feature identifier column" ),
2353 QObject::tr(
"Name for the geometry column" ),
2354 QStringLiteral(
"geometry" )
2358 QObject::tr(
"Name of the coordinate system for the edges." ),
2360 << QStringLiteral(
"PLANAR" )
2361 << QStringLiteral(
"SPHERICAL" ),
2362 QStringLiteral(
"PLANAR" ),
2366 driverMetadata.insert( QStringLiteral(
"Parquet" ),
2368 QStringLiteral(
"(Geo)Parquet" ),
2369 QObject::tr(
"(Geo)Parquet" ),
2370 QStringLiteral(
"*.parquet" ),
2371 QStringLiteral(
"parquet" ),
2374 QStringLiteral(
"UTF-8" )
2379 datasetOptions.clear();
2380 layerOptions.clear();
2383 QObject::tr(
"Line termination character sequence." ),
2385 << QStringLiteral(
"CRLF" )
2386 << QStringLiteral(
"LF" ),
2387 QStringLiteral(
"LF" ),
2393 QObject::tr(
"Format of geometry columns." ),
2395 << QStringLiteral(
"geometry" )
2396 << QStringLiteral(
"geography" ),
2397 QStringLiteral(
"geometry" ),
2402 QObject::tr(
"Controls whether layer and field names will be laundered for easier use. "
2403 "Laundered names will be converted to lower case and some special "
2404 "characters(' - #) will be changed to underscores." ),
2409 QObject::tr(
"Name for the geometry column. Defaults to wkb_geometry "
2410 "for GEOM_TYPE=geometry or the_geog for GEOM_TYPE=geography" ) ) );
2413 QObject::tr(
"Name of schema into which to create the new table" ) ) );
2416 QObject::tr(
"Whether to explicitly emit the CREATE SCHEMA statement to create the specified schema." ),
2421 QObject::tr(
"Whether to explicitly recreate the table if necessary." ),
2426 QObject::tr(
"Whether to explicitly destroy tables before recreating them." ),
2428 << QStringLiteral(
"YES" )
2429 << QStringLiteral(
"NO" )
2430 << QStringLiteral(
"IF_EXISTS" ),
2431 QStringLiteral(
"YES" ),
2436 QObject::tr(
"Used to force the SRID number of the SRS associated with the layer. "
2437 "When this option isn't specified and that a SRS is associated with the "
2438 "layer, a search is made in the spatial_ref_sys to find a match for the "
2439 "SRS, and, if there is no match, a new entry is inserted for the SRS in "
2440 "the spatial_ref_sys table. When the SRID option is specified, this "
2441 "search (and the eventual insertion of a new entry) will not be done: "
2442 "the specified SRID is used as such." ),
2447 QObject::tr(
"Can be set to 2.0 or 2.2 for PostGIS 2.0/2.2 compatibility. "
2448 "Important to set it correctly if using non-linear geometry types" ),
2449 QStringLiteral(
"2.2" )
2452 driverMetadata.insert( QStringLiteral(
"PGDUMP" ),
2454 QStringLiteral(
"PostgreSQL SQL dump" ),
2455 QObject::tr(
"PostgreSQL SQL dump" ),
2456 QStringLiteral(
"*.sql" ),
2457 QStringLiteral(
"sql" ),
2460 QStringLiteral(
"UTF-8" )
2466 QgsVectorFileWriterMetadataContainer(
const QgsVectorFileWriterMetadataContainer &other ) =
delete;
2467 QgsVectorFileWriterMetadataContainer &operator=(
const QgsVectorFileWriterMetadataContainer &other ) =
delete;
2468 ~QgsVectorFileWriterMetadataContainer()
2470 for (
auto it = driverMetadata.constBegin(); it != driverMetadata.constEnd(); ++it )
2472 for (
auto optionIt = it.value().driverOptions.constBegin(); optionIt != it.value().driverOptions.constEnd(); ++optionIt )
2473 delete optionIt.value();
2474 for (
auto optionIt = it.value().layerOptions.constBegin(); optionIt != it.value().layerOptions.constEnd(); ++optionIt )
2475 delete optionIt.value();
2479 QMap<QString, QgsVectorFileWriter::MetaData> driverMetadata;
2486 static QgsVectorFileWriterMetadataContainer sDriverMetadata;
2487 QMap<QString, MetaData>::ConstIterator it = sDriverMetadata.driverMetadata.constBegin();
2489 for ( ; it != sDriverMetadata.driverMetadata.constEnd(); ++it )
2491 if ( it.key() == QLatin1String(
"PGDUMP" ) &&
2492 driverName != QLatin1String(
"PGDUMP" ) &&
2493 driverName != QLatin1String(
"PostgreSQL SQL dump" ) )
2498 if ( it.key().startsWith( driverName ) || it.value().longName.startsWith( driverName ) )
2513 return QStringList();
2522 return QStringList();
2529 OGRwkbGeometryType ogrType =
static_cast<OGRwkbGeometryType
>( type );
2555 QgsFeatureList::iterator fIt = features.begin();
2557 for ( ; fIt != features.end(); ++fIt )
2582 QString styleString;
2583 QString currentStyle;
2585 QgsSymbolList::const_iterator symbolIt = symbols.constBegin();
2586 for ( ; symbolIt != symbols.constEnd(); ++symbolIt )
2588 int nSymbolLayers = ( *symbolIt )->symbolLayerCount();
2589 for (
int i = 0; i < nSymbolLayers; ++i )
2592 QMap< QgsSymbolLayer *, QString >::const_iterator it =
mSymbolLayerTable.find( ( *symbolIt )->symbolLayer( i ) );
2598 double mmsf = mmScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
2599 double musf = mapUnitScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
2601 currentStyle = ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf );
2605 if ( symbolIt != symbols.constBegin() || i != 0 )
2607 styleString.append(
';' );
2609 styleString.append( currentStyle );
2613 OGR_F_SetStyleString( poFeature.get(), currentStyle.toLocal8Bit().constData() );
2614 if ( !writeFeature(
mLayer, poFeature.get() ) )
2621 OGR_F_SetStyleString( poFeature.get(), styleString.toLocal8Bit().constData() );
2626 if ( !writeFeature(
mLayer, poFeature.get() ) )
2645 int fldIdx = it.key();
2646 int ogrField = it.value();
2648 QVariant attrValue = feature.
attribute( fldIdx );
2653 OGR_F_UnsetField( poFeature.get(), ogrField );
2666 OGR_F_SetFieldNull( poFeature.get(), ogrField );
2681 mErrorMessage = QObject::tr(
"Error converting value (%1) for attribute field %2: %3" )
2682 .arg( feature.
attribute( fldIdx ).toString(),
2692 OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
2694 case QVariant::LongLong:
2695 OGR_F_SetFieldInteger64( poFeature.get(), ogrField, attrValue.toLongLong() );
2697 case QVariant::Bool:
2698 OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
2700 case QVariant::String:
2701 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toString() ).constData() );
2703 case QVariant::Double:
2704 OGR_F_SetFieldDouble( poFeature.get(), ogrField, attrValue.toDouble() );
2706 case QVariant::Date:
2707 OGR_F_SetFieldDateTime( poFeature.get(), ogrField,
2708 attrValue.toDate().year(),
2709 attrValue.toDate().month(),
2710 attrValue.toDate().day(),
2713 case QVariant::DateTime:
2716 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toDateTime().toString( QStringLiteral(
"yyyy/MM/dd hh:mm:ss.zzz" ) ) ).constData() );
2720 const QDateTime dt = attrValue.toDateTime();
2721 const QDate date = dt.date();
2722 const QTime time = dt.time();
2723 OGR_F_SetFieldDateTimeEx( poFeature.get(), ogrField,
2729 static_cast<float>( time.second() +
static_cast< double >( time.msec() ) / 1000 ),
2733 case QVariant::Time:
2736 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toString() ).constData() );
2740 const QTime time = attrValue.toTime();
2741 OGR_F_SetFieldDateTimeEx( poFeature.get(), ogrField,
2745 static_cast<float>( time.second() +
static_cast< double >( time.msec() ) / 1000 ),
2750 case QVariant::ByteArray:
2752 const QByteArray ba = attrValue.toByteArray();
2753 OGR_F_SetFieldBinary( poFeature.get(), ogrField, ba.size(),
const_cast< GByte *
>(
reinterpret_cast< const GByte *
>( ba.data() ) ) );
2757 case QVariant::Invalid:
2760 case QVariant::StringList:
2765 const QJsonDocument doc = QJsonDocument::fromVariant( attrValue );
2767 if ( !doc.isNull() )
2769 jsonString = QString::fromUtf8( doc.toJson( QJsonDocument::Compact ).constData() );
2771 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( jsonString.constData() ) );
2775 QStringList list = attrValue.toStringList();
2776 if ( mSupportedListSubTypes.contains( QVariant::String ) )
2778 int count = list.count();
2779 char **lst =
new char *[count + 1];
2783 for (
const QString &
string : list )
2785 lst[pos] = CPLStrdup(
mCodec->fromUnicode(
string ).data() );
2789 lst[count] =
nullptr;
2790 OGR_F_SetFieldStringList( poFeature.get(), ogrField, lst );
2795 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( list.join(
',' ) ).constData() );
2800 case QVariant::List:
2804 const QJsonDocument doc = QJsonDocument::fromVariant( attrValue );
2806 if ( !doc.isNull() )
2808 jsonString = QString::fromUtf8( doc.toJson( QJsonDocument::Compact ).data() );
2810 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( jsonString.constData() ) );
2817 QStringList list = attrValue.toStringList();
2818 if ( mSupportedListSubTypes.contains( QVariant::String ) )
2820 int count = list.count();
2821 char **lst =
new char *[count + 1];
2825 for (
const QString &
string : list )
2827 lst[pos] = CPLStrdup(
mCodec->fromUnicode(
string ).data() );
2831 lst[count] =
nullptr;
2832 OGR_F_SetFieldStringList( poFeature.get(), ogrField, lst );
2837 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( list.join(
',' ) ).constData() );
2843 const QVariantList list = attrValue.toList();
2844 if ( mSupportedListSubTypes.contains( QVariant::Int ) )
2846 const int count = list.count();
2847 int *lst =
new int[count];
2851 for (
const QVariant &value : list )
2853 lst[pos] = value.toInt();
2857 OGR_F_SetFieldIntegerList( poFeature.get(), ogrField, count, lst );
2862 QStringList strings;
2863 strings.reserve( list.size() );
2864 for (
const QVariant &value : list )
2866 strings << QString::number( value.toInt() );
2868 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
2874 const QVariantList list = attrValue.toList();
2875 if ( mSupportedListSubTypes.contains( QVariant::Double ) )
2877 const int count = list.count();
2878 double *lst =
new double[count];
2882 for (
const QVariant &value : list )
2884 lst[pos] = value.toDouble();
2888 OGR_F_SetFieldDoubleList( poFeature.get(), ogrField, count, lst );
2893 QStringList strings;
2894 strings.reserve( list.size() );
2895 for (
const QVariant &value : list )
2897 strings << QString::number( value.toDouble() );
2899 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
2905 const QVariantList list = attrValue.toList();
2906 if ( mSupportedListSubTypes.contains( QVariant::LongLong ) )
2908 const int count = list.count();
2909 long long *lst =
new long long[count];
2913 for (
const QVariant &value : list )
2915 lst[pos] = value.toLongLong();
2919 OGR_F_SetFieldInteger64List( poFeature.get(), ogrField, count, lst );
2924 QStringList strings;
2925 strings.reserve( list.size() );
2926 for (
const QVariant &value : list )
2928 strings << QString::number( value.toLongLong() );
2930 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
2940 const char *pszDataSubTypes = GDALGetMetadataItem( OGRGetDriverByName(
mOgrDriverName.toLocal8Bit().constData() ), GDAL_DMD_CREATIONFIELDDATASUBTYPES,
nullptr );
2941 if ( pszDataSubTypes && strstr( pszDataSubTypes,
"JSON" ) )
2943 const QJsonDocument doc = QJsonDocument::fromVariant( attrValue );
2945 if ( !doc.isNull() )
2947 const QByteArray json { doc.toJson( QJsonDocument::Compact ) };
2948 jsonString = QString::fromUtf8( json.data() );
2950 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( jsonString.constData() ) );
2960 mErrorMessage = QObject::tr(
"Invalid variant type for field %1[%2]: received %3 with type %4" )
2963 .arg( attrValue.typeName(),
2964 attrValue.toString() );
2977 if ( mCoordinateTransform )
2982 geom.
transform( *mCoordinateTransform );
3000 OGRGeometryH mGeom2 =
nullptr;
3029 geom.
get()->
addZValue( std::numeric_limits<double>::quiet_NaN() );
3036 geom.
get()->
addMValue( std::numeric_limits<double>::quiet_NaN() );
3056 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
3057 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
3063 QgsAbstractGeometry::WkbFlags wkbFlags;
3067 QByteArray wkb( geom.
asWkb( wkbFlags ) );
3068 OGRErr err = OGR_G_ImportFromWkb( mGeom2,
reinterpret_cast<unsigned char *
>(
const_cast<char *
>( wkb.constData() ) ), wkb.length() );
3069 if ( err != OGRERR_NONE )
3071 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
3072 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
3079 OGR_F_SetGeometryDirectly( poFeature.get(), mGeom2 );
3087 QByteArray wkb( geom.
asWkb( wkbFlags ) );
3089 OGRErr err = OGR_G_ImportFromWkb( ogrGeom,
reinterpret_cast<unsigned char *
>(
const_cast<char *
>( wkb.constData() ) ), wkb.length() );
3090 if ( err != OGRERR_NONE )
3092 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
3093 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
3100 OGR_F_SetGeometryDirectly( poFeature.get(), ogrGeom );
3115 for (
int i = 0; i < attributes.size(); i++ )
3117 if ( omap.find( i ) != omap.end() )
3122bool QgsVectorFileWriter::writeFeature( OGRLayerH layer, OGRFeatureH feature )
3124 if ( OGR_L_CreateFeature( layer, feature ) != OGRERR_NONE )
3126 mErrorMessage = QObject::tr(
"Feature creation error (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
3136 if ( mUsingTransaction )
3138 if ( OGRERR_NONE != OGR_L_CommitTransaction(
mLayer ) )
3140 QgsDebugMsg( QStringLiteral(
"Error while committing transaction on OGRLayer." ) );
3153 const QString &fileName,
3154 const QString &fileEncoding,
3156 const QString &driverName,
3158 QString *errorMessage,
3159 const QStringList &datasourceOptions,
3160 const QStringList &layerOptions,
3161 bool skipAttributeCreation,
3162 QString *newFilename,
3164 double symbologyScale,
3174 if ( destCRS.
isValid() && layer )
3200 const QString &fileName,
3201 const QString &fileEncoding,
3203 const QString &driverName,
3205 QString *errorMessage,
3206 const QStringList &datasourceOptions,
3207 const QStringList &layerOptions,
3208 bool skipAttributeCreation,
3209 QString *newFilename,
3211 double symbologyScale,
3242 : driverName( QStringLiteral(
"GPKG" ) )
3250 if ( !layer || !layer->
isValid() )
3257 details.sourceCrs = layer->
crs();
3258 details.sourceWkbType = layer->
wkbType();
3259 details.sourceFields = layer->
fields();
3268 if ( details.storageType == QLatin1String(
"ESRI Shapefile" ) )
3276 details.geometryTypeScanIterator = layer->
getFeatures( req );
3280 details.renderContext.setExpressionContext( details.expressionContext );
3281 details.renderContext.setRendererScale( options.
symbologyScale );
3283 details.shallTransform =
false;
3288 details.shallTransform =
true;
3293 details.outputCrs = details.sourceCrs;
3296 details.destWkbType = details.sourceWkbType;
3310 details.attributes.clear();
3311 else if ( details.attributes.isEmpty() )
3313 const QgsAttributeList allAttributes = details.sourceFields.allAttributesList();
3314 for (
int idx : allAttributes )
3316 QgsField fld = details.sourceFields.at( idx );
3317 if ( details.providerType == QLatin1String(
"oracle" ) && fld.
typeName().contains( QLatin1String(
"SDO_GEOMETRY" ) ) )
3319 details.attributes.append( idx );
3323 if ( !details.attributes.isEmpty() )
3325 for (
int attrIdx : std::as_const( details.attributes ) )
3327 if ( details.sourceFields.exists( attrIdx ) )
3331 details.outputFields.append(
field );
3335 QgsDebugMsg( QStringLiteral(
"No such source field with index '%1' available." ).arg( attrIdx ) );
3342 if ( details.providerType == QLatin1String(
"spatialite" ) )
3344 for (
int i = 0; i < details.outputFields.size(); i++ )
3346 if ( details.outputFields.at( i ).type() == QVariant::LongLong )
3351 if ( std::max( std::llabs( min.toLongLong() ), std::llabs( max.toLongLong() ) ) < std::numeric_limits<int>::max() )
3353 details.outputFields[i].setType( QVariant::Int );
3361 addRendererAttributes( details.renderer.get(), details.renderContext, details.sourceFields, details.attributes );
3371 bool useFilterRect =
true;
3372 if ( details.shallTransform )
3383 useFilterRect =
false;
3386 if ( useFilterRect )
3392 details.filterRectEngine->prepareGeometry();
3394 details.sourceFeatureIterator = layer->
getFeatures( req );
3408 int lastProgressReport = 0;
3409 long long total = details.featureCount;
3412 if ( details.providerType == QLatin1String(
"ogr" ) && !details.dataSourceUri.isEmpty() )
3414 QString srcFileName( details.providerUriParams.value( QStringLiteral(
"path" ) ).toString() );
3415 if ( QFile::exists( srcFileName ) && QFileInfo( fileName ).canonicalFilePath() == QFileInfo( srcFileName ).canonicalFilePath() )
3419 if ( !( ( options.
driverName == QLatin1String(
"GPKG" ) ||
3420 options.
driverName == QLatin1String(
"SpatiaLite" ) ||
3421 options.
driverName == QLatin1String(
"SQLite" ) ) &&
3422 options.
layerName != details.providerUriParams.value( QStringLiteral(
"layerName" ) ) ) )
3425 *
errorMessage = QObject::tr(
"Cannot overwrite a OGR layer in place" );
3445 int newProgress =
static_cast<int>( ( 5.0 * scanned ) / total );
3446 if ( newProgress != lastProgressReport )
3448 lastProgressReport = newProgress;
3463 QString tempNewFilename;
3464 QString tempNewLayer;
3466 std::unique_ptr< QgsVectorFileWriter > writer(
create( fileName, details.outputFields, destWkbType, details.outputCrs, transformContext, options, QgsFeatureSink::SinkFlags(), &tempNewFilename, &tempNewLayer ) );
3470 *newFilename = tempNewFilename;
3473 *newLayer = tempNewLayer;
3513 int n = 0, errors = 0;
3522 writer->startRender( details.renderer.get(), details.sourceFields );
3524 writer->resetMap( details.attributes );
3526 writer->mFields = details.sourceFields;
3530 int initialProgress = lastProgressReport;
3531 while ( details.sourceFeatureIterator.nextFeature( fet ) )
3542 int newProgress =
static_cast<int>( initialProgress + ( ( 100.0 - initialProgress ) * saved ) / total );
3543 if ( newProgress < 100 && newProgress != lastProgressReport )
3545 lastProgressReport = newProgress;
3550 if ( details.shallTransform )
3563 QString msg = QObject::tr(
"Failed to transform a point while drawing a feature with ID '%1'. Writing stopped. (Exception: %2)" )
3564 .arg( fet.
id() ).arg( e.
what() );
3581 if ( !writer->addFeatureWithStyle( fet, writer->mRenderer.get(), mapUnits ) )
3588 *
errorMessage = QObject::tr(
"Feature write errors:" );
3594 if ( errors > 1000 )
3598 *
errorMessage += QObject::tr(
"Stopping after %n error(s)",
nullptr, errors );
3608 writer->stopRender();
3612 *
errorMessage += QObject::tr(
"\nOnly %1 of %2 features written." ).arg( n - errors ).arg( n );
3617 bool metadataFailure =
false;
3622 {QStringLiteral(
"path" ), tempNewFilename },
3623 {QStringLiteral(
"layerName" ), tempNewLayer }
3637 metadataFailure =
true;
3648 metadataFailure =
true;
3656 const QString &fileName,
3658 QString *newFilename,
3662 QgsVectorFileWriter::PreparedWriterDetails details;
3663 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
3671 const QString &fileName,
3674 QString *newFilename,
3678 QgsVectorFileWriter::PreparedWriterDetails details;
3679 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
3688 QgsVectorFileWriter::PreparedWriterDetails details;
3689 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
3698 QFileInfo fi( fileName );
3699 QDir dir = fi.dir();
3702 for (
const char *suffix : {
".shp",
".shx",
".dbf",
".prj",
".qix",
".qpj",
".cpg",
".sbn",
".sbx",
".idm",
".ind" } )
3704 filter << fi.completeBaseName() + suffix;
3708 const auto constEntryList = dir.entryList( filter );
3709 for (
const QString &file : constEntryList )
3711 QFile f( dir.canonicalPath() +
'/' + file );
3714 QgsDebugMsg( QStringLiteral(
"Removing file %1 failed: %2" ).arg( file, f.errorString() ) );
3730 static QReadWriteLock sFilterLock;
3731 static QMap< VectorFormatOptions, QList< QgsVectorFileWriter::FilterFormatDetails > > sFilters;
3735 const auto it = sFilters.constFind( options );
3736 if ( it != sFilters.constEnd() )
3740 QList< QgsVectorFileWriter::FilterFormatDetails > results;
3743 int const drvCount = OGRGetDriverCount();
3745 for (
int i = 0; i < drvCount; ++i )
3747 OGRSFDriverH drv = OGRGetDriver( i );
3750 QString drvName = OGR_Dr_GetName( drv );
3752 GDALDriverH gdalDriver = GDALGetDriverByName( drvName.toLocal8Bit().constData() );
3753 char **metadata =
nullptr;
3756 metadata = GDALGetMetadata( gdalDriver,
nullptr );
3759 bool nonSpatialFormat = CSLFetchBoolean( metadata, GDAL_DCAP_NONSPATIAL,
false );
3761 if ( OGR_Dr_TestCapability( drv,
"CreateDataSource" ) != 0 )
3766 if ( nonSpatialFormat )
3771 if ( filterString.isEmpty() )
3778 globs = metadata.
glob.toLower().split(
' ' );
3784 details.
globs = globs;
3793 if ( options & SortRecommended )
3795 if ( a.driverName == QLatin1String(
"GPKG" ) )
3797 else if ( b.driverName == QLatin1String(
"GPKG" ) )
3799 else if ( a.driverName == QLatin1String(
"ESRI Shapefile" ) )
3801 else if ( b.driverName == QLatin1String(
"ESRI Shapefile" ) )
3808 sFilters.insert( options, results );
3815 QSet< QString > extensions;
3817 const QRegularExpression rx( QStringLiteral(
"\\*\\.(.*)$" ) );
3821 for (
const QString &glob : format.globs )
3823 const QRegularExpressionMatch match = rx.match( glob );
3824 if ( !match.hasMatch() )
3827 const QString matched = match.captured( 1 );
3828 extensions.insert( matched );
3832 QStringList extensionList( extensions.constBegin(), extensions.constEnd() );
3834 std::sort( extensionList.begin(), extensionList.end(), [options](
const QString & a,
const QString & b ) ->
bool
3836 if ( options & SortRecommended )
3838 if ( a == QLatin1String(
"gpkg" ) )
3840 else if ( b == QLatin1String(
"gpkg" ) )
3842 else if ( a == QLatin1String(
"shp" ) )
3844 else if ( b == QLatin1String(
"shp" ) )
3848 return a.toLower().localeAwareCompare( b.toLower() ) < 0;
3851 return extensionList;
3856 QList< QgsVectorFileWriter::DriverDetails > results;
3859 const int drvCount = OGRGetDriverCount();
3861 QStringList writableDrivers;
3862 for (
int i = 0; i < drvCount; ++i )
3864 OGRSFDriverH drv = OGRGetDriver( i );
3867 QString drvName = OGR_Dr_GetName( drv );
3873 if ( drvName == QLatin1String(
"ODS" ) || drvName == QLatin1String(
"XLSX" ) || drvName == QLatin1String(
"XLS" ) )
3877 if ( drvName == QLatin1String(
"ESRI Shapefile" ) )
3879 writableDrivers << QStringLiteral(
"DBF file" );
3881 if ( OGR_Dr_TestCapability( drv,
"CreateDataSource" ) != 0 )
3884 if ( drvName == QLatin1String(
"MapInfo File" ) )
3886 writableDrivers << QStringLiteral(
"MapInfo MIF" );
3888 else if ( drvName == QLatin1String(
"SQLite" ) )
3895 QString option = QStringLiteral(
"SPATIALITE=YES" );
3896 char *options[2] = { CPLStrdup( option.toLocal8Bit().constData() ),
nullptr };
3897 OGRSFDriverH poDriver;
3899 poDriver = OGRGetDriverByName( drvName.toLocal8Bit().constData() );
3902 gdal::ogr_datasource_unique_ptr ds( OGR_Dr_CreateDataSource( poDriver, QStringLiteral(
"/vsimem/spatialitetest.sqlite" ).toUtf8().constData(), options ) );
3905 writableDrivers << QStringLiteral(
"SpatiaLite" );
3906 OGR_Dr_DeleteDataSource( poDriver, QStringLiteral(
"/vsimem/spatialitetest.sqlite" ).toUtf8().constData() );
3909 CPLFree( options[0] );
3911 writableDrivers << drvName;
3916 results.reserve( writableDrivers.count() );
3917 for (
const QString &drvName : std::as_const( writableDrivers ) )
3931 if ( options & SortRecommended )
3933 if ( a.driverName == QLatin1String(
"GPKG" ) )
3935 else if ( b.driverName == QLatin1String(
"GPKG" ) )
3937 else if ( a.driverName == QLatin1String(
"ESRI Shapefile" ) )
3939 else if ( b.driverName == QLatin1String(
"ESRI Shapefile" ) )
3943 return a.
longName.toLower().localeAwareCompare( b.
longName.toLower() ) < 0;
3950 QString ext = extension.trimmed();
3951 if ( ext.isEmpty() )
3954 if ( ext.startsWith(
'.' ) )
3958 int const drvCount = GDALGetDriverCount();
3960 for (
int i = 0; i < drvCount; ++i )
3962 GDALDriverH drv = GDALGetDriver( i );
3968 QString drvName = GDALGetDriverShortName( drv );
3969 QStringList driverExtensions = QString( GDALGetMetadataItem( drv, GDAL_DMD_EXTENSIONS,
nullptr ) ).split(
' ' );
3971 const auto constDriverExtensions = driverExtensions;
3972 for (
const QString &driver : constDriverExtensions )
3974 if ( driver.compare( ext, Qt::CaseInsensitive ) == 0 )
3985 QString filterString;
3989 if ( !filterString.isEmpty() )
3990 filterString += QLatin1String(
";;" );
3992 filterString += details.filterString;
3994 return filterString;
4003 return QStringLiteral(
"%1 (%2 %3)" ).arg( metadata.
trLongName,
4004 metadata.
glob.toLower(),
4005 metadata.
glob.toUpper() );
4010 if ( codecName == QLatin1String(
"System" ) )
4011 return QStringLiteral(
"LDID/0" );
4013 const QRegularExpression re( QRegularExpression::anchoredPattern( QString(
"(CP|windows-|ISO[ -])(.+)" ) ), QRegularExpression::CaseInsensitiveOption );
4014 const QRegularExpressionMatch match = re.match( codecName );
4015 if ( match.hasMatch() )
4017 QString
c = match.captured( 2 ).remove(
'-' );
4019 ( void )
c.toInt( &isNumber );
4047 OGRStyleTableH ogrStyleTable = OGR_STBL_Create();
4048 OGRStyleMgrH styleManager = OGR_SM_Create( ogrStyleTable );
4051 int nTotalLevels = 0;
4053 QgsSymbolList::iterator symbolIt = symbolList.begin();
4054 for ( ; symbolIt != symbolList.end(); ++symbolIt )
4056 double mmsf = mmScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
4057 double musf = mapUnitScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
4059 int nLevels = ( *symbolIt )->symbolLayerCount();
4060 for (
int i = 0; i < nLevels; ++i )
4062 mSymbolLayerTable.insert( ( *symbolIt )->symbolLayer( i ), QString::number( nTotalLevels ) );
4063 OGR_SM_AddStyle( styleManager, QString::number( nTotalLevels ).toLocal8Bit(),
4064 ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf ).toLocal8Bit() );
4068 OGR_DS_SetStyleTableDirectly( ds, ogrStyleTable );
4074 if ( !details.renderer )
4079 QHash< QgsSymbol *, QList<QgsFeature> > features;
4088 startRender( details.renderer.get(), details.sourceFields );
4108 QString msg = QObject::tr(
"Failed to transform, writing stopped. (Exception: %1)" )
4119 featureSymbol = mRenderer->symbolForFeature( fet, mRenderContext );
4120 if ( !featureSymbol )
4125 QHash< QgsSymbol *, QList<QgsFeature> >::iterator it = features.find( featureSymbol );
4126 if ( it == features.end() )
4128 it = features.insert( featureSymbol, QList<QgsFeature>() );
4130 it.value().append( fet );
4135 QgsSymbolList symbols = mRenderer->symbols( mRenderContext );
4136 for (
int i = 0; i < symbols.count(); i++ )
4142 if ( level < 0 || level >= 1000 )
4145 while ( level >= levels.count() )
4147 levels[level].append( item );
4152 int nTotalFeatures = 0;
4155 for (
int l = 0; l < levels.count(); l++ )
4158 for (
int i = 0; i < level.count(); i++ )
4161 QHash< QgsSymbol *, QList<QgsFeature> >::iterator levelIt = features.find( item.
symbol() );
4162 if ( levelIt == features.end() )
4168 double mmsf = mmScaleFactor(
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
4169 double musf = mapUnitScaleFactor(
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
4171 int llayer = item.
layer();
4172 QList<QgsFeature> &featureList = levelIt.value();
4173 QList<QgsFeature>::iterator featureIt = featureList.begin();
4174 for ( ; featureIt != featureList.end(); ++featureIt )
4184 QString styleString = levelIt.key()->symbolLayer( llayer )->ogrFeatureStyle( mmsf, musf );
4185 if ( !styleString.isEmpty() )
4187 OGR_F_SetStyleString( ogrFeature.get(), styleString.toLocal8Bit().constData() );
4188 if ( !writeFeature(
mLayer, ogrFeature.get() ) )
4201 *
errorMessage += QObject::tr(
"\nOnly %1 of %2 features written." ).arg( nTotalFeatures - nErrors ).arg( nTotalFeatures );
4218 return 1000 / scale;
4235 return scale / 1000;
4243 mRenderer = createSymbologyRenderer( sourceRenderer );
4249 mRenderer->startRender( mRenderContext, fields );
4252void QgsVectorFileWriter::stopRender()
4259 mRenderer->stopRender( mRenderContext );
4262std::unique_ptr<QgsFeatureRenderer> QgsVectorFileWriter::createSymbologyRenderer(
QgsFeatureRenderer *sourceRenderer )
const
4268 if ( !sourceRenderer )
4273 return std::unique_ptr< QgsFeatureRenderer >( sourceRenderer->
clone() );
4280 const QSet<QString> rendererAttributes = renderer->
usedAttributes( context );
4281 for (
const QString &attr : rendererAttributes )
4286 attList.append( index );
4292QStringList QgsVectorFileWriter::concatenateOptions(
const QMap<QString, QgsVectorFileWriter::Option *> &options )
4295 QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
4297 for ( it = options.constBegin(); it != options.constEnd(); ++it )
4300 switch ( option->
type )
4307 list.append( QStringLiteral(
"%1=%2" ).arg( it.key() ).arg( opt->
defaultValue ) );
4317 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
defaultValue ) );
4327 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
defaultValue ) );
4334 if ( opt && !opt->
mValue.isEmpty() )
4336 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
mValue ) );
4347 OGRSFDriverH hDriver =
nullptr;
4350 return QgsVectorFileWriter::EditionCapabilities();
4351 QString drvName = OGR_Dr_GetName( hDriver );
4352 QgsVectorFileWriter::EditionCapabilities caps = QgsVectorFileWriter::EditionCapabilities();
4353 if ( OGR_DS_TestCapability( hDS.get(), ODsCCreateLayer ) )
4358 if ( !( drvName == QLatin1String(
"ESRI Shapefile" ) && QFile::exists( datasetName ) ) )
4361 if ( OGR_DS_TestCapability( hDS.get(), ODsCDeleteLayer ) )
4365 int layer_count = OGR_DS_GetLayerCount( hDS.get() );
4368 OGRLayerH hLayer = OGR_DS_GetLayer( hDS.get(), 0 );
4371 if ( OGR_L_TestCapability( hLayer, OLCSequentialWrite ) )
4374 if ( OGR_L_TestCapability( hLayer, OLCCreateField ) )
4385 const QString &layerNameIn )
4387 OGRSFDriverH hDriver =
nullptr;
4392 QString layerName( layerNameIn );
4393 if ( layerName.isEmpty() )
4394 layerName = QFileInfo( datasetName ).baseName();
4396 return OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
4401 const QString &layerName,
4405 OGRSFDriverH hDriver =
nullptr;
4409 OGRLayerH hLayer = OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
4415 OGRFeatureDefnH defn = OGR_L_GetLayerDefn( hLayer );
4416 const auto constAttributes = attributes;
4417 for (
int idx : constAttributes )
4420 if ( OGR_FD_GetFieldIndex( defn, fld.
name().toUtf8().constData() ) < 0 )
@ Reverse
Reverse/inverse transform (from destination to source)
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.
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 (since QGIS 3.30)
static void registerOgrDrivers()
Register OGR drivers ensuring this only happens once.
This class 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.
QgsUnitTypes::DistanceUnit mapUnits
Contains information about the context in which a coordinate transform is executed.
Custom exception class for Coordinate Reference System related exceptions.
virtual QString dataSourceUri(bool expandAuthConfig=false) const
Gets the data source specification.
Class for storing the component parts of a RDBMS data source URI (e.g.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
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.
This class 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.
@ 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.
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.
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.
QVariant::Type subType() const
If the field is a collection, gets its element's type.
Container of fields for a vector layer.
int count() const
Returns number of items.
int size() const
Returns number of items.
void clear()
Removes all fields.
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
A geometry is the spatial representation of a feature.
QgsWkbTypes::Type wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
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.
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry)
Creates and returns a new geometry engine representing the specified geometry.
bool convertToMultiType()
Converts single type geometry into multitype geometry e.g.
QByteArray asWkb(QgsAbstractGeometry::WkbFlags flags=QgsAbstractGeometry::WkbFlags()) const
Export the geometry to WKB.
static void warning(const QString &msg)
Goes to qWarning.
QString providerType() const
Returns the provider type (provider key) for this layer.
QgsCoordinateReferenceSystem crs
QgsCoordinateTransformContext transformContext() const
Returns the layer data provider coordinate transform context or a default transform context if the la...
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
Custom exception class which is raised when an operation is not supported.
static OGRSpatialReferenceH crsToOGRSpatialReference(const QgsCoordinateReferenceSystem &crs)
Returns a OGRSpatialReferenceH corresponding to the specified crs object.
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.
bool saveLayerMetadata(const QString &providerKey, const QString &uri, const QgsLayerMetadata &metadata, QString &errorMessage)
Saves metadata to the layer corresponding to the specified uri.
The QgsReadWriteLocker class is a convenience class that simplifies locking and unlocking QReadWriteL...
void changeMode(Mode mode)
Change the mode of the lock to mode.
A rectangle specified with double values.
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()).
Contains information about the context of a rendering operation.
QgsExpressionContext & expressionContext()
Gets the expression context.
void setRendererScale(double scale)
Sets the renderer map scale.
This class is a composition of two QSettings instances:
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
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.
Abstract base class for all rendered symbols.
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.
DistanceUnit
Units of distance.
RenderUnit
Rendering size units.
@ RenderMillimeters
Millimeters.
@ RenderMapUnits
Map units.
static bool isNull(const QVariant &variant)
Returns true if the specified variant should be considered a NULL value.
Interface to convert raw field values to their user-friendly value.
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.
QgsVectorFileWriter::OptionType type
Options to pass to writeAsVectorFormat()
QString fileEncoding
Encoding to use.
bool forceMulti
Sets to true to force creation of multi* geometries.
FieldNameSource fieldNameSource
Source for exported field names.
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.
SaveVectorOptions()
Constructor.
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.
QgsVectorFileWriter::FieldValueConverter * fieldValueConverter
Field value converter.
QStringList layerOptions
List of OGR layer creation options.
QgsVectorFileWriter::SymbologyExport symbologyExport
Symbology to export.
bool includeZ
Sets to true to include z dimension in output. This option is only valid if overrideGeometryType is s...
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.
bool skipAttributeCreation
Only write geometries.
double symbologyScale
Scale of symbology.
QStringList datasourceOptions
List of OGR data source creation options.
QgsWkbTypes::Type overrideGeometryType
Set to a valid geometry type to override the default geometry type for the layer.
QgsFeedback * feedback
Optional feedback object allowing cancellation of layer save.
A convenience class for writing vector layers to disk based formats (e.g.
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.
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.
static QgsVectorFileWriter * create(const QString &fileName, const QgsFields &fields, QgsWkbTypes::Type 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.
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.
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)
OGRGeometryH createEmptyGeometry(QgsWkbTypes::Type wkbType)
QMap< int, int > mAttrIdxToOgrIdx
Map attribute indizes to OGR field indexes.
@ 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.
~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.
SymbologyExport mSymbologyExport
static QString driverForExtension(const QString &extension)
Returns the OGR driver name for a specified file extension.
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 bool deleteShapeFile(const QString &fileName)
Delete a shapefile (and its accompanying shx / dbf / prj / qix / qpj / cpg / sbn / sbx / idm / ind)
static QString filterForDriver(const QString &driverName)
Creates a filter for an OGR driver key.
QgsWkbTypes::Type mWkbType
Geometry type which is being used.
QgsVectorFileWriter::WriterError hasError() const
Checks whether there were any errors in constructor.
static OGRwkbGeometryType ogrTypeFromWkbType(QgsWkbTypes::Type type)
Gets the ogr geometry type from an internal QGIS wkb type enum.
@ 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.
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, QgsVectorFileWriter::SymbologyExport symbologyExport=QgsVectorFileWriter::NoSymbology, double symbologyScale=1.0, const QgsRectangle *filterExtent=nullptr, QgsWkbTypes::Type overrideGeometryType=QgsWkbTypes::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.
WriterError mError
Contains error value if construction was not successful.
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.
static QStringList defaultDatasetOptions(const QString &driverName)
Returns a list of the default dataset options for a specified driver.
static QStringList supportedFormatExtensions(VectorFormatOptions options=SortRecommended)
Returns a list of file extensions for supported formats, e.g "shp", "gpkg".
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.
bool addFeatureWithStyle(QgsFeature &feature, QgsFeatureRenderer *renderer, QgsUnitTypes::DistanceUnit outputUnit=QgsUnitTypes::DistanceMeters)
Adds a feature to the currently opened data source, using the style from a specified renderer.
QString errorMessage() const
Retrieves error message.
QgsVectorFileWriter::SymbologyExport symbologyExport() const
void setSymbologyScale(double scale)
Set reference scale for output.
Q_DECL_DEPRECATED QgsVectorFileWriter(const QString &vectorFileName, const QString &fileEncoding, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &srs=QgsCoordinateReferenceSystem(), const QString &driverName="GPKG", const QStringList &datasourceOptions=QStringList(), const QStringList &layerOptions=QStringList(), QString *newFilename=nullptr, QgsVectorFileWriter::SymbologyExport symbologyExport=QgsVectorFileWriter::NoSymbology, QgsFeatureSink::SinkFlags sinkFlags=QgsFeatureSink::SinkFlags(), QString *newLayer=nullptr, const QgsCoordinateTransformContext &transformContext=QgsCoordinateTransformContext(), FieldNameSource fieldNameSource=Original)
Create a new vector file writer.
QMap< QgsSymbolLayer *, QString > mSymbolLayerTable
static QString fileFilterString(VectorFormatOptions options=SortRecommended)
Returns filter string that can be used for dialogs.
ActionOnExistingFile
Combination of CanAddNewLayer, CanAppendToExistingLayer, CanAddNewFieldsToExistingLayer or CanDeleteL...
@ 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 data sets.
Q_INVOKABLE QgsWkbTypes::Type wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
long long featureCount(const QString &legendKey) const
Number of features rendered with specified legend key.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
int selectedFeatureCount() const
Returns the number of features that are selected in this layer.
Q_INVOKABLE const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
QgsFeatureRenderer * renderer()
Returns the feature renderer used for rendering the features in the layer in 2D map views.
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
void minimumAndMaximumValue(int index, QVariant &minimum, QVariant &maximum) const
Calculates both the minimum and maximum value for an attribute column.
static Type to25D(Type type)
Will convert the 25D version of the flat type if supported or Unknown if not supported.
Type
The WKB type describes the number of dimensions a geometry has.
static bool hasZ(Type type)
Tests whether a WKB type contains the z-dimension.
static bool hasM(Type type)
Tests whether a WKB type contains m values.
static Type multiType(Type type)
Returns the multi type for a WKB type.
static Type addZ(Type type)
Adds the z dimension to a WKB type and returns the new type.
static Type flatType(Type type)
Returns the flat type for a WKB type.
static Type singleType(Type type)
Returns the single type for a WKB type.
static bool isMultiType(Type 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)
QList< QgsSymbolLevel > QgsSymbolLevelOrder
QList< QgsSymbolLevelItem > QgsSymbolLevel
QList< QgsSymbol * > QgsSymbolList
Details of available driver formats.
QString longName
Descriptive, user friendly name for the driver.
QString driverName
Unique driver name.