43#include <QRegularExpression>
44#include <QJsonDocument>
50#include <ogr_srs_api.h>
53#include <cpl_string.h>
72 const QString &vectorFileName,
73 const QString &fileEncoding,
77 const QString &driverName,
78 const QStringList &datasourceOptions,
79 const QStringList &layerOptions,
82 QgsFeatureSink::SinkFlags sinkFlags,
92 init( vectorFileName, fileEncoding, fields, geometryType,
93 srs, driverName, datasourceOptions, layerOptions, newFilename,
nullptr,
98 const QString &vectorFileName,
99 const QString &fileEncoding,
103 const QString &driverName,
104 const QStringList &datasourceOptions,
105 const QStringList &layerOptions,
106 QString *newFilename,
109 const QString &layerName,
113 QgsFeatureSink::SinkFlags sinkFlags,
117 , mWkbType( geometryType )
118 , mSymbologyExport( symbologyExport )
119 , mSymbologyScale( 1.0 )
121 init( vectorFileName, fileEncoding, fields, geometryType, srs, driverName,
122 datasourceOptions, layerOptions, newFilename, fieldValueConverter,
123 layerName, action, newLayer, sinkFlags, transformContext, fieldNameSource );
127 const QString &fileName,
133 QgsFeatureSink::SinkFlags sinkFlags,
134 QString *newFilename,
148 if ( driverName == QLatin1String(
"MapInfo MIF" ) )
152 GDALDriverH gdalDriver = GDALGetDriverByName( driverName.toLocal8Bit().constData() );
160#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,7,0)
161 return CSLFetchBoolean(
driverMetadata, GDAL_DCAP_FEATURE_STYLES_WRITE,
false );
163 return CSLFetchBoolean(
driverMetadata, GDAL_DCAP_FEATURE_STYLES,
false );
167void QgsVectorFileWriter::init( QString vectorFileName,
168 QString fileEncoding,
172 const QString &driverName,
173 QStringList datasourceOptions,
174 QStringList layerOptions,
175 QString *newFilename,
176 FieldValueConverter *fieldValueConverter,
177 const QString &layerNameIn,
178 ActionOnExistingFile action,
179 QString *newLayer, SinkFlags sinkFlags,
184 if ( vectorFileName.isEmpty() )
191 if ( driverName == QLatin1String(
"MapInfo MIF" ) )
195 else if ( driverName == QLatin1String(
"SpatiaLite" ) )
198 if ( !datasourceOptions.contains( QStringLiteral(
"SPATIALITE=YES" ) ) )
200 datasourceOptions.append( QStringLiteral(
"SPATIALITE=YES" ) );
203 else if ( driverName == QLatin1String(
"DBF file" ) )
206 if ( !layerOptions.contains( QStringLiteral(
"SHPT=NULL" ) ) )
208 layerOptions.append( QStringLiteral(
"SHPT=NULL" ) );
217#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,3,1)
218 QString fidFieldName;
221 for (
const QString &layerOption : layerOptions )
223 if ( layerOption.startsWith( QLatin1String(
"FID=" ) ) )
225 fidFieldName = layerOption.mid( 4 );
229 if ( fidFieldName.isEmpty() )
230 fidFieldName = QStringLiteral(
"fid" );
235 OGRSFDriverH poDriver;
238 poDriver = OGRGetDriverByName(
mOgrDriverName.toLocal8Bit().constData() );
242 mErrorMessage = QObject::tr(
"OGR driver for '%1' not found (OGR error: %2)" )
244 QString::fromUtf8( CPLGetLastErrorMsg() ) );
254 if ( layerOptions.join( QString() ).toUpper().indexOf( QLatin1String(
"ENCODING=" ) ) == -1 )
259 if ( driverName == QLatin1String(
"ESRI Shapefile" ) && !vectorFileName.endsWith( QLatin1String(
".shp" ), Qt::CaseInsensitive ) )
261 vectorFileName += QLatin1String(
".shp" );
263 else if ( driverName == QLatin1String(
"DBF file" ) && !vectorFileName.endsWith( QLatin1String(
".dbf" ), Qt::CaseInsensitive ) )
265 vectorFileName += QLatin1String(
".dbf" );
275#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
276 QStringList allExts = metadata.ext.split(
' ', QString::SkipEmptyParts );
278 QStringList allExts = metadata.ext.split(
' ', Qt::SkipEmptyParts );
281 const auto constAllExts = allExts;
282 for (
const QString &ext : constAllExts )
284 if ( vectorFileName.endsWith(
'.' + ext, Qt::CaseInsensitive ) )
293 vectorFileName +=
'.' + allExts[0];
299 if ( vectorFileName.endsWith( QLatin1String(
".gdb" ), Qt::CaseInsensitive ) )
301 QDir dir( vectorFileName );
304 QFileInfoList fileList = dir.entryInfoList(
305 QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files, QDir::DirsFirst );
306 const auto constFileList = fileList;
307 for (
const QFileInfo &info : constFileList )
309 QFile::remove( info.absoluteFilePath() );
312 QDir().rmdir( vectorFileName );
316 QFile::remove( vectorFileName );
321 if ( metadataFound && !metadata.compulsoryEncoding.isEmpty() )
323 if ( fileEncoding.compare( metadata.compulsoryEncoding, Qt::CaseInsensitive ) != 0 )
325 QgsDebugMsgLevel( QStringLiteral(
"forced %1 encoding for %2" ).arg( metadata.compulsoryEncoding, driverName ), 2 );
326 fileEncoding = metadata.compulsoryEncoding;
331 char **options =
nullptr;
332 if ( !datasourceOptions.isEmpty() )
334 options =
new char *[ datasourceOptions.size() + 1 ];
335 for (
int i = 0; i < datasourceOptions.size(); i++ )
337 QgsDebugMsgLevel( QStringLiteral(
"-dsco=%1" ).arg( datasourceOptions[i] ), 2 );
338 options[i] = CPLStrdup( datasourceOptions[i].toLocal8Bit().constData() );
340 options[ datasourceOptions.size()] =
nullptr;
347 mDS.reset( OGR_Dr_CreateDataSource( poDriver, vectorFileName.toUtf8().constData(), options ) );
349 mDS.reset( OGROpen( vectorFileName.toUtf8().constData(), TRUE,
nullptr ) );
353 for (
int i = 0; i < datasourceOptions.size(); i++ )
354 CPLFree( options[i] );
363 mErrorMessage = QObject::tr(
"Creation of data source failed (OGR error: %1)" )
364 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
366 mErrorMessage = QObject::tr(
"Opening of data source in update mode failed (OGR error: %1)" )
367 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
371 QString layerName( layerNameIn );
372 if ( layerName.isEmpty() )
373 layerName = QFileInfo( vectorFileName ).baseName();
377 const int layer_count = OGR_DS_GetLayerCount(
mDS.get() );
378 for (
int i = 0; i < layer_count; i++ )
380 OGRLayerH hLayer = OGR_DS_GetLayer(
mDS.get(), i );
381 if ( EQUAL( OGR_L_GetName( hLayer ), layerName.toUtf8().constData() ) )
383 if ( OGR_DS_DeleteLayer(
mDS.get(), i ) != OGRERR_NONE )
386 mErrorMessage = QObject::tr(
"Overwriting of existing layer failed (OGR error: %1)" )
387 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
401 QgsDebugMsgLevel( QStringLiteral(
"Opened data source in update mode" ), 2 );
405 mCodec = QTextCodec::codecForName( fileEncoding.toLocal8Bit().constData() );
408 QgsDebugMsg(
"error finding QTextCodec for " + fileEncoding );
411 QString enc = settings.
value( QStringLiteral(
"UI/encoding" ),
"System" ).toString();
412 mCodec = QTextCodec::codecForName( enc.toLocal8Bit().constData() );
415 QgsDebugMsg(
"error finding QTextCodec for " + enc );
416 mCodec = QTextCodec::codecForLocale();
422 if ( driverName == QLatin1String(
"KML" ) || driverName == QLatin1String(
"LIBKML" ) || driverName == QLatin1String(
"GPX" ) )
424 if ( srs.
authid() != QLatin1String(
"EPSG:4326" ) )
439 int optIndex = layerOptions.indexOf( QLatin1String(
"FEATURE_DATASET=" ) );
440 if ( optIndex != -1 )
442 layerOptions.removeAt( optIndex );
445 if ( !layerOptions.isEmpty() )
447 options =
new char *[ layerOptions.size() + 1 ];
448 for (
int i = 0; i < layerOptions.size(); i++ )
451 options[i] = CPLStrdup( layerOptions[i].toLocal8Bit().constData() );
453 options[ layerOptions.size()] =
nullptr;
457 CPLSetConfigOption(
"SHAPE_ENCODING",
"" );
461 mLayer = OGR_DS_CreateLayer(
mDS.get(), layerName.toUtf8().constData(),
mOgrRef, wkbType, options );
464 *newLayer = OGR_L_GetName(
mLayer );
465 if ( driverName == QLatin1String(
"GPX" ) )
472 if ( !EQUAL( layerName.toUtf8().constData(),
"track_points" ) &&
473 !EQUAL( layerName.toUtf8().constData(),
"route_points" ) )
475 *newLayer = QStringLiteral(
"waypoints" );
482 const char *pszForceGPXTrack
483 = CSLFetchNameValue( options,
"FORCE_GPX_TRACK" );
484 if ( pszForceGPXTrack && CPLTestBool( pszForceGPXTrack ) )
485 *newLayer = QStringLiteral(
"tracks" );
487 *newLayer = QStringLiteral(
"routes" );
494 const char *pszForceGPXRoute
495 = CSLFetchNameValue( options,
"FORCE_GPX_ROUTE" );
496 if ( pszForceGPXRoute && CPLTestBool( pszForceGPXRoute ) )
497 *newLayer = QStringLiteral(
"routes" );
499 *newLayer = QStringLiteral(
"tracks" );
509 else if ( driverName == QLatin1String(
"DGN" ) )
511 mLayer = OGR_DS_GetLayerByName(
mDS.get(),
"elements" );
515 mLayer = OGR_DS_GetLayerByName(
mDS.get(), layerName.toUtf8().constData() );
520 for (
int i = 0; i < layerOptions.size(); i++ )
521 CPLFree( options[i] );
530 QString layerName = vectorFileName.left( vectorFileName.indexOf( QLatin1String(
".shp" ), Qt::CaseInsensitive ) );
531 QFile prjFile( layerName +
".qpj" );
532 if ( prjFile.exists() )
540 mErrorMessage = QObject::tr(
"Creation of layer failed (OGR error: %1)" )
541 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
543 mErrorMessage = QObject::tr(
"Opening of layer failed (OGR error: %1)" )
544 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
549 OGRFeatureDefnH defn = OGR_L_GetLayerDefn(
mLayer );
558 QSet<int> existingIdxs;
568 for (
int fldIdx = 0; fldIdx < fields.
count(); ++fldIdx )
572 if ( fieldValueConverter )
574 attrField = fieldValueConverter->fieldDefinition( fields.
at( fldIdx ) );
579 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( attrField.
name() ) );
588 switch ( fieldNameSource )
591 name = attrField.
name();
595 name = !attrField.
alias().isEmpty() ? attrField.
alias() : attrField.
name();
599 OGRFieldType ogrType = OFTString;
600 OGRFieldSubType ogrSubType = OFSTNone;
601 int ogrWidth = attrField.
length();
602 int ogrPrecision = attrField.
precision();
603 if ( ogrPrecision > 0 )
606 switch ( attrField.
type() )
608 case QVariant::LongLong:
610 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
611 if ( pszDataTypes && strstr( pszDataTypes,
"Integer64" ) )
612 ogrType = OFTInteger64;
615 ogrWidth = ogrWidth > 0 && ogrWidth <= 20 ? ogrWidth : 20;
619 case QVariant::String:
621 if ( ( ogrWidth <= 0 || ogrWidth > 255 ) &&
mOgrDriverName == QLatin1String(
"ESRI Shapefile" ) )
626 ogrType = OFTInteger;
627 ogrWidth = ogrWidth > 0 && ogrWidth <= 10 ? ogrWidth : 10;
632 ogrType = OFTInteger;
633 ogrSubType = OFSTBoolean;
638 case QVariant::Double:
639#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,3,1)
640 if (
mOgrDriverName == QLatin1String(
"GPKG" ) && attrField.
precision() == 0 && attrField.
name().compare( fidFieldName, Qt::CaseInsensitive ) == 0 )
643 ogrType = OFTInteger64;
666 case QVariant::DateTime:
674 ogrType = OFTDateTime;
678 case QVariant::ByteArray:
682 case QVariant::StringList:
688 ogrSubType = OFSTJSON;
692 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
693 if ( pszDataTypes && strstr( pszDataTypes,
"StringList" ) )
695 ogrType = OFTStringList;
696 mSupportedListSubTypes.insert( QVariant::String );
711 ogrSubType = OFSTJSON;
716 if ( attrField.
subType() == QVariant::String )
718 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
719 if ( pszDataTypes && strstr( pszDataTypes,
"StringList" ) )
721 ogrType = OFTStringList;
722 mSupportedListSubTypes.insert( QVariant::String );
731 else if ( attrField.
subType() == QVariant::Int )
733 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
734 if ( pszDataTypes && strstr( pszDataTypes,
"IntegerList" ) )
736 ogrType = OFTIntegerList;
737 mSupportedListSubTypes.insert( QVariant::Int );
746 else if ( attrField.
subType() == QVariant::Double )
748 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
749 if ( pszDataTypes && strstr( pszDataTypes,
"RealList" ) )
751 ogrType = OFTRealList;
752 mSupportedListSubTypes.insert( QVariant::Double );
761 else if ( attrField.
subType() == QVariant::LongLong )
763 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
764 if ( pszDataTypes && strstr( pszDataTypes,
"Integer64List" ) )
766 ogrType = OFTInteger64List;
767 mSupportedListSubTypes.insert( QVariant::LongLong );
781 mErrorMessage = QObject::tr(
"Unsupported type for field %1" )
782 .arg( attrField.
name() );
787 if (
mOgrDriverName == QLatin1String(
"SQLite" ) && name.compare( QLatin1String(
"ogc_fid" ), Qt::CaseInsensitive ) == 0 )
790 for ( i = 0; i < 10; i++ )
792 name = QStringLiteral(
"ogc_fid%1" ).arg( i );
795 for ( j = 0; j < fields.
size() && name.compare( fields.
at( j ).
name(), Qt::CaseInsensitive ) != 0; j++ )
798 if ( j == fields.
size() )
804 mErrorMessage = QObject::tr(
"No available replacement for internal fieldname ogc_fid found" ).arg( attrField.
name() );
809 QgsMessageLog::logMessage( QObject::tr(
"Reserved attribute name ogc_fid replaced with %1" ).arg( name ), QObject::tr(
"OGR" ) );
816 OGR_Fld_SetWidth( fld.get(), ogrWidth );
819 if ( ogrPrecision >= 0 )
821 OGR_Fld_SetPrecision( fld.get(), ogrPrecision );
824 if ( ogrSubType != OFSTNone )
825 OGR_Fld_SetSubType( fld.get(), ogrSubType );
829 " type " + QString( QVariant::typeToName( attrField.
type() ) ) +
830 " width " + QString::number( ogrWidth ) +
831 " precision " + QString::number( ogrPrecision ), 2 );
832 if ( OGR_L_CreateField(
mLayer, fld.get(),
true ) != OGRERR_NONE )
835 mErrorMessage = QObject::tr(
"Creation of field %1 failed (OGR error: %2)" )
836 .arg( attrField.
name(),
837 QString::fromUtf8( CPLGetLastErrorMsg() ) );
842 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( name ) );
843 QgsDebugMsgLevel( QStringLiteral(
"returned field index for %1: %2" ).arg( name ).arg( ogrIdx ), 2 );
844 if ( ogrIdx < 0 || existingIdxs.contains( ogrIdx ) )
847 ogrIdx = OGR_FD_GetFieldCount( defn ) - 1;
852 mErrorMessage = QObject::tr(
"Created field %1 not found (OGR error: %2)" )
853 .arg( attrField.
name(),
854 QString::fromUtf8( CPLGetLastErrorMsg() ) );
860 existingIdxs.insert( ogrIdx );
868 for (
int fldIdx = 0; fldIdx < fields.
count(); ++fldIdx )
871 QString name( attrField.
name() );
872 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( name ) );
884 int fidIdx = fields.
lookupField( QStringLiteral(
"FID" ) );
895 *newFilename = vectorFileName;
898 mUsingTransaction =
true;
899 if ( OGRERR_NONE != OGR_L_StartTransaction(
mLayer ) )
901 mUsingTransaction =
false;
911class QgsVectorFileWriterMetadataContainer
915 QgsVectorFileWriterMetadataContainer()
917 QMap<QString, QgsVectorFileWriter::Option *> datasetOptions;
918 QMap<QString, QgsVectorFileWriter::Option *> layerOptions;
921 datasetOptions.clear();
922 layerOptions.clear();
925 QObject::tr(
"Compression method." ),
927 << QStringLiteral(
"UNCOMPRESSED" )
928 << QStringLiteral(
"ZSTD" )
929 << QStringLiteral(
"LZ4" ),
930 QStringLiteral(
"LZ4" ),
935 QObject::tr(
"Geometry encoding." ),
937 << QStringLiteral(
"GEOARROW" )
938 << QStringLiteral(
"WKB" )
939 << QStringLiteral(
"WKT" ),
940 QStringLiteral(
"GEOARROW" ),
945 QObject::tr(
"Maximum number of rows per batch." ),
950 QObject::tr(
"Name for the feature identifier column" ),
955 QObject::tr(
"Name for the geometry column" ),
956 QStringLiteral(
"geometry" )
959 driverMetadata.insert( QStringLiteral(
"Arrow" ),
961 QStringLiteral(
"(Geo)Arrow" ),
962 QObject::tr(
"(Geo)Arrow" ),
963 QStringLiteral(
"*.arrow *.feather *.arrows *.ipc" ),
964 QStringLiteral(
"arrow" ),
967 QStringLiteral(
"UTF-8" )
972 datasetOptions.clear();
973 layerOptions.clear();
975 driverMetadata.insert( QStringLiteral(
"AVCE00" ),
977 QStringLiteral(
"Arc/Info ASCII Coverage" ),
978 QObject::tr(
"Arc/Info ASCII Coverage" ),
979 QStringLiteral(
"*.e00" ),
980 QStringLiteral(
"e00" ),
987#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,3,0)
991 datasetOptions.clear();
992 layerOptions.clear();
995 QObject::tr(
"New BNA files are created by the "
996 "systems default line termination conventions. "
997 "This may be overridden here." ),
999 << QStringLiteral(
"CRLF" )
1000 << QStringLiteral(
"LF" ),
1006 QObject::tr(
"By default, BNA files are created in multi-line format. "
1007 "For each record, the first line contains the identifiers and the "
1008 "type/number of coordinates to follow. Each following line contains "
1009 "a pair of coordinates." ),
1014 QObject::tr(
"BNA records may contain from 2 to 4 identifiers per record. "
1015 "Some software packages only support a precise number of identifiers. "
1016 "You can override the default value (2) by a precise value." ),
1018 << QStringLiteral(
"2" )
1019 << QStringLiteral(
"3" )
1020 << QStringLiteral(
"4" )
1021 << QStringLiteral(
"NB_SOURCE_FIELDS" ),
1022 QStringLiteral(
"2" )
1026 QObject::tr(
"The BNA writer will try to recognize ellipses and circles when writing a polygon. "
1027 "This will only work if the feature has previously been read from a BNA file. "
1028 "As some software packages do not support ellipses/circles in BNA data file, "
1029 "it may be useful to tell the writer by specifying ELLIPSES_AS_ELLIPSES=NO not "
1030 "to export them as such, but keep them as polygons." ),
1035 QObject::tr(
"Limit the number of coordinate pairs per line in multiline format." ),
1040 QObject::tr(
"Set the number of decimal for coordinates. Default value is 10." ),
1044 driverMetadata.insert( QStringLiteral(
"BNA" ),
1046 QStringLiteral(
"Atlas BNA" ),
1047 QObject::tr(
"Atlas BNA" ),
1048 QStringLiteral(
"*.bna" ),
1049 QStringLiteral(
"bna" ),
1057 datasetOptions.clear();
1058 layerOptions.clear();
1061 QObject::tr(
"By default when creating new .csv files they "
1062 "are created with the line termination conventions "
1063 "of the local platform (CR/LF on Win32 or LF on all other systems). "
1064 "This may be overridden through the use of the LINEFORMAT option." ),
1066 << QStringLiteral(
"CRLF" )
1067 << QStringLiteral(
"LF" ),
1073 QObject::tr(
"By default, the geometry of a feature written to a .csv file is discarded. "
1074 "It is possible to export the geometry in its WKT representation by "
1075 "specifying GEOMETRY=AS_WKT. It is also possible to export point geometries "
1076 "into their X,Y,Z components by specifying GEOMETRY=AS_XYZ, GEOMETRY=AS_XY "
1077 "or GEOMETRY=AS_YX." ),
1079 << QStringLiteral(
"AS_WKT" )
1080 << QStringLiteral(
"AS_XYZ" )
1081 << QStringLiteral(
"AS_XY" )
1082 << QStringLiteral(
"AS_YX" ),
1088 QObject::tr(
"Create the associated .csvt file to describe the type of each "
1089 "column of the layer and its optional width and precision." ),
1094 QObject::tr(
"Field separator character." ),
1096 << QStringLiteral(
"COMMA" )
1097 << QStringLiteral(
"SEMICOLON" )
1098 << QStringLiteral(
"TAB" ),
1099 QStringLiteral(
"COMMA" )
1103 QObject::tr(
"Double-quote strings. IF_AMBIGUOUS means that string values that look like numbers will be quoted." ),
1105 << QStringLiteral(
"IF_NEEDED" )
1106 << QStringLiteral(
"IF_AMBIGUOUS" )
1107 << QStringLiteral(
"ALWAYS" ),
1108 QStringLiteral(
"IF_AMBIGUOUS" )
1112 QObject::tr(
"Write a UTF-8 Byte Order Mark (BOM) at the start of the file." ),
1116 driverMetadata.insert( QStringLiteral(
"CSV" ),
1118 QStringLiteral(
"Comma Separated Value [CSV]" ),
1119 QObject::tr(
"Comma Separated Value [CSV]" ),
1120 QStringLiteral(
"*.csv" ),
1121 QStringLiteral(
"csv" ),
1128 datasetOptions.clear();
1129 layerOptions.clear();
1131 driverMetadata.insert( QStringLiteral(
"FlatGeobuf" ),
1133 QStringLiteral(
"FlatGeobuf" ),
1134 QObject::tr(
"FlatGeobuf" ),
1135 QStringLiteral(
"*.fgb" ),
1136 QStringLiteral(
"fgb" ),
1139 QStringLiteral(
"UTF-8" )
1144 datasetOptions.clear();
1145 layerOptions.clear();
1148 QObject::tr(
"Override the type of shapefile created. "
1149 "Can be one of NULL for a simple .dbf file with no .shp file, POINT, "
1150 "ARC, POLYGON or MULTIPOINT for 2D, or POINTZ, ARCZ, POLYGONZ or "
1151 "MULTIPOINTZ for 3D;" ) +
1152 QObject::tr(
" POINTM, ARCM, POLYGONM or MULTIPOINTM for measured geometries"
1153 " and POINTZM, ARCZM, POLYGONZM or MULTIPOINTZM for 3D measured"
1155 QObject::tr(
" MULTIPATCH files are supported since GDAL 2.2." ) +
1158 << QStringLiteral(
"NULL" )
1159 << QStringLiteral(
"POINT" )
1160 << QStringLiteral(
"ARC" )
1161 << QStringLiteral(
"POLYGON" )
1162 << QStringLiteral(
"MULTIPOINT" )
1163 << QStringLiteral(
"POINTZ" )
1164 << QStringLiteral(
"ARCZ" )
1165 << QStringLiteral(
"POLYGONZ" )
1166 << QStringLiteral(
"MULTIPOINTZ" )
1167 << QStringLiteral(
"POINTM" )
1168 << QStringLiteral(
"ARCM" )
1169 << QStringLiteral(
"POLYGONM" )
1170 << QStringLiteral(
"MULTIPOINTM" )
1171 << QStringLiteral(
"POINTZM" )
1172 << QStringLiteral(
"ARCZM" )
1173 << QStringLiteral(
"POLYGONZM" )
1174 << QStringLiteral(
"MULTIPOINTZM" )
1175 << QStringLiteral(
"MULTIPATCH" )
1185 QObject::tr(
"Set the encoding value in the DBF file. "
1186 "The default value is LDID/87. It is not clear "
1187 "what other values may be appropriate." ),
1195 QObject::tr(
"Set to YES to resize fields to their optimal size." ),
1199 driverMetadata.insert( QStringLiteral(
"ESRI" ),
1201 QStringLiteral(
"ESRI Shapefile" ),
1202 QObject::tr(
"ESRI Shapefile" ),
1203 QStringLiteral(
"*.shp" ),
1204 QStringLiteral(
"shp" ),
1211 datasetOptions.clear();
1212 layerOptions.clear();
1214 driverMetadata.insert( QStringLiteral(
"DBF File" ),
1216 QStringLiteral(
"DBF File" ),
1217 QObject::tr(
"DBF File" ),
1218 QStringLiteral(
"*.dbf" ),
1219 QStringLiteral(
"dbf" ),
1226 datasetOptions.clear();
1227 layerOptions.clear();
1229 driverMetadata.insert( QStringLiteral(
"FMEObjects Gateway" ),
1231 QStringLiteral(
"FMEObjects Gateway" ),
1232 QObject::tr(
"FMEObjects Gateway" ),
1233 QStringLiteral(
"*.fdd" ),
1234 QStringLiteral(
"fdd" ),
1241 datasetOptions.clear();
1242 layerOptions.clear();
1245 QObject::tr(
"Set to YES to write a bbox property with the bounding box "
1246 "of the geometries at the feature and feature collection level." ),
1251 QObject::tr(
"Maximum number of figures after decimal separator to write in coordinates. "
1252 "Defaults to 15. Truncation will occur to remove trailing zeros." ),
1257 QObject::tr(
"Whether to use RFC 7946 standard. "
1258 "If disabled GeoJSON 2008 initial version will be used. "
1259 "Default is NO (thus GeoJSON 2008). See also Documentation (via Help button)" ),
1263 driverMetadata.insert( QStringLiteral(
"GeoJSON" ),
1265 QStringLiteral(
"GeoJSON" ),
1266 QObject::tr(
"GeoJSON" ),
1267 QStringLiteral(
"*.geojson" ),
1268 QStringLiteral(
"geojson" ),
1271 QStringLiteral(
"UTF-8" )
1276 datasetOptions.clear();
1277 layerOptions.clear();
1280 QObject::tr(
"Maximum number of figures after decimal separator to write in coordinates. "
1281 "Defaults to 15. Truncation will occur to remove trailing zeros." ),
1286 QObject::tr(
"Whether to start records with the RS=0x1E character (RFC 8142 standard). "
1287 "Defaults to NO: Newline Delimited JSON (geojsonl). \n"
1288 "If set to YES: RFC 8142 standard: GeoJSON Text Sequences (geojsons)." ),
1292 driverMetadata.insert( QStringLiteral(
"GeoJSONSeq" ),
1294 QStringLiteral(
"GeoJSON - Newline Delimited" ),
1295 QObject::tr(
"GeoJSON - Newline Delimited" ),
1296 QStringLiteral(
"*.geojsonl *.geojsons *.json" ),
1297 QStringLiteral(
"json" ),
1300 QStringLiteral(
"UTF-8" )
1305 datasetOptions.clear();
1306 layerOptions.clear();
1309 QObject::tr(
"whether the document must be in RSS 2.0 or Atom 1.0 format. "
1310 "Default value : RSS" ),
1312 << QStringLiteral(
"RSS" )
1313 << QStringLiteral(
"ATOM" ),
1314 QStringLiteral(
"RSS" )
1318 QObject::tr(
"The encoding of location information. Default value : SIMPLE. "
1319 "W3C_GEO only supports point geometries. "
1320 "SIMPLE or W3C_GEO only support geometries in geographic WGS84 coordinates." ),
1322 << QStringLiteral(
"SIMPLE" )
1323 << QStringLiteral(
"GML" )
1324 << QStringLiteral(
"W3C_GEO" ),
1325 QStringLiteral(
"SIMPLE" )
1329 QObject::tr(
"If defined to YES, extension fields will be written. "
1330 "If the field name not found in the base schema matches "
1331 "the foo_bar pattern, foo will be considered as the namespace "
1332 "of the element, and a <foo:bar> element will be written. "
1333 "Otherwise, elements will be written in the <ogr:> namespace." ),
1338 QObject::tr(
"If defined to NO, only <entry> or <item> elements will be written. "
1339 "The user will have to provide the appropriate header and footer of the document." ),
1344 QObject::tr(
"XML content that will be put between the <channel> element and the "
1345 "first <item> element for a RSS document, or between the xml tag and "
1346 "the first <entry> element for an Atom document." ),
1351 QObject::tr(
"Value put inside the <title> element in the header. "
1352 "If not provided, a dummy value will be used as that element is compulsory." ),
1357 QObject::tr(
"Value put inside the <description> element in the header. "
1358 "If not provided, a dummy value will be used as that element is compulsory." ),
1363 QObject::tr(
"Value put inside the <link> element in the header. "
1364 "If not provided, a dummy value will be used as that element is compulsory." ),
1369 QObject::tr(
"Value put inside the <updated> element in the header. "
1370 "Should be formatted as a XML datetime. "
1371 "If not provided, a dummy value will be used as that element is compulsory." ),
1376 QObject::tr(
"Value put inside the <author><name> element in the header. "
1377 "If not provided, a dummy value will be used as that element is compulsory." ),
1382 QObject::tr(
"Value put inside the <id> element in the header. "
1383 "If not provided, a dummy value will be used as that element is compulsory." ),
1387 driverMetadata.insert( QStringLiteral(
"GeoRSS" ),
1389 QStringLiteral(
"GeoRSS" ),
1390 QObject::tr(
"GeoRSS" ),
1391 QStringLiteral(
"*.xml" ),
1392 QStringLiteral(
"xml" ),
1395 QStringLiteral(
"UTF-8" )
1400 datasetOptions.clear();
1401 layerOptions.clear();
1404 QObject::tr(
"If provided, this URI will be inserted as the schema location. "
1405 "Note that the schema file isn't actually accessed by OGR, so it "
1406 "is up to the user to ensure it will match the schema of the OGR "
1407 "produced GML data file." ),
1412 QObject::tr(
"This writes a GML application schema file to a corresponding "
1413 ".xsd file (with the same basename). If INTERNAL is used the "
1414 "schema is written within the GML file, but this is experimental "
1415 "and almost certainly not valid XML. "
1416 "OFF disables schema generation (and is implicit if XSISCHEMAURI is used)." ),
1418 << QStringLiteral(
"EXTERNAL" )
1419 << QStringLiteral(
"INTERNAL" )
1420 << QStringLiteral(
"OFF" ),
1421 QStringLiteral(
"EXTERNAL" )
1425 QObject::tr(
"This is the prefix for the application target namespace." ),
1426 QStringLiteral(
"ogr" )
1430 QObject::tr(
"Can be set to TRUE to avoid writing the prefix of the "
1431 "application target namespace in the GML file." ),
1436 QObject::tr(
"Defaults to 'http://ogr.maptools.org/'. "
1437 "This is the application target namespace." ),
1438 QStringLiteral(
"http://ogr.maptools.org/" )
1442 QObject::tr(
"If not specified, GML2 will be used." ),
1444 << QStringLiteral(
"GML3" )
1445 << QStringLiteral(
"GML3Deegree" )
1446 << QStringLiteral(
"GML3.2" ),
1452 QObject::tr(
"Only valid when FORMAT=GML3/GML3Degree/GML3.2. Default to YES. "
1453 "If YES, SRS with EPSG authority will be written with the "
1454 "'urn:ogc:def:crs:EPSG::' prefix. In the case the SRS is a "
1455 "geographic SRS without explicit AXIS order, but that the same "
1456 "SRS authority code imported with ImportFromEPSGA() should be "
1457 "treated as lat/long, then the function will take care of coordinate "
1458 "order swapping. If set to NO, SRS with EPSG authority will be "
1459 "written with the 'EPSG:' prefix, even if they are in lat/long order." ),
1464 QObject::tr(
"only valid when FORMAT=GML3/GML3Degree/GML3.2) Default to YES. "
1465 "If set to NO, the <gml:boundedBy> element will not be written for "
1471 QObject::tr(
"Default to YES. If YES, the output will be indented with spaces "
1472 "for more readability, but at the expense of file size." ),
1477 driverMetadata.insert( QStringLiteral(
"GML" ),
1479 QStringLiteral(
"Geography Markup Language [GML]" ),
1480 QObject::tr(
"Geography Markup Language [GML]" ),
1481 QStringLiteral(
"*.gml" ),
1482 QStringLiteral(
"gml" ),
1485 QStringLiteral(
"UTF-8" )
1490 datasetOptions.clear();
1491 layerOptions.clear();
1494 QObject::tr(
"Human-readable identifier (e.g. short name) for the layer content" ),
1499 QObject::tr(
"Human-readable description for the layer content" ),
1504 QObject::tr(
"Name for the feature identifier column" ),
1505 QStringLiteral(
"fid" )
1509 QObject::tr(
"Name for the geometry column" ),
1510 QStringLiteral(
"geom" )
1514 QObject::tr(
"If a spatial index must be created." ),
1518 driverMetadata.insert( QStringLiteral(
"GPKG" ),
1520 QStringLiteral(
"GeoPackage" ),
1521 QObject::tr(
"GeoPackage" ),
1522 QStringLiteral(
"*.gpkg" ),
1523 QStringLiteral(
"gpkg" ),
1526 QStringLiteral(
"UTF-8" )
1531 datasetOptions.clear();
1532 layerOptions.clear();
1534 driverMetadata.insert( QStringLiteral(
"GMT" ),
1536 QStringLiteral(
"Generic Mapping Tools [GMT]" ),
1537 QObject::tr(
"Generic Mapping Tools [GMT]" ),
1538 QStringLiteral(
"*.gmt" ),
1539 QStringLiteral(
"gmt" ),
1546 datasetOptions.clear();
1547 layerOptions.clear();
1550 QObject::tr(
"By default when writing a layer whose features are of "
1551 "type wkbLineString, the GPX driver chooses to write "
1552 "them as routes. If FORCE_GPX_TRACK=YES is specified, "
1553 "they will be written as tracks." ),
1558 QObject::tr(
"By default when writing a layer whose features are of "
1559 "type wkbMultiLineString, the GPX driver chooses to write "
1560 "them as tracks. If FORCE_GPX_ROUTE=YES is specified, "
1561 "they will be written as routes, provided that the multilines "
1562 "are composed of only one single line." ),
1567 QObject::tr(
"If GPX_USE_EXTENSIONS=YES is specified, "
1568 "extra fields will be written inside the <extensions> tag." ),
1573 QObject::tr(
"Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS_URL "
1574 "is set. The namespace value used for extension tags. By default, 'ogr'." ),
1575 QStringLiteral(
"ogr" )
1579 QObject::tr(
"Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS "
1580 "is set. The namespace URI. By default, 'http://osgeo.org/gdal'." ),
1581 QStringLiteral(
"http://osgeo.org/gdal" )
1585 QObject::tr(
"By default files are created with the line termination "
1586 "conventions of the local platform (CR/LF on win32 or LF "
1587 "on all other systems). This may be overridden through use "
1588 "of the LINEFORMAT layer creation option which may have a value "
1589 "of CRLF (DOS format) or LF (Unix format)." ),
1591 << QStringLiteral(
"CRLF" )
1592 << QStringLiteral(
"LF" ),
1597 driverMetadata.insert( QStringLiteral(
"GPX" ),
1599 QStringLiteral(
"GPS eXchange Format [GPX]" ),
1600 QObject::tr(
"GPS eXchange Format [GPX]" ),
1601 QStringLiteral(
"*.gpx" ),
1602 QStringLiteral(
"gpx" ),
1605 QStringLiteral(
"UTF-8" )
1610 datasetOptions.clear();
1611 layerOptions.clear();
1613 driverMetadata.insert( QStringLiteral(
"Interlis 1" ),
1615 QStringLiteral(
"INTERLIS 1" ),
1616 QObject::tr(
"INTERLIS 1" ),
1617 QStringLiteral(
"*.itf *.xml *.ili" ),
1618 QStringLiteral(
"ili" ),
1625 datasetOptions.clear();
1626 layerOptions.clear();
1628 driverMetadata.insert( QStringLiteral(
"Interlis 2" ),
1630 QStringLiteral(
"INTERLIS 2" ),
1631 QObject::tr(
"INTERLIS 2" ),
1632 QStringLiteral(
"*.xtf *.xml *.ili" ),
1633 QStringLiteral(
"ili" ),
1640 datasetOptions.clear();
1641 layerOptions.clear();
1644 QObject::tr(
"Allows you to specify the field to use for the KML <name> element." ),
1645 QStringLiteral(
"Name" )
1649 QObject::tr(
"Allows you to specify the field to use for the KML <description> element." ),
1650 QStringLiteral(
"Description" )
1654 QObject::tr(
"Allows you to specify the AltitudeMode to use for KML geometries. "
1655 "This will only affect 3D geometries and must be one of the valid KML options." ),
1657 << QStringLiteral(
"clampToGround" )
1658 << QStringLiteral(
"relativeToGround" )
1659 << QStringLiteral(
"absolute" ),
1660 QStringLiteral(
"relativeToGround" )
1664 QObject::tr(
"The DOCUMENT_ID datasource creation option can be used to specified "
1665 "the id of the root <Document> node. The default value is root_doc." ),
1666 QStringLiteral(
"root_doc" )
1669 driverMetadata.insert( QStringLiteral(
"KML" ),
1671 QStringLiteral(
"Keyhole Markup Language [KML]" ),
1672 QObject::tr(
"Keyhole Markup Language [KML]" ),
1673 QStringLiteral(
"*.kml" ),
1674 QStringLiteral(
"kml" ),
1677 QStringLiteral(
"UTF-8" )
1682 datasetOptions.clear();
1683 layerOptions.clear();
1685 auto insertMapInfoOptions = []( QMap<QString, QgsVectorFileWriter::Option *> &datasetOptions, QMap<QString, QgsVectorFileWriter::Option *> &layerOptions )
1688 QObject::tr(
"Use this to turn on 'quick spatial index mode'. "
1689 "In this mode writing files can be about 5 times faster, "
1690 "but spatial queries can be up to 30 times slower." ),
1692 << QStringLiteral(
"QUICK" )
1693 << QStringLiteral(
"OPTIMIZED" ),
1694 QStringLiteral(
"QUICK" ),
1699 QObject::tr(
"(multiples of 512): Block size for .map files. Defaults "
1700 "to 512. MapInfo 15.2 and above creates .tab files with a "
1701 "blocksize of 16384 bytes. Any MapInfo version should be "
1702 "able to handle block sizes from 512 to 32256." ),
1706 QObject::tr(
"xmin,ymin,xmax,ymax: Define custom layer bounds to increase the "
1707 "accuracy of the coordinates. Note: the geometry of written "
1708 "features must be within the defined box." ),
1712 insertMapInfoOptions( datasetOptions, layerOptions );
1714 driverMetadata.insert( QStringLiteral(
"MapInfo File" ),
1716 QStringLiteral(
"Mapinfo" ),
1717 QObject::tr(
"Mapinfo TAB" ),
1718 QStringLiteral(
"*.tab" ),
1719 QStringLiteral(
"tab" ),
1724 datasetOptions.clear();
1725 layerOptions.clear();
1726 insertMapInfoOptions( datasetOptions, layerOptions );
1729 driverMetadata.insert( QStringLiteral(
"MapInfo MIF" ),
1731 QStringLiteral(
"Mapinfo" ),
1732 QObject::tr(
"Mapinfo MIF" ),
1733 QStringLiteral(
"*.mif" ),
1734 QStringLiteral(
"mif" ),
1741 datasetOptions.clear();
1742 layerOptions.clear();
1745 QObject::tr(
"Determine whether 2D (seed_2d.dgn) or 3D (seed_3d.dgn) "
1746 "seed file should be used. This option is ignored if the SEED option is provided." ),
1751 QObject::tr(
"Override the seed file to use." ),
1756 QObject::tr(
"Indicate whether the whole seed file should be copied. "
1757 "If not, only the first three elements will be copied." ),
1762 QObject::tr(
"Indicates whether the color table should be copied from the seed file." ),
1767 QObject::tr(
"Override the master unit name from the seed file with "
1768 "the provided one or two character unit name." ),
1773 QObject::tr(
"Override the sub unit name from the seed file with the provided "
1774 "one or two character unit name." ),
1779 QObject::tr(
"Override the number of subunits per master unit. "
1780 "By default the seed file value is used." ),
1785 QObject::tr(
"Override the number of UORs (Units of Resolution) "
1786 "per sub unit. By default the seed file value is used." ),
1791 QObject::tr(
"ORIGIN=x,y,z: Override the origin of the design plane. "
1792 "By default the origin from the seed file is used." ),
1796 driverMetadata.insert( QStringLiteral(
"DGN" ),
1798 QStringLiteral(
"Microstation DGN" ),
1799 QObject::tr(
"Microstation DGN" ),
1800 QStringLiteral(
"*.dgn" ),
1801 QStringLiteral(
"dgn" ),
1808 datasetOptions.clear();
1809 layerOptions.clear();
1812 QObject::tr(
"Should update files be incorporated into the base data on the fly." ),
1814 << QStringLiteral(
"APPLY" )
1815 << QStringLiteral(
"IGNORE" ),
1816 QStringLiteral(
"APPLY" )
1820 QObject::tr(
"Should multipoint soundings be split into many single point sounding features. "
1821 "Multipoint geometries are not well handled by many formats, "
1822 "so it can be convenient to split single sounding features with many points "
1823 "into many single point features." ),
1828 QObject::tr(
"Should a DEPTH attribute be added on SOUNDG features and assign the depth "
1829 "of the sounding. This should only be enabled when SPLIT_MULTIPOINT is "
1835 QObject::tr(
"Should all the low level geometry primitives be returned as special "
1836 "IsolatedNode, ConnectedNode, Edge and Face layers." ),
1841 QObject::tr(
"If enabled, numeric attributes assigned an empty string as a value will "
1842 "be preserved as a special numeric value. This option should not generally "
1843 "be needed, but may be useful when translated S-57 to S-57 losslessly." ),
1848 QObject::tr(
"Should LNAM and LNAM_REFS fields be attached to features capturing "
1849 "the feature to feature relationships in the FFPT group of the S-57 file." ),
1854 QObject::tr(
"Should additional attributes relating features to their underlying "
1855 "geometric primitives be attached. These are the values of the FSPT group, "
1856 "and are primarily needed when doing S-57 to S-57 translations." ),
1861 QObject::tr(
"Should attribute values be recoded to UTF-8 from the character encoding "
1862 "specified in the S57 DSSI record." ),
1868 driverMetadata.insert( QStringLiteral(
"S57" ),
1870 QStringLiteral(
"S-57 Base file" ),
1871 QObject::tr(
"S-57 Base file" ),
1872 QStringLiteral(
"*.000" ),
1873 QStringLiteral(
"000" ),
1880 datasetOptions.clear();
1881 layerOptions.clear();
1883 driverMetadata.insert( QStringLiteral(
"SDTS" ),
1885 QStringLiteral(
"Spatial Data Transfer Standard [SDTS]" ),
1886 QObject::tr(
"Spatial Data Transfer Standard [SDTS]" ),
1887 QStringLiteral(
"*catd.ddf" ),
1888 QStringLiteral(
"ddf" ),
1895 datasetOptions.clear();
1896 layerOptions.clear();
1899 QObject::tr(
"Can be used to avoid creating the geometry_columns and spatial_ref_sys "
1900 "tables in a new database. By default these metadata tables are created "
1901 "when a new database is created." ),
1907 QStringLiteral(
"NO" )
1912 QStringLiteral(
"NO" )
1916 QObject::tr(
"Controls the format used for the geometry column. Defaults to WKB. "
1917 "This is generally more space and processing efficient, but harder "
1918 "to inspect or use in simple applications than WKT (Well Known Text)." ),
1920 << QStringLiteral(
"WKB" )
1921 << QStringLiteral(
"WKT" ),
1922 QStringLiteral(
"WKB" )
1926 QObject::tr(
"Controls whether layer and field names will be laundered for easier use "
1927 "in SQLite. Laundered names will be converted to lower case and some special "
1928 "characters(' - #) will be changed to underscores." ),
1933 QStringLiteral(
"NO" )
1937 QStringLiteral(
"NO" )
1945 QObject::tr(
"column_name1[,column_name2, …] A list of (String) columns that "
1946 "must be compressed with ZLib DEFLATE algorithm. This might be beneficial "
1947 "for databases that have big string blobs. However, use with care, since "
1948 "the value of such columns will be seen as compressed binary content with "
1949 "other SQLite utilities (or previous OGR versions). With OGR, when inserting, "
1950 "modifying or querying compressed columns, compression/decompression is "
1951 "done transparently. However, such columns cannot be (easily) queried with "
1952 "an attribute filter or WHERE clause. Note: in table definition, such columns "
1953 "have the 'VARCHAR_deflate' declaration type." ),
1957 driverMetadata.insert( QStringLiteral(
"SQLite" ),
1959 QStringLiteral(
"SQLite" ),
1960 QObject::tr(
"SQLite" ),
1961 QStringLiteral(
"*.sqlite" ),
1962 QStringLiteral(
"sqlite" ),
1965 QStringLiteral(
"UTF-8" )
1970 datasetOptions.clear();
1971 layerOptions.clear();
1974 QObject::tr(
"Can be used to avoid creating the geometry_columns and spatial_ref_sys "
1975 "tables in a new database. By default these metadata tables are created "
1976 "when a new database is created." ),
1981 QStringLiteral(
"YES" )
1985 QObject::tr(
"Insert the content of the EPSG CSV files into the spatial_ref_sys table. "
1986 "Set to NO for regular SQLite databases." ),
1991 QStringLiteral(
"SPATIALITE" )
1995 QObject::tr(
"Controls whether layer and field names will be laundered for easier use "
1996 "in SQLite. Laundered names will be converted to lower case and some special "
1997 "characters(' - #) will be changed to underscores." ),
2002 QObject::tr(
"If the database is of the SpatiaLite flavor, and if OGR is linked "
2003 "against libspatialite, this option can be used to control if a spatial "
2004 "index must be created." ),
2009 QObject::tr(
"If the format of the geometry BLOB is of the SpatiaLite flavor, "
2010 "this option can be used to control if the compressed format for "
2011 "geometries (LINESTRINGs, POLYGONs) must be used." ),
2016 QObject::tr(
"Used to force the SRID number of the SRS associated with the layer. "
2017 "When this option isn't specified and that a SRS is associated with the "
2018 "layer, a search is made in the spatial_ref_sys to find a match for the "
2019 "SRS, and, if there is no match, a new entry is inserted for the SRS in "
2020 "the spatial_ref_sys table. When the SRID option is specified, this "
2021 "search (and the eventual insertion of a new entry) will not be done: "
2022 "the specified SRID is used as such." ),
2027 QObject::tr(
"column_name1[,column_name2, …] A list of (String) columns that "
2028 "must be compressed with ZLib DEFLATE algorithm. This might be beneficial "
2029 "for databases that have big string blobs. However, use with care, since "
2030 "the value of such columns will be seen as compressed binary content with "
2031 "other SQLite utilities (or previous OGR versions). With OGR, when inserting, "
2032 "modifying or queryings compressed columns, compression/decompression is "
2033 "done transparently. However, such columns cannot be (easily) queried with "
2034 "an attribute filter or WHERE clause. Note: in table definition, such columns "
2035 "have the 'VARCHAR_deflate' declaration type." ),
2039 driverMetadata.insert( QStringLiteral(
"SpatiaLite" ),
2041 QStringLiteral(
"SpatiaLite" ),
2042 QObject::tr(
"SpatiaLite" ),
2043 QStringLiteral(
"*.sqlite" ),
2044 QStringLiteral(
"sqlite" ),
2047 QStringLiteral(
"UTF-8" )
2051 datasetOptions.clear();
2052 layerOptions.clear();
2055 QObject::tr(
"Override the header file used - in place of header.dxf." ),
2060 QObject::tr(
"Override the trailer file used - in place of trailer.dxf." ),
2064 driverMetadata.insert( QStringLiteral(
"DXF" ),
2066 QStringLiteral(
"AutoCAD DXF" ),
2067 QObject::tr(
"AutoCAD DXF" ),
2068 QStringLiteral(
"*.dxf" ),
2069 QStringLiteral(
"dxf" ),
2076 datasetOptions.clear();
2077 layerOptions.clear();
2080 QObject::tr(
"Indicates the GeoConcept export file extension. "
2081 "TXT was used by earlier releases of GeoConcept. GXT is currently used." ),
2083 << QStringLiteral(
"GXT" )
2084 << QStringLiteral(
"TXT" ),
2085 QStringLiteral(
"GXT" )
2089 QObject::tr(
"Path to the GCT: the GCT file describes the GeoConcept types definitions: "
2090 "In this file, every line must start with //# followed by a keyword. "
2091 "Lines starting with // are comments." ),
2096 QObject::tr(
"Defines the feature to be created. The TYPE corresponds to one of the Name "
2097 "found in the GCT file for a type section. The SUBTYPE corresponds to one of "
2098 "the Name found in the GCT file for a sub-type section within the previous "
2103 driverMetadata.insert( QStringLiteral(
"Geoconcept" ),
2105 QStringLiteral(
"Geoconcept" ),
2106 QObject::tr(
"Geoconcept" ),
2107 QStringLiteral(
"*.gxt *.txt" ),
2108 QStringLiteral(
"gxt" ),
2115 datasetOptions.clear();
2116 layerOptions.clear();
2119 QObject::tr(
"When this option is set, the new layer will be created inside the named "
2120 "FeatureDataset folder. If the folder does not already exist, it will be created." ),
2125 QObject::tr(
"Set layer name alias." ),
2130 QObject::tr(
"Set name of geometry column in new layer. Defaults to 'SHAPE'." ),
2131 QStringLiteral(
"SHAPE" )
2135 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'." ),
2140 QObject::tr(
"Name of the OID column to create. Defaults to 'OBJECTID'." ),
2141 QStringLiteral(
"OBJECTID" )
2157 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." ),
2162 QObject::tr(
"XML documentation for the layer." ),
2166 QObject::tr(
"Customize how data is stored. By default text in UTF-8 and data up to 1TB." ),
2167 {QStringLiteral(
"DEFAULTS" ), QStringLiteral(
"MAX_FILE_SIZE_4GB" ), QStringLiteral(
"MAX_FILE_SIZE_256TB" )},
2168 QStringLiteral(
"DEFAULTS" ),
2173 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." ),
2177 driverMetadata.insert( QStringLiteral(
"OpenFileGDB" ),
2179 QStringLiteral(
"ESRI File Geodatabase" ),
2180 QObject::tr(
"ESRI File Geodatabase" ),
2181 QStringLiteral(
"*.gdb" ),
2182 QStringLiteral(
"gdb" ),
2185 QStringLiteral(
"UTF-8" )
2190 datasetOptions.clear();
2191 layerOptions.clear();
2194 QObject::tr(
"When this option is set, the new layer will be created inside the named "
2195 "FeatureDataset folder. If the folder does not already exist, it will be created." ),
2200 QObject::tr(
"Set name of geometry column in new layer. Defaults to 'SHAPE'." ),
2201 QStringLiteral(
"SHAPE" )
2205 QObject::tr(
"Name of the OID column to create. Defaults to 'OBJECTID'." ),
2206 QStringLiteral(
"OBJECTID" )
2209 driverMetadata.insert( QStringLiteral(
"FileGDB" ),
2211 QStringLiteral(
"ESRI FileGDB" ),
2212 QObject::tr(
"ESRI FileGDB" ),
2213 QStringLiteral(
"*.gdb" ),
2214 QStringLiteral(
"gdb" ),
2217 QStringLiteral(
"UTF-8" )
2222 datasetOptions.clear();
2223 layerOptions.clear();
2226 QObject::tr(
"By default, the driver will try to detect the data type of fields. If set "
2227 "to STRING, all fields will be of String type." ),
2229 << QStringLiteral(
"AUTO" )
2230 << QStringLiteral(
"STRING" ),
2231 QStringLiteral(
"AUTO" ),
2236 QObject::tr(
"By default, the driver will read the first lines of each sheet to detect "
2237 "if the first line might be the name of columns. If set to FORCE, the driver "
2238 "will consider the first line as the header line. If set to "
2239 "DISABLE, it will be considered as the first feature. Otherwise "
2240 "auto-detection will occur." ),
2242 << QStringLiteral(
"FORCE" )
2243 << QStringLiteral(
"DISABLE" )
2244 << QStringLiteral(
"AUTO" ),
2245 QStringLiteral(
"AUTO" ),
2249 driverMetadata.insert( QStringLiteral(
"XLSX" ),
2251 QStringLiteral(
"MS Office Open XML spreadsheet" ),
2252 QObject::tr(
"MS Office Open XML spreadsheet [XLSX]" ),
2253 QStringLiteral(
"*.xlsx" ),
2254 QStringLiteral(
"xlsx" ),
2257 QStringLiteral(
"UTF-8" )
2262 datasetOptions.clear();
2263 layerOptions.clear();
2266 QObject::tr(
"By default, the driver will try to detect the data type of fields. If set "
2267 "to STRING, all fields will be of String type." ),
2269 << QStringLiteral(
"AUTO" )
2270 << QStringLiteral(
"STRING" ),
2271 QStringLiteral(
"AUTO" ),
2276 QObject::tr(
"By default, the driver will read the first lines of each sheet to detect "
2277 "if the first line might be the name of columns. If set to FORCE, the driver "
2278 "will consider the first line as the header line. If set to "
2279 "DISABLE, it will be considered as the first feature. Otherwise "
2280 "auto-detection will occur." ),
2282 << QStringLiteral(
"FORCE" )
2283 << QStringLiteral(
"DISABLE" )
2284 << QStringLiteral(
"AUTO" ),
2285 QStringLiteral(
"AUTO" ),
2289 driverMetadata.insert( QStringLiteral(
"ODS" ),
2291 QStringLiteral(
"Open Document Spreadsheet" ),
2292 QObject::tr(
"Open Document Spreadsheet [ODS]" ),
2293 QStringLiteral(
"*.ods" ),
2294 QStringLiteral(
"ods" ),
2297 QStringLiteral(
"UTF-8" )
2302 datasetOptions.clear();
2303 layerOptions.clear();
2306 QObject::tr(
"Compression method." ),
2308 << QStringLiteral(
"UNCOMPRESSED" )
2309 << QStringLiteral(
"SNAPPY" ),
2310 QStringLiteral(
"SNAPPY" ),
2315 QObject::tr(
"Geometry encoding." ),
2317 << QStringLiteral(
"WKB" )
2318 << QStringLiteral(
"WKT" )
2319 << QStringLiteral(
"GEOARROW" ),
2320 QStringLiteral(
"WKB" ),
2325 QObject::tr(
"Maximum number of rows per group." ),
2330 QObject::tr(
"Name for the feature identifier column" ),
2335 QObject::tr(
"Name for the geometry column" ),
2336 QStringLiteral(
"geometry" )
2340 QObject::tr(
"Name of the coordinate system for the edges." ),
2342 << QStringLiteral(
"PLANAR" )
2343 << QStringLiteral(
"SPHERICAL" ),
2344 QStringLiteral(
"PLANAR" ),
2348 driverMetadata.insert( QStringLiteral(
"Parquet" ),
2350 QStringLiteral(
"(Geo)Parquet" ),
2351 QObject::tr(
"(Geo)Parquet" ),
2352 QStringLiteral(
"*.parquet" ),
2353 QStringLiteral(
"parquet" ),
2356 QStringLiteral(
"UTF-8" )
2361 datasetOptions.clear();
2362 layerOptions.clear();
2365 QObject::tr(
"Line termination character sequence." ),
2367 << QStringLiteral(
"CRLF" )
2368 << QStringLiteral(
"LF" ),
2369 QStringLiteral(
"LF" ),
2375 QObject::tr(
"Format of geometry columns." ),
2377 << QStringLiteral(
"geometry" )
2378 << QStringLiteral(
"geography" ),
2379 QStringLiteral(
"geometry" ),
2384 QObject::tr(
"Controls whether layer and field names will be laundered for easier use. "
2385 "Laundered names will be converted to lower case and some special "
2386 "characters(' - #) will be changed to underscores." ),
2391 QObject::tr(
"Name for the geometry column. Defaults to wkb_geometry "
2392 "for GEOM_TYPE=geometry or the_geog for GEOM_TYPE=geography" ) ) );
2395 QObject::tr(
"Name of schema into which to create the new table" ) ) );
2398 QObject::tr(
"Whether to explicitly emit the CREATE SCHEMA statement to create the specified schema." ),
2403 QObject::tr(
"Whether to explicitly recreate the table if necessary." ),
2408 QObject::tr(
"Whether to explicitly destroy tables before recreating them." ),
2410 << QStringLiteral(
"YES" )
2411 << QStringLiteral(
"NO" )
2412 << QStringLiteral(
"IF_EXISTS" ),
2413 QStringLiteral(
"YES" ),
2418 QObject::tr(
"Used to force the SRID number of the SRS associated with the layer. "
2419 "When this option isn't specified and that a SRS is associated with the "
2420 "layer, a search is made in the spatial_ref_sys to find a match for the "
2421 "SRS, and, if there is no match, a new entry is inserted for the SRS in "
2422 "the spatial_ref_sys table. When the SRID option is specified, this "
2423 "search (and the eventual insertion of a new entry) will not be done: "
2424 "the specified SRID is used as such." ),
2429 QObject::tr(
"Can be set to 2.0 or 2.2 for PostGIS 2.0/2.2 compatibility. "
2430 "Important to set it correctly if using non-linear geometry types" ),
2431 QStringLiteral(
"2.2" )
2434 driverMetadata.insert( QStringLiteral(
"PGDUMP" ),
2436 QStringLiteral(
"PostgreSQL SQL dump" ),
2437 QObject::tr(
"PostgreSQL SQL dump" ),
2438 QStringLiteral(
"*.sql" ),
2439 QStringLiteral(
"sql" ),
2442 QStringLiteral(
"UTF-8" )
2448 QgsVectorFileWriterMetadataContainer(
const QgsVectorFileWriterMetadataContainer &other ) =
delete;
2449 QgsVectorFileWriterMetadataContainer &operator=(
const QgsVectorFileWriterMetadataContainer &other ) =
delete;
2450 ~QgsVectorFileWriterMetadataContainer()
2452 for (
auto it = driverMetadata.constBegin(); it != driverMetadata.constEnd(); ++it )
2454 for (
auto optionIt = it.value().driverOptions.constBegin(); optionIt != it.value().driverOptions.constEnd(); ++optionIt )
2455 delete optionIt.value();
2456 for (
auto optionIt = it.value().layerOptions.constBegin(); optionIt != it.value().layerOptions.constEnd(); ++optionIt )
2457 delete optionIt.value();
2461 QMap<QString, QgsVectorFileWriter::MetaData> driverMetadata;
2468 static QgsVectorFileWriterMetadataContainer sDriverMetadata;
2469 QMap<QString, MetaData>::ConstIterator it = sDriverMetadata.driverMetadata.constBegin();
2471 for ( ; it != sDriverMetadata.driverMetadata.constEnd(); ++it )
2473 if ( it.key() == QLatin1String(
"PGDUMP" ) &&
2474 driverName != QLatin1String(
"PGDUMP" ) &&
2475 driverName != QLatin1String(
"PostgreSQL SQL dump" ) )
2480 if ( it.key().startsWith( driverName ) || it.value().longName.startsWith( driverName ) )
2495 return QStringList();
2504 return QStringList();
2511 OGRwkbGeometryType ogrType =
static_cast<OGRwkbGeometryType
>( type );
2537 QgsFeatureList::iterator fIt = features.begin();
2539 for ( ; fIt != features.end(); ++fIt )
2564 QString styleString;
2565 QString currentStyle;
2567 QgsSymbolList::const_iterator symbolIt = symbols.constBegin();
2568 for ( ; symbolIt != symbols.constEnd(); ++symbolIt )
2570 int nSymbolLayers = ( *symbolIt )->symbolLayerCount();
2571 for (
int i = 0; i < nSymbolLayers; ++i )
2574 QMap< QgsSymbolLayer *, QString >::const_iterator it =
mSymbolLayerTable.find( ( *symbolIt )->symbolLayer( i ) );
2580 double mmsf = mmScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
2581 double musf = mapUnitScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
2583 currentStyle = ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf );
2587 if ( symbolIt != symbols.constBegin() || i != 0 )
2589 styleString.append(
';' );
2591 styleString.append( currentStyle );
2595 OGR_F_SetStyleString( poFeature.get(), currentStyle.toLocal8Bit().constData() );
2596 if ( !writeFeature(
mLayer, poFeature.get() ) )
2603 OGR_F_SetStyleString( poFeature.get(), styleString.toLocal8Bit().constData() );
2608 if ( !writeFeature(
mLayer, poFeature.get() ) )
2627 int fldIdx = it.key();
2628 int ogrField = it.value();
2630 QVariant attrValue = feature.
attribute( fldIdx );
2635 OGR_F_UnsetField( poFeature.get(), ogrField );
2648 OGR_F_SetFieldNull( poFeature.get(), ogrField );
2663 mErrorMessage = QObject::tr(
"Error converting value (%1) for attribute field %2: %3" )
2664 .arg( feature.
attribute( fldIdx ).toString(),
2674 OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
2676 case QVariant::LongLong:
2677 OGR_F_SetFieldInteger64( poFeature.get(), ogrField, attrValue.toLongLong() );
2679 case QVariant::Bool:
2680 OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
2682 case QVariant::String:
2683 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toString() ).constData() );
2685 case QVariant::Double:
2686 OGR_F_SetFieldDouble( poFeature.get(), ogrField, attrValue.toDouble() );
2688 case QVariant::Date:
2689 OGR_F_SetFieldDateTime( poFeature.get(), ogrField,
2690 attrValue.toDate().year(),
2691 attrValue.toDate().month(),
2692 attrValue.toDate().day(),
2695 case QVariant::DateTime:
2698 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toDateTime().toString( QStringLiteral(
"yyyy/MM/dd hh:mm:ss.zzz" ) ) ).constData() );
2702 const QDateTime dt = attrValue.toDateTime();
2703 const QDate date = dt.date();
2704 const QTime time = dt.time();
2705 OGR_F_SetFieldDateTimeEx( poFeature.get(), ogrField,
2711 static_cast<float>( time.second() +
static_cast< double >( time.msec() ) / 1000 ),
2715 case QVariant::Time:
2718 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toString() ).constData() );
2722 const QTime time = attrValue.toTime();
2723 OGR_F_SetFieldDateTimeEx( poFeature.get(), ogrField,
2727 static_cast<float>( time.second() +
static_cast< double >( time.msec() ) / 1000 ),
2732 case QVariant::ByteArray:
2734 const QByteArray ba = attrValue.toByteArray();
2735 OGR_F_SetFieldBinary( poFeature.get(), ogrField, ba.size(),
const_cast< GByte *
>(
reinterpret_cast< const GByte *
>( ba.data() ) ) );
2739 case QVariant::Invalid:
2742 case QVariant::StringList:
2747 const QJsonDocument doc = QJsonDocument::fromVariant( attrValue );
2749 if ( !doc.isNull() )
2751 jsonString = QString::fromUtf8( doc.toJson( QJsonDocument::Compact ).constData() );
2753 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( jsonString.constData() ) );
2757 QStringList list = attrValue.toStringList();
2758 if ( mSupportedListSubTypes.contains( QVariant::String ) )
2760 int count = list.count();
2761 char **lst =
new char *[count + 1];
2765 for (
const QString &
string : list )
2767 lst[pos] = CPLStrdup(
mCodec->fromUnicode(
string ).data() );
2771 lst[count] =
nullptr;
2772 OGR_F_SetFieldStringList( poFeature.get(), ogrField, lst );
2777 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( list.join(
',' ) ).constData() );
2782 case QVariant::List:
2786 const QJsonDocument doc = QJsonDocument::fromVariant( attrValue );
2788 if ( !doc.isNull() )
2790 jsonString = QString::fromUtf8( doc.toJson( QJsonDocument::Compact ).data() );
2792 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( jsonString.constData() ) );
2799 QStringList list = attrValue.toStringList();
2800 if ( mSupportedListSubTypes.contains( QVariant::String ) )
2802 int count = list.count();
2803 char **lst =
new char *[count + 1];
2807 for (
const QString &
string : list )
2809 lst[pos] = CPLStrdup(
mCodec->fromUnicode(
string ).data() );
2813 lst[count] =
nullptr;
2814 OGR_F_SetFieldStringList( poFeature.get(), ogrField, lst );
2819 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( list.join(
',' ) ).constData() );
2825 const QVariantList list = attrValue.toList();
2826 if ( mSupportedListSubTypes.contains( QVariant::Int ) )
2828 const int count = list.count();
2829 int *lst =
new int[count];
2833 for (
const QVariant &value : list )
2835 lst[pos] = value.toInt();
2839 OGR_F_SetFieldIntegerList( poFeature.get(), ogrField, count, lst );
2844 QStringList strings;
2845 strings.reserve( list.size() );
2846 for (
const QVariant &value : list )
2848 strings << QString::number( value.toInt() );
2850 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
2856 const QVariantList list = attrValue.toList();
2857 if ( mSupportedListSubTypes.contains( QVariant::Double ) )
2859 const int count = list.count();
2860 double *lst =
new double[count];
2864 for (
const QVariant &value : list )
2866 lst[pos] = value.toDouble();
2870 OGR_F_SetFieldDoubleList( poFeature.get(), ogrField, count, lst );
2875 QStringList strings;
2876 strings.reserve( list.size() );
2877 for (
const QVariant &value : list )
2879 strings << QString::number( value.toDouble() );
2881 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
2887 const QVariantList list = attrValue.toList();
2888 if ( mSupportedListSubTypes.contains( QVariant::LongLong ) )
2890 const int count = list.count();
2891 long long *lst =
new long long[count];
2895 for (
const QVariant &value : list )
2897 lst[pos] = value.toLongLong();
2901 OGR_F_SetFieldInteger64List( poFeature.get(), ogrField, count, lst );
2906 QStringList strings;
2907 strings.reserve( list.size() );
2908 for (
const QVariant &value : list )
2910 strings << QString::number( value.toLongLong() );
2912 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
2920 mErrorMessage = QObject::tr(
"Invalid variant type for field %1[%2]: received %3 with type %4" )
2923 .arg( attrValue.typeName(),
2924 attrValue.toString() );
2937 if ( mCoordinateTransform )
2942 geom.
transform( *mCoordinateTransform );
2960 OGRGeometryH mGeom2 =
nullptr;
2989 geom.
get()->
addZValue( std::numeric_limits<double>::quiet_NaN() );
2996 geom.
get()->
addMValue( std::numeric_limits<double>::quiet_NaN() );
3016 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
3017 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
3023 QgsAbstractGeometry::WkbFlags wkbFlags;
3027 QByteArray wkb( geom.
asWkb( wkbFlags ) );
3028 OGRErr err = OGR_G_ImportFromWkb( mGeom2,
reinterpret_cast<unsigned char *
>(
const_cast<char *
>( wkb.constData() ) ), wkb.length() );
3029 if ( err != OGRERR_NONE )
3031 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
3032 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
3039 OGR_F_SetGeometryDirectly( poFeature.get(), mGeom2 );
3047 QByteArray wkb( geom.
asWkb( wkbFlags ) );
3049 OGRErr err = OGR_G_ImportFromWkb( ogrGeom,
reinterpret_cast<unsigned char *
>(
const_cast<char *
>( wkb.constData() ) ), wkb.length() );
3050 if ( err != OGRERR_NONE )
3052 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
3053 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
3060 OGR_F_SetGeometryDirectly( poFeature.get(), ogrGeom );
3075 for (
int i = 0; i < attributes.size(); i++ )
3077 if ( omap.find( i ) != omap.end() )
3082bool QgsVectorFileWriter::writeFeature( OGRLayerH layer, OGRFeatureH feature )
3084 if ( OGR_L_CreateFeature( layer, feature ) != OGRERR_NONE )
3086 mErrorMessage = QObject::tr(
"Feature creation error (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
3096 if ( mUsingTransaction )
3098 if ( OGRERR_NONE != OGR_L_CommitTransaction(
mLayer ) )
3100 QgsDebugMsg( QStringLiteral(
"Error while committing transaction on OGRLayer." ) );
3113 const QString &fileName,
3114 const QString &fileEncoding,
3116 const QString &driverName,
3118 QString *errorMessage,
3119 const QStringList &datasourceOptions,
3120 const QStringList &layerOptions,
3121 bool skipAttributeCreation,
3122 QString *newFilename,
3124 double symbologyScale,
3134 if ( destCRS.
isValid() && layer )
3160 const QString &fileName,
3161 const QString &fileEncoding,
3163 const QString &driverName,
3165 QString *errorMessage,
3166 const QStringList &datasourceOptions,
3167 const QStringList &layerOptions,
3168 bool skipAttributeCreation,
3169 QString *newFilename,
3171 double symbologyScale,
3202 : driverName( QStringLiteral(
"GPKG" ) )
3210 if ( !layer || !layer->
isValid() )
3217 details.sourceCrs = layer->
crs();
3218 details.sourceWkbType = layer->
wkbType();
3219 details.sourceFields = layer->
fields();
3228 if ( details.storageType == QLatin1String(
"ESRI Shapefile" ) )
3236 details.geometryTypeScanIterator = layer->
getFeatures( req );
3240 details.renderContext.setExpressionContext( details.expressionContext );
3241 details.renderContext.setRendererScale( options.
symbologyScale );
3243 details.shallTransform =
false;
3248 details.shallTransform =
true;
3253 details.outputCrs = details.sourceCrs;
3256 details.destWkbType = details.sourceWkbType;
3270 details.attributes.clear();
3271 else if ( details.attributes.isEmpty() )
3273 const QgsAttributeList allAttributes = details.sourceFields.allAttributesList();
3274 for (
int idx : allAttributes )
3276 QgsField fld = details.sourceFields.at( idx );
3277 if ( details.providerType == QLatin1String(
"oracle" ) && fld.
typeName().contains( QLatin1String(
"SDO_GEOMETRY" ) ) )
3279 details.attributes.append( idx );
3283 if ( !details.attributes.isEmpty() )
3285 for (
int attrIdx : std::as_const( details.attributes ) )
3287 if ( details.sourceFields.exists( attrIdx ) )
3291 details.outputFields.append(
field );
3295 QgsDebugMsg( QStringLiteral(
"No such source field with index '%1' available." ).arg( attrIdx ) );
3302 if ( details.providerType == QLatin1String(
"spatialite" ) )
3304 for (
int i = 0; i < details.outputFields.size(); i++ )
3306 if ( details.outputFields.at( i ).type() == QVariant::LongLong )
3311 if ( std::max( std::llabs( min.toLongLong() ), std::llabs( max.toLongLong() ) ) < std::numeric_limits<int>::max() )
3313 details.outputFields[i].setType( QVariant::Int );
3321 addRendererAttributes( details.renderer.get(), details.renderContext, details.sourceFields, details.attributes );
3331 bool useFilterRect =
true;
3332 if ( details.shallTransform )
3339 filterRect = extentTransform.
transformBoundingBox( filterRect, Qgis::TransformDirection::Reverse );
3343 useFilterRect =
false;
3346 if ( useFilterRect )
3352 details.filterRectEngine->prepareGeometry();
3354 details.sourceFeatureIterator = layer->
getFeatures( req );
3368 int lastProgressReport = 0;
3369 long long total = details.featureCount;
3372 if ( details.providerType == QLatin1String(
"ogr" ) && !details.dataSourceUri.isEmpty() )
3374 QString srcFileName( details.providerUriParams.value( QStringLiteral(
"path" ) ).toString() );
3375 if ( QFile::exists( srcFileName ) && QFileInfo( fileName ).canonicalFilePath() == QFileInfo( srcFileName ).canonicalFilePath() )
3379 if ( !( ( options.
driverName == QLatin1String(
"GPKG" ) ||
3380 options.
driverName == QLatin1String(
"SpatiaLite" ) ||
3381 options.
driverName == QLatin1String(
"SQLite" ) ) &&
3382 options.
layerName != details.providerUriParams.value( QStringLiteral(
"layerName" ) ) ) )
3385 *
errorMessage = QObject::tr(
"Cannot overwrite a OGR layer in place" );
3405 int newProgress =
static_cast<int>( ( 5.0 * scanned ) / total );
3406 if ( newProgress != lastProgressReport )
3408 lastProgressReport = newProgress;
3423 QString tempNewFilename;
3424 QString tempNewLayer;
3426 std::unique_ptr< QgsVectorFileWriter > writer(
create( fileName, details.outputFields, destWkbType, details.outputCrs, transformContext, options, QgsFeatureSink::SinkFlags(), &tempNewFilename, &tempNewLayer ) );
3430 *newFilename = tempNewFilename;
3433 *newLayer = tempNewLayer;
3473 int n = 0, errors = 0;
3482 writer->startRender( details.renderer.get(), details.sourceFields );
3484 writer->resetMap( details.attributes );
3486 writer->mFields = details.sourceFields;
3490 int initialProgress = lastProgressReport;
3491 while ( details.sourceFeatureIterator.nextFeature( fet ) )
3502 int newProgress =
static_cast<int>( initialProgress + ( ( 100.0 - initialProgress ) * saved ) / total );
3503 if ( newProgress < 100 && newProgress != lastProgressReport )
3505 lastProgressReport = newProgress;
3510 if ( details.shallTransform )
3523 QString msg = QObject::tr(
"Failed to transform a point while drawing a feature with ID '%1'. Writing stopped. (Exception: %2)" )
3524 .arg( fet.
id() ).arg( e.
what() );
3541 if ( !writer->addFeatureWithStyle( fet, writer->mRenderer.get(), mapUnits ) )
3548 *
errorMessage = QObject::tr(
"Feature write errors:" );
3554 if ( errors > 1000 )
3558 *
errorMessage += QObject::tr(
"Stopping after %n error(s)",
nullptr, errors );
3568 writer->stopRender();
3572 *
errorMessage += QObject::tr(
"\nOnly %1 of %2 features written." ).arg( n - errors ).arg( n );
3577 bool metadataFailure =
false;
3582 {QStringLiteral(
"path" ), tempNewFilename },
3583 {QStringLiteral(
"layerName" ), tempNewLayer }
3597 metadataFailure =
true;
3608 metadataFailure =
true;
3616 const QString &fileName,
3618 QString *newFilename,
3622 QgsVectorFileWriter::PreparedWriterDetails details;
3623 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
3631 const QString &fileName,
3634 QString *newFilename,
3638 QgsVectorFileWriter::PreparedWriterDetails details;
3639 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
3648 QgsVectorFileWriter::PreparedWriterDetails details;
3649 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
3658 QFileInfo fi( fileName );
3659 QDir dir = fi.dir();
3662 for (
const char *suffix : {
".shp",
".shx",
".dbf",
".prj",
".qix",
".qpj",
".cpg",
".sbn",
".sbx",
".idm",
".ind" } )
3664 filter << fi.completeBaseName() + suffix;
3668 const auto constEntryList = dir.entryList( filter );
3669 for (
const QString &file : constEntryList )
3671 QFile f( dir.canonicalPath() +
'/' + file );
3674 QgsDebugMsg( QStringLiteral(
"Removing file %1 failed: %2" ).arg( file, f.errorString() ) );
3690 static QReadWriteLock sFilterLock;
3691 static QMap< VectorFormatOptions, QList< QgsVectorFileWriter::FilterFormatDetails > > sFilters;
3695 const auto it = sFilters.constFind( options );
3696 if ( it != sFilters.constEnd() )
3700 QList< QgsVectorFileWriter::FilterFormatDetails > results;
3703 int const drvCount = OGRGetDriverCount();
3705 for (
int i = 0; i < drvCount; ++i )
3707 OGRSFDriverH drv = OGRGetDriver( i );
3710 QString drvName = OGR_Dr_GetName( drv );
3712 GDALDriverH gdalDriver = GDALGetDriverByName( drvName.toLocal8Bit().constData() );
3713 char **metadata =
nullptr;
3716 metadata = GDALGetMetadata( gdalDriver,
nullptr );
3719 bool nonSpatialFormat = CSLFetchBoolean( metadata, GDAL_DCAP_NONSPATIAL,
false );
3721 if ( OGR_Dr_TestCapability( drv,
"CreateDataSource" ) != 0 )
3726 if ( nonSpatialFormat )
3731 if ( filterString.isEmpty() )
3738 globs = metadata.
glob.toLower().split(
' ' );
3744 details.
globs = globs;
3753 if ( options & SortRecommended )
3755 if ( a.driverName == QLatin1String(
"GPKG" ) )
3757 else if ( b.driverName == QLatin1String(
"GPKG" ) )
3759 else if ( a.driverName == QLatin1String(
"ESRI Shapefile" ) )
3761 else if ( b.driverName == QLatin1String(
"ESRI Shapefile" ) )
3768 sFilters.insert( options, results );
3775 QSet< QString > extensions;
3777 const QRegularExpression rx( QStringLiteral(
"\\*\\.(.*)$" ) );
3781 for (
const QString &glob : format.globs )
3783 const QRegularExpressionMatch match = rx.match( glob );
3784 if ( !match.hasMatch() )
3787 const QString matched = match.captured( 1 );
3788 extensions.insert( matched );
3792 QStringList extensionList( extensions.constBegin(), extensions.constEnd() );
3794 std::sort( extensionList.begin(), extensionList.end(), [options](
const QString & a,
const QString & b ) ->
bool
3796 if ( options & SortRecommended )
3798 if ( a == QLatin1String(
"gpkg" ) )
3800 else if ( b == QLatin1String(
"gpkg" ) )
3802 else if ( a == QLatin1String(
"shp" ) )
3804 else if ( b == QLatin1String(
"shp" ) )
3808 return a.toLower().localeAwareCompare( b.toLower() ) < 0;
3811 return extensionList;
3816 QList< QgsVectorFileWriter::DriverDetails > results;
3819 const int drvCount = OGRGetDriverCount();
3821 QStringList writableDrivers;
3822 for (
int i = 0; i < drvCount; ++i )
3824 OGRSFDriverH drv = OGRGetDriver( i );
3827 QString drvName = OGR_Dr_GetName( drv );
3833 if ( drvName == QLatin1String(
"ODS" ) || drvName == QLatin1String(
"XLSX" ) || drvName == QLatin1String(
"XLS" ) )
3837 if ( drvName == QLatin1String(
"ESRI Shapefile" ) )
3839 writableDrivers << QStringLiteral(
"DBF file" );
3841 if ( OGR_Dr_TestCapability( drv,
"CreateDataSource" ) != 0 )
3844 if ( drvName == QLatin1String(
"MapInfo File" ) )
3846 writableDrivers << QStringLiteral(
"MapInfo MIF" );
3848 else if ( drvName == QLatin1String(
"SQLite" ) )
3855 QString option = QStringLiteral(
"SPATIALITE=YES" );
3856 char *options[2] = { CPLStrdup( option.toLocal8Bit().constData() ),
nullptr };
3857 OGRSFDriverH poDriver;
3859 poDriver = OGRGetDriverByName( drvName.toLocal8Bit().constData() );
3862 gdal::ogr_datasource_unique_ptr ds( OGR_Dr_CreateDataSource( poDriver, QStringLiteral(
"/vsimem/spatialitetest.sqlite" ).toUtf8().constData(), options ) );
3865 writableDrivers << QStringLiteral(
"SpatiaLite" );
3866 OGR_Dr_DeleteDataSource( poDriver, QStringLiteral(
"/vsimem/spatialitetest.sqlite" ).toUtf8().constData() );
3869 CPLFree( options[0] );
3871 writableDrivers << drvName;
3876 results.reserve( writableDrivers.count() );
3877 for (
const QString &drvName : std::as_const( writableDrivers ) )
3891 if ( options & SortRecommended )
3893 if ( a.driverName == QLatin1String(
"GPKG" ) )
3895 else if ( b.driverName == QLatin1String(
"GPKG" ) )
3897 else if ( a.driverName == QLatin1String(
"ESRI Shapefile" ) )
3899 else if ( b.driverName == QLatin1String(
"ESRI Shapefile" ) )
3903 return a.
longName.toLower().localeAwareCompare( b.
longName.toLower() ) < 0;
3910 QString ext = extension.trimmed();
3911 if ( ext.isEmpty() )
3914 if ( ext.startsWith(
'.' ) )
3918 int const drvCount = GDALGetDriverCount();
3920 for (
int i = 0; i < drvCount; ++i )
3922 GDALDriverH drv = GDALGetDriver( i );
3928 QString drvName = GDALGetDriverShortName( drv );
3929 QStringList driverExtensions = QString( GDALGetMetadataItem( drv, GDAL_DMD_EXTENSIONS,
nullptr ) ).split(
' ' );
3931 const auto constDriverExtensions = driverExtensions;
3932 for (
const QString &driver : constDriverExtensions )
3934 if ( driver.compare( ext, Qt::CaseInsensitive ) == 0 )
3945 QString filterString;
3949 if ( !filterString.isEmpty() )
3950 filterString += QLatin1String(
";;" );
3952 filterString += details.filterString;
3954 return filterString;
3963 return QStringLiteral(
"%1 (%2 %3)" ).arg( metadata.
trLongName,
3964 metadata.
glob.toLower(),
3965 metadata.
glob.toUpper() );
3970 if ( codecName == QLatin1String(
"System" ) )
3971 return QStringLiteral(
"LDID/0" );
3973 const QRegularExpression re( QRegularExpression::anchoredPattern( QString(
"(CP|windows-|ISO[ -])(.+)" ) ), QRegularExpression::CaseInsensitiveOption );
3974 const QRegularExpressionMatch match = re.match( codecName );
3975 if ( match.hasMatch() )
3977 QString
c = match.captured( 2 ).remove(
'-' );
3979 ( void )
c.toInt( &isNumber );
4007 OGRStyleTableH ogrStyleTable = OGR_STBL_Create();
4008 OGRStyleMgrH styleManager = OGR_SM_Create( ogrStyleTable );
4011 int nTotalLevels = 0;
4013 QgsSymbolList::iterator symbolIt = symbolList.begin();
4014 for ( ; symbolIt != symbolList.end(); ++symbolIt )
4016 double mmsf = mmScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
4017 double musf = mapUnitScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
4019 int nLevels = ( *symbolIt )->symbolLayerCount();
4020 for (
int i = 0; i < nLevels; ++i )
4022 mSymbolLayerTable.insert( ( *symbolIt )->symbolLayer( i ), QString::number( nTotalLevels ) );
4023 OGR_SM_AddStyle( styleManager, QString::number( nTotalLevels ).toLocal8Bit(),
4024 ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf ).toLocal8Bit() );
4028 OGR_DS_SetStyleTableDirectly( ds, ogrStyleTable );
4034 if ( !details.renderer )
4039 QHash< QgsSymbol *, QList<QgsFeature> > features;
4048 startRender( details.renderer.get(), details.sourceFields );
4068 QString msg = QObject::tr(
"Failed to transform, writing stopped. (Exception: %1)" )
4079 featureSymbol = mRenderer->symbolForFeature( fet, mRenderContext );
4080 if ( !featureSymbol )
4085 QHash< QgsSymbol *, QList<QgsFeature> >::iterator it = features.find( featureSymbol );
4086 if ( it == features.end() )
4088 it = features.insert( featureSymbol, QList<QgsFeature>() );
4090 it.value().append( fet );
4095 QgsSymbolList symbols = mRenderer->symbols( mRenderContext );
4096 for (
int i = 0; i < symbols.count(); i++ )
4102 if ( level < 0 || level >= 1000 )
4105 while ( level >= levels.count() )
4107 levels[level].append( item );
4112 int nTotalFeatures = 0;
4115 for (
int l = 0; l < levels.count(); l++ )
4118 for (
int i = 0; i < level.count(); i++ )
4121 QHash< QgsSymbol *, QList<QgsFeature> >::iterator levelIt = features.find( item.
symbol() );
4122 if ( levelIt == features.end() )
4128 double mmsf = mmScaleFactor(
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
4129 double musf = mapUnitScaleFactor(
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
4131 int llayer = item.
layer();
4132 QList<QgsFeature> &featureList = levelIt.value();
4133 QList<QgsFeature>::iterator featureIt = featureList.begin();
4134 for ( ; featureIt != featureList.end(); ++featureIt )
4144 QString styleString = levelIt.key()->symbolLayer( llayer )->ogrFeatureStyle( mmsf, musf );
4145 if ( !styleString.isEmpty() )
4147 OGR_F_SetStyleString( ogrFeature.get(), styleString.toLocal8Bit().constData() );
4148 if ( !writeFeature(
mLayer, ogrFeature.get() ) )
4161 *
errorMessage += QObject::tr(
"\nOnly %1 of %2 features written." ).arg( nTotalFeatures - nErrors ).arg( nTotalFeatures );
4169 if ( symbolUnits == Qgis::RenderUnit::Millimeters )
4176 if ( mapUnits == Qgis::DistanceUnit::Meters )
4178 return 1000 / scale;
4187 if ( symbolUnits == Qgis::RenderUnit::MapUnits )
4193 if ( symbolUnits == Qgis::RenderUnit::Millimeters && mapUnits == Qgis::DistanceUnit::Meters )
4195 return scale / 1000;
4203 mRenderer = createSymbologyRenderer( sourceRenderer );
4209 mRenderer->startRender( mRenderContext, fields );
4212void QgsVectorFileWriter::stopRender()
4219 mRenderer->stopRender( mRenderContext );
4222std::unique_ptr<QgsFeatureRenderer> QgsVectorFileWriter::createSymbologyRenderer(
QgsFeatureRenderer *sourceRenderer )
const
4228 if ( !sourceRenderer )
4233 return std::unique_ptr< QgsFeatureRenderer >( sourceRenderer->
clone() );
4240 const QSet<QString> rendererAttributes = renderer->
usedAttributes( context );
4241 for (
const QString &attr : rendererAttributes )
4246 attList.append( index );
4252QStringList QgsVectorFileWriter::concatenateOptions(
const QMap<QString, QgsVectorFileWriter::Option *> &options )
4255 QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
4257 for ( it = options.constBegin(); it != options.constEnd(); ++it )
4260 switch ( option->
type )
4267 list.append( QStringLiteral(
"%1=%2" ).arg( it.key() ).arg( opt->
defaultValue ) );
4277 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
defaultValue ) );
4287 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
defaultValue ) );
4296 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
mValue ) );
4307 OGRSFDriverH hDriver =
nullptr;
4310 return QgsVectorFileWriter::EditionCapabilities();
4311 QString drvName = OGR_Dr_GetName( hDriver );
4312 QgsVectorFileWriter::EditionCapabilities caps = QgsVectorFileWriter::EditionCapabilities();
4313 if ( OGR_DS_TestCapability( hDS.get(), ODsCCreateLayer ) )
4318 if ( !( drvName == QLatin1String(
"ESRI Shapefile" ) && QFile::exists( datasetName ) ) )
4321 if ( OGR_DS_TestCapability( hDS.get(), ODsCDeleteLayer ) )
4325 int layer_count = OGR_DS_GetLayerCount( hDS.get() );
4328 OGRLayerH hLayer = OGR_DS_GetLayer( hDS.get(), 0 );
4331 if ( OGR_L_TestCapability( hLayer, OLCSequentialWrite ) )
4334 if ( OGR_L_TestCapability( hLayer, OLCCreateField ) )
4345 const QString &layerNameIn )
4347 OGRSFDriverH hDriver =
nullptr;
4352 QString layerName( layerNameIn );
4353 if ( layerName.isEmpty() )
4354 layerName = QFileInfo( datasetName ).baseName();
4356 return OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
4361 const QString &layerName,
4365 OGRSFDriverH hDriver =
nullptr;
4369 OGRLayerH hLayer = OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
4375 OGRFeatureDefnH defn = OGR_L_GetLayerDefn( hLayer );
4376 const auto constAttributes = attributes;
4377 for (
int idx : constAttributes )
4380 if ( OGR_FD_GetFieldIndex( defn, fld.
name().toUtf8().constData() ) < 0 )
DistanceUnit
Units of distance.
RenderUnit
Rendering size units.
WkbType
The WKB type describes the number of dimensions a geometry has.
@ MultiPolygon25D
MultiPolygon25D.
@ GeometryCollectionZ
GeometryCollectionZ.
@ MultiLineString
MultiLineString.
@ MultiPolygonZ
MultiPolygonZ.
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.
Q_GADGET Qgis::DistanceUnit mapUnits
static Q_INVOKABLE QgsCoordinateReferenceSystem fromEpsgId(long epsg)
Creates a CRS from a given EPSG ID.
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 SIP_HOLDGIL
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.
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.
const QgsAbstractGeometry * constGet() const SIP_HOLDGIL
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false) SIP_THROW(QgsCsException)
Transforms this geometry as described by the coordinate transform ct.
Qgis::WkbType wkbType() const SIP_HOLDGIL
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
QgsAbstractGeometry * get()
Returns a modifiable (non-const) reference to the underlying abstract geometry primitive.
static QgsGeometry fromRect(const QgsRectangle &rect) SIP_HOLDGIL
Creates a new geometry from a QgsRectangle.
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) SIP_THROW(QgsNotSupportedException)
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.
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.
Qgis::WkbType overrideGeometryType
Set to a valid geometry type to override the default geometry type for the layer.
bool includeZ
Sets to true to include z dimension in output. This option is only valid if overrideGeometryType is s...
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.
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.
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a single feature to the sink.
static bool supportsFeatureStyles(const QString &driverName)
Returns true if the specified driverName supports feature styles.
Qgis::WkbType mWkbType
Geometry type which is being used.
bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a list of features to the sink.
double mSymbologyScale
Scale for symbology export (e.g. for symbols units in map units)
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.
OGRGeometryH createEmptyGeometry(Qgis::WkbType wkbType)
~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 QgsVectorFileWriter * create(const QString &fileName, const QgsFields &fields, Qgis::WkbType geometryType, const QgsCoordinateReferenceSystem &srs, const QgsCoordinateTransformContext &transformContext, const QgsVectorFileWriter::SaveVectorOptions &options, QgsFeatureSink::SinkFlags sinkFlags=QgsFeatureSink::SinkFlags(), QString *newFilename=nullptr, QString *newLayer=nullptr)
Create a new vector file writer.
static 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.
QgsVectorFileWriter::WriterError hasError() const
Checks whether there were any errors in constructor.
@ SkipNonSpatialFormats
Filter out any formats which do not have spatial support (e.g. those which cannot save geometries)
Q_DECL_DEPRECATED QgsVectorFileWriter(const QString &vectorFileName, const QString &fileEncoding, const QgsFields &fields, Qgis::WkbType geometryType, const QgsCoordinateReferenceSystem &srs=QgsCoordinateReferenceSystem(), const QString &driverName="GPKG", const QStringList &datasourceOptions=QStringList(), const QStringList &layerOptions=QStringList(), QString *newFilename=nullptr, 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.
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.
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.
bool addFeatureWithStyle(QgsFeature &feature, QgsFeatureRenderer *renderer, Qgis::DistanceUnit outputUnit=Qgis::DistanceUnit::Meters)
Adds a feature to the currently opened data source, using the style from a specified renderer.
static 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, Qgis::WkbType overrideGeometryType=Qgis::WkbType::Unknown, bool forceMulti=false, bool includeZ=false, const QgsAttributeList &attributes=QgsAttributeList(), QgsVectorFileWriter::FieldValueConverter *fieldValueConverter=nullptr, QString *newLayer=nullptr)
Write contents of vector layer to an (OGR supported) vector format.
static 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.
QString errorMessage() const
Retrieves error message.
QgsVectorFileWriter::SymbologyExport symbologyExport() const
void setSymbologyScale(double scale)
Set reference scale for output.
static OGRwkbGeometryType ogrTypeFromWkbType(Qgis::WkbType type)
Gets the ogr geometry type from an internal QGIS wkb type enum.
QMap< QgsSymbolLayer *, QString > mSymbolLayerTable
static QString fileFilterString(VectorFormatOptions options=SortRecommended)
Returns filter string that can be used for dialogs.
ActionOnExistingFile
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.
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.
Q_INVOKABLE Qgis::WkbType wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
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 Qgis::WkbType to25D(Qgis::WkbType type) SIP_HOLDGIL
Will convert the 25D version of the flat type if supported or Unknown if not supported.
static Qgis::WkbType addZ(Qgis::WkbType type) SIP_HOLDGIL
Adds the z dimension to a WKB type and returns the new type.
static bool isMultiType(Qgis::WkbType type) SIP_HOLDGIL
Returns true if the WKB type is a multi type.
static bool hasZ(Qgis::WkbType type) SIP_HOLDGIL
Tests whether a WKB type contains the z-dimension.
static Qgis::WkbType singleType(Qgis::WkbType type) SIP_HOLDGIL
Returns the single type for a WKB type.
static Qgis::WkbType multiType(Qgis::WkbType type) SIP_HOLDGIL
Returns the multi type for a WKB type.
static bool hasM(Qgis::WkbType type) SIP_HOLDGIL
Tests whether a WKB type contains m values.
static Qgis::WkbType flatType(Qgis::WkbType type) SIP_HOLDGIL
Returns the flat type for a WKB 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.