44#include <QRegularExpression>
45#include <QJsonDocument>
51#include <ogr_srs_api.h>
54#include <cpl_string.h>
73 const QString &vectorFileName,
74 const QString &fileEncoding,
78 const QString &driverName,
79 const QStringList &datasourceOptions,
80 const QStringList &layerOptions,
83 QgsFeatureSink::SinkFlags sinkFlags,
93 init( vectorFileName, fileEncoding, fields, geometryType,
94 srs, driverName, datasourceOptions, layerOptions, newFilename,
nullptr,
99 const QString &vectorFileName,
100 const QString &fileEncoding,
104 const QString &driverName,
105 const QStringList &datasourceOptions,
106 const QStringList &layerOptions,
107 QString *newFilename,
110 const QString &layerName,
114 QgsFeatureSink::SinkFlags sinkFlags,
118 , mWkbType( geometryType )
119 , mSymbologyExport( symbologyExport )
120 , mSymbologyScale( 1.0 )
122 init( vectorFileName, fileEncoding, fields, geometryType, srs, driverName,
123 datasourceOptions, layerOptions, newFilename, fieldValueConverter,
124 layerName, action, newLayer, sinkFlags, transformContext, fieldNameSource );
128 const QString &fileName,
134 QgsFeatureSink::SinkFlags sinkFlags,
135 QString *newFilename,
149 if ( driverName == QLatin1String(
"MapInfo MIF" ) )
153 GDALDriverH gdalDriver = GDALGetDriverByName( driverName.toLocal8Bit().constData() );
161#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,7,0)
162 return CSLFetchBoolean(
driverMetadata, GDAL_DCAP_FEATURE_STYLES_WRITE,
false );
164 return CSLFetchBoolean(
driverMetadata, GDAL_DCAP_FEATURE_STYLES,
false );
168void QgsVectorFileWriter::init( QString vectorFileName,
169 QString fileEncoding,
173 const QString &driverName,
174 QStringList datasourceOptions,
175 QStringList layerOptions,
176 QString *newFilename,
177 FieldValueConverter *fieldValueConverter,
178 const QString &layerNameIn,
179 ActionOnExistingFile action,
180 QString *newLayer, SinkFlags sinkFlags,
185 if ( vectorFileName.isEmpty() )
192 if ( driverName == QLatin1String(
"MapInfo MIF" ) )
196 else if ( driverName == QLatin1String(
"SpatiaLite" ) )
199 if ( !datasourceOptions.contains( QStringLiteral(
"SPATIALITE=YES" ) ) )
201 datasourceOptions.append( QStringLiteral(
"SPATIALITE=YES" ) );
204 else if ( driverName == QLatin1String(
"DBF file" ) )
207 if ( !layerOptions.contains( QStringLiteral(
"SHPT=NULL" ) ) )
209 layerOptions.append( QStringLiteral(
"SHPT=NULL" ) );
218#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,3,1)
219 QString fidFieldName;
222 for (
const QString &layerOption : layerOptions )
224 if ( layerOption.startsWith( QLatin1String(
"FID=" ) ) )
226 fidFieldName = layerOption.mid( 4 );
230 if ( fidFieldName.isEmpty() )
231 fidFieldName = QStringLiteral(
"fid" );
236 OGRSFDriverH poDriver;
239 poDriver = OGRGetDriverByName(
mOgrDriverName.toLocal8Bit().constData() );
243 mErrorMessage = QObject::tr(
"OGR driver for '%1' not found (OGR error: %2)" )
245 QString::fromUtf8( CPLGetLastErrorMsg() ) );
250 mOgrDriverLongName = QString( GDALGetMetadataItem( poDriver, GDAL_DMD_LONGNAME,
nullptr ) );
257 if ( layerOptions.join( QString() ).toUpper().indexOf( QLatin1String(
"ENCODING=" ) ) == -1 )
262 if ( driverName == QLatin1String(
"ESRI Shapefile" ) && !vectorFileName.endsWith( QLatin1String(
".shp" ), Qt::CaseInsensitive ) )
264 vectorFileName += QLatin1String(
".shp" );
266 else if ( driverName == QLatin1String(
"DBF file" ) && !vectorFileName.endsWith( QLatin1String(
".dbf" ), Qt::CaseInsensitive ) )
268 vectorFileName += QLatin1String(
".dbf" );
278#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
279 QStringList allExts = metadata.ext.split(
' ', QString::SkipEmptyParts );
281 QStringList allExts = metadata.ext.split(
' ', Qt::SkipEmptyParts );
284 const auto constAllExts = allExts;
285 for (
const QString &ext : constAllExts )
287 if ( vectorFileName.endsWith(
'.' + ext, Qt::CaseInsensitive ) )
296 vectorFileName +=
'.' + allExts[0];
302 if ( vectorFileName.endsWith( QLatin1String(
".gdb" ), Qt::CaseInsensitive ) )
304 QDir dir( vectorFileName );
307 QFileInfoList fileList = dir.entryInfoList(
308 QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files, QDir::DirsFirst );
309 const auto constFileList = fileList;
310 for (
const QFileInfo &info : constFileList )
312 QFile::remove( info.absoluteFilePath() );
315 QDir().rmdir( vectorFileName );
319 QFile::remove( vectorFileName );
324 if ( metadataFound && !metadata.compulsoryEncoding.isEmpty() )
326 if ( fileEncoding.compare( metadata.compulsoryEncoding, Qt::CaseInsensitive ) != 0 )
328 QgsDebugMsgLevel( QStringLiteral(
"forced %1 encoding for %2" ).arg( metadata.compulsoryEncoding, driverName ), 2 );
329 fileEncoding = metadata.compulsoryEncoding;
334 char **options =
nullptr;
335 if ( !datasourceOptions.isEmpty() )
337 options =
new char *[ datasourceOptions.size() + 1 ];
338 for (
int i = 0; i < datasourceOptions.size(); i++ )
340 QgsDebugMsgLevel( QStringLiteral(
"-dsco=%1" ).arg( datasourceOptions[i] ), 2 );
341 options[i] = CPLStrdup( datasourceOptions[i].toLocal8Bit().constData() );
343 options[ datasourceOptions.size()] =
nullptr;
350 mDS.reset( OGR_Dr_CreateDataSource( poDriver, vectorFileName.toUtf8().constData(), options ) );
352 mDS.reset( OGROpen( vectorFileName.toUtf8().constData(), TRUE,
nullptr ) );
356 for (
int i = 0; i < datasourceOptions.size(); i++ )
357 CPLFree( options[i] );
366 mErrorMessage = QObject::tr(
"Creation of data source failed (OGR error: %1)" )
367 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
369 mErrorMessage = QObject::tr(
"Opening of data source in update mode failed (OGR error: %1)" )
370 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
374 QString layerName( layerNameIn );
375 if ( layerName.isEmpty() )
376 layerName = QFileInfo( vectorFileName ).baseName();
380 const int layer_count = OGR_DS_GetLayerCount(
mDS.get() );
381 for (
int i = 0; i < layer_count; i++ )
383 OGRLayerH hLayer = OGR_DS_GetLayer(
mDS.get(), i );
384 if ( EQUAL( OGR_L_GetName( hLayer ), layerName.toUtf8().constData() ) )
386 if ( OGR_DS_DeleteLayer(
mDS.get(), i ) != OGRERR_NONE )
389 mErrorMessage = QObject::tr(
"Overwriting of existing layer failed (OGR error: %1)" )
390 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
404 QgsDebugMsgLevel( QStringLiteral(
"Opened data source in update mode" ), 2 );
408 mCodec = QTextCodec::codecForName( fileEncoding.toLocal8Bit().constData() );
411 QgsDebugError(
"error finding QTextCodec for " + fileEncoding );
414 QString enc = settings.
value( QStringLiteral(
"UI/encoding" ),
"System" ).toString();
415 mCodec = QTextCodec::codecForName( enc.toLocal8Bit().constData() );
419 mCodec = QTextCodec::codecForLocale();
425 if ( driverName == QLatin1String(
"KML" ) || driverName == QLatin1String(
"LIBKML" ) || driverName == QLatin1String(
"GPX" ) )
427 if ( srs.
authid() != QLatin1String(
"EPSG:4326" ) )
442 int optIndex = layerOptions.indexOf( QLatin1String(
"FEATURE_DATASET=" ) );
443 if ( optIndex != -1 )
445 layerOptions.removeAt( optIndex );
448 if ( !layerOptions.isEmpty() )
450 options =
new char *[ layerOptions.size() + 1 ];
451 for (
int i = 0; i < layerOptions.size(); i++ )
454 options[i] = CPLStrdup( layerOptions[i].toLocal8Bit().constData() );
456 options[ layerOptions.size()] =
nullptr;
460 CPLSetConfigOption(
"SHAPE_ENCODING",
"" );
464 mLayer = OGR_DS_CreateLayer(
mDS.get(), layerName.toUtf8().constData(),
mOgrRef, wkbType, options );
467 *newLayer = OGR_L_GetName(
mLayer );
468 if ( driverName == QLatin1String(
"GPX" ) )
475 if ( !EQUAL( layerName.toUtf8().constData(),
"track_points" ) &&
476 !EQUAL( layerName.toUtf8().constData(),
"route_points" ) )
478 *newLayer = QStringLiteral(
"waypoints" );
485 const char *pszForceGPXTrack
486 = CSLFetchNameValue( options,
"FORCE_GPX_TRACK" );
487 if ( pszForceGPXTrack && CPLTestBool( pszForceGPXTrack ) )
488 *newLayer = QStringLiteral(
"tracks" );
490 *newLayer = QStringLiteral(
"routes" );
497 const char *pszForceGPXRoute
498 = CSLFetchNameValue( options,
"FORCE_GPX_ROUTE" );
499 if ( pszForceGPXRoute && CPLTestBool( pszForceGPXRoute ) )
500 *newLayer = QStringLiteral(
"routes" );
502 *newLayer = QStringLiteral(
"tracks" );
512 else if ( driverName == QLatin1String(
"DGN" ) )
514 mLayer = OGR_DS_GetLayerByName(
mDS.get(),
"elements" );
518 mLayer = OGR_DS_GetLayerByName(
mDS.get(), layerName.toUtf8().constData() );
523 for (
int i = 0; i < layerOptions.size(); i++ )
524 CPLFree( options[i] );
533 QString layerName = vectorFileName.left( vectorFileName.indexOf( QLatin1String(
".shp" ), Qt::CaseInsensitive ) );
534 QFile prjFile( layerName +
".qpj" );
535 if ( prjFile.exists() )
543 mErrorMessage = QObject::tr(
"Creation of layer failed (OGR error: %1)" )
544 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
546 mErrorMessage = QObject::tr(
"Opening of layer failed (OGR error: %1)" )
547 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
552 OGRFeatureDefnH defn = OGR_L_GetLayerDefn(
mLayer );
561 QSet<int> existingIdxs;
565#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,7,0)
566 if (
const char *pszCreateFieldDefnFlags = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATION_FIELD_DEFN_FLAGS,
nullptr ) )
568 char **papszTokens = CSLTokenizeString2( pszCreateFieldDefnFlags,
" ", 0 );
569 if ( CSLFindString( papszTokens,
"AlternativeName" ) >= 0 )
573 if ( CSLFindString( papszTokens,
"Comment" ) >= 0 )
577 CSLDestroy( papszTokens );
587 for (
int fldIdx = 0; fldIdx < fields.
count(); ++fldIdx )
591 if ( fieldValueConverter )
593 attrField = fieldValueConverter->fieldDefinition( fields.
at( fldIdx ) );
598 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( attrField.
name() ) );
607 switch ( fieldNameSource )
610 name = attrField.
name();
614 name = !attrField.
alias().isEmpty() ? attrField.
alias() : attrField.
name();
618 OGRFieldType ogrType = OFTString;
619 OGRFieldSubType ogrSubType = OFSTNone;
620 int ogrWidth = attrField.
length();
621 int ogrPrecision = attrField.
precision();
622 if ( ogrPrecision > 0 )
625 switch ( attrField.
type() )
627 case QVariant::LongLong:
629 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
630 if ( pszDataTypes && strstr( pszDataTypes,
"Integer64" ) )
631 ogrType = OFTInteger64;
634 ogrWidth = ogrWidth > 0 && ogrWidth <= 20 ? ogrWidth : 20;
638 case QVariant::String:
640 if ( ( ogrWidth <= 0 || ogrWidth > 255 ) &&
mOgrDriverName == QLatin1String(
"ESRI Shapefile" ) )
645 ogrType = OFTInteger;
646 ogrWidth = ogrWidth > 0 && ogrWidth <= 10 ? ogrWidth : 10;
651 ogrType = OFTInteger;
652 ogrSubType = OFSTBoolean;
657 case QVariant::Double:
658#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,3,1)
659 if (
mOgrDriverName == QLatin1String(
"GPKG" ) && attrField.
precision() == 0 && attrField.
name().compare( fidFieldName, Qt::CaseInsensitive ) == 0 )
662 ogrType = OFTInteger64;
685 case QVariant::DateTime:
693 ogrType = OFTDateTime;
697 case QVariant::ByteArray:
701 case QVariant::StringList:
707 ogrSubType = OFSTJSON;
711 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
712 if ( pszDataTypes && strstr( pszDataTypes,
"StringList" ) )
714 ogrType = OFTStringList;
715 mSupportedListSubTypes.insert( QVariant::String );
728 const char *pszDataSubTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATASUBTYPES,
nullptr );
729 if ( pszDataSubTypes && strstr( pszDataSubTypes,
"JSON" ) )
732 ogrSubType = OFSTJSON;
745 ogrSubType = OFSTJSON;
750 if ( attrField.
subType() == QVariant::String )
752 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
753 if ( pszDataTypes && strstr( pszDataTypes,
"StringList" ) )
755 ogrType = OFTStringList;
756 mSupportedListSubTypes.insert( QVariant::String );
765 else if ( attrField.
subType() == QVariant::Int )
767 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
768 if ( pszDataTypes && strstr( pszDataTypes,
"IntegerList" ) )
770 ogrType = OFTIntegerList;
771 mSupportedListSubTypes.insert( QVariant::Int );
780 else if ( attrField.
subType() == QVariant::Double )
782 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
783 if ( pszDataTypes && strstr( pszDataTypes,
"RealList" ) )
785 ogrType = OFTRealList;
786 mSupportedListSubTypes.insert( QVariant::Double );
795 else if ( attrField.
subType() == QVariant::LongLong )
797 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
798 if ( pszDataTypes && strstr( pszDataTypes,
"Integer64List" ) )
800 ogrType = OFTInteger64List;
801 mSupportedListSubTypes.insert( QVariant::LongLong );
815 mErrorMessage = QObject::tr(
"Unsupported type for field %1" )
816 .arg( attrField.
name() );
821 if (
mOgrDriverName == QLatin1String(
"SQLite" ) && name.compare( QLatin1String(
"ogc_fid" ), Qt::CaseInsensitive ) == 0 )
824 for ( i = 0; i < 10; i++ )
826 name = QStringLiteral(
"ogc_fid%1" ).arg( i );
829 for ( j = 0; j < fields.
size() && name.compare( fields.
at( j ).
name(), Qt::CaseInsensitive ) != 0; j++ )
832 if ( j == fields.
size() )
838 mErrorMessage = QObject::tr(
"No available replacement for internal fieldname ogc_fid found" ).arg( attrField.
name() );
843 QgsMessageLog::logMessage( QObject::tr(
"Reserved attribute name ogc_fid replaced with %1" ).arg( name ), QObject::tr(
"OGR" ) );
850 OGR_Fld_SetWidth( fld.get(), ogrWidth );
853 if ( ogrPrecision >= 0 )
855 OGR_Fld_SetPrecision( fld.get(), ogrPrecision );
858 if ( ogrSubType != OFSTNone )
859 OGR_Fld_SetSubType( fld.get(), ogrSubType );
861#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,6,0)
862 OGR_Fld_SetAlternativeName( fld.get(),
mCodec->fromUnicode( attrField.
alias() ).constData() );
864#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,7,0)
865 OGR_Fld_SetComment( fld.get(),
mCodec->fromUnicode( attrField.
comment() ).constData() );
870 " type " + QString( QVariant::typeToName( attrField.
type() ) ) +
871 " width " + QString::number( ogrWidth ) +
872 " precision " + QString::number( ogrPrecision ), 2 );
873 if ( OGR_L_CreateField(
mLayer, fld.get(),
true ) != OGRERR_NONE )
876 mErrorMessage = QObject::tr(
"Creation of field %1 failed (OGR error: %2)" )
877 .arg( attrField.
name(),
878 QString::fromUtf8( CPLGetLastErrorMsg() ) );
883 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( name ) );
884 QgsDebugMsgLevel( QStringLiteral(
"returned field index for %1: %2" ).arg( name ).arg( ogrIdx ), 2 );
885 if ( ogrIdx < 0 || existingIdxs.contains( ogrIdx ) )
888 ogrIdx = OGR_FD_GetFieldCount( defn ) - 1;
893 mErrorMessage = QObject::tr(
"Created field %1 not found (OGR error: %2)" )
894 .arg( attrField.
name(),
895 QString::fromUtf8( CPLGetLastErrorMsg() ) );
901 existingIdxs.insert( ogrIdx );
909 for (
int fldIdx = 0; fldIdx < fields.
count(); ++fldIdx )
912 QString name( attrField.
name() );
913 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( name ) );
925 int fidIdx = fields.
lookupField( QStringLiteral(
"FID" ) );
936 *newFilename = vectorFileName;
939 mUsingTransaction =
true;
940 if ( OGRERR_NONE != OGR_L_StartTransaction(
mLayer ) )
942 mUsingTransaction =
false;
952class QgsVectorFileWriterMetadataContainer
956 QgsVectorFileWriterMetadataContainer()
958 QMap<QString, QgsVectorFileWriter::Option *> datasetOptions;
959 QMap<QString, QgsVectorFileWriter::Option *> layerOptions;
962 datasetOptions.clear();
963 layerOptions.clear();
966 QObject::tr(
"Compression method." ),
968 << QStringLiteral(
"UNCOMPRESSED" )
969 << QStringLiteral(
"ZSTD" )
970 << QStringLiteral(
"LZ4" ),
971 QStringLiteral(
"LZ4" ),
976 QObject::tr(
"Geometry encoding." ),
978 << QStringLiteral(
"GEOARROW" )
979 << QStringLiteral(
"WKB" )
980 << QStringLiteral(
"WKT" ),
981 QStringLiteral(
"GEOARROW" ),
986 QObject::tr(
"Maximum number of rows per batch." ),
991 QObject::tr(
"Name for the feature identifier column" ),
996 QObject::tr(
"Name for the geometry column" ),
997 QStringLiteral(
"geometry" )
1000 driverMetadata.insert( QStringLiteral(
"Arrow" ),
1002 QStringLiteral(
"(Geo)Arrow" ),
1003 QObject::tr(
"(Geo)Arrow" ),
1004 QStringLiteral(
"*.arrow *.feather *.arrows *.ipc" ),
1005 QStringLiteral(
"arrow" ),
1008 QStringLiteral(
"UTF-8" )
1013 datasetOptions.clear();
1014 layerOptions.clear();
1016 driverMetadata.insert( QStringLiteral(
"AVCE00" ),
1018 QStringLiteral(
"Arc/Info ASCII Coverage" ),
1019 QObject::tr(
"Arc/Info ASCII Coverage" ),
1020 QStringLiteral(
"*.e00" ),
1021 QStringLiteral(
"e00" ),
1028#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,3,0)
1032 datasetOptions.clear();
1033 layerOptions.clear();
1036 QObject::tr(
"New BNA files are created by the "
1037 "systems default line termination conventions. "
1038 "This may be overridden here." ),
1040 << QStringLiteral(
"CRLF" )
1041 << QStringLiteral(
"LF" ),
1047 QObject::tr(
"By default, BNA files are created in multi-line format. "
1048 "For each record, the first line contains the identifiers and the "
1049 "type/number of coordinates to follow. Each following line contains "
1050 "a pair of coordinates." ),
1055 QObject::tr(
"BNA records may contain from 2 to 4 identifiers per record. "
1056 "Some software packages only support a precise number of identifiers. "
1057 "You can override the default value (2) by a precise value." ),
1059 << QStringLiteral(
"2" )
1060 << QStringLiteral(
"3" )
1061 << QStringLiteral(
"4" )
1062 << QStringLiteral(
"NB_SOURCE_FIELDS" ),
1063 QStringLiteral(
"2" )
1067 QObject::tr(
"The BNA writer will try to recognize ellipses and circles when writing a polygon. "
1068 "This will only work if the feature has previously been read from a BNA file. "
1069 "As some software packages do not support ellipses/circles in BNA data file, "
1070 "it may be useful to tell the writer by specifying ELLIPSES_AS_ELLIPSES=NO not "
1071 "to export them as such, but keep them as polygons." ),
1076 QObject::tr(
"Limit the number of coordinate pairs per line in multiline format." ),
1081 QObject::tr(
"Set the number of decimal for coordinates. Default value is 10." ),
1085 driverMetadata.insert( QStringLiteral(
"BNA" ),
1087 QStringLiteral(
"Atlas BNA" ),
1088 QObject::tr(
"Atlas BNA" ),
1089 QStringLiteral(
"*.bna" ),
1090 QStringLiteral(
"bna" ),
1098 datasetOptions.clear();
1099 layerOptions.clear();
1102 QObject::tr(
"By default when creating new .csv files they "
1103 "are created with the line termination conventions "
1104 "of the local platform (CR/LF on Win32 or LF on all other systems). "
1105 "This may be overridden through the use of the LINEFORMAT option." ),
1107 << QStringLiteral(
"CRLF" )
1108 << QStringLiteral(
"LF" ),
1114 QObject::tr(
"By default, the geometry of a feature written to a .csv file is discarded. "
1115 "It is possible to export the geometry in its WKT representation by "
1116 "specifying GEOMETRY=AS_WKT. It is also possible to export point geometries "
1117 "into their X,Y,Z components by specifying GEOMETRY=AS_XYZ, GEOMETRY=AS_XY "
1118 "or GEOMETRY=AS_YX." ),
1120 << QStringLiteral(
"AS_WKT" )
1121 << QStringLiteral(
"AS_XYZ" )
1122 << QStringLiteral(
"AS_XY" )
1123 << QStringLiteral(
"AS_YX" ),
1129 QObject::tr(
"Create the associated .csvt file to describe the type of each "
1130 "column of the layer and its optional width and precision." ),
1135 QObject::tr(
"Field separator character." ),
1137 << QStringLiteral(
"COMMA" )
1138 << QStringLiteral(
"SEMICOLON" )
1139 << QStringLiteral(
"TAB" ),
1140 QStringLiteral(
"COMMA" )
1144 QObject::tr(
"Double-quote strings. IF_AMBIGUOUS means that string values that look like numbers will be quoted." ),
1146 << QStringLiteral(
"IF_NEEDED" )
1147 << QStringLiteral(
"IF_AMBIGUOUS" )
1148 << QStringLiteral(
"ALWAYS" ),
1149 QStringLiteral(
"IF_AMBIGUOUS" )
1153 QObject::tr(
"Write a UTF-8 Byte Order Mark (BOM) at the start of the file." ),
1157 driverMetadata.insert( QStringLiteral(
"CSV" ),
1159 QStringLiteral(
"Comma Separated Value [CSV]" ),
1160 QObject::tr(
"Comma Separated Value [CSV]" ),
1161 QStringLiteral(
"*.csv" ),
1162 QStringLiteral(
"csv" ),
1169 datasetOptions.clear();
1170 layerOptions.clear();
1172 driverMetadata.insert( QStringLiteral(
"FlatGeobuf" ),
1174 QStringLiteral(
"FlatGeobuf" ),
1175 QObject::tr(
"FlatGeobuf" ),
1176 QStringLiteral(
"*.fgb" ),
1177 QStringLiteral(
"fgb" ),
1180 QStringLiteral(
"UTF-8" )
1185 datasetOptions.clear();
1186 layerOptions.clear();
1189 QObject::tr(
"Override the type of shapefile created. "
1190 "Can be one of NULL for a simple .dbf file with no .shp file, POINT, "
1191 "ARC, POLYGON or MULTIPOINT for 2D, or POINTZ, ARCZ, POLYGONZ or "
1192 "MULTIPOINTZ for 3D;" ) +
1193 QObject::tr(
" POINTM, ARCM, POLYGONM or MULTIPOINTM for measured geometries"
1194 " and POINTZM, ARCZM, POLYGONZM or MULTIPOINTZM for 3D measured"
1196 QObject::tr(
" MULTIPATCH files are supported since GDAL 2.2." ) +
1199 << QStringLiteral(
"NULL" )
1200 << QStringLiteral(
"POINT" )
1201 << QStringLiteral(
"ARC" )
1202 << QStringLiteral(
"POLYGON" )
1203 << QStringLiteral(
"MULTIPOINT" )
1204 << QStringLiteral(
"POINTZ" )
1205 << QStringLiteral(
"ARCZ" )
1206 << QStringLiteral(
"POLYGONZ" )
1207 << QStringLiteral(
"MULTIPOINTZ" )
1208 << QStringLiteral(
"POINTM" )
1209 << QStringLiteral(
"ARCM" )
1210 << QStringLiteral(
"POLYGONM" )
1211 << QStringLiteral(
"MULTIPOINTM" )
1212 << QStringLiteral(
"POINTZM" )
1213 << QStringLiteral(
"ARCZM" )
1214 << QStringLiteral(
"POLYGONZM" )
1215 << QStringLiteral(
"MULTIPOINTZM" )
1216 << QStringLiteral(
"MULTIPATCH" )
1226 QObject::tr(
"Set the encoding value in the DBF file. "
1227 "The default value is LDID/87. It is not clear "
1228 "what other values may be appropriate." ),
1236 QObject::tr(
"Set to YES to resize fields to their optimal size." ),
1240 driverMetadata.insert( QStringLiteral(
"ESRI" ),
1242 QStringLiteral(
"ESRI Shapefile" ),
1243 QObject::tr(
"ESRI Shapefile" ),
1244 QStringLiteral(
"*.shp" ),
1245 QStringLiteral(
"shp" ),
1252 datasetOptions.clear();
1253 layerOptions.clear();
1255 driverMetadata.insert( QStringLiteral(
"DBF File" ),
1257 QStringLiteral(
"DBF File" ),
1258 QObject::tr(
"DBF File" ),
1259 QStringLiteral(
"*.dbf" ),
1260 QStringLiteral(
"dbf" ),
1267 datasetOptions.clear();
1268 layerOptions.clear();
1270 driverMetadata.insert( QStringLiteral(
"FMEObjects Gateway" ),
1272 QStringLiteral(
"FMEObjects Gateway" ),
1273 QObject::tr(
"FMEObjects Gateway" ),
1274 QStringLiteral(
"*.fdd" ),
1275 QStringLiteral(
"fdd" ),
1282 datasetOptions.clear();
1283 layerOptions.clear();
1286 QObject::tr(
"Set to YES to write a bbox property with the bounding box "
1287 "of the geometries at the feature and feature collection level." ),
1292 QObject::tr(
"Maximum number of figures after decimal separator to write in coordinates. "
1293 "Defaults to 15. Truncation will occur to remove trailing zeros." ),
1298 QObject::tr(
"Whether to use RFC 7946 standard. "
1299 "If disabled GeoJSON 2008 initial version will be used. "
1300 "Default is NO (thus GeoJSON 2008). See also Documentation (via Help button)" ),
1304 driverMetadata.insert( QStringLiteral(
"GeoJSON" ),
1306 QStringLiteral(
"GeoJSON" ),
1307 QObject::tr(
"GeoJSON" ),
1308 QStringLiteral(
"*.geojson" ),
1309 QStringLiteral(
"geojson" ),
1312 QStringLiteral(
"UTF-8" )
1317 datasetOptions.clear();
1318 layerOptions.clear();
1321 QObject::tr(
"Maximum number of figures after decimal separator to write in coordinates. "
1322 "Defaults to 15. Truncation will occur to remove trailing zeros." ),
1327 QObject::tr(
"Whether to start records with the RS=0x1E character (RFC 8142 standard). "
1328 "Defaults to NO: Newline Delimited JSON (geojsonl). \n"
1329 "If set to YES: RFC 8142 standard: GeoJSON Text Sequences (geojsons)." ),
1333 driverMetadata.insert( QStringLiteral(
"GeoJSONSeq" ),
1335 QStringLiteral(
"GeoJSON - Newline Delimited" ),
1336 QObject::tr(
"GeoJSON - Newline Delimited" ),
1337 QStringLiteral(
"*.geojsonl *.geojsons *.json" ),
1338 QStringLiteral(
"json" ),
1341 QStringLiteral(
"UTF-8" )
1346 datasetOptions.clear();
1347 layerOptions.clear();
1350 QObject::tr(
"whether the document must be in RSS 2.0 or Atom 1.0 format. "
1351 "Default value : RSS" ),
1353 << QStringLiteral(
"RSS" )
1354 << QStringLiteral(
"ATOM" ),
1355 QStringLiteral(
"RSS" )
1359 QObject::tr(
"The encoding of location information. Default value : SIMPLE. "
1360 "W3C_GEO only supports point geometries. "
1361 "SIMPLE or W3C_GEO only support geometries in geographic WGS84 coordinates." ),
1363 << QStringLiteral(
"SIMPLE" )
1364 << QStringLiteral(
"GML" )
1365 << QStringLiteral(
"W3C_GEO" ),
1366 QStringLiteral(
"SIMPLE" )
1370 QObject::tr(
"If defined to YES, extension fields will be written. "
1371 "If the field name not found in the base schema matches "
1372 "the foo_bar pattern, foo will be considered as the namespace "
1373 "of the element, and a <foo:bar> element will be written. "
1374 "Otherwise, elements will be written in the <ogr:> namespace." ),
1379 QObject::tr(
"If defined to NO, only <entry> or <item> elements will be written. "
1380 "The user will have to provide the appropriate header and footer of the document." ),
1385 QObject::tr(
"XML content that will be put between the <channel> element and the "
1386 "first <item> element for a RSS document, or between the xml tag and "
1387 "the first <entry> element for an Atom document." ),
1392 QObject::tr(
"Value put inside the <title> element in the header. "
1393 "If not provided, a dummy value will be used as that element is compulsory." ),
1398 QObject::tr(
"Value put inside the <description> element in the header. "
1399 "If not provided, a dummy value will be used as that element is compulsory." ),
1404 QObject::tr(
"Value put inside the <link> element in the header. "
1405 "If not provided, a dummy value will be used as that element is compulsory." ),
1410 QObject::tr(
"Value put inside the <updated> element in the header. "
1411 "Should be formatted as a XML datetime. "
1412 "If not provided, a dummy value will be used as that element is compulsory." ),
1417 QObject::tr(
"Value put inside the <author><name> element in the header. "
1418 "If not provided, a dummy value will be used as that element is compulsory." ),
1423 QObject::tr(
"Value put inside the <id> element in the header. "
1424 "If not provided, a dummy value will be used as that element is compulsory." ),
1428 driverMetadata.insert( QStringLiteral(
"GeoRSS" ),
1430 QStringLiteral(
"GeoRSS" ),
1431 QObject::tr(
"GeoRSS" ),
1432 QStringLiteral(
"*.xml" ),
1433 QStringLiteral(
"xml" ),
1436 QStringLiteral(
"UTF-8" )
1441 datasetOptions.clear();
1442 layerOptions.clear();
1445 QObject::tr(
"If provided, this URI will be inserted as the schema location. "
1446 "Note that the schema file isn't actually accessed by OGR, so it "
1447 "is up to the user to ensure it will match the schema of the OGR "
1448 "produced GML data file." ),
1453 QObject::tr(
"This writes a GML application schema file to a corresponding "
1454 ".xsd file (with the same basename). If INTERNAL is used the "
1455 "schema is written within the GML file, but this is experimental "
1456 "and almost certainly not valid XML. "
1457 "OFF disables schema generation (and is implicit if XSISCHEMAURI is used)." ),
1459 << QStringLiteral(
"EXTERNAL" )
1460 << QStringLiteral(
"INTERNAL" )
1461 << QStringLiteral(
"OFF" ),
1462 QStringLiteral(
"EXTERNAL" )
1466 QObject::tr(
"This is the prefix for the application target namespace." ),
1467 QStringLiteral(
"ogr" )
1471 QObject::tr(
"Can be set to TRUE to avoid writing the prefix of the "
1472 "application target namespace in the GML file." ),
1477 QObject::tr(
"Defaults to 'http://ogr.maptools.org/'. "
1478 "This is the application target namespace." ),
1479 QStringLiteral(
"http://ogr.maptools.org/" )
1483 QObject::tr(
"GML version to use." ),
1485 << QStringLiteral(
"GML2" )
1486 << QStringLiteral(
"GML3" )
1487 << QStringLiteral(
"GML3Deegree" )
1488 << QStringLiteral(
"GML3.2" ),
1489 QStringLiteral(
"GML3.2" )
1493 QObject::tr(
"Only valid when FORMAT=GML3/GML3Degree/GML3.2. Default to YES. "
1494 "If YES, SRS with EPSG authority will be written with the "
1495 "'urn:ogc:def:crs:EPSG::' prefix. In the case the SRS is a "
1496 "geographic SRS without explicit AXIS order, but that the same "
1497 "SRS authority code imported with ImportFromEPSGA() should be "
1498 "treated as lat/long, then the function will take care of coordinate "
1499 "order swapping. If set to NO, SRS with EPSG authority will be "
1500 "written with the 'EPSG:' prefix, even if they are in lat/long order." ),
1505 QObject::tr(
"only valid when FORMAT=GML3/GML3Degree/GML3.2) Default to YES. "
1506 "If set to NO, the <gml:boundedBy> element will not be written for "
1512 QObject::tr(
"Default to YES. If YES, the output will be indented with spaces "
1513 "for more readability, but at the expense of file size." ),
1518 driverMetadata.insert( QStringLiteral(
"GML" ),
1520 QStringLiteral(
"Geography Markup Language [GML]" ),
1521 QObject::tr(
"Geography Markup Language [GML]" ),
1522 QStringLiteral(
"*.gml" ),
1523 QStringLiteral(
"gml" ),
1526 QStringLiteral(
"UTF-8" )
1531 datasetOptions.clear();
1532 layerOptions.clear();
1535 QObject::tr(
"Human-readable identifier (e.g. short name) for the layer content" ),
1540 QObject::tr(
"Human-readable description for the layer content" ),
1545 QObject::tr(
"Name for the feature identifier column" ),
1546 QStringLiteral(
"fid" )
1550 QObject::tr(
"Name for the geometry column" ),
1551 QStringLiteral(
"geom" )
1555 QObject::tr(
"If a spatial index must be created." ),
1559 driverMetadata.insert( QStringLiteral(
"GPKG" ),
1561 QStringLiteral(
"GeoPackage" ),
1562 QObject::tr(
"GeoPackage" ),
1563 QStringLiteral(
"*.gpkg" ),
1564 QStringLiteral(
"gpkg" ),
1567 QStringLiteral(
"UTF-8" )
1572 datasetOptions.clear();
1573 layerOptions.clear();
1575 driverMetadata.insert( QStringLiteral(
"GMT" ),
1577 QStringLiteral(
"Generic Mapping Tools [GMT]" ),
1578 QObject::tr(
"Generic Mapping Tools [GMT]" ),
1579 QStringLiteral(
"*.gmt" ),
1580 QStringLiteral(
"gmt" ),
1587 datasetOptions.clear();
1588 layerOptions.clear();
1591 QObject::tr(
"By default when writing a layer whose features are of "
1592 "type wkbLineString, the GPX driver chooses to write "
1593 "them as routes. If FORCE_GPX_TRACK=YES is specified, "
1594 "they will be written as tracks." ),
1599 QObject::tr(
"By default when writing a layer whose features are of "
1600 "type wkbMultiLineString, the GPX driver chooses to write "
1601 "them as tracks. If FORCE_GPX_ROUTE=YES is specified, "
1602 "they will be written as routes, provided that the multilines "
1603 "are composed of only one single line." ),
1608 QObject::tr(
"If GPX_USE_EXTENSIONS=YES is specified, "
1609 "extra fields will be written inside the <extensions> tag." ),
1614 QObject::tr(
"Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS_URL "
1615 "is set. The namespace value used for extension tags. By default, 'ogr'." ),
1616 QStringLiteral(
"ogr" )
1620 QObject::tr(
"Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS "
1621 "is set. The namespace URI. By default, 'http://osgeo.org/gdal'." ),
1622 QStringLiteral(
"http://osgeo.org/gdal" )
1626 QObject::tr(
"By default files are created with the line termination "
1627 "conventions of the local platform (CR/LF on win32 or LF "
1628 "on all other systems). This may be overridden through use "
1629 "of the LINEFORMAT layer creation option which may have a value "
1630 "of CRLF (DOS format) or LF (Unix format)." ),
1632 << QStringLiteral(
"CRLF" )
1633 << QStringLiteral(
"LF" ),
1638 driverMetadata.insert( QStringLiteral(
"GPX" ),
1640 QStringLiteral(
"GPS eXchange Format [GPX]" ),
1641 QObject::tr(
"GPS eXchange Format [GPX]" ),
1642 QStringLiteral(
"*.gpx" ),
1643 QStringLiteral(
"gpx" ),
1646 QStringLiteral(
"UTF-8" )
1651 datasetOptions.clear();
1652 layerOptions.clear();
1654 driverMetadata.insert( QStringLiteral(
"Interlis 1" ),
1656 QStringLiteral(
"INTERLIS 1" ),
1657 QObject::tr(
"INTERLIS 1" ),
1658 QStringLiteral(
"*.itf *.xml *.ili" ),
1659 QStringLiteral(
"ili" ),
1666 datasetOptions.clear();
1667 layerOptions.clear();
1669 driverMetadata.insert( QStringLiteral(
"Interlis 2" ),
1671 QStringLiteral(
"INTERLIS 2" ),
1672 QObject::tr(
"INTERLIS 2" ),
1673 QStringLiteral(
"*.xtf *.xml *.ili" ),
1674 QStringLiteral(
"ili" ),
1681 datasetOptions.clear();
1682 layerOptions.clear();
1685 QObject::tr(
"Allows you to specify the field to use for the KML <name> element." ),
1686 QStringLiteral(
"Name" )
1690 QObject::tr(
"Allows you to specify the field to use for the KML <description> element." ),
1691 QStringLiteral(
"Description" )
1695 QObject::tr(
"Allows you to specify the AltitudeMode to use for KML geometries. "
1696 "This will only affect 3D geometries and must be one of the valid KML options." ),
1698 << QStringLiteral(
"clampToGround" )
1699 << QStringLiteral(
"relativeToGround" )
1700 << QStringLiteral(
"absolute" ),
1701 QStringLiteral(
"relativeToGround" )
1705 QObject::tr(
"The DOCUMENT_ID datasource creation option can be used to specified "
1706 "the id of the root <Document> node. The default value is root_doc." ),
1707 QStringLiteral(
"root_doc" )
1710 driverMetadata.insert( QStringLiteral(
"KML" ),
1712 QStringLiteral(
"Keyhole Markup Language [KML]" ),
1713 QObject::tr(
"Keyhole Markup Language [KML]" ),
1714 QStringLiteral(
"*.kml" ),
1715 QStringLiteral(
"kml" ),
1718 QStringLiteral(
"UTF-8" )
1723 datasetOptions.clear();
1724 layerOptions.clear();
1726 auto insertMapInfoOptions = []( QMap<QString, QgsVectorFileWriter::Option *> &datasetOptions, QMap<QString, QgsVectorFileWriter::Option *> &layerOptions )
1729 QObject::tr(
"Use this to turn on 'quick spatial index mode'. "
1730 "In this mode writing files can be about 5 times faster, "
1731 "but spatial queries can be up to 30 times slower." ),
1733 << QStringLiteral(
"QUICK" )
1734 << QStringLiteral(
"OPTIMIZED" ),
1735 QStringLiteral(
"QUICK" ),
1740 QObject::tr(
"(multiples of 512): Block size for .map files. Defaults "
1741 "to 512. MapInfo 15.2 and above creates .tab files with a "
1742 "blocksize of 16384 bytes. Any MapInfo version should be "
1743 "able to handle block sizes from 512 to 32256." ),
1747 QObject::tr(
"xmin,ymin,xmax,ymax: Define custom layer bounds to increase the "
1748 "accuracy of the coordinates. Note: the geometry of written "
1749 "features must be within the defined box." ),
1753 insertMapInfoOptions( datasetOptions, layerOptions );
1755 driverMetadata.insert( QStringLiteral(
"MapInfo File" ),
1757 QStringLiteral(
"Mapinfo" ),
1758 QObject::tr(
"Mapinfo TAB" ),
1759 QStringLiteral(
"*.tab" ),
1760 QStringLiteral(
"tab" ),
1765 datasetOptions.clear();
1766 layerOptions.clear();
1767 insertMapInfoOptions( datasetOptions, layerOptions );
1770 driverMetadata.insert( QStringLiteral(
"MapInfo MIF" ),
1772 QStringLiteral(
"Mapinfo" ),
1773 QObject::tr(
"Mapinfo MIF" ),
1774 QStringLiteral(
"*.mif" ),
1775 QStringLiteral(
"mif" ),
1782 datasetOptions.clear();
1783 layerOptions.clear();
1786 QObject::tr(
"Determine whether 2D (seed_2d.dgn) or 3D (seed_3d.dgn) "
1787 "seed file should be used. This option is ignored if the SEED option is provided." ),
1792 QObject::tr(
"Override the seed file to use." ),
1797 QObject::tr(
"Indicate whether the whole seed file should be copied. "
1798 "If not, only the first three elements will be copied." ),
1803 QObject::tr(
"Indicates whether the color table should be copied from the seed file." ),
1808 QObject::tr(
"Override the master unit name from the seed file with "
1809 "the provided one or two character unit name." ),
1814 QObject::tr(
"Override the sub unit name from the seed file with the provided "
1815 "one or two character unit name." ),
1820 QObject::tr(
"Override the number of subunits per master unit. "
1821 "By default the seed file value is used." ),
1826 QObject::tr(
"Override the number of UORs (Units of Resolution) "
1827 "per sub unit. By default the seed file value is used." ),
1832 QObject::tr(
"ORIGIN=x,y,z: Override the origin of the design plane. "
1833 "By default the origin from the seed file is used." ),
1837 driverMetadata.insert( QStringLiteral(
"DGN" ),
1839 QStringLiteral(
"Microstation DGN" ),
1840 QObject::tr(
"Microstation DGN" ),
1841 QStringLiteral(
"*.dgn" ),
1842 QStringLiteral(
"dgn" ),
1849 datasetOptions.clear();
1850 layerOptions.clear();
1853 QObject::tr(
"Should update files be incorporated into the base data on the fly." ),
1855 << QStringLiteral(
"APPLY" )
1856 << QStringLiteral(
"IGNORE" ),
1857 QStringLiteral(
"APPLY" )
1861 QObject::tr(
"Should multipoint soundings be split into many single point sounding features. "
1862 "Multipoint geometries are not well handled by many formats, "
1863 "so it can be convenient to split single sounding features with many points "
1864 "into many single point features." ),
1869 QObject::tr(
"Should a DEPTH attribute be added on SOUNDG features and assign the depth "
1870 "of the sounding. This should only be enabled when SPLIT_MULTIPOINT is "
1876 QObject::tr(
"Should all the low level geometry primitives be returned as special "
1877 "IsolatedNode, ConnectedNode, Edge and Face layers." ),
1882 QObject::tr(
"If enabled, numeric attributes assigned an empty string as a value will "
1883 "be preserved as a special numeric value. This option should not generally "
1884 "be needed, but may be useful when translated S-57 to S-57 losslessly." ),
1889 QObject::tr(
"Should LNAM and LNAM_REFS fields be attached to features capturing "
1890 "the feature to feature relationships in the FFPT group of the S-57 file." ),
1895 QObject::tr(
"Should additional attributes relating features to their underlying "
1896 "geometric primitives be attached. These are the values of the FSPT group, "
1897 "and are primarily needed when doing S-57 to S-57 translations." ),
1902 QObject::tr(
"Should attribute values be recoded to UTF-8 from the character encoding "
1903 "specified in the S57 DSSI record." ),
1909 driverMetadata.insert( QStringLiteral(
"S57" ),
1911 QStringLiteral(
"S-57 Base file" ),
1912 QObject::tr(
"S-57 Base file" ),
1913 QStringLiteral(
"*.000" ),
1914 QStringLiteral(
"000" ),
1921 datasetOptions.clear();
1922 layerOptions.clear();
1924 driverMetadata.insert( QStringLiteral(
"SDTS" ),
1926 QStringLiteral(
"Spatial Data Transfer Standard [SDTS]" ),
1927 QObject::tr(
"Spatial Data Transfer Standard [SDTS]" ),
1928 QStringLiteral(
"*catd.ddf" ),
1929 QStringLiteral(
"ddf" ),
1936 datasetOptions.clear();
1937 layerOptions.clear();
1940 QObject::tr(
"Can be used to avoid creating the geometry_columns and spatial_ref_sys "
1941 "tables in a new database. By default these metadata tables are created "
1942 "when a new database is created." ),
1948 QStringLiteral(
"NO" )
1953 QStringLiteral(
"NO" )
1957 QObject::tr(
"Controls the format used for the geometry column. Defaults to WKB. "
1958 "This is generally more space and processing efficient, but harder "
1959 "to inspect or use in simple applications than WKT (Well Known Text)." ),
1961 << QStringLiteral(
"WKB" )
1962 << QStringLiteral(
"WKT" ),
1963 QStringLiteral(
"WKB" )
1967 QObject::tr(
"Controls whether layer and field names will be laundered for easier use "
1968 "in SQLite. Laundered names will be converted to lower case and some special "
1969 "characters(' - #) will be changed to underscores." ),
1974 QStringLiteral(
"NO" )
1978 QStringLiteral(
"NO" )
1986 QObject::tr(
"column_name1[,column_name2, …] A list of (String) columns that "
1987 "must be compressed with ZLib DEFLATE algorithm. This might be beneficial "
1988 "for databases that have big string blobs. However, use with care, since "
1989 "the value of such columns will be seen as compressed binary content with "
1990 "other SQLite utilities (or previous OGR versions). With OGR, when inserting, "
1991 "modifying or querying compressed columns, compression/decompression is "
1992 "done transparently. However, such columns cannot be (easily) queried with "
1993 "an attribute filter or WHERE clause. Note: in table definition, such columns "
1994 "have the 'VARCHAR_deflate' declaration type." ),
1998 driverMetadata.insert( QStringLiteral(
"SQLite" ),
2000 QStringLiteral(
"SQLite" ),
2001 QObject::tr(
"SQLite" ),
2002 QStringLiteral(
"*.sqlite" ),
2003 QStringLiteral(
"sqlite" ),
2006 QStringLiteral(
"UTF-8" )
2011 datasetOptions.clear();
2012 layerOptions.clear();
2015 QObject::tr(
"Can be used to avoid creating the geometry_columns and spatial_ref_sys "
2016 "tables in a new database. By default these metadata tables are created "
2017 "when a new database is created." ),
2022 QStringLiteral(
"YES" )
2026 QObject::tr(
"Insert the content of the EPSG CSV files into the spatial_ref_sys table. "
2027 "Set to NO for regular SQLite databases." ),
2032 QStringLiteral(
"SPATIALITE" )
2036 QObject::tr(
"Controls whether layer and field names will be laundered for easier use "
2037 "in SQLite. Laundered names will be converted to lower case and some special "
2038 "characters(' - #) will be changed to underscores." ),
2043 QObject::tr(
"If the database is of the SpatiaLite flavor, and if OGR is linked "
2044 "against libspatialite, this option can be used to control if a spatial "
2045 "index must be created." ),
2050 QObject::tr(
"If the format of the geometry BLOB is of the SpatiaLite flavor, "
2051 "this option can be used to control if the compressed format for "
2052 "geometries (LINESTRINGs, POLYGONs) must be used." ),
2057 QObject::tr(
"Used to force the SRID number of the SRS associated with the layer. "
2058 "When this option isn't specified and that a SRS is associated with the "
2059 "layer, a search is made in the spatial_ref_sys to find a match for the "
2060 "SRS, and, if there is no match, a new entry is inserted for the SRS in "
2061 "the spatial_ref_sys table. When the SRID option is specified, this "
2062 "search (and the eventual insertion of a new entry) will not be done: "
2063 "the specified SRID is used as such." ),
2068 QObject::tr(
"column_name1[,column_name2, …] A list of (String) columns that "
2069 "must be compressed with ZLib DEFLATE algorithm. This might be beneficial "
2070 "for databases that have big string blobs. However, use with care, since "
2071 "the value of such columns will be seen as compressed binary content with "
2072 "other SQLite utilities (or previous OGR versions). With OGR, when inserting, "
2073 "modifying or queryings compressed columns, compression/decompression is "
2074 "done transparently. However, such columns cannot be (easily) queried with "
2075 "an attribute filter or WHERE clause. Note: in table definition, such columns "
2076 "have the 'VARCHAR_deflate' declaration type." ),
2080 driverMetadata.insert( QStringLiteral(
"SpatiaLite" ),
2082 QStringLiteral(
"SpatiaLite" ),
2083 QObject::tr(
"SpatiaLite" ),
2084 QStringLiteral(
"*.sqlite" ),
2085 QStringLiteral(
"sqlite" ),
2088 QStringLiteral(
"UTF-8" )
2092 datasetOptions.clear();
2093 layerOptions.clear();
2096 QObject::tr(
"Override the header file used - in place of header.dxf." ),
2101 QObject::tr(
"Override the trailer file used - in place of trailer.dxf." ),
2105 driverMetadata.insert( QStringLiteral(
"DXF" ),
2107 QStringLiteral(
"AutoCAD DXF" ),
2108 QObject::tr(
"AutoCAD DXF" ),
2109 QStringLiteral(
"*.dxf" ),
2110 QStringLiteral(
"dxf" ),
2117 datasetOptions.clear();
2118 layerOptions.clear();
2121 QObject::tr(
"Indicates the GeoConcept export file extension. "
2122 "TXT was used by earlier releases of GeoConcept. GXT is currently used." ),
2124 << QStringLiteral(
"GXT" )
2125 << QStringLiteral(
"TXT" ),
2126 QStringLiteral(
"GXT" )
2130 QObject::tr(
"Path to the GCT: the GCT file describes the GeoConcept types definitions: "
2131 "In this file, every line must start with //# followed by a keyword. "
2132 "Lines starting with // are comments." ),
2137 QObject::tr(
"Defines the feature to be created. The TYPE corresponds to one of the Name "
2138 "found in the GCT file for a type section. The SUBTYPE corresponds to one of "
2139 "the Name found in the GCT file for a sub-type section within the previous "
2144 driverMetadata.insert( QStringLiteral(
"Geoconcept" ),
2146 QStringLiteral(
"Geoconcept" ),
2147 QObject::tr(
"Geoconcept" ),
2148 QStringLiteral(
"*.gxt *.txt" ),
2149 QStringLiteral(
"gxt" ),
2156 datasetOptions.clear();
2157 layerOptions.clear();
2160 QObject::tr(
"When this option is set, the new layer will be created inside the named "
2161 "FeatureDataset folder. If the folder does not already exist, it will be created." ),
2166 QObject::tr(
"Set layer name alias." ),
2171 QObject::tr(
"Set name of geometry column in new layer. Defaults to 'SHAPE'." ),
2172 QStringLiteral(
"SHAPE" )
2176 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'." ),
2181 QObject::tr(
"Name of the OID column to create. Defaults to 'OBJECTID'." ),
2182 QStringLiteral(
"OBJECTID" )
2198 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." ),
2203 QObject::tr(
"XML documentation for the layer." ),
2207 QObject::tr(
"Customize how data is stored. By default text in UTF-8 and data up to 1TB." ),
2208 {QStringLiteral(
"DEFAULTS" ), QStringLiteral(
"MAX_FILE_SIZE_4GB" ), QStringLiteral(
"MAX_FILE_SIZE_256TB" )},
2209 QStringLiteral(
"DEFAULTS" ),
2214 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." ),
2218 driverMetadata.insert( QStringLiteral(
"OpenFileGDB" ),
2220 QStringLiteral(
"ESRI File Geodatabase" ),
2221 QObject::tr(
"ESRI File Geodatabase" ),
2222 QStringLiteral(
"*.gdb" ),
2223 QStringLiteral(
"gdb" ),
2226 QStringLiteral(
"UTF-8" )
2231 datasetOptions.clear();
2232 layerOptions.clear();
2235 QObject::tr(
"When this option is set, the new layer will be created inside the named "
2236 "FeatureDataset folder. If the folder does not already exist, it will be created." ),
2241 QObject::tr(
"Set name of geometry column in new layer. Defaults to 'SHAPE'." ),
2242 QStringLiteral(
"SHAPE" )
2246 QObject::tr(
"Name of the OID column to create. Defaults to 'OBJECTID'." ),
2247 QStringLiteral(
"OBJECTID" )
2250 driverMetadata.insert( QStringLiteral(
"FileGDB" ),
2252 QStringLiteral(
"ESRI FileGDB" ),
2253 QObject::tr(
"ESRI FileGDB" ),
2254 QStringLiteral(
"*.gdb" ),
2255 QStringLiteral(
"gdb" ),
2258 QStringLiteral(
"UTF-8" )
2263 datasetOptions.clear();
2264 layerOptions.clear();
2267 QObject::tr(
"By default, the driver will try to detect the data type of fields. If set "
2268 "to STRING, all fields will be of String type." ),
2270 << QStringLiteral(
"AUTO" )
2271 << QStringLiteral(
"STRING" ),
2272 QStringLiteral(
"AUTO" ),
2277 QObject::tr(
"By default, the driver will read the first lines of each sheet to detect "
2278 "if the first line might be the name of columns. If set to FORCE, the driver "
2279 "will consider the first line as the header line. If set to "
2280 "DISABLE, it will be considered as the first feature. Otherwise "
2281 "auto-detection will occur." ),
2283 << QStringLiteral(
"FORCE" )
2284 << QStringLiteral(
"DISABLE" )
2285 << QStringLiteral(
"AUTO" ),
2286 QStringLiteral(
"AUTO" ),
2290 driverMetadata.insert( QStringLiteral(
"XLSX" ),
2292 QStringLiteral(
"MS Office Open XML spreadsheet" ),
2293 QObject::tr(
"MS Office Open XML spreadsheet [XLSX]" ),
2294 QStringLiteral(
"*.xlsx" ),
2295 QStringLiteral(
"xlsx" ),
2298 QStringLiteral(
"UTF-8" )
2303 datasetOptions.clear();
2304 layerOptions.clear();
2307 QObject::tr(
"By default, the driver will try to detect the data type of fields. If set "
2308 "to STRING, all fields will be of String type." ),
2310 << QStringLiteral(
"AUTO" )
2311 << QStringLiteral(
"STRING" ),
2312 QStringLiteral(
"AUTO" ),
2317 QObject::tr(
"By default, the driver will read the first lines of each sheet to detect "
2318 "if the first line might be the name of columns. If set to FORCE, the driver "
2319 "will consider the first line as the header line. If set to "
2320 "DISABLE, it will be considered as the first feature. Otherwise "
2321 "auto-detection will occur." ),
2323 << QStringLiteral(
"FORCE" )
2324 << QStringLiteral(
"DISABLE" )
2325 << QStringLiteral(
"AUTO" ),
2326 QStringLiteral(
"AUTO" ),
2330 driverMetadata.insert( QStringLiteral(
"ODS" ),
2332 QStringLiteral(
"Open Document Spreadsheet" ),
2333 QObject::tr(
"Open Document Spreadsheet [ODS]" ),
2334 QStringLiteral(
"*.ods" ),
2335 QStringLiteral(
"ods" ),
2338 QStringLiteral(
"UTF-8" )
2343 datasetOptions.clear();
2344 layerOptions.clear();
2347 QObject::tr(
"Compression method." ),
2349 << QStringLiteral(
"UNCOMPRESSED" )
2350 << QStringLiteral(
"SNAPPY" ),
2351 QStringLiteral(
"SNAPPY" ),
2356 QObject::tr(
"Geometry encoding." ),
2358 << QStringLiteral(
"WKB" )
2359 << QStringLiteral(
"WKT" )
2360 << QStringLiteral(
"GEOARROW" ),
2361 QStringLiteral(
"WKB" ),
2366 QObject::tr(
"Maximum number of rows per group." ),
2371 QObject::tr(
"Name for the feature identifier column" ),
2376 QObject::tr(
"Name for the geometry column" ),
2377 QStringLiteral(
"geometry" )
2381 QObject::tr(
"Name of the coordinate system for the edges." ),
2383 << QStringLiteral(
"PLANAR" )
2384 << QStringLiteral(
"SPHERICAL" ),
2385 QStringLiteral(
"PLANAR" ),
2389 driverMetadata.insert( QStringLiteral(
"Parquet" ),
2391 QStringLiteral(
"(Geo)Parquet" ),
2392 QObject::tr(
"(Geo)Parquet" ),
2393 QStringLiteral(
"*.parquet" ),
2394 QStringLiteral(
"parquet" ),
2397 QStringLiteral(
"UTF-8" )
2402 datasetOptions.clear();
2403 layerOptions.clear();
2406 QObject::tr(
"Line termination character sequence." ),
2408 << QStringLiteral(
"CRLF" )
2409 << QStringLiteral(
"LF" ),
2410 QStringLiteral(
"LF" ),
2416 QObject::tr(
"Format of geometry columns." ),
2418 << QStringLiteral(
"geometry" )
2419 << QStringLiteral(
"geography" ),
2420 QStringLiteral(
"geometry" ),
2425 QObject::tr(
"Controls whether layer and field names will be laundered for easier use. "
2426 "Laundered names will be converted to lower case and some special "
2427 "characters(' - #) will be changed to underscores." ),
2432 QObject::tr(
"Name for the geometry column. Defaults to wkb_geometry "
2433 "for GEOM_TYPE=geometry or the_geog for GEOM_TYPE=geography" ) ) );
2436 QObject::tr(
"Name of schema into which to create the new table" ) ) );
2439 QObject::tr(
"Whether to explicitly emit the CREATE SCHEMA statement to create the specified schema." ),
2444 QObject::tr(
"Whether to explicitly recreate the table if necessary." ),
2449 QObject::tr(
"Whether to explicitly destroy tables before recreating them." ),
2451 << QStringLiteral(
"YES" )
2452 << QStringLiteral(
"NO" )
2453 << QStringLiteral(
"IF_EXISTS" ),
2454 QStringLiteral(
"YES" ),
2459 QObject::tr(
"Used to force the SRID number of the SRS associated with the layer. "
2460 "When this option isn't specified and that a SRS is associated with the "
2461 "layer, a search is made in the spatial_ref_sys to find a match for the "
2462 "SRS, and, if there is no match, a new entry is inserted for the SRS in "
2463 "the spatial_ref_sys table. When the SRID option is specified, this "
2464 "search (and the eventual insertion of a new entry) will not be done: "
2465 "the specified SRID is used as such." ),
2470 QObject::tr(
"Can be set to 2.0 or 2.2 for PostGIS 2.0/2.2 compatibility. "
2471 "Important to set it correctly if using non-linear geometry types" ),
2472 QStringLiteral(
"2.2" )
2475 driverMetadata.insert( QStringLiteral(
"PGDUMP" ),
2477 QStringLiteral(
"PostgreSQL SQL dump" ),
2478 QObject::tr(
"PostgreSQL SQL dump" ),
2479 QStringLiteral(
"*.sql" ),
2480 QStringLiteral(
"sql" ),
2483 QStringLiteral(
"UTF-8" )
2489 QgsVectorFileWriterMetadataContainer(
const QgsVectorFileWriterMetadataContainer &other ) =
delete;
2490 QgsVectorFileWriterMetadataContainer &operator=(
const QgsVectorFileWriterMetadataContainer &other ) =
delete;
2491 ~QgsVectorFileWriterMetadataContainer()
2493 for (
auto it = driverMetadata.constBegin(); it != driverMetadata.constEnd(); ++it )
2495 for (
auto optionIt = it.value().driverOptions.constBegin(); optionIt != it.value().driverOptions.constEnd(); ++optionIt )
2496 delete optionIt.value();
2497 for (
auto optionIt = it.value().layerOptions.constBegin(); optionIt != it.value().layerOptions.constEnd(); ++optionIt )
2498 delete optionIt.value();
2502 QMap<QString, QgsVectorFileWriter::MetaData> driverMetadata;
2509 static QgsVectorFileWriterMetadataContainer sDriverMetadata;
2510 QMap<QString, MetaData>::ConstIterator it = sDriverMetadata.driverMetadata.constBegin();
2512 for ( ; it != sDriverMetadata.driverMetadata.constEnd(); ++it )
2514 if ( it.key() == QLatin1String(
"PGDUMP" ) &&
2515 driverName != QLatin1String(
"PGDUMP" ) &&
2516 driverName != QLatin1String(
"PostgreSQL SQL dump" ) )
2521 if ( it.key().startsWith( driverName ) || it.value().longName.startsWith( driverName ) )
2536 return QStringList();
2545 return QStringList();
2552 OGRwkbGeometryType ogrType =
static_cast<OGRwkbGeometryType
>( type );
2583 return mCapabilities;
2593 QgsFeatureList::iterator fIt = features.begin();
2595 for ( ; fIt != features.end(); ++fIt )
2620 QString styleString;
2621 QString currentStyle;
2623 QgsSymbolList::const_iterator symbolIt = symbols.constBegin();
2624 for ( ; symbolIt != symbols.constEnd(); ++symbolIt )
2626 int nSymbolLayers = ( *symbolIt )->symbolLayerCount();
2627 for (
int i = 0; i < nSymbolLayers; ++i )
2630 QMap< QgsSymbolLayer *, QString >::const_iterator it =
mSymbolLayerTable.find( ( *symbolIt )->symbolLayer( i ) );
2636 double mmsf = mmScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
2637 double musf = mapUnitScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
2639 currentStyle = ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf );
2643 case Qgis::FeatureSymbologyExport::PerFeature:
2645 if ( symbolIt != symbols.constBegin() || i != 0 )
2647 styleString.append(
';' );
2649 styleString.append( currentStyle );
2652 case Qgis::FeatureSymbologyExport::PerSymbolLayer:
2654 OGR_F_SetStyleString( poFeature.get(), currentStyle.toLocal8Bit().constData() );
2655 if ( !writeFeature(
mLayer, poFeature.get() ) )
2667 OGR_F_SetStyleString( poFeature.get(), styleString.toLocal8Bit().constData() );
2673 case Qgis::FeatureSymbologyExport::PerFeature:
2675 if ( !writeFeature(
mLayer, poFeature.get() ) )
2682 case Qgis::FeatureSymbologyExport::PerSymbolLayer:
2699 int fldIdx = it.key();
2700 int ogrField = it.value();
2702 QVariant attrValue = feature.
attribute( fldIdx );
2707 OGR_F_UnsetField( poFeature.get(), ogrField );
2720 OGR_F_SetFieldNull( poFeature.get(), ogrField );
2735 mErrorMessage = QObject::tr(
"Error converting value (%1) for attribute field %2: %3" )
2736 .arg( feature.
attribute( fldIdx ).toString(),
2746 OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
2748 case QVariant::LongLong:
2749 OGR_F_SetFieldInteger64( poFeature.get(), ogrField, attrValue.toLongLong() );
2751 case QVariant::Bool:
2752 OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
2754 case QVariant::String:
2755 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toString() ).constData() );
2757 case QVariant::Double:
2758 OGR_F_SetFieldDouble( poFeature.get(), ogrField, attrValue.toDouble() );
2760 case QVariant::Date:
2761 OGR_F_SetFieldDateTime( poFeature.get(), ogrField,
2762 attrValue.toDate().year(),
2763 attrValue.toDate().month(),
2764 attrValue.toDate().day(),
2767 case QVariant::DateTime:
2770 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toDateTime().toString( QStringLiteral(
"yyyy/MM/dd hh:mm:ss.zzz" ) ) ).constData() );
2774 const QDateTime dt = attrValue.toDateTime();
2775 const QDate date = dt.date();
2776 const QTime time = dt.time();
2777 OGR_F_SetFieldDateTimeEx( poFeature.get(), ogrField,
2783 static_cast<float>( time.second() +
static_cast< double >( time.msec() ) / 1000 ),
2787 case QVariant::Time:
2790 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toString() ).constData() );
2794 const QTime time = attrValue.toTime();
2795 OGR_F_SetFieldDateTimeEx( poFeature.get(), ogrField,
2799 static_cast<float>( time.second() +
static_cast< double >( time.msec() ) / 1000 ),
2804 case QVariant::ByteArray:
2806 const QByteArray ba = attrValue.toByteArray();
2807 OGR_F_SetFieldBinary( poFeature.get(), ogrField, ba.size(),
const_cast< GByte *
>(
reinterpret_cast< const GByte *
>( ba.data() ) ) );
2811 case QVariant::Invalid:
2814 case QVariant::StringList:
2819 const QJsonDocument doc = QJsonDocument::fromVariant( attrValue );
2821 if ( !doc.isNull() )
2823 jsonString = QString::fromUtf8( doc.toJson( QJsonDocument::Compact ).constData() );
2825 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( jsonString.constData() ) );
2829 QStringList list = attrValue.toStringList();
2830 if ( mSupportedListSubTypes.contains( QVariant::String ) )
2832 int count = list.count();
2833 char **lst =
new char *[count + 1];
2837 for (
const QString &
string : list )
2839 lst[pos] = CPLStrdup(
mCodec->fromUnicode(
string ).data() );
2843 lst[count] =
nullptr;
2844 OGR_F_SetFieldStringList( poFeature.get(), ogrField, lst );
2849 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( list.join(
',' ) ).constData() );
2854 case QVariant::List:
2858 const QJsonDocument doc = QJsonDocument::fromVariant( attrValue );
2860 if ( !doc.isNull() )
2862 jsonString = QString::fromUtf8( doc.toJson( QJsonDocument::Compact ).data() );
2864 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( jsonString.constData() ) );
2871 QStringList list = attrValue.toStringList();
2872 if ( mSupportedListSubTypes.contains( QVariant::String ) )
2874 int count = list.count();
2875 char **lst =
new char *[count + 1];
2879 for (
const QString &
string : list )
2881 lst[pos] = CPLStrdup(
mCodec->fromUnicode(
string ).data() );
2885 lst[count] =
nullptr;
2886 OGR_F_SetFieldStringList( poFeature.get(), ogrField, lst );
2891 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( list.join(
',' ) ).constData() );
2897 const QVariantList list = attrValue.toList();
2898 if ( mSupportedListSubTypes.contains( QVariant::Int ) )
2900 const int count = list.count();
2901 int *lst =
new int[count];
2905 for (
const QVariant &value : list )
2907 lst[pos] = value.toInt();
2911 OGR_F_SetFieldIntegerList( poFeature.get(), ogrField, count, lst );
2916 QStringList strings;
2917 strings.reserve( list.size() );
2918 for (
const QVariant &value : list )
2920 strings << QString::number( value.toInt() );
2922 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
2928 const QVariantList list = attrValue.toList();
2929 if ( mSupportedListSubTypes.contains( QVariant::Double ) )
2931 const int count = list.count();
2932 double *lst =
new double[count];
2936 for (
const QVariant &value : list )
2938 lst[pos] = value.toDouble();
2942 OGR_F_SetFieldDoubleList( poFeature.get(), ogrField, count, lst );
2947 QStringList strings;
2948 strings.reserve( list.size() );
2949 for (
const QVariant &value : list )
2951 strings << QString::number( value.toDouble() );
2953 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
2959 const QVariantList list = attrValue.toList();
2960 if ( mSupportedListSubTypes.contains( QVariant::LongLong ) )
2962 const int count = list.count();
2963 long long *lst =
new long long[count];
2967 for (
const QVariant &value : list )
2969 lst[pos] = value.toLongLong();
2973 OGR_F_SetFieldInteger64List( poFeature.get(), ogrField, count, lst );
2978 QStringList strings;
2979 strings.reserve( list.size() );
2980 for (
const QVariant &value : list )
2982 strings << QString::number( value.toLongLong() );
2984 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
2994 const char *pszDataSubTypes = GDALGetMetadataItem( OGRGetDriverByName(
mOgrDriverName.toLocal8Bit().constData() ), GDAL_DMD_CREATIONFIELDDATASUBTYPES,
nullptr );
2995 if ( pszDataSubTypes && strstr( pszDataSubTypes,
"JSON" ) )
2997 const QJsonDocument doc = QJsonDocument::fromVariant( attrValue );
2999 if ( !doc.isNull() )
3001 const QByteArray json { doc.toJson( QJsonDocument::Compact ) };
3002 jsonString = QString::fromUtf8( json.data() );
3004 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( jsonString.constData() ) );
3014 mErrorMessage = QObject::tr(
"Invalid variant type for field %1[%2]: received %3 with type %4" )
3017 .arg( attrValue.typeName(),
3018 attrValue.toString() );
3031 if ( mCoordinateTransform )
3036 geom.
transform( *mCoordinateTransform );
3054 OGRGeometryH mGeom2 =
nullptr;
3083 geom.
get()->
addZValue( std::numeric_limits<double>::quiet_NaN() );
3090 geom.
get()->
addMValue( std::numeric_limits<double>::quiet_NaN() );
3110 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
3111 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
3117 QgsAbstractGeometry::WkbFlags wkbFlags;
3121 QByteArray wkb( geom.
asWkb( wkbFlags ) );
3122 OGRErr err = OGR_G_ImportFromWkb( mGeom2,
reinterpret_cast<unsigned char *
>(
const_cast<char *
>( wkb.constData() ) ), wkb.length() );
3123 if ( err != OGRERR_NONE )
3125 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
3126 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
3133 OGR_F_SetGeometryDirectly( poFeature.get(), mGeom2 );
3141 QByteArray wkb( geom.
asWkb( wkbFlags ) );
3143 OGRErr err = OGR_G_ImportFromWkb( ogrGeom,
reinterpret_cast<unsigned char *
>(
const_cast<char *
>( wkb.constData() ) ), wkb.length() );
3144 if ( err != OGRERR_NONE )
3146 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
3147 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
3154 OGR_F_SetGeometryDirectly( poFeature.get(), ogrGeom );
3169 for (
int i = 0; i < attributes.size(); i++ )
3171 if ( omap.find( i ) != omap.end() )
3176bool QgsVectorFileWriter::writeFeature( OGRLayerH layer, OGRFeatureH feature )
3178 if ( OGR_L_CreateFeature( layer, feature ) != OGRERR_NONE )
3180 mErrorMessage = QObject::tr(
"Feature creation error (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
3190 if ( mUsingTransaction )
3192 if ( OGRERR_NONE != OGR_L_CommitTransaction(
mLayer ) )
3194 QgsDebugError( QStringLiteral(
"Error while committing transaction on OGRLayer." ) );
3207 const QString &fileName,
3208 const QString &fileEncoding,
3210 const QString &driverName,
3212 QString *errorMessage,
3213 const QStringList &datasourceOptions,
3214 const QStringList &layerOptions,
3215 bool skipAttributeCreation,
3216 QString *newFilename,
3218 double symbologyScale,
3228 if ( destCRS.
isValid() && layer )
3254 const QString &fileName,
3255 const QString &fileEncoding,
3257 const QString &driverName,
3259 QString *errorMessage,
3260 const QStringList &datasourceOptions,
3261 const QStringList &layerOptions,
3262 bool skipAttributeCreation,
3263 QString *newFilename,
3265 double symbologyScale,
3296 : driverName( QStringLiteral(
"GPKG" ) )
3304 if ( !layer || !layer->
isValid() )
3311 details.sourceCrs = layer->
crs();
3312 details.sourceWkbType = layer->
wkbType();
3313 details.sourceFields = layer->
fields();
3322 if ( details.storageType == QLatin1String(
"ESRI Shapefile" ) )
3330 details.geometryTypeScanIterator = layer->
getFeatures( req );
3334 details.renderContext.setExpressionContext( details.expressionContext );
3335 details.renderContext.setRendererScale( options.
symbologyScale );
3337 details.shallTransform =
false;
3342 details.shallTransform =
true;
3347 details.outputCrs = details.sourceCrs;
3350 details.destWkbType = details.sourceWkbType;
3364 details.attributes.clear();
3365 else if ( details.attributes.isEmpty() )
3367 const QgsAttributeList allAttributes = details.sourceFields.allAttributesList();
3368 for (
int idx : allAttributes )
3370 QgsField fld = details.sourceFields.at( idx );
3371 if ( details.providerType == QLatin1String(
"oracle" ) && fld.
typeName().contains( QLatin1String(
"SDO_GEOMETRY" ) ) )
3373 details.attributes.append( idx );
3377 if ( !details.attributes.isEmpty() )
3379 for (
int attrIdx : std::as_const( details.attributes ) )
3381 if ( details.sourceFields.exists( attrIdx ) )
3385 details.outputFields.append(
field );
3389 QgsDebugError( QStringLiteral(
"No such source field with index '%1' available." ).arg( attrIdx ) );
3396 if ( details.providerType == QLatin1String(
"spatialite" ) )
3398 for (
int i = 0; i < details.outputFields.size(); i++ )
3400 if ( details.outputFields.at( i ).type() == QVariant::LongLong )
3405 if ( std::max( std::llabs( min.toLongLong() ), std::llabs( max.toLongLong() ) ) < std::numeric_limits<int>::max() )
3407 details.outputFields[i].setType( QVariant::Int );
3415 addRendererAttributes( details.renderer.get(), details.renderContext, details.sourceFields, details.attributes );
3425 bool useFilterRect =
true;
3426 if ( details.shallTransform )
3433 filterRect = extentTransform.
transformBoundingBox( filterRect, Qgis::TransformDirection::Reverse );
3437 useFilterRect =
false;
3440 if ( useFilterRect )
3446 details.filterRectEngine->prepareGeometry();
3448 details.sourceFeatureIterator = layer->
getFeatures( req );
3462 int lastProgressReport = 0;
3463 long long total = details.featureCount;
3466 if ( details.providerType == QLatin1String(
"ogr" ) && !details.dataSourceUri.isEmpty() )
3468 QString srcFileName( details.providerUriParams.value( QStringLiteral(
"path" ) ).toString() );
3469 if ( QFile::exists( srcFileName ) && QFileInfo( fileName ).canonicalFilePath() == QFileInfo( srcFileName ).canonicalFilePath() )
3473 if ( !( ( options.
driverName == QLatin1String(
"GPKG" ) ||
3474 options.
driverName == QLatin1String(
"SpatiaLite" ) ||
3475 options.
driverName == QLatin1String(
"SQLite" ) ) &&
3476 options.
layerName != details.providerUriParams.value( QStringLiteral(
"layerName" ) ) ) )
3479 *
errorMessage = QObject::tr(
"Cannot overwrite a OGR layer in place" );
3499 int newProgress =
static_cast<int>( ( 5.0 * scanned ) / total );
3500 if ( newProgress != lastProgressReport )
3502 lastProgressReport = newProgress;
3517 QString tempNewFilename;
3518 QString tempNewLayer;
3520 std::unique_ptr< QgsVectorFileWriter > writer(
create( fileName, details.outputFields, destWkbType, details.outputCrs, transformContext, options, QgsFeatureSink::SinkFlags(), &tempNewFilename, &tempNewLayer ) );
3524 *newFilename = tempNewFilename;
3527 *newLayer = tempNewLayer;
3556 switch ( writer->symbologyExport() )
3558 case Qgis::FeatureSymbologyExport::PerSymbolLayer:
3570 case Qgis::FeatureSymbologyExport::PerFeature:
3574 int n = 0, errors = 0;
3583 writer->startRender( details.renderer.get(), details.sourceFields );
3585 writer->resetMap( details.attributes );
3587 writer->mFields = details.sourceFields;
3591 int initialProgress = lastProgressReport;
3592 while ( details.sourceFeatureIterator.nextFeature( fet ) )
3603 int newProgress =
static_cast<int>( initialProgress + ( ( 100.0 - initialProgress ) * saved ) / total );
3604 if ( newProgress < 100 && newProgress != lastProgressReport )
3606 lastProgressReport = newProgress;
3611 if ( details.shallTransform )
3624 QString msg = QObject::tr(
"Failed to transform a point while drawing a feature with ID '%1'. Writing stopped. (Exception: %2)" )
3625 .arg( fet.
id() ).arg( e.
what() );
3642 if ( !writer->addFeatureWithStyle( fet, writer->mRenderer.get(), mapUnits ) )
3649 *
errorMessage = QObject::tr(
"Feature write errors:" );
3655 if ( errors > 1000 )
3659 *
errorMessage += QObject::tr(
"Stopping after %n error(s)",
nullptr, errors );
3669 writer->stopRender();
3673 *
errorMessage += QObject::tr(
"\nOnly %1 of %2 features written." ).arg( n - errors ).arg( n );
3678 bool metadataFailure =
false;
3683 {QStringLiteral(
"path" ), tempNewFilename },
3684 {QStringLiteral(
"layerName" ), tempNewLayer }
3698 metadataFailure =
true;
3709 metadataFailure =
true;
3717 const QString &fileName,
3719 QString *newFilename,
3723 QgsVectorFileWriter::PreparedWriterDetails details;
3724 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
3732 const QString &fileName,
3735 QString *newFilename,
3739 QgsVectorFileWriter::PreparedWriterDetails details;
3740 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
3749 QgsVectorFileWriter::PreparedWriterDetails details;
3750 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
3759 QFileInfo fi( fileName );
3760 QDir dir = fi.dir();
3763 for (
const char *suffix : {
".shp",
".shx",
".dbf",
".prj",
".qix",
".qpj",
".cpg",
".sbn",
".sbx",
".idm",
".ind" } )
3765 filter << fi.completeBaseName() + suffix;
3769 const auto constEntryList = dir.entryList( filter );
3770 for (
const QString &file : constEntryList )
3772 QFile f( dir.canonicalPath() +
'/' + file );
3775 QgsDebugError( QStringLiteral(
"Removing file %1 failed: %2" ).arg( file, f.errorString() ) );
3791 QStringList driverNames;
3794 for (
int i = 0; i < GDALGetDriverCount(); ++i )
3796 GDALDriverH
driver = GDALGetDriver( i );
3803 const QString driverExtensions = GDALGetMetadataItem(
driver, GDAL_DMD_EXTENSIONS,
"" );
3804 if ( driverExtensions.isEmpty() )
3807 const QSet< QString > splitExtensions = qgis::listToSet( driverExtensions.split(
' ', Qt::SkipEmptyParts ) );
3808 if ( splitExtensions.intersects( multiLayerExtensions ) )
3810 driverNames << OGR_Dr_GetName(
driver );
3818 static QReadWriteLock sFilterLock;
3819 static QMap< VectorFormatOptions, QList< QgsVectorFileWriter::FilterFormatDetails > > sFilters;
3823 const auto it = sFilters.constFind( options );
3824 if ( it != sFilters.constEnd() )
3828 QList< QgsVectorFileWriter::FilterFormatDetails > results;
3831 int const drvCount = OGRGetDriverCount();
3835 for (
int i = 0; i < drvCount; ++i )
3837 OGRSFDriverH drv = OGRGetDriver( i );
3840 const QString drvName = OGR_Dr_GetName( drv );
3844 if ( !multiLayerDrivers.contains( drvName ) )
3848 GDALDriverH gdalDriver = GDALGetDriverByName( drvName.toLocal8Bit().constData() );
3849 char **metadata =
nullptr;
3852 metadata = GDALGetMetadata( gdalDriver,
nullptr );
3855 bool nonSpatialFormat = CSLFetchBoolean( metadata, GDAL_DCAP_NONSPATIAL,
false );
3857 if ( OGR_Dr_TestCapability( drv,
"CreateDataSource" ) != 0 )
3862 if ( nonSpatialFormat )
3867 if ( filterString.isEmpty() )
3874 globs = metadata.
glob.toLower().split(
' ' );
3880 details.
globs = globs;
3889 if ( options & SortRecommended )
3891 if ( a.driverName == QLatin1String(
"GPKG" ) )
3893 else if ( b.driverName == QLatin1String(
"GPKG" ) )
3895 else if ( a.driverName == QLatin1String(
"ESRI Shapefile" ) )
3897 else if ( b.driverName == QLatin1String(
"ESRI Shapefile" ) )
3904 sFilters.insert( options, results );
3911 QSet< QString > extensions;
3913 const thread_local QRegularExpression rx( QStringLiteral(
"\\*\\.(.*)$" ) );
3917 for (
const QString &glob : format.globs )
3919 const QRegularExpressionMatch match = rx.match( glob );
3920 if ( !match.hasMatch() )
3923 const QString matched = match.captured( 1 );
3924 extensions.insert( matched );
3928 QStringList extensionList( extensions.constBegin(), extensions.constEnd() );
3930 std::sort( extensionList.begin(), extensionList.end(), [options](
const QString & a,
const QString & b ) ->
bool
3932 if ( options & SortRecommended )
3934 if ( a == QLatin1String(
"gpkg" ) )
3936 else if ( b == QLatin1String(
"gpkg" ) )
3938 else if ( a == QLatin1String(
"shp" ) )
3940 else if ( b == QLatin1String(
"shp" ) )
3944 return a.toLower().localeAwareCompare( b.toLower() ) < 0;
3947 return extensionList;
3952 QList< QgsVectorFileWriter::DriverDetails > results;
3955 const int drvCount = OGRGetDriverCount();
3959 QStringList writableDrivers;
3960 for (
int i = 0; i < drvCount; ++i )
3962 OGRSFDriverH drv = OGRGetDriver( i );
3965 const QString drvName = OGR_Dr_GetName( drv );
3969 if ( !multiLayerDrivers.contains( drvName ) )
3977 if ( drvName == QLatin1String(
"ODS" ) || drvName == QLatin1String(
"XLSX" ) || drvName == QLatin1String(
"XLS" ) )
3981 if ( drvName == QLatin1String(
"ESRI Shapefile" ) )
3983 writableDrivers << QStringLiteral(
"DBF file" );
3985 if ( OGR_Dr_TestCapability( drv,
"CreateDataSource" ) != 0 )
3988 if ( drvName == QLatin1String(
"MapInfo File" ) )
3990 writableDrivers << QStringLiteral(
"MapInfo MIF" );
3992 else if ( drvName == QLatin1String(
"SQLite" ) )
3999 QString option = QStringLiteral(
"SPATIALITE=YES" );
4000 char *options[2] = { CPLStrdup( option.toLocal8Bit().constData() ),
nullptr };
4001 OGRSFDriverH poDriver;
4003 poDriver = OGRGetDriverByName( drvName.toLocal8Bit().constData() );
4006 gdal::ogr_datasource_unique_ptr ds( OGR_Dr_CreateDataSource( poDriver, QStringLiteral(
"/vsimem/spatialitetest.sqlite" ).toUtf8().constData(), options ) );
4009 writableDrivers << QStringLiteral(
"SpatiaLite" );
4010 OGR_Dr_DeleteDataSource( poDriver, QStringLiteral(
"/vsimem/spatialitetest.sqlite" ).toUtf8().constData() );
4013 CPLFree( options[0] );
4015 writableDrivers << drvName;
4020 results.reserve( writableDrivers.count() );
4021 for (
const QString &drvName : std::as_const( writableDrivers ) )
4035 if ( options & SortRecommended )
4037 if ( a.driverName == QLatin1String(
"GPKG" ) )
4039 else if ( b.driverName == QLatin1String(
"GPKG" ) )
4041 else if ( a.driverName == QLatin1String(
"ESRI Shapefile" ) )
4043 else if ( b.driverName == QLatin1String(
"ESRI Shapefile" ) )
4047 return a.
longName.toLower().localeAwareCompare( b.
longName.toLower() ) < 0;
4054 QString ext = extension.trimmed();
4055 if ( ext.isEmpty() )
4058 if ( ext.startsWith(
'.' ) )
4062 int const drvCount = GDALGetDriverCount();
4064 for (
int i = 0; i < drvCount; ++i )
4066 GDALDriverH drv = GDALGetDriver( i );
4072 QString drvName = GDALGetDriverShortName( drv );
4073 QStringList driverExtensions = QString( GDALGetMetadataItem( drv, GDAL_DMD_EXTENSIONS,
nullptr ) ).split(
' ' );
4075 const auto constDriverExtensions = driverExtensions;
4076 for (
const QString &
driver : constDriverExtensions )
4078 if (
driver.compare( ext, Qt::CaseInsensitive ) == 0 )
4089 QString filterString;
4093 if ( !filterString.isEmpty() )
4094 filterString += QLatin1String(
";;" );
4096 filterString += details.filterString;
4098 return filterString;
4107 return QStringLiteral(
"%1 (%2 %3)" ).arg( metadata.
trLongName,
4108 metadata.
glob.toLower(),
4109 metadata.
glob.toUpper() );
4114 if ( codecName == QLatin1String(
"System" ) )
4115 return QStringLiteral(
"LDID/0" );
4117 const thread_local QRegularExpression re( QRegularExpression::anchoredPattern( QString(
"(CP|windows-|ISO[ -])(.+)" ) ), QRegularExpression::CaseInsensitiveOption );
4118 const QRegularExpressionMatch match = re.match( codecName );
4119 if ( match.hasMatch() )
4121 QString
c = match.captured( 2 ).remove(
'-' );
4123 ( void )
c.toInt( &isNumber );
4151 OGRStyleTableH ogrStyleTable = OGR_STBL_Create();
4152 OGRStyleMgrH styleManager = OGR_SM_Create( ogrStyleTable );
4155 int nTotalLevels = 0;
4157 QgsSymbolList::iterator symbolIt = symbolList.begin();
4158 for ( ; symbolIt != symbolList.end(); ++symbolIt )
4160 double mmsf = mmScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
4161 double musf = mapUnitScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
4163 int nLevels = ( *symbolIt )->symbolLayerCount();
4164 for (
int i = 0; i < nLevels; ++i )
4166 mSymbolLayerTable.insert( ( *symbolIt )->symbolLayer( i ), QString::number( nTotalLevels ) );
4167 OGR_SM_AddStyle( styleManager, QString::number( nTotalLevels ).toLocal8Bit(),
4168 ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf ).toLocal8Bit() );
4172 OGR_DS_SetStyleTableDirectly( ds, ogrStyleTable );
4178 if ( !details.renderer )
4183 QHash< QgsSymbol *, QList<QgsFeature> > features;
4192 startRender( details.renderer.get(), details.sourceFields );
4212 QString msg = QObject::tr(
"Failed to transform, writing stopped. (Exception: %1)" )
4223 featureSymbol = mRenderer->symbolForFeature( fet, mRenderContext );
4224 if ( !featureSymbol )
4229 QHash< QgsSymbol *, QList<QgsFeature> >::iterator it = features.find( featureSymbol );
4230 if ( it == features.end() )
4232 it = features.insert( featureSymbol, QList<QgsFeature>() );
4234 it.value().append( fet );
4239 QgsSymbolList symbols = mRenderer->symbols( mRenderContext );
4240 for (
int i = 0; i < symbols.count(); i++ )
4246 if ( level < 0 || level >= 1000 )
4249 while ( level >= levels.count() )
4251 levels[level].append( item );
4256 int nTotalFeatures = 0;
4259 for (
int l = 0; l < levels.count(); l++ )
4262 for (
int i = 0; i < level.count(); i++ )
4265 QHash< QgsSymbol *, QList<QgsFeature> >::iterator levelIt = features.find( item.
symbol() );
4266 if ( levelIt == features.end() )
4272 double mmsf = mmScaleFactor(
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
4273 double musf = mapUnitScaleFactor(
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
4275 int llayer = item.
layer();
4276 QList<QgsFeature> &featureList = levelIt.value();
4277 QList<QgsFeature>::iterator featureIt = featureList.begin();
4278 for ( ; featureIt != featureList.end(); ++featureIt )
4288 QString styleString = levelIt.key()->symbolLayer( llayer )->ogrFeatureStyle( mmsf, musf );
4289 if ( !styleString.isEmpty() )
4291 OGR_F_SetStyleString( ogrFeature.get(), styleString.toLocal8Bit().constData() );
4292 if ( !writeFeature(
mLayer, ogrFeature.get() ) )
4305 *
errorMessage += QObject::tr(
"\nOnly %1 of %2 features written." ).arg( nTotalFeatures - nErrors ).arg( nTotalFeatures );
4313 if ( symbolUnits == Qgis::RenderUnit::Millimeters )
4320 if ( mapUnits == Qgis::DistanceUnit::Meters )
4322 return 1000 / scale;
4331 if ( symbolUnits == Qgis::RenderUnit::MapUnits )
4337 if ( symbolUnits == Qgis::RenderUnit::Millimeters && mapUnits == Qgis::DistanceUnit::Meters )
4339 return scale / 1000;
4347 mRenderer = createSymbologyRenderer( sourceRenderer );
4353 mRenderer->startRender( mRenderContext, fields );
4356void QgsVectorFileWriter::stopRender()
4363 mRenderer->stopRender( mRenderContext );
4366std::unique_ptr<QgsFeatureRenderer> QgsVectorFileWriter::createSymbologyRenderer(
QgsFeatureRenderer *sourceRenderer )
const
4374 case Qgis::FeatureSymbologyExport::PerFeature:
4375 case Qgis::FeatureSymbologyExport::PerSymbolLayer:
4379 if ( !sourceRenderer )
4384 return std::unique_ptr< QgsFeatureRenderer >( sourceRenderer->
clone() );
4391 const QSet<QString> rendererAttributes = renderer->
usedAttributes( context );
4392 for (
const QString &attr : rendererAttributes )
4397 attList.append( index );
4403QStringList QgsVectorFileWriter::concatenateOptions(
const QMap<QString, QgsVectorFileWriter::Option *> &options )
4406 QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
4408 for ( it = options.constBegin(); it != options.constEnd(); ++it )
4411 switch ( option->
type )
4418 list.append( QStringLiteral(
"%1=%2" ).arg( it.key() ).arg( opt->
defaultValue ) );
4428 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
defaultValue ) );
4438 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
defaultValue ) );
4447 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
mValue ) );
4458 OGRSFDriverH hDriver =
nullptr;
4461 return QgsVectorFileWriter::EditionCapabilities();
4462 QString drvName = OGR_Dr_GetName( hDriver );
4463 QgsVectorFileWriter::EditionCapabilities caps = QgsVectorFileWriter::EditionCapabilities();
4464 if ( OGR_DS_TestCapability( hDS.get(), ODsCCreateLayer ) )
4469 if ( !( drvName == QLatin1String(
"ESRI Shapefile" ) && QFile::exists( datasetName ) ) )
4472 if ( OGR_DS_TestCapability( hDS.get(), ODsCDeleteLayer ) )
4476 int layer_count = OGR_DS_GetLayerCount( hDS.get() );
4479 OGRLayerH hLayer = OGR_DS_GetLayer( hDS.get(), 0 );
4482 if ( OGR_L_TestCapability( hLayer, OLCSequentialWrite ) )
4485 if ( OGR_L_TestCapability( hLayer, OLCCreateField ) )
4496 const QString &layerNameIn )
4498 OGRSFDriverH hDriver =
nullptr;
4503 QString layerName( layerNameIn );
4504 if ( layerName.isEmpty() )
4505 layerName = QFileInfo( datasetName ).baseName();
4507 return OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
4512 const QString &layerName,
4516 OGRSFDriverH hDriver =
nullptr;
4520 OGRLayerH hLayer = OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
4526 OGRFeatureDefnH defn = OGR_L_GetLayerDefn( hLayer );
4527 const auto constAttributes = attributes;
4528 for (
int idx : constAttributes )
4531 if ( OGR_FD_GetFieldIndex( defn, fld.
name().toUtf8().constData() ) < 0 )
@ FieldComments
Writer can support field comments.
@ FieldAliases
Writer can support field aliases.
DistanceUnit
Units of distance.
RenderUnit
Rendering size units.
WkbType
The WKB type describes the number of dimensions a geometry has.
@ MultiPolygon25D
MultiPolygon25D.
@ GeometryCollectionZ
GeometryCollectionZ.
@ MultiLineString
MultiLineString.
@ MultiPolygonZ
MultiPolygonZ.
FeatureSymbologyExport
Options for exporting features considering their symbology.
@ NoSymbology
Export only data.
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.
static QStringList multiLayerFileExtensions()
Returns a list of file extensions which potentially contain multiple layers representing GDAL raster ...
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.
Qgis::WkbType overrideGeometryType
Set to a valid geometry type to override the default geometry type for the layer.
bool includeZ
Sets to true to include z dimension in output. This option is only valid if overrideGeometryType is s...
Qgis::FeatureSymbologyExport symbologyExport
Symbology to export.
bool saveMetadata
Set to true to save layer metadata for the exported vector file.
QgsVectorFileWriter::ActionOnExistingFile actionOnExistingFile
Action on existing file.
QgsAttributeList attributes
Attributes to export (empty means all unless skipAttributeCreation is set)
bool onlySelectedFeatures
Write only selected features of layer.
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.
Qgis::FeatureSymbologyExport mSymbologyExport
QString lastError() const override
Returns the most recent error encountered by the sink, e.g.
@ CanAddNewFieldsToExistingLayer
Flag to indicate that new fields can be added to an existing layer. Imply CanAppendToExistingLayer.
@ CanAppendToExistingLayer
Flag to indicate that new features can be added to an existing layer.
@ CanAddNewLayer
Flag to indicate that a new layer can be added to the dataset.
@ CanDeleteLayer
Flag to indicate that an existing layer can be deleted.
static QgsVectorFileWriter::EditionCapabilities editionCapabilities(const QString &datasetName)
Returns edition capabilities for an existing dataset name.
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a single feature to the sink.
static bool supportsFeatureStyles(const QString &driverName)
Returns true if the specified driverName supports feature styles.
Qgis::WkbType mWkbType
Geometry type which is being used.
bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a list of features to the sink.
double mSymbologyScale
Scale for symbology export (e.g. for symbols units in map units)
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)
QString mOgrDriverLongName
~QgsVectorFileWriter() override
Close opened shapefile for writing.
static bool targetLayerExists(const QString &datasetName, const QString &layerName)
Returns whether the target layer already exists.
double symbologyScale() const
Returns the reference scale for output.
static QStringList defaultLayerOptions(const QString &driverName)
Returns a list of the default layer options for a specified driver.
static QString driverForExtension(const QString &extension)
Returns the OGR driver name for a specified file extension.
Qgis::VectorFileWriterCapabilities capabilities() const
Returns the capabilities supported by the writer.
static QList< QgsVectorFileWriter::FilterFormatDetails > supportedFiltersAndFormats(VectorFormatOptions options=SortRecommended)
Returns a list or pairs, with format filter string as first element and OGR format key as second elem...
OGRSpatialReferenceH mOgrRef
static bool driverMetadata(const QString &driverName, MetaData &driverMetadata)
static QgsVectorFileWriter * create(const QString &fileName, const QgsFields &fields, Qgis::WkbType geometryType, const QgsCoordinateReferenceSystem &srs, const QgsCoordinateTransformContext &transformContext, const QgsVectorFileWriter::SaveVectorOptions &options, QgsFeatureSink::SinkFlags sinkFlags=QgsFeatureSink::SinkFlags(), QString *newFilename=nullptr, QString *newLayer=nullptr)
Create a new vector file writer.
QString driver() const
Returns the GDAL (short) driver name associated with the output file.
static bool deleteShapeFile(const QString &fileName)
Delete a shapefile (and its accompanying shx / dbf / prj / qix / qpj / cpg / sbn / sbx / idm / ind)
Q_DECL_DEPRECATED QgsVectorFileWriter(const QString &vectorFileName, const QString &fileEncoding, const QgsFields &fields, Qgis::WkbType geometryType, const QgsCoordinateReferenceSystem &srs=QgsCoordinateReferenceSystem(), const QString &driverName="GPKG", const QStringList &datasourceOptions=QStringList(), const QStringList &layerOptions=QStringList(), QString *newFilename=nullptr, Qgis::FeatureSymbologyExport symbologyExport=Qgis::FeatureSymbologyExport::NoSymbology, QgsFeatureSink::SinkFlags sinkFlags=QgsFeatureSink::SinkFlags(), QString *newLayer=nullptr, const QgsCoordinateTransformContext &transformContext=QgsCoordinateTransformContext(), FieldNameSource fieldNameSource=Original)
Create a new vector file writer.
static Q_DECL_DEPRECATED QgsVectorFileWriter::WriterError writeAsVectorFormat(QgsVectorLayer *layer, const QString &fileName, const QString &fileEncoding, const QgsCoordinateReferenceSystem &destCRS=QgsCoordinateReferenceSystem(), const QString &driverName="GPKG", bool onlySelected=false, QString *errorMessage=nullptr, const QStringList &datasourceOptions=QStringList(), const QStringList &layerOptions=QStringList(), bool skipAttributeCreation=false, QString *newFilename=nullptr, Qgis::FeatureSymbologyExport symbologyExport=Qgis::FeatureSymbologyExport::NoSymbology, double symbologyScale=1.0, const QgsRectangle *filterExtent=nullptr, Qgis::WkbType overrideGeometryType=Qgis::WkbType::Unknown, bool forceMulti=false, bool includeZ=false, const QgsAttributeList &attributes=QgsAttributeList(), QgsVectorFileWriter::FieldValueConverter *fieldValueConverter=nullptr, QString *newLayer=nullptr)
Write contents of vector layer to an (OGR supported) vector format.
static QString filterForDriver(const QString &driverName)
Creates a filter for an OGR driver key.
QgsVectorFileWriter::WriterError hasError() const
Checks whether there were any errors in constructor.
@ SupportsMultipleLayers
Filter to only formats which support multiple layers (since QGIS 3.32)
@ SkipNonSpatialFormats
Filter out any formats which do not have spatial support (e.g. those which cannot save geometries)
static bool areThereNewFieldsToCreate(const QString &datasetName, const QString &layerName, QgsVectorLayer *layer, const QgsAttributeList &attributes)
Returns whether there are among the attributes specified some that do not exist yet in the layer.
static QList< QgsVectorFileWriter::DriverDetails > ogrDriverList(VectorFormatOptions options=SortRecommended)
Returns the driver list that can be used for dialogs.
QString driverLongName() const
Returns the GDAL long driver name associated with the output file.
WriterError mError
Contains error value if construction was not successful.
Qgis::FeatureSymbologyExport symbologyExport() const
Returns the feature symbology export handling for the writer.
FieldNameSource
Source for exported field names.
@ PreferAlias
Use the field alias as the exported field name, wherever one is set. Otherwise use the original field...
@ Original
Use original field names.
static QStringList defaultDatasetOptions(const QString &driverName)
Returns a list of the default dataset options for a specified driver.
bool addFeatureWithStyle(QgsFeature &feature, QgsFeatureRenderer *renderer, Qgis::DistanceUnit outputUnit=Qgis::DistanceUnit::Meters)
Adds a feature to the currently opened data source, using the style from a specified renderer.
static QStringList supportedFormatExtensions(VectorFormatOptions options=SortRecommended)
Returns a list of file extensions for supported formats, e.g "shp", "gpkg".
static QString convertCodecNameForEncodingOption(const QString &codecName)
Converts codec name to string passed to ENCODING layer creation option of OGR Shapefile.
FieldValueConverter * mFieldValueConverter
Field value converter.
QString errorMessage() const
Retrieves error message.
void setSymbologyScale(double scale)
Set reference scale for output.
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)
#define QgsDebugError(str)
QList< QgsSymbolLevel > QgsSymbolLevelOrder
QList< QgsSymbolLevelItem > QgsSymbolLevel
QList< QgsSymbol * > QgsSymbolList
QStringList multiLayerFormats()
Details of available driver formats.
QString longName
Descriptive, user friendly name for the driver.
QString driverName
Unique driver name.