37 #include "qgsogrproviderutils.h"
47 #include <QTextStream>
51 #include <QRegularExpression>
52 #include <QJsonDocument>
58 #include <ogr_srs_api.h>
59 #include <cpl_error.h>
61 #include <cpl_string.h>
80 const QString &vectorFileName,
81 const QString &fileEncoding,
85 const QString &driverName,
86 const QStringList &datasourceOptions,
87 const QStringList &layerOptions,
90 QgsFeatureSink::SinkFlags sinkFlags,
100 init( vectorFileName, fileEncoding, fields, geometryType,
101 srs, driverName, datasourceOptions, layerOptions, newFilename,
nullptr,
106 const QString &vectorFileName,
107 const QString &fileEncoding,
111 const QString &driverName,
112 const QStringList &datasourceOptions,
113 const QStringList &layerOptions,
114 QString *newFilename,
117 const QString &layerName,
121 QgsFeatureSink::SinkFlags sinkFlags,
125 , mWkbType( geometryType )
126 , mSymbologyExport( symbologyExport )
127 , mSymbologyScale( 1.0 )
129 init( vectorFileName, fileEncoding, fields, geometryType, srs, driverName,
130 datasourceOptions, layerOptions, newFilename, fieldValueConverter,
131 layerName, action, newLayer, sinkFlags, transformContext, fieldNameSource );
135 const QString &fileName,
141 QgsFeatureSink::SinkFlags sinkFlags,
142 QString *newFilename,
156 if ( driverName == QLatin1String(
"MapInfo MIF" ) )
160 GDALDriverH gdalDriver = GDALGetDriverByName( driverName.toLocal8Bit().constData() );
168 return CSLFetchBoolean(
driverMetadata, GDAL_DCAP_FEATURE_STYLES,
false );
171 void QgsVectorFileWriter::init( QString vectorFileName,
172 QString fileEncoding,
176 const QString &driverName,
177 QStringList datasourceOptions,
178 QStringList layerOptions,
179 QString *newFilename,
180 FieldValueConverter *fieldValueConverter,
181 const QString &layerNameIn,
182 ActionOnExistingFile action,
183 QString *newLayer, SinkFlags sinkFlags,
188 if ( vectorFileName.isEmpty() )
195 if ( driverName == QLatin1String(
"MapInfo MIF" ) )
199 else if ( driverName == QLatin1String(
"SpatiaLite" ) )
202 if ( !datasourceOptions.contains( QStringLiteral(
"SPATIALITE=YES" ) ) )
204 datasourceOptions.append( QStringLiteral(
"SPATIALITE=YES" ) );
207 else if ( driverName == QLatin1String(
"DBF file" ) )
210 if ( !layerOptions.contains( QStringLiteral(
"SHPT=NULL" ) ) )
212 layerOptions.append( QStringLiteral(
"SHPT=NULL" ) );
221 #if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,3,1)
222 QString fidFieldName;
225 for (
const QString &layerOption : layerOptions )
227 if ( layerOption.startsWith( QLatin1String(
"FID=" ) ) )
229 fidFieldName = layerOption.mid( 4 );
233 if ( fidFieldName.isEmpty() )
234 fidFieldName = QStringLiteral(
"fid" );
239 OGRSFDriverH poDriver;
242 poDriver = OGRGetDriverByName(
mOgrDriverName.toLocal8Bit().constData() );
246 mErrorMessage = QObject::tr(
"OGR driver for '%1' not found (OGR error: %2)" )
248 QString::fromUtf8( CPLGetLastErrorMsg() ) );
258 if ( layerOptions.join( QString() ).toUpper().indexOf( QLatin1String(
"ENCODING=" ) ) == -1 )
263 if ( driverName == QLatin1String(
"ESRI Shapefile" ) && !vectorFileName.endsWith( QLatin1String(
".shp" ), Qt::CaseInsensitive ) )
265 vectorFileName += QLatin1String(
".shp" );
267 else if ( driverName == QLatin1String(
"DBF file" ) && !vectorFileName.endsWith( QLatin1String(
".dbf" ), Qt::CaseInsensitive ) )
269 vectorFileName += QLatin1String(
".dbf" );
279 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
280 QStringList allExts = metadata.ext.split(
' ', QString::SkipEmptyParts );
282 QStringList allExts = metadata.ext.split(
' ', Qt::SkipEmptyParts );
285 const auto constAllExts = allExts;
286 for (
const QString &ext : constAllExts )
288 if ( vectorFileName.endsWith(
'.' + ext, Qt::CaseInsensitive ) )
297 vectorFileName +=
'.' + allExts[0];
303 if ( vectorFileName.endsWith( QLatin1String(
".gdb" ), Qt::CaseInsensitive ) )
305 QDir dir( vectorFileName );
308 QFileInfoList fileList = dir.entryInfoList(
309 QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files, QDir::DirsFirst );
310 const auto constFileList = fileList;
311 for (
const QFileInfo &info : constFileList )
313 QFile::remove( info.absoluteFilePath() );
316 QDir().rmdir( vectorFileName );
320 QFile::remove( vectorFileName );
325 if ( metadataFound && !metadata.compulsoryEncoding.isEmpty() )
327 if ( fileEncoding.compare( metadata.compulsoryEncoding, Qt::CaseInsensitive ) != 0 )
329 QgsDebugMsgLevel( QStringLiteral(
"forced %1 encoding for %2" ).arg( metadata.compulsoryEncoding, driverName ), 2 );
330 fileEncoding = metadata.compulsoryEncoding;
335 char **options =
nullptr;
336 if ( !datasourceOptions.isEmpty() )
338 options =
new char *[ datasourceOptions.size() + 1 ];
339 for (
int i = 0; i < datasourceOptions.size(); i++ )
341 QgsDebugMsgLevel( QStringLiteral(
"-dsco=%1" ).arg( datasourceOptions[i] ), 2 );
342 options[i] = CPLStrdup( datasourceOptions[i].toLocal8Bit().constData() );
344 options[ datasourceOptions.size()] =
nullptr;
350 mDS.reset( OGR_Dr_CreateDataSource( poDriver, vectorFileName.toUtf8().constData(), options ) );
352 mDS.reset( OGROpen( vectorFileName.toUtf8().constData(), TRUE,
nullptr ) );
356 for (
int i = 0; i < datasourceOptions.size(); i++ )
357 CPLFree( options[i] );
366 mErrorMessage = QObject::tr(
"Creation of data source failed (OGR error: %1)" )
367 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
369 mErrorMessage = QObject::tr(
"Opening of data source in update mode failed (OGR error: %1)" )
370 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
374 QString layerName( layerNameIn );
375 if ( layerName.isEmpty() )
376 layerName = QFileInfo( vectorFileName ).baseName();
380 const int layer_count = OGR_DS_GetLayerCount(
mDS.get() );
381 for (
int i = 0; i < layer_count; i++ )
383 OGRLayerH hLayer = OGR_DS_GetLayer(
mDS.get(), i );
384 if ( EQUAL( OGR_L_GetName( hLayer ), layerName.toUtf8().constData() ) )
386 if ( OGR_DS_DeleteLayer(
mDS.get(), i ) != OGRERR_NONE )
389 mErrorMessage = QObject::tr(
"Overwriting of existing layer failed (OGR error: %1)" )
390 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
404 QgsDebugMsgLevel( QStringLiteral(
"Opened data source in update mode" ), 2 );
408 mCodec = QTextCodec::codecForName( fileEncoding.toLocal8Bit().constData() );
411 QgsDebugMsg(
"error finding QTextCodec for " + fileEncoding );
414 QString enc = settings.
value( QStringLiteral(
"UI/encoding" ),
"System" ).toString();
415 mCodec = QTextCodec::codecForName( enc.toLocal8Bit().constData() );
418 QgsDebugMsg(
"error finding QTextCodec for " + enc );
419 mCodec = QTextCodec::codecForLocale();
425 if ( driverName == QLatin1String(
"KML" ) || driverName == QLatin1String(
"LIBKML" ) || driverName == QLatin1String(
"GPX" ) )
427 if ( srs.
authid() != QLatin1String(
"EPSG:4326" ) )
442 int optIndex = layerOptions.indexOf( QLatin1String(
"FEATURE_DATASET=" ) );
443 if ( optIndex != -1 )
445 layerOptions.removeAt( optIndex );
448 if ( !layerOptions.isEmpty() )
450 options =
new char *[ layerOptions.size() + 1 ];
451 for (
int i = 0; i < layerOptions.size(); i++ )
454 options[i] = CPLStrdup( layerOptions[i].toLocal8Bit().constData() );
456 options[ layerOptions.size()] =
nullptr;
460 CPLSetConfigOption(
"SHAPE_ENCODING",
"" );
464 mLayer = OGR_DS_CreateLayer(
mDS.get(), layerName.toUtf8().constData(),
mOgrRef, wkbType, options );
467 *newLayer = OGR_L_GetName(
mLayer );
468 if ( driverName == QLatin1String(
"GPX" ) )
475 if ( !EQUAL( layerName.toUtf8().constData(),
"track_points" ) &&
476 !EQUAL( layerName.toUtf8().constData(),
"route_points" ) )
478 *newLayer = QStringLiteral(
"waypoints" );
485 const char *pszForceGPXTrack
486 = CSLFetchNameValue( options,
"FORCE_GPX_TRACK" );
487 if ( pszForceGPXTrack && CPLTestBool( pszForceGPXTrack ) )
488 *newLayer = QStringLiteral(
"tracks" );
490 *newLayer = QStringLiteral(
"routes" );
497 const char *pszForceGPXRoute
498 = CSLFetchNameValue( options,
"FORCE_GPX_ROUTE" );
499 if ( pszForceGPXRoute && CPLTestBool( pszForceGPXRoute ) )
500 *newLayer = QStringLiteral(
"routes" );
502 *newLayer = QStringLiteral(
"tracks" );
512 else if ( driverName == QLatin1String(
"DGN" ) )
514 mLayer = OGR_DS_GetLayerByName(
mDS.get(),
"elements" );
518 mLayer = OGR_DS_GetLayerByName(
mDS.get(), layerName.toUtf8().constData() );
523 for (
int i = 0; i < layerOptions.size(); i++ )
524 CPLFree( options[i] );
533 QString layerName = vectorFileName.left( vectorFileName.indexOf( QLatin1String(
".shp" ), Qt::CaseInsensitive ) );
534 QFile prjFile( layerName +
".qpj" );
535 if ( prjFile.exists() )
543 mErrorMessage = QObject::tr(
"Creation of layer failed (OGR error: %1)" )
544 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
546 mErrorMessage = QObject::tr(
"Opening of layer failed (OGR error: %1)" )
547 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
552 OGRFeatureDefnH defn = OGR_L_GetLayerDefn(
mLayer );
561 QSet<int> existingIdxs;
571 for (
int fldIdx = 0; fldIdx < fields.
count(); ++fldIdx )
575 if ( fieldValueConverter )
577 attrField = fieldValueConverter->fieldDefinition( fields.
at( fldIdx ) );
582 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( attrField.
name() ) );
591 switch ( fieldNameSource )
594 name = attrField.
name();
598 name = !attrField.
alias().isEmpty() ? attrField.
alias() : attrField.
name();
602 OGRFieldType ogrType = OFTString;
603 OGRFieldSubType ogrSubType = OFSTNone;
604 int ogrWidth = attrField.
length();
605 int ogrPrecision = attrField.
precision();
606 if ( ogrPrecision > 0 )
609 switch ( attrField.
type() )
611 case QVariant::LongLong:
613 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
614 if ( pszDataTypes && strstr( pszDataTypes,
"Integer64" ) )
615 ogrType = OFTInteger64;
618 ogrWidth = ogrWidth > 0 && ogrWidth <= 20 ? ogrWidth : 20;
622 case QVariant::String:
624 if ( ( ogrWidth <= 0 || ogrWidth > 255 ) &&
mOgrDriverName == QLatin1String(
"ESRI Shapefile" ) )
629 ogrType = OFTInteger;
630 ogrWidth = ogrWidth > 0 && ogrWidth <= 10 ? ogrWidth : 10;
635 ogrType = OFTInteger;
636 ogrSubType = OFSTBoolean;
641 case QVariant::Double:
642 #if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,3,1)
643 if (
mOgrDriverName == QLatin1String(
"GPKG" ) && attrField.
precision() == 0 && attrField.
name().compare( fidFieldName, Qt::CaseInsensitive ) == 0 )
646 ogrType = OFTInteger64;
669 case QVariant::DateTime:
677 ogrType = OFTDateTime;
681 case QVariant::ByteArray:
685 case QVariant::StringList:
691 ogrSubType = OFSTJSON;
695 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
696 if ( pszDataTypes && strstr( pszDataTypes,
"StringList" ) )
698 ogrType = OFTStringList;
699 mSupportedListSubTypes.insert( QVariant::String );
714 ogrSubType = OFSTJSON;
719 if ( attrField.
subType() == QVariant::String )
721 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
722 if ( pszDataTypes && strstr( pszDataTypes,
"StringList" ) )
724 ogrType = OFTStringList;
725 mSupportedListSubTypes.insert( QVariant::String );
734 else if ( attrField.
subType() == QVariant::Int )
736 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
737 if ( pszDataTypes && strstr( pszDataTypes,
"IntegerList" ) )
739 ogrType = OFTIntegerList;
740 mSupportedListSubTypes.insert( QVariant::Int );
749 else if ( attrField.
subType() == QVariant::Double )
751 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
752 if ( pszDataTypes && strstr( pszDataTypes,
"RealList" ) )
754 ogrType = OFTRealList;
755 mSupportedListSubTypes.insert( QVariant::Double );
764 else if ( attrField.
subType() == QVariant::LongLong )
766 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
767 if ( pszDataTypes && strstr( pszDataTypes,
"Integer64List" ) )
769 ogrType = OFTInteger64List;
770 mSupportedListSubTypes.insert( QVariant::LongLong );
784 mErrorMessage = QObject::tr(
"Unsupported type for field %1" )
785 .arg( attrField.
name() );
790 if (
mOgrDriverName == QLatin1String(
"SQLite" ) && name.compare( QLatin1String(
"ogc_fid" ), Qt::CaseInsensitive ) == 0 )
793 for ( i = 0; i < 10; i++ )
795 name = QStringLiteral(
"ogc_fid%1" ).arg( i );
798 for ( j = 0; j < fields.
size() && name.compare( fields.
at( j ).
name(), Qt::CaseInsensitive ) != 0; j++ )
801 if ( j == fields.
size() )
807 mErrorMessage = QObject::tr(
"No available replacement for internal fieldname ogc_fid found" ).arg( attrField.
name() );
812 QgsMessageLog::logMessage( QObject::tr(
"Reserved attribute name ogc_fid replaced with %1" ).arg( name ), QObject::tr(
"OGR" ) );
819 OGR_Fld_SetWidth( fld.get(), ogrWidth );
822 if ( ogrPrecision >= 0 )
824 OGR_Fld_SetPrecision( fld.get(), ogrPrecision );
827 if ( ogrSubType != OFSTNone )
828 OGR_Fld_SetSubType( fld.get(), ogrSubType );
832 " type " + QString( QVariant::typeToName( attrField.
type() ) ) +
833 " width " + QString::number( ogrWidth ) +
834 " precision " + QString::number( ogrPrecision ), 2 );
835 if ( OGR_L_CreateField(
mLayer, fld.get(),
true ) != OGRERR_NONE )
838 mErrorMessage = QObject::tr(
"Creation of field %1 failed (OGR error: %2)" )
839 .arg( attrField.
name(),
840 QString::fromUtf8( CPLGetLastErrorMsg() ) );
845 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( name ) );
846 QgsDebugMsgLevel( QStringLiteral(
"returned field index for %1: %2" ).arg( name ).arg( ogrIdx ), 2 );
847 if ( ogrIdx < 0 || existingIdxs.contains( ogrIdx ) )
850 ogrIdx = OGR_FD_GetFieldCount( defn ) - 1;
855 mErrorMessage = QObject::tr(
"Created field %1 not found (OGR error: %2)" )
856 .arg( attrField.
name(),
857 QString::fromUtf8( CPLGetLastErrorMsg() ) );
863 existingIdxs.insert( ogrIdx );
871 for (
int fldIdx = 0; fldIdx < fields.
count(); ++fldIdx )
874 QString name( attrField.
name() );
875 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( name ) );
887 int fidIdx = fields.
lookupField( QStringLiteral(
"FID" ) );
898 *newFilename = vectorFileName;
901 mUsingTransaction =
true;
902 if ( OGRERR_NONE != OGR_L_StartTransaction(
mLayer ) )
904 mUsingTransaction =
false;
914 class QgsVectorFileWriterMetadataContainer
918 QgsVectorFileWriterMetadataContainer()
920 QMap<QString, QgsVectorFileWriter::Option *> datasetOptions;
921 QMap<QString, QgsVectorFileWriter::Option *> layerOptions;
924 datasetOptions.clear();
925 layerOptions.clear();
927 driverMetadata.insert( QStringLiteral(
"AVCE00" ),
929 QStringLiteral(
"Arc/Info ASCII Coverage" ),
930 QObject::tr(
"Arc/Info ASCII Coverage" ),
931 QStringLiteral(
"*.e00" ),
932 QStringLiteral(
"e00" ),
939 #if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,3,0)
943 datasetOptions.clear();
944 layerOptions.clear();
947 QObject::tr(
"New BNA files are created by the "
948 "systems default line termination conventions. "
949 "This may be overridden here." ),
951 << QStringLiteral(
"CRLF" )
952 << QStringLiteral(
"LF" ),
958 QObject::tr(
"By default, BNA files are created in multi-line format. "
959 "For each record, the first line contains the identifiers and the "
960 "type/number of coordinates to follow. Each following line contains "
961 "a pair of coordinates." ),
966 QObject::tr(
"BNA records may contain from 2 to 4 identifiers per record. "
967 "Some software packages only support a precise number of identifiers. "
968 "You can override the default value (2) by a precise value." ),
970 << QStringLiteral(
"2" )
971 << QStringLiteral(
"3" )
972 << QStringLiteral(
"4" )
973 << QStringLiteral(
"NB_SOURCE_FIELDS" ),
974 QStringLiteral(
"2" )
978 QObject::tr(
"The BNA writer will try to recognize ellipses and circles when writing a polygon. "
979 "This will only work if the feature has previously been read from a BNA file. "
980 "As some software packages do not support ellipses/circles in BNA data file, "
981 "it may be useful to tell the writer by specifying ELLIPSES_AS_ELLIPSES=NO not "
982 "to export them as such, but keep them as polygons." ),
987 QObject::tr(
"Limit the number of coordinate pairs per line in multiline format." ),
992 QObject::tr(
"Set the number of decimal for coordinates. Default value is 10." ),
996 driverMetadata.insert( QStringLiteral(
"BNA" ),
998 QStringLiteral(
"Atlas BNA" ),
999 QObject::tr(
"Atlas BNA" ),
1000 QStringLiteral(
"*.bna" ),
1001 QStringLiteral(
"bna" ),
1009 datasetOptions.clear();
1010 layerOptions.clear();
1013 QObject::tr(
"By default when creating new .csv files they "
1014 "are created with the line termination conventions "
1015 "of the local platform (CR/LF on Win32 or LF on all other systems). "
1016 "This may be overridden through the use of the LINEFORMAT option." ),
1018 << QStringLiteral(
"CRLF" )
1019 << QStringLiteral(
"LF" ),
1025 QObject::tr(
"By default, the geometry of a feature written to a .csv file is discarded. "
1026 "It is possible to export the geometry in its WKT representation by "
1027 "specifying GEOMETRY=AS_WKT. It is also possible to export point geometries "
1028 "into their X,Y,Z components by specifying GEOMETRY=AS_XYZ, GEOMETRY=AS_XY "
1029 "or GEOMETRY=AS_YX." ),
1031 << QStringLiteral(
"AS_WKT" )
1032 << QStringLiteral(
"AS_XYZ" )
1033 << QStringLiteral(
"AS_XY" )
1034 << QStringLiteral(
"AS_YX" ),
1040 QObject::tr(
"Create the associated .csvt file to describe the type of each "
1041 "column of the layer and its optional width and precision." ),
1046 QObject::tr(
"Field separator character." ),
1048 << QStringLiteral(
"COMMA" )
1049 << QStringLiteral(
"SEMICOLON" )
1050 << QStringLiteral(
"TAB" ),
1051 QStringLiteral(
"COMMA" )
1055 QObject::tr(
"Double-quote strings. IF_AMBIGUOUS means that string values that look like numbers will be quoted." ),
1057 << QStringLiteral(
"IF_NEEDED" )
1058 << QStringLiteral(
"IF_AMBIGUOUS" )
1059 << QStringLiteral(
"ALWAYS" ),
1060 QStringLiteral(
"IF_AMBIGUOUS" )
1064 QObject::tr(
"Write a UTF-8 Byte Order Mark (BOM) at the start of the file." ),
1068 driverMetadata.insert( QStringLiteral(
"CSV" ),
1070 QStringLiteral(
"Comma Separated Value [CSV]" ),
1071 QObject::tr(
"Comma Separated Value [CSV]" ),
1072 QStringLiteral(
"*.csv" ),
1073 QStringLiteral(
"csv" ),
1079 #if defined(GDAL_COMPUTE_VERSION) && GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,1,0)
1081 datasetOptions.clear();
1082 layerOptions.clear();
1084 driverMetadata.insert( QStringLiteral(
"FlatGeobuf" ),
1086 QStringLiteral(
"FlatGeobuf" ),
1087 QObject::tr(
"FlatGeobuf" ),
1088 QStringLiteral(
"*.fgb" ),
1089 QStringLiteral(
"fgb" ),
1092 QStringLiteral(
"UTF-8" )
1098 datasetOptions.clear();
1099 layerOptions.clear();
1102 QObject::tr(
"Override the type of shapefile created. "
1103 "Can be one of NULL for a simple .dbf file with no .shp file, POINT, "
1104 "ARC, POLYGON or MULTIPOINT for 2D, or POINTZ, ARCZ, POLYGONZ or "
1105 "MULTIPOINTZ for 3D;" ) +
1106 QObject::tr(
" POINTM, ARCM, POLYGONM or MULTIPOINTM for measured geometries"
1107 " and POINTZM, ARCZM, POLYGONZM or MULTIPOINTZM for 3D measured"
1109 QObject::tr(
" MULTIPATCH files are supported since GDAL 2.2." ) +
1112 << QStringLiteral(
"NULL" )
1113 << QStringLiteral(
"POINT" )
1114 << QStringLiteral(
"ARC" )
1115 << QStringLiteral(
"POLYGON" )
1116 << QStringLiteral(
"MULTIPOINT" )
1117 << QStringLiteral(
"POINTZ" )
1118 << QStringLiteral(
"ARCZ" )
1119 << QStringLiteral(
"POLYGONZ" )
1120 << QStringLiteral(
"MULTIPOINTZ" )
1121 << QStringLiteral(
"POINTM" )
1122 << QStringLiteral(
"ARCM" )
1123 << QStringLiteral(
"POLYGONM" )
1124 << QStringLiteral(
"MULTIPOINTM" )
1125 << QStringLiteral(
"POINTZM" )
1126 << QStringLiteral(
"ARCZM" )
1127 << QStringLiteral(
"POLYGONZM" )
1128 << QStringLiteral(
"MULTIPOINTZM" )
1129 << QStringLiteral(
"MULTIPATCH" )
1139 QObject::tr(
"Set the encoding value in the DBF file. "
1140 "The default value is LDID/87. It is not clear "
1141 "what other values may be appropriate." ),
1149 QObject::tr(
"Set to YES to resize fields to their optimal size." ),
1153 driverMetadata.insert( QStringLiteral(
"ESRI" ),
1155 QStringLiteral(
"ESRI Shapefile" ),
1156 QObject::tr(
"ESRI Shapefile" ),
1157 QStringLiteral(
"*.shp" ),
1158 QStringLiteral(
"shp" ),
1165 datasetOptions.clear();
1166 layerOptions.clear();
1168 driverMetadata.insert( QStringLiteral(
"DBF File" ),
1170 QStringLiteral(
"DBF File" ),
1171 QObject::tr(
"DBF File" ),
1172 QStringLiteral(
"*.dbf" ),
1173 QStringLiteral(
"dbf" ),
1180 datasetOptions.clear();
1181 layerOptions.clear();
1183 driverMetadata.insert( QStringLiteral(
"FMEObjects Gateway" ),
1185 QStringLiteral(
"FMEObjects Gateway" ),
1186 QObject::tr(
"FMEObjects Gateway" ),
1187 QStringLiteral(
"*.fdd" ),
1188 QStringLiteral(
"fdd" ),
1195 datasetOptions.clear();
1196 layerOptions.clear();
1199 QObject::tr(
"Set to YES to write a bbox property with the bounding box "
1200 "of the geometries at the feature and feature collection level." ),
1205 QObject::tr(
"Maximum number of figures after decimal separator to write in coordinates. "
1206 "Defaults to 15. Truncation will occur to remove trailing zeros." ),
1211 QObject::tr(
"Whether to use RFC 7946 standard. "
1212 "If disabled GeoJSON 2008 initial version will be used. "
1213 "Default is NO (thus GeoJSON 2008). See also Documentation (via Help button)" ),
1217 driverMetadata.insert( QStringLiteral(
"GeoJSON" ),
1219 QStringLiteral(
"GeoJSON" ),
1220 QObject::tr(
"GeoJSON" ),
1221 QStringLiteral(
"*.geojson" ),
1222 QStringLiteral(
"geojson" ),
1225 QStringLiteral(
"UTF-8" )
1230 datasetOptions.clear();
1231 layerOptions.clear();
1234 QObject::tr(
"Maximum number of figures after decimal separator to write in coordinates. "
1235 "Defaults to 15. Truncation will occur to remove trailing zeros." ),
1240 QObject::tr(
"Whether to start records with the RS=0x1E character (RFC 8142 standard). "
1241 "Defaults to NO: Newline Delimited JSON (geojsonl). \n"
1242 "If set to YES: RFC 8142 standard: GeoJSON Text Sequences (geojsons)." ),
1246 driverMetadata.insert( QStringLiteral(
"GeoJSONSeq" ),
1248 QStringLiteral(
"GeoJSON - Newline Delimited" ),
1249 QObject::tr(
"GeoJSON - Newline Delimited" ),
1250 QStringLiteral(
"*.geojsonl *.geojsons *.json" ),
1251 QStringLiteral(
"json" ),
1254 QStringLiteral(
"UTF-8" )
1259 datasetOptions.clear();
1260 layerOptions.clear();
1263 QObject::tr(
"whether the document must be in RSS 2.0 or Atom 1.0 format. "
1264 "Default value : RSS" ),
1266 << QStringLiteral(
"RSS" )
1267 << QStringLiteral(
"ATOM" ),
1268 QStringLiteral(
"RSS" )
1272 QObject::tr(
"The encoding of location information. Default value : SIMPLE. "
1273 "W3C_GEO only supports point geometries. "
1274 "SIMPLE or W3C_GEO only support geometries in geographic WGS84 coordinates." ),
1276 << QStringLiteral(
"SIMPLE" )
1277 << QStringLiteral(
"GML" )
1278 << QStringLiteral(
"W3C_GEO" ),
1279 QStringLiteral(
"SIMPLE" )
1283 QObject::tr(
"If defined to YES, extension fields will be written. "
1284 "If the field name not found in the base schema matches "
1285 "the foo_bar pattern, foo will be considered as the namespace "
1286 "of the element, and a <foo:bar> element will be written. "
1287 "Otherwise, elements will be written in the <ogr:> namespace." ),
1292 QObject::tr(
"If defined to NO, only <entry> or <item> elements will be written. "
1293 "The user will have to provide the appropriate header and footer of the document." ),
1298 QObject::tr(
"XML content that will be put between the <channel> element and the "
1299 "first <item> element for a RSS document, or between the xml tag and "
1300 "the first <entry> element for an Atom document." ),
1305 QObject::tr(
"Value put inside the <title> element in the header. "
1306 "If not provided, a dummy value will be used as that element is compulsory." ),
1311 QObject::tr(
"Value put inside the <description> element in the header. "
1312 "If not provided, a dummy value will be used as that element is compulsory." ),
1317 QObject::tr(
"Value put inside the <link> element in the header. "
1318 "If not provided, a dummy value will be used as that element is compulsory." ),
1323 QObject::tr(
"Value put inside the <updated> element in the header. "
1324 "Should be formatted as a XML datetime. "
1325 "If not provided, a dummy value will be used as that element is compulsory." ),
1330 QObject::tr(
"Value put inside the <author><name> element in the header. "
1331 "If not provided, a dummy value will be used as that element is compulsory." ),
1336 QObject::tr(
"Value put inside the <id> element in the header. "
1337 "If not provided, a dummy value will be used as that element is compulsory." ),
1341 driverMetadata.insert( QStringLiteral(
"GeoRSS" ),
1343 QStringLiteral(
"GeoRSS" ),
1344 QObject::tr(
"GeoRSS" ),
1345 QStringLiteral(
"*.xml" ),
1346 QStringLiteral(
"xml" ),
1349 QStringLiteral(
"UTF-8" )
1354 datasetOptions.clear();
1355 layerOptions.clear();
1358 QObject::tr(
"If provided, this URI will be inserted as the schema location. "
1359 "Note that the schema file isn't actually accessed by OGR, so it "
1360 "is up to the user to ensure it will match the schema of the OGR "
1361 "produced GML data file." ),
1366 QObject::tr(
"This writes a GML application schema file to a corresponding "
1367 ".xsd file (with the same basename). If INTERNAL is used the "
1368 "schema is written within the GML file, but this is experimental "
1369 "and almost certainly not valid XML. "
1370 "OFF disables schema generation (and is implicit if XSISCHEMAURI is used)." ),
1372 << QStringLiteral(
"EXTERNAL" )
1373 << QStringLiteral(
"INTERNAL" )
1374 << QStringLiteral(
"OFF" ),
1375 QStringLiteral(
"EXTERNAL" )
1379 QObject::tr(
"This is the prefix for the application target namespace." ),
1380 QStringLiteral(
"ogr" )
1384 QObject::tr(
"Can be set to TRUE to avoid writing the prefix of the "
1385 "application target namespace in the GML file." ),
1390 QObject::tr(
"Defaults to 'http://ogr.maptools.org/'. "
1391 "This is the application target namespace." ),
1392 QStringLiteral(
"http://ogr.maptools.org/" )
1396 QObject::tr(
"If not specified, GML2 will be used." ),
1398 << QStringLiteral(
"GML3" )
1399 << QStringLiteral(
"GML3Deegree" )
1400 << QStringLiteral(
"GML3.2" ),
1406 QObject::tr(
"Only valid when FORMAT=GML3/GML3Degree/GML3.2. Default to YES. "
1407 "If YES, SRS with EPSG authority will be written with the "
1408 "'urn:ogc:def:crs:EPSG::' prefix. In the case the SRS is a "
1409 "geographic SRS without explicit AXIS order, but that the same "
1410 "SRS authority code imported with ImportFromEPSGA() should be "
1411 "treated as lat/long, then the function will take care of coordinate "
1412 "order swapping. If set to NO, SRS with EPSG authority will be "
1413 "written with the 'EPSG:' prefix, even if they are in lat/long order." ),
1418 QObject::tr(
"only valid when FORMAT=GML3/GML3Degree/GML3.2) Default to YES. "
1419 "If set to NO, the <gml:boundedBy> element will not be written for "
1425 QObject::tr(
"Default to YES. If YES, the output will be indented with spaces "
1426 "for more readability, but at the expense of file size." ),
1431 driverMetadata.insert( QStringLiteral(
"GML" ),
1433 QStringLiteral(
"Geography Markup Language [GML]" ),
1434 QObject::tr(
"Geography Markup Language [GML]" ),
1435 QStringLiteral(
"*.gml" ),
1436 QStringLiteral(
"gml" ),
1439 QStringLiteral(
"UTF-8" )
1444 datasetOptions.clear();
1445 layerOptions.clear();
1448 QObject::tr(
"Human-readable identifier (e.g. short name) for the layer content" ),
1453 QObject::tr(
"Human-readable description for the layer content" ),
1458 QObject::tr(
"Name for the feature identifier column" ),
1459 QStringLiteral(
"fid" )
1463 QObject::tr(
"Name for the geometry column" ),
1464 QStringLiteral(
"geom" )
1468 QObject::tr(
"If a spatial index must be created." ),
1472 driverMetadata.insert( QStringLiteral(
"GPKG" ),
1474 QStringLiteral(
"GeoPackage" ),
1475 QObject::tr(
"GeoPackage" ),
1476 QStringLiteral(
"*.gpkg" ),
1477 QStringLiteral(
"gpkg" ),
1480 QStringLiteral(
"UTF-8" )
1485 datasetOptions.clear();
1486 layerOptions.clear();
1488 driverMetadata.insert( QStringLiteral(
"GMT" ),
1490 QStringLiteral(
"Generic Mapping Tools [GMT]" ),
1491 QObject::tr(
"Generic Mapping Tools [GMT]" ),
1492 QStringLiteral(
"*.gmt" ),
1493 QStringLiteral(
"gmt" ),
1500 datasetOptions.clear();
1501 layerOptions.clear();
1504 QObject::tr(
"By default when writing a layer whose features are of "
1505 "type wkbLineString, the GPX driver chooses to write "
1506 "them as routes. If FORCE_GPX_TRACK=YES is specified, "
1507 "they will be written as tracks." ),
1512 QObject::tr(
"By default when writing a layer whose features are of "
1513 "type wkbMultiLineString, the GPX driver chooses to write "
1514 "them as tracks. If FORCE_GPX_ROUTE=YES is specified, "
1515 "they will be written as routes, provided that the multilines "
1516 "are composed of only one single line." ),
1521 QObject::tr(
"If GPX_USE_EXTENSIONS=YES is specified, "
1522 "extra fields will be written inside the <extensions> tag." ),
1527 QObject::tr(
"Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS_URL "
1528 "is set. The namespace value used for extension tags. By default, 'ogr'." ),
1529 QStringLiteral(
"ogr" )
1533 QObject::tr(
"Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS "
1534 "is set. The namespace URI. By default, 'http://osgeo.org/gdal'." ),
1535 QStringLiteral(
"http://osgeo.org/gdal" )
1539 QObject::tr(
"By default files are created with the line termination "
1540 "conventions of the local platform (CR/LF on win32 or LF "
1541 "on all other systems). This may be overridden through use "
1542 "of the LINEFORMAT layer creation option which may have a value "
1543 "of CRLF (DOS format) or LF (Unix format)." ),
1545 << QStringLiteral(
"CRLF" )
1546 << QStringLiteral(
"LF" ),
1551 driverMetadata.insert( QStringLiteral(
"GPX" ),
1553 QStringLiteral(
"GPS eXchange Format [GPX]" ),
1554 QObject::tr(
"GPS eXchange Format [GPX]" ),
1555 QStringLiteral(
"*.gpx" ),
1556 QStringLiteral(
"gpx" ),
1559 QStringLiteral(
"UTF-8" )
1564 datasetOptions.clear();
1565 layerOptions.clear();
1567 driverMetadata.insert( QStringLiteral(
"Interlis 1" ),
1569 QStringLiteral(
"INTERLIS 1" ),
1570 QObject::tr(
"INTERLIS 1" ),
1571 QStringLiteral(
"*.itf *.xml *.ili" ),
1572 QStringLiteral(
"ili" ),
1579 datasetOptions.clear();
1580 layerOptions.clear();
1582 driverMetadata.insert( QStringLiteral(
"Interlis 2" ),
1584 QStringLiteral(
"INTERLIS 2" ),
1585 QObject::tr(
"INTERLIS 2" ),
1586 QStringLiteral(
"*.xtf *.xml *.ili" ),
1587 QStringLiteral(
"ili" ),
1594 datasetOptions.clear();
1595 layerOptions.clear();
1598 QObject::tr(
"Allows you to specify the field to use for the KML <name> element." ),
1599 QStringLiteral(
"Name" )
1603 QObject::tr(
"Allows you to specify the field to use for the KML <description> element." ),
1604 QStringLiteral(
"Description" )
1608 QObject::tr(
"Allows you to specify the AltitudeMode to use for KML geometries. "
1609 "This will only affect 3D geometries and must be one of the valid KML options." ),
1611 << QStringLiteral(
"clampToGround" )
1612 << QStringLiteral(
"relativeToGround" )
1613 << QStringLiteral(
"absolute" ),
1614 QStringLiteral(
"relativeToGround" )
1618 QObject::tr(
"The DOCUMENT_ID datasource creation option can be used to specified "
1619 "the id of the root <Document> node. The default value is root_doc." ),
1620 QStringLiteral(
"root_doc" )
1623 driverMetadata.insert( QStringLiteral(
"KML" ),
1625 QStringLiteral(
"Keyhole Markup Language [KML]" ),
1626 QObject::tr(
"Keyhole Markup Language [KML]" ),
1627 QStringLiteral(
"*.kml" ),
1628 QStringLiteral(
"kml" ),
1631 QStringLiteral(
"UTF-8" )
1636 datasetOptions.clear();
1637 layerOptions.clear();
1639 auto insertMapInfoOptions = []( QMap<QString, QgsVectorFileWriter::Option *> &datasetOptions, QMap<QString, QgsVectorFileWriter::Option *> &layerOptions )
1642 QObject::tr(
"Use this to turn on 'quick spatial index mode'. "
1643 "In this mode writing files can be about 5 times faster, "
1644 "but spatial queries can be up to 30 times slower." ),
1646 << QStringLiteral(
"QUICK" )
1647 << QStringLiteral(
"OPTIMIZED" ),
1648 QStringLiteral(
"QUICK" ),
1653 QObject::tr(
"(multiples of 512): Block size for .map files. Defaults "
1654 "to 512. MapInfo 15.2 and above creates .tab files with a "
1655 "blocksize of 16384 bytes. Any MapInfo version should be "
1656 "able to handle block sizes from 512 to 32256." ),
1660 QObject::tr(
"xmin,ymin,xmax,ymax: Define custom layer bounds to increase the "
1661 "accuracy of the coordinates. Note: the geometry of written "
1662 "features must be within the defined box." ),
1666 insertMapInfoOptions( datasetOptions, layerOptions );
1668 driverMetadata.insert( QStringLiteral(
"MapInfo File" ),
1670 QStringLiteral(
"Mapinfo" ),
1671 QObject::tr(
"Mapinfo TAB" ),
1672 QStringLiteral(
"*.tab" ),
1673 QStringLiteral(
"tab" ),
1678 datasetOptions.clear();
1679 layerOptions.clear();
1680 insertMapInfoOptions( datasetOptions, layerOptions );
1683 driverMetadata.insert( QStringLiteral(
"MapInfo MIF" ),
1685 QStringLiteral(
"Mapinfo" ),
1686 QObject::tr(
"Mapinfo MIF" ),
1687 QStringLiteral(
"*.mif" ),
1688 QStringLiteral(
"mif" ),
1695 datasetOptions.clear();
1696 layerOptions.clear();
1699 QObject::tr(
"Determine whether 2D (seed_2d.dgn) or 3D (seed_3d.dgn) "
1700 "seed file should be used. This option is ignored if the SEED option is provided." ),
1705 QObject::tr(
"Override the seed file to use." ),
1710 QObject::tr(
"Indicate whether the whole seed file should be copied. "
1711 "If not, only the first three elements will be copied." ),
1716 QObject::tr(
"Indicates whether the color table should be copied from the seed file." ),
1721 QObject::tr(
"Override the master unit name from the seed file with "
1722 "the provided one or two character unit name." ),
1727 QObject::tr(
"Override the sub unit name from the seed file with the provided "
1728 "one or two character unit name." ),
1733 QObject::tr(
"Override the number of subunits per master unit. "
1734 "By default the seed file value is used." ),
1739 QObject::tr(
"Override the number of UORs (Units of Resolution) "
1740 "per sub unit. By default the seed file value is used." ),
1745 QObject::tr(
"ORIGIN=x,y,z: Override the origin of the design plane. "
1746 "By default the origin from the seed file is used." ),
1750 driverMetadata.insert( QStringLiteral(
"DGN" ),
1752 QStringLiteral(
"Microstation DGN" ),
1753 QObject::tr(
"Microstation DGN" ),
1754 QStringLiteral(
"*.dgn" ),
1755 QStringLiteral(
"dgn" ),
1762 datasetOptions.clear();
1763 layerOptions.clear();
1766 QObject::tr(
"Should update files be incorporated into the base data on the fly." ),
1768 << QStringLiteral(
"APPLY" )
1769 << QStringLiteral(
"IGNORE" ),
1770 QStringLiteral(
"APPLY" )
1774 QObject::tr(
"Should multipoint soundings be split into many single point sounding features. "
1775 "Multipoint geometries are not well handled by many formats, "
1776 "so it can be convenient to split single sounding features with many points "
1777 "into many single point features." ),
1782 QObject::tr(
"Should a DEPTH attribute be added on SOUNDG features and assign the depth "
1783 "of the sounding. This should only be enabled when SPLIT_MULTIPOINT is "
1789 QObject::tr(
"Should all the low level geometry primitives be returned as special "
1790 "IsolatedNode, ConnectedNode, Edge and Face layers." ),
1795 QObject::tr(
"If enabled, numeric attributes assigned an empty string as a value will "
1796 "be preserved as a special numeric value. This option should not generally "
1797 "be needed, but may be useful when translated S-57 to S-57 losslessly." ),
1802 QObject::tr(
"Should LNAM and LNAM_REFS fields be attached to features capturing "
1803 "the feature to feature relationships in the FFPT group of the S-57 file." ),
1808 QObject::tr(
"Should additional attributes relating features to their underlying "
1809 "geometric primitives be attached. These are the values of the FSPT group, "
1810 "and are primarily needed when doing S-57 to S-57 translations." ),
1815 QObject::tr(
"Should attribute values be recoded to UTF-8 from the character encoding "
1816 "specified in the S57 DSSI record." ),
1822 driverMetadata.insert( QStringLiteral(
"S57" ),
1824 QStringLiteral(
"S-57 Base file" ),
1825 QObject::tr(
"S-57 Base file" ),
1826 QStringLiteral(
"*.000" ),
1827 QStringLiteral(
"000" ),
1834 datasetOptions.clear();
1835 layerOptions.clear();
1837 driverMetadata.insert( QStringLiteral(
"SDTS" ),
1839 QStringLiteral(
"Spatial Data Transfer Standard [SDTS]" ),
1840 QObject::tr(
"Spatial Data Transfer Standard [SDTS]" ),
1841 QStringLiteral(
"*catd.ddf" ),
1842 QStringLiteral(
"ddf" ),
1849 datasetOptions.clear();
1850 layerOptions.clear();
1853 QObject::tr(
"Can be used to avoid creating the geometry_columns and spatial_ref_sys "
1854 "tables in a new database. By default these metadata tables are created "
1855 "when a new database is created." ),
1861 QStringLiteral(
"NO" )
1866 QStringLiteral(
"NO" )
1870 QObject::tr(
"Controls the format used for the geometry column. Defaults to WKB. "
1871 "This is generally more space and processing efficient, but harder "
1872 "to inspect or use in simple applications than WKT (Well Known Text)." ),
1874 << QStringLiteral(
"WKB" )
1875 << QStringLiteral(
"WKT" ),
1876 QStringLiteral(
"WKB" )
1880 QObject::tr(
"Controls whether layer and field names will be laundered for easier use "
1881 "in SQLite. Laundered names will be converted to lower case and some special "
1882 "characters(' - #) will be changed to underscores." ),
1887 QStringLiteral(
"NO" )
1891 QStringLiteral(
"NO" )
1899 QObject::tr(
"column_name1[,column_name2, …] A list of (String) columns that "
1900 "must be compressed with ZLib DEFLATE algorithm. This might be beneficial "
1901 "for databases that have big string blobs. However, use with care, since "
1902 "the value of such columns will be seen as compressed binary content with "
1903 "other SQLite utilities (or previous OGR versions). With OGR, when inserting, "
1904 "modifying or querying compressed columns, compression/decompression is "
1905 "done transparently. However, such columns cannot be (easily) queried with "
1906 "an attribute filter or WHERE clause. Note: in table definition, such columns "
1907 "have the 'VARCHAR_deflate' declaration type." ),
1911 driverMetadata.insert( QStringLiteral(
"SQLite" ),
1913 QStringLiteral(
"SQLite" ),
1914 QObject::tr(
"SQLite" ),
1915 QStringLiteral(
"*.sqlite" ),
1916 QStringLiteral(
"sqlite" ),
1919 QStringLiteral(
"UTF-8" )
1924 datasetOptions.clear();
1925 layerOptions.clear();
1928 QObject::tr(
"Can be used to avoid creating the geometry_columns and spatial_ref_sys "
1929 "tables in a new database. By default these metadata tables are created "
1930 "when a new database is created." ),
1935 QStringLiteral(
"YES" )
1939 QObject::tr(
"Insert the content of the EPSG CSV files into the spatial_ref_sys table. "
1940 "Set to NO for regular SQLite databases." ),
1945 QStringLiteral(
"SPATIALITE" )
1949 QObject::tr(
"Controls whether layer and field names will be laundered for easier use "
1950 "in SQLite. Laundered names will be converted to lower case and some special "
1951 "characters(' - #) will be changed to underscores." ),
1956 QObject::tr(
"If the database is of the SpatiaLite flavor, and if OGR is linked "
1957 "against libspatialite, this option can be used to control if a spatial "
1958 "index must be created." ),
1963 QObject::tr(
"If the format of the geometry BLOB is of the SpatiaLite flavor, "
1964 "this option can be used to control if the compressed format for "
1965 "geometries (LINESTRINGs, POLYGONs) must be used." ),
1970 QObject::tr(
"Used to force the SRID number of the SRS associated with the layer. "
1971 "When this option isn't specified and that a SRS is associated with the "
1972 "layer, a search is made in the spatial_ref_sys to find a match for the "
1973 "SRS, and, if there is no match, a new entry is inserted for the SRS in "
1974 "the spatial_ref_sys table. When the SRID option is specified, this "
1975 "search (and the eventual insertion of a new entry) will not be done: "
1976 "the specified SRID is used as such." ),
1981 QObject::tr(
"column_name1[,column_name2, …] A list of (String) columns that "
1982 "must be compressed with ZLib DEFLATE algorithm. This might be beneficial "
1983 "for databases that have big string blobs. However, use with care, since "
1984 "the value of such columns will be seen as compressed binary content with "
1985 "other SQLite utilities (or previous OGR versions). With OGR, when inserting, "
1986 "modifying or queryings compressed columns, compression/decompression is "
1987 "done transparently. However, such columns cannot be (easily) queried with "
1988 "an attribute filter or WHERE clause. Note: in table definition, such columns "
1989 "have the 'VARCHAR_deflate' declaration type." ),
1993 driverMetadata.insert( QStringLiteral(
"SpatiaLite" ),
1995 QStringLiteral(
"SpatiaLite" ),
1996 QObject::tr(
"SpatiaLite" ),
1997 QStringLiteral(
"*.sqlite" ),
1998 QStringLiteral(
"sqlite" ),
2001 QStringLiteral(
"UTF-8" )
2005 datasetOptions.clear();
2006 layerOptions.clear();
2009 QObject::tr(
"Override the header file used - in place of header.dxf." ),
2014 QObject::tr(
"Override the trailer file used - in place of trailer.dxf." ),
2018 driverMetadata.insert( QStringLiteral(
"DXF" ),
2020 QStringLiteral(
"AutoCAD DXF" ),
2021 QObject::tr(
"AutoCAD DXF" ),
2022 QStringLiteral(
"*.dxf" ),
2023 QStringLiteral(
"dxf" ),
2030 datasetOptions.clear();
2031 layerOptions.clear();
2034 QObject::tr(
"Indicates the GeoConcept export file extension. "
2035 "TXT was used by earlier releases of GeoConcept. GXT is currently used." ),
2037 << QStringLiteral(
"GXT" )
2038 << QStringLiteral(
"TXT" ),
2039 QStringLiteral(
"GXT" )
2043 QObject::tr(
"Path to the GCT: the GCT file describes the GeoConcept types definitions: "
2044 "In this file, every line must start with //# followed by a keyword. "
2045 "Lines starting with // are comments." ),
2050 QObject::tr(
"Defines the feature to be created. The TYPE corresponds to one of the Name "
2051 "found in the GCT file for a type section. The SUBTYPE corresponds to one of "
2052 "the Name found in the GCT file for a sub-type section within the previous "
2057 driverMetadata.insert( QStringLiteral(
"Geoconcept" ),
2059 QStringLiteral(
"Geoconcept" ),
2060 QObject::tr(
"Geoconcept" ),
2061 QStringLiteral(
"*.gxt *.txt" ),
2062 QStringLiteral(
"gxt" ),
2069 datasetOptions.clear();
2070 layerOptions.clear();
2073 QObject::tr(
"When this option is set, the new layer will be created inside the named "
2074 "FeatureDataset folder. If the folder does not already exist, it will be created." ),
2079 QObject::tr(
"Set name of geometry column in new layer. Defaults to 'SHAPE'." ),
2080 QStringLiteral(
"SHAPE" )
2084 QObject::tr(
"Name of the OID column to create. Defaults to 'OBJECTID'." ),
2085 QStringLiteral(
"OBJECTID" )
2088 driverMetadata.insert( QStringLiteral(
"FileGDB" ),
2090 QStringLiteral(
"ESRI FileGDB" ),
2091 QObject::tr(
"ESRI FileGDB" ),
2092 QStringLiteral(
"*.gdb" ),
2093 QStringLiteral(
"gdb" ),
2096 QStringLiteral(
"UTF-8" )
2101 datasetOptions.clear();
2102 layerOptions.clear();
2105 QObject::tr(
"By default, the driver will try to detect the data type of fields. If set "
2106 "to STRING, all fields will be of String type." ),
2108 << QStringLiteral(
"AUTO" )
2109 << QStringLiteral(
"STRING" ),
2110 QStringLiteral(
"AUTO" ),
2115 QObject::tr(
"By default, the driver will read the first lines of each sheet to detect "
2116 "if the first line might be the name of columns. If set to FORCE, the driver "
2117 "will consider the first line as the header line. If set to "
2118 "DISABLE, it will be considered as the first feature. Otherwise "
2119 "auto-detection will occur." ),
2121 << QStringLiteral(
"FORCE" )
2122 << QStringLiteral(
"DISABLE" )
2123 << QStringLiteral(
"AUTO" ),
2124 QStringLiteral(
"AUTO" ),
2128 driverMetadata.insert( QStringLiteral(
"XLSX" ),
2130 QStringLiteral(
"MS Office Open XML spreadsheet" ),
2131 QObject::tr(
"MS Office Open XML spreadsheet [XLSX]" ),
2132 QStringLiteral(
"*.xlsx" ),
2133 QStringLiteral(
"xlsx" ),
2136 QStringLiteral(
"UTF-8" )
2141 datasetOptions.clear();
2142 layerOptions.clear();
2145 QObject::tr(
"By default, the driver will try to detect the data type of fields. If set "
2146 "to STRING, all fields will be of String type." ),
2148 << QStringLiteral(
"AUTO" )
2149 << QStringLiteral(
"STRING" ),
2150 QStringLiteral(
"AUTO" ),
2155 QObject::tr(
"By default, the driver will read the first lines of each sheet to detect "
2156 "if the first line might be the name of columns. If set to FORCE, the driver "
2157 "will consider the first line as the header line. If set to "
2158 "DISABLE, it will be considered as the first feature. Otherwise "
2159 "auto-detection will occur." ),
2161 << QStringLiteral(
"FORCE" )
2162 << QStringLiteral(
"DISABLE" )
2163 << QStringLiteral(
"AUTO" ),
2164 QStringLiteral(
"AUTO" ),
2168 driverMetadata.insert( QStringLiteral(
"ODS" ),
2170 QStringLiteral(
"Open Document Spreadsheet" ),
2171 QObject::tr(
"Open Document Spreadsheet [ODS]" ),
2172 QStringLiteral(
"*.ods" ),
2173 QStringLiteral(
"ods" ),
2176 QStringLiteral(
"UTF-8" )
2181 datasetOptions.clear();
2182 layerOptions.clear();
2185 QObject::tr(
"Line termination character sequence." ),
2187 << QStringLiteral(
"CRLF" )
2188 << QStringLiteral(
"LF" ),
2189 QStringLiteral(
"LF" ),
2195 QObject::tr(
"Format of geometry columns." ),
2197 << QStringLiteral(
"geometry" )
2198 << QStringLiteral(
"geography" ),
2199 QStringLiteral(
"geometry" ),
2204 QObject::tr(
"Controls whether layer and field names will be laundered for easier use. "
2205 "Laundered names will be converted to lower case and some special "
2206 "characters(' - #) will be changed to underscores." ),
2211 QObject::tr(
"Name for the geometry column. Defaults to wkb_geometry "
2212 "for GEOM_TYPE=geometry or the_geog for GEOM_TYPE=geography" ) ) );
2215 QObject::tr(
"Name of schema into which to create the new table" ) ) );
2218 QObject::tr(
"Whether to explicitly emit the CREATE SCHEMA statement to create the specified schema." ),
2223 QObject::tr(
"Whether to explicitly recreate the table if necessary." ),
2228 QObject::tr(
"Whether to explicitly destroy tables before recreating them." ),
2230 << QStringLiteral(
"YES" )
2231 << QStringLiteral(
"NO" )
2232 << QStringLiteral(
"IF_EXISTS" ),
2233 QStringLiteral(
"YES" ),
2238 QObject::tr(
"Used to force the SRID number of the SRS associated with the layer. "
2239 "When this option isn't specified and that a SRS is associated with the "
2240 "layer, a search is made in the spatial_ref_sys to find a match for the "
2241 "SRS, and, if there is no match, a new entry is inserted for the SRS in "
2242 "the spatial_ref_sys table. When the SRID option is specified, this "
2243 "search (and the eventual insertion of a new entry) will not be done: "
2244 "the specified SRID is used as such." ),
2249 QObject::tr(
"Can be set to 2.0 or 2.2 for PostGIS 2.0/2.2 compatibility. "
2250 "Important to set it correctly if using non-linear geometry types" ),
2251 QStringLiteral(
"2.2" )
2254 driverMetadata.insert( QStringLiteral(
"PGDUMP" ),
2256 QStringLiteral(
"PostgreSQL SQL dump" ),
2257 QObject::tr(
"PostgreSQL SQL dump" ),
2258 QStringLiteral(
"*.sql" ),
2259 QStringLiteral(
"sql" ),
2262 QStringLiteral(
"UTF-8" )
2268 QgsVectorFileWriterMetadataContainer(
const QgsVectorFileWriterMetadataContainer &other ) =
delete;
2269 QgsVectorFileWriterMetadataContainer &operator=(
const QgsVectorFileWriterMetadataContainer &other ) =
delete;
2270 ~QgsVectorFileWriterMetadataContainer()
2272 for (
auto it = driverMetadata.constBegin(); it != driverMetadata.constEnd(); ++it )
2274 for (
auto optionIt = it.value().driverOptions.constBegin(); optionIt != it.value().driverOptions.constEnd(); ++optionIt )
2275 delete optionIt.value();
2276 for (
auto optionIt = it.value().layerOptions.constBegin(); optionIt != it.value().layerOptions.constEnd(); ++optionIt )
2277 delete optionIt.value();
2281 QMap<QString, QgsVectorFileWriter::MetaData> driverMetadata;
2288 static QgsVectorFileWriterMetadataContainer sDriverMetadata;
2289 QMap<QString, MetaData>::ConstIterator it = sDriverMetadata.driverMetadata.constBegin();
2291 for ( ; it != sDriverMetadata.driverMetadata.constEnd(); ++it )
2293 if ( it.key() == QLatin1String(
"PGDUMP" ) &&
2294 driverName != QLatin1String(
"PGDUMP" ) &&
2295 driverName != QLatin1String(
"PostgreSQL SQL dump" ) )
2300 if ( it.key().startsWith( driverName ) || it.value().longName.startsWith( driverName ) )
2315 return QStringList();
2324 return QStringList();
2331 OGRwkbGeometryType ogrType =
static_cast<OGRwkbGeometryType
>( type );
2357 QgsFeatureList::iterator fIt = features.begin();
2359 for ( ; fIt != features.end(); ++fIt )
2384 QString styleString;
2385 QString currentStyle;
2387 QgsSymbolList::const_iterator symbolIt = symbols.constBegin();
2388 for ( ; symbolIt != symbols.constEnd(); ++symbolIt )
2390 int nSymbolLayers = ( *symbolIt )->symbolLayerCount();
2391 for (
int i = 0; i < nSymbolLayers; ++i )
2394 QMap< QgsSymbolLayer *, QString >::const_iterator it =
mSymbolLayerTable.find( ( *symbolIt )->symbolLayer( i ) );
2400 double mmsf = mmScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
2401 double musf = mapUnitScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
2403 currentStyle = ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf );
2407 if ( symbolIt != symbols.constBegin() || i != 0 )
2409 styleString.append(
';' );
2411 styleString.append( currentStyle );
2415 OGR_F_SetStyleString( poFeature.get(), currentStyle.toLocal8Bit().constData() );
2416 if ( !writeFeature(
mLayer, poFeature.get() ) )
2423 OGR_F_SetStyleString( poFeature.get(), styleString.toLocal8Bit().constData() );
2428 if ( !writeFeature(
mLayer, poFeature.get() ) )
2447 int fldIdx = it.key();
2448 int ogrField = it.value();
2450 QVariant attrValue = feature.
attribute( fldIdx );
2453 if ( !attrValue.isValid() || attrValue.isNull() )
2462 #ifdef OGRNullMarker
2463 OGR_F_SetFieldNull( poFeature.get(), ogrField );
2478 mErrorMessage = QObject::tr(
"Error converting value (%1) for attribute field %2: %3" )
2479 .arg( feature.
attribute( fldIdx ).toString(),
2489 OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
2491 case QVariant::LongLong:
2492 OGR_F_SetFieldInteger64( poFeature.get(), ogrField, attrValue.toLongLong() );
2494 case QVariant::Bool:
2495 OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
2497 case QVariant::String:
2498 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toString() ).constData() );
2500 case QVariant::Double:
2501 OGR_F_SetFieldDouble( poFeature.get(), ogrField, attrValue.toDouble() );
2503 case QVariant::Date:
2504 OGR_F_SetFieldDateTime( poFeature.get(), ogrField,
2505 attrValue.toDate().year(),
2506 attrValue.toDate().month(),
2507 attrValue.toDate().day(),
2510 case QVariant::DateTime:
2513 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toDateTime().toString( QStringLiteral(
"yyyy/MM/dd hh:mm:ss.zzz" ) ) ).constData() );
2517 OGR_F_SetFieldDateTime( poFeature.get(), ogrField,
2518 attrValue.toDateTime().date().year(),
2519 attrValue.toDateTime().date().month(),
2520 attrValue.toDateTime().date().day(),
2521 attrValue.toDateTime().time().hour(),
2522 attrValue.toDateTime().time().minute(),
2523 attrValue.toDateTime().time().second(),
2527 case QVariant::Time:
2530 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toString() ).constData() );
2534 OGR_F_SetFieldDateTime( poFeature.get(), ogrField,
2536 attrValue.toTime().hour(),
2537 attrValue.toTime().minute(),
2538 attrValue.toTime().second(),
2543 case QVariant::ByteArray:
2545 const QByteArray ba = attrValue.toByteArray();
2546 OGR_F_SetFieldBinary( poFeature.get(), ogrField, ba.size(),
const_cast< GByte *
>(
reinterpret_cast< const GByte *
>( ba.data() ) ) );
2550 case QVariant::Invalid:
2553 case QVariant::StringList:
2558 const QJsonDocument doc = QJsonDocument::fromVariant( attrValue );
2560 if ( !doc.isNull() )
2562 jsonString = QString::fromUtf8( doc.toJson( QJsonDocument::Compact ).constData() );
2564 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( jsonString.constData() ) );
2568 QStringList list = attrValue.toStringList();
2569 if ( mSupportedListSubTypes.contains( QVariant::String ) )
2571 int count = list.count();
2572 char **lst =
new char *[count + 1];
2576 for (
const QString &
string : list )
2578 lst[pos] = CPLStrdup(
mCodec->fromUnicode(
string ).data() );
2582 lst[count] =
nullptr;
2583 OGR_F_SetFieldStringList( poFeature.get(), ogrField, lst );
2588 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( list.join(
',' ) ).constData() );
2593 case QVariant::List:
2597 const QJsonDocument doc = QJsonDocument::fromVariant( attrValue );
2599 if ( !doc.isNull() )
2601 jsonString = QString::fromUtf8( doc.toJson( QJsonDocument::Compact ).data() );
2603 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( jsonString.constData() ) );
2610 QStringList list = attrValue.toStringList();
2611 if ( mSupportedListSubTypes.contains( QVariant::String ) )
2613 int count = list.count();
2614 char **lst =
new char *[count + 1];
2618 for (
const QString &
string : list )
2620 lst[pos] = CPLStrdup(
mCodec->fromUnicode(
string ).data() );
2624 lst[count] =
nullptr;
2625 OGR_F_SetFieldStringList( poFeature.get(), ogrField, lst );
2630 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( list.join(
',' ) ).constData() );
2636 const QVariantList list = attrValue.toList();
2637 if ( mSupportedListSubTypes.contains( QVariant::Int ) )
2639 const int count = list.count();
2640 int *lst =
new int[count];
2644 for (
const QVariant &value : list )
2646 lst[pos] = value.toInt();
2650 OGR_F_SetFieldIntegerList( poFeature.get(), ogrField, count, lst );
2655 QStringList strings;
2656 strings.reserve( list.size() );
2657 for (
const QVariant &value : list )
2659 strings << QString::number( value.toInt() );
2661 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
2667 const QVariantList list = attrValue.toList();
2668 if ( mSupportedListSubTypes.contains( QVariant::Double ) )
2670 const int count = list.count();
2671 double *lst =
new double[count];
2675 for (
const QVariant &value : list )
2677 lst[pos] = value.toDouble();
2681 OGR_F_SetFieldDoubleList( poFeature.get(), ogrField, count, lst );
2686 QStringList strings;
2687 strings.reserve( list.size() );
2688 for (
const QVariant &value : list )
2690 strings << QString::number( value.toDouble() );
2692 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
2698 const QVariantList list = attrValue.toList();
2699 if ( mSupportedListSubTypes.contains( QVariant::LongLong ) )
2701 const int count = list.count();
2702 long long *lst =
new long long[count];
2706 for (
const QVariant &value : list )
2708 lst[pos] = value.toLongLong();
2712 OGR_F_SetFieldInteger64List( poFeature.get(), ogrField, count, lst );
2717 QStringList strings;
2718 strings.reserve( list.size() );
2719 for (
const QVariant &value : list )
2721 strings << QString::number( value.toLongLong() );
2723 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
2731 mErrorMessage = QObject::tr(
"Invalid variant type for field %1[%2]: received %3 with type %4" )
2734 .arg( attrValue.typeName(),
2735 attrValue.toString() );
2748 if ( mCoordinateTransform )
2753 geom.
transform( *mCoordinateTransform );
2771 OGRGeometryH mGeom2 =
nullptr;
2817 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
2818 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
2824 QByteArray wkb( geom.
asWkb() );
2825 OGRErr err = OGR_G_ImportFromWkb( mGeom2,
reinterpret_cast<unsigned char *
>(
const_cast<char *
>( wkb.constData() ) ), wkb.length() );
2826 if ( err != OGRERR_NONE )
2828 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
2829 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
2836 OGR_F_SetGeometryDirectly( poFeature.get(), mGeom2 );
2842 OGRErr err = OGR_G_ImportFromWkb( ogrGeom,
reinterpret_cast<unsigned char *
>(
const_cast<char *
>( wkb.constData() ) ), wkb.length() );
2843 if ( err != OGRERR_NONE )
2845 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
2846 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
2853 OGR_F_SetGeometryDirectly( poFeature.get(), ogrGeom );
2868 for (
int i = 0; i < attributes.size(); i++ )
2870 if ( omap.find( i ) != omap.end() )
2875 bool QgsVectorFileWriter::writeFeature( OGRLayerH layer, OGRFeatureH feature )
2877 if ( OGR_L_CreateFeature( layer, feature ) != OGRERR_NONE )
2879 mErrorMessage = QObject::tr(
"Feature creation error (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
2889 if ( mUsingTransaction )
2891 if ( OGRERR_NONE != OGR_L_CommitTransaction(
mLayer ) )
2893 QgsDebugMsg( QStringLiteral(
"Error while committing transaction on OGRLayer." ) );
2897 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,1,0) && GDAL_VERSION_NUM <= GDAL_COMPUTE_VERSION(3,1,3)
2901 QString drvName = GDALGetDriverShortName( GDALGetDatasetDriver(
mDS.get() ) );
2902 if ( drvName == QLatin1String(
"XLSX" ) ||
2903 drvName == QLatin1String(
"ODS" ) )
2905 CPLSetThreadLocalConfigOption(
"CPL_CREATE_ZIP64",
"NO" );
2907 CPLSetThreadLocalConfigOption(
"CPL_CREATE_ZIP64",
nullptr );
2915 mFilename = QString::fromUtf8( GDALGetDescription(
mDS.get() ) );
2920 if ( !mFilename.isEmpty() )
2922 QgsOgrProviderUtils::invalidateCachedDatasets( mFilename );
2933 const QString &fileName,
2934 const QString &fileEncoding,
2936 const QString &driverName,
2938 QString *errorMessage,
2939 const QStringList &datasourceOptions,
2940 const QStringList &layerOptions,
2941 bool skipAttributeCreation,
2942 QString *newFilename,
2944 double symbologyScale,
2954 if ( destCRS.
isValid() && layer )
2980 const QString &fileName,
2981 const QString &fileEncoding,
2983 const QString &driverName,
2985 QString *errorMessage,
2986 const QStringList &datasourceOptions,
2987 const QStringList &layerOptions,
2988 bool skipAttributeCreation,
2989 QString *newFilename,
2991 double symbologyScale,
3022 : driverName( QStringLiteral(
"GPKG" ) )
3030 if ( !layer || !layer->
isValid() )
3037 details.sourceCrs = layer->
crs();
3038 details.sourceWkbType = layer->
wkbType();
3039 details.sourceFields = layer->
fields();
3048 if ( details.storageType == QLatin1String(
"ESRI Shapefile" ) )
3056 details.geometryTypeScanIterator = layer->
getFeatures( req );
3060 details.renderContext.setExpressionContext( details.expressionContext );
3061 details.renderContext.setRendererScale( options.
symbologyScale );
3063 details.shallTransform =
false;
3068 details.shallTransform =
true;
3073 details.outputCrs = details.sourceCrs;
3076 details.destWkbType = details.sourceWkbType;
3090 details.attributes.clear();
3091 else if ( details.attributes.isEmpty() )
3093 const QgsAttributeList allAttributes = details.sourceFields.allAttributesList();
3094 for (
int idx : allAttributes )
3096 QgsField fld = details.sourceFields.at( idx );
3097 if ( details.providerType == QLatin1String(
"oracle" ) && fld.
typeName().contains( QLatin1String(
"SDO_GEOMETRY" ) ) )
3099 details.attributes.append( idx );
3103 if ( !details.attributes.isEmpty() )
3105 for (
int attrIdx : std::as_const( details.attributes ) )
3107 details.outputFields.append( details.sourceFields.at( attrIdx ) );
3113 if ( details.providerType == QLatin1String(
"spatialite" ) )
3115 for (
int i = 0; i < details.outputFields.size(); i++ )
3117 if ( details.outputFields.at( i ).type() == QVariant::LongLong )
3122 if ( std::max( std::llabs( min.toLongLong() ), std::llabs( max.toLongLong() ) ) < std::numeric_limits<int>::max() )
3124 details.outputFields[i].setType( QVariant::Int );
3132 addRendererAttributes( details.renderer.get(), details.renderContext, details.sourceFields, details.attributes );
3142 bool useFilterRect =
true;
3143 if ( details.shallTransform )
3150 filterRect = extentTransform.
transformBoundingBox( filterRect, Qgis::TransformDirection::Reverse );
3154 useFilterRect =
false;
3157 if ( useFilterRect )
3163 details.filterRectEngine->prepareGeometry();
3165 details.sourceFeatureIterator = layer->
getFeatures( req );
3179 int lastProgressReport = 0;
3180 long long total = details.featureCount;
3183 if ( details.providerType == QLatin1String(
"ogr" ) && !details.dataSourceUri.isEmpty() )
3185 QString srcFileName( details.providerUriParams.value( QStringLiteral(
"path" ) ).toString() );
3186 if ( QFile::exists( srcFileName ) && QFileInfo( fileName ).canonicalFilePath() == QFileInfo( srcFileName ).canonicalFilePath() )
3190 if ( !( ( options.
driverName == QLatin1String(
"GPKG" ) ||
3191 options.
driverName == QLatin1String(
"SpatiaLite" ) ||
3192 options.
driverName == QLatin1String(
"SQLite" ) ) &&
3193 options.
layerName != details.providerUriParams.value( QStringLiteral(
"layerName" ) ) ) )
3196 *
errorMessage = QObject::tr(
"Cannot overwrite a OGR layer in place" );
3216 int newProgress =
static_cast<int>( ( 5.0 * scanned ) / total );
3217 if ( newProgress != lastProgressReport )
3219 lastProgressReport = newProgress;
3234 QString tempNewFilename;
3235 QString tempNewLayer;
3237 std::unique_ptr< QgsVectorFileWriter > writer(
create( fileName, details.outputFields, destWkbType, details.outputCrs, transformContext, options, QgsFeatureSink::SinkFlags(), &tempNewFilename, &tempNewLayer ) );
3241 *newFilename = tempNewFilename;
3244 *newLayer = tempNewLayer;
3284 int n = 0, errors = 0;
3293 writer->startRender( details.renderer.get(), details.sourceFields );
3295 writer->resetMap( details.attributes );
3297 writer->mFields = details.sourceFields;
3301 int initialProgress = lastProgressReport;
3302 while ( details.sourceFeatureIterator.nextFeature( fet ) )
3313 int newProgress =
static_cast<int>( initialProgress + ( ( 100.0 - initialProgress ) * saved ) / total );
3314 if ( newProgress < 100 && newProgress != lastProgressReport )
3316 lastProgressReport = newProgress;
3321 if ( details.shallTransform )
3334 QString msg = QObject::tr(
"Failed to transform a point while drawing a feature with ID '%1'. Writing stopped. (Exception: %2)" )
3335 .arg( fet.
id() ).arg( e.
what() );
3352 if ( !writer->addFeatureWithStyle( fet, writer->mRenderer.get(), mapUnits ) )
3359 *
errorMessage = QObject::tr(
"Feature write errors:" );
3365 if ( errors > 1000 )
3369 *
errorMessage += QObject::tr(
"Stopping after %n error(s)",
nullptr, errors );
3379 writer->stopRender();
3383 *
errorMessage += QObject::tr(
"\nOnly %1 of %2 features written." ).arg( n - errors ).arg( n );
3388 bool metadataFailure =
false;
3393 {QStringLiteral(
"path" ), tempNewFilename },
3394 {QStringLiteral(
"layerName" ), tempNewLayer }
3408 metadataFailure =
true;
3419 metadataFailure =
true;
3427 const QString &fileName,
3429 QString *newFilename,
3433 QgsVectorFileWriter::PreparedWriterDetails details;
3434 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
3442 const QString &fileName,
3445 QString *newFilename,
3449 QgsVectorFileWriter::PreparedWriterDetails details;
3450 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
3459 QgsVectorFileWriter::PreparedWriterDetails details;
3460 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
3469 QFileInfo fi( fileName );
3470 QDir dir = fi.dir();
3473 for (
const char *suffix : {
".shp",
".shx",
".dbf",
".prj",
".qix",
".qpj",
".cpg",
".sbn",
".sbx",
".idm",
".ind" } )
3475 filter << fi.completeBaseName() + suffix;
3479 const auto constEntryList = dir.entryList( filter );
3480 for (
const QString &file : constEntryList )
3482 QFile f( dir.canonicalPath() +
'/' + file );
3485 QgsDebugMsg( QStringLiteral(
"Removing file %1 failed: %2" ).arg( file, f.errorString() ) );
3501 static QReadWriteLock sFilterLock;
3502 static QMap< VectorFormatOptions, QList< QgsVectorFileWriter::FilterFormatDetails > > sFilters;
3506 const auto it = sFilters.constFind( options );
3507 if ( it != sFilters.constEnd() )
3511 QList< QgsVectorFileWriter::FilterFormatDetails > results;
3514 int const drvCount = OGRGetDriverCount();
3516 for (
int i = 0; i < drvCount; ++i )
3518 OGRSFDriverH drv = OGRGetDriver( i );
3521 QString drvName = OGR_Dr_GetName( drv );
3523 GDALDriverH gdalDriver = GDALGetDriverByName( drvName.toLocal8Bit().constData() );
3524 char **metadata =
nullptr;
3527 metadata = GDALGetMetadata( gdalDriver,
nullptr );
3530 bool nonSpatialFormat = CSLFetchBoolean( metadata, GDAL_DCAP_NONSPATIAL,
false );
3532 if ( OGR_Dr_TestCapability( drv,
"CreateDataSource" ) != 0 )
3537 if ( nonSpatialFormat )
3542 if ( filterString.isEmpty() )
3549 globs = metadata.
glob.toLower().split(
' ' );
3555 details.
globs = globs;
3564 if ( options & SortRecommended )
3566 if ( a.driverName == QLatin1String(
"GPKG" ) )
3568 else if ( b.driverName == QLatin1String(
"GPKG" ) )
3570 else if ( a.driverName == QLatin1String(
"ESRI Shapefile" ) )
3572 else if ( b.driverName == QLatin1String(
"ESRI Shapefile" ) )
3579 sFilters.insert( options, results );
3586 QSet< QString > extensions;
3588 const QRegularExpression rx( QStringLiteral(
"\\*\\.(.*)$" ) );
3592 for (
const QString &glob : format.globs )
3594 const QRegularExpressionMatch match = rx.match( glob );
3595 if ( !match.hasMatch() )
3598 const QString matched = match.captured( 1 );
3599 extensions.insert( matched );
3603 QStringList extensionList = qgis::setToList( extensions );
3605 std::sort( extensionList.begin(), extensionList.end(), [options](
const QString & a,
const QString & b ) ->
bool
3607 if ( options & SortRecommended )
3609 if ( a == QLatin1String(
"gpkg" ) )
3611 else if ( b == QLatin1String(
"gpkg" ) )
3613 else if ( a == QLatin1String(
"shp" ) )
3615 else if ( b == QLatin1String(
"shp" ) )
3619 return a.toLower().localeAwareCompare( b.toLower() ) < 0;
3622 return extensionList;
3627 QList< QgsVectorFileWriter::DriverDetails > results;
3630 const int drvCount = OGRGetDriverCount();
3632 QStringList writableDrivers;
3633 for (
int i = 0; i < drvCount; ++i )
3635 OGRSFDriverH drv = OGRGetDriver( i );
3638 QString drvName = OGR_Dr_GetName( drv );
3644 if ( drvName == QLatin1String(
"ODS" ) || drvName == QLatin1String(
"XLSX" ) || drvName == QLatin1String(
"XLS" ) )
3648 if ( drvName == QLatin1String(
"ESRI Shapefile" ) )
3650 writableDrivers << QStringLiteral(
"DBF file" );
3652 if ( OGR_Dr_TestCapability( drv,
"CreateDataSource" ) != 0 )
3655 if ( drvName == QLatin1String(
"MapInfo File" ) )
3657 writableDrivers << QStringLiteral(
"MapInfo MIF" );
3659 else if ( drvName == QLatin1String(
"SQLite" ) )
3666 QString option = QStringLiteral(
"SPATIALITE=YES" );
3667 char *options[2] = { CPLStrdup( option.toLocal8Bit().constData() ),
nullptr };
3668 OGRSFDriverH poDriver;
3670 poDriver = OGRGetDriverByName( drvName.toLocal8Bit().constData() );
3673 gdal::ogr_datasource_unique_ptr ds( OGR_Dr_CreateDataSource( poDriver, QStringLiteral(
"/vsimem/spatialitetest.sqlite" ).toUtf8().constData(), options ) );
3676 writableDrivers << QStringLiteral(
"SpatiaLite" );
3677 OGR_Dr_DeleteDataSource( poDriver, QStringLiteral(
"/vsimem/spatialitetest.sqlite" ).toUtf8().constData() );
3680 CPLFree( options[0] );
3682 writableDrivers << drvName;
3687 results.reserve( writableDrivers.count() );
3688 for (
const QString &drvName : std::as_const( writableDrivers ) )
3702 if ( options & SortRecommended )
3704 if ( a.driverName == QLatin1String(
"GPKG" ) )
3706 else if ( b.driverName == QLatin1String(
"GPKG" ) )
3708 else if ( a.driverName == QLatin1String(
"ESRI Shapefile" ) )
3710 else if ( b.driverName == QLatin1String(
"ESRI Shapefile" ) )
3714 return a.
longName.toLower().localeAwareCompare( b.
longName.toLower() ) < 0;
3721 QString ext = extension.trimmed();
3722 if ( ext.isEmpty() )
3725 if ( ext.startsWith(
'.' ) )
3729 int const drvCount = GDALGetDriverCount();
3731 for (
int i = 0; i < drvCount; ++i )
3733 GDALDriverH drv = GDALGetDriver( i );
3739 QString drvName = GDALGetDriverShortName( drv );
3740 QStringList driverExtensions = QString( GDALGetMetadataItem( drv, GDAL_DMD_EXTENSIONS,
nullptr ) ).split(
' ' );
3742 const auto constDriverExtensions = driverExtensions;
3743 for (
const QString &driver : constDriverExtensions )
3745 if ( driver.compare( ext, Qt::CaseInsensitive ) == 0 )
3756 QString filterString;
3760 if ( !filterString.isEmpty() )
3761 filterString += QLatin1String(
";;" );
3763 filterString += details.filterString;
3765 return filterString;
3774 return QStringLiteral(
"%1 (%2 %3)" ).arg( metadata.
trLongName,
3775 metadata.
glob.toLower(),
3776 metadata.
glob.toUpper() );
3781 if ( codecName == QLatin1String(
"System" ) )
3782 return QStringLiteral(
"LDID/0" );
3784 const QRegularExpression re( QRegularExpression::anchoredPattern( QString(
"(CP|windows-|ISO[ -])(.+)" ) ), QRegularExpression::CaseInsensitiveOption );
3785 const QRegularExpressionMatch match = re.match( codecName );
3786 if ( match.hasMatch() )
3788 QString
c = match.captured( 2 ).remove(
'-' );
3790 ( void )
c.toInt( &isNumber );
3818 OGRStyleTableH ogrStyleTable = OGR_STBL_Create();
3819 OGRStyleMgrH styleManager = OGR_SM_Create( ogrStyleTable );
3822 int nTotalLevels = 0;
3824 QgsSymbolList::iterator symbolIt = symbolList.begin();
3825 for ( ; symbolIt != symbolList.end(); ++symbolIt )
3827 double mmsf = mmScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
3828 double musf = mapUnitScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
3830 int nLevels = ( *symbolIt )->symbolLayerCount();
3831 for (
int i = 0; i < nLevels; ++i )
3833 mSymbolLayerTable.insert( ( *symbolIt )->symbolLayer( i ), QString::number( nTotalLevels ) );
3834 OGR_SM_AddStyle( styleManager, QString::number( nTotalLevels ).toLocal8Bit(),
3835 ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf ).toLocal8Bit() );
3839 OGR_DS_SetStyleTableDirectly( ds, ogrStyleTable );
3845 if ( !details.renderer )
3850 QHash< QgsSymbol *, QList<QgsFeature> > features;
3859 startRender( details.renderer.get(), details.sourceFields );
3879 QString msg = QObject::tr(
"Failed to transform, writing stopped. (Exception: %1)" )
3890 featureSymbol = mRenderer->symbolForFeature( fet, mRenderContext );
3891 if ( !featureSymbol )
3896 QHash< QgsSymbol *, QList<QgsFeature> >::iterator it = features.find( featureSymbol );
3897 if ( it == features.end() )
3899 it = features.insert( featureSymbol, QList<QgsFeature>() );
3901 it.value().append( fet );
3906 QgsSymbolList symbols = mRenderer->symbols( mRenderContext );
3907 for (
int i = 0; i < symbols.count(); i++ )
3913 if ( level < 0 || level >= 1000 )
3916 while ( level >= levels.count() )
3918 levels[level].append( item );
3923 int nTotalFeatures = 0;
3926 for (
int l = 0; l < levels.count(); l++ )
3929 for (
int i = 0; i < level.count(); i++ )
3932 QHash< QgsSymbol *, QList<QgsFeature> >::iterator levelIt = features.find( item.
symbol() );
3933 if ( levelIt == features.end() )
3939 double mmsf = mmScaleFactor(
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
3940 double musf = mapUnitScaleFactor(
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
3942 int llayer = item.
layer();
3943 QList<QgsFeature> &featureList = levelIt.value();
3944 QList<QgsFeature>::iterator featureIt = featureList.begin();
3945 for ( ; featureIt != featureList.end(); ++featureIt )
3955 QString styleString = levelIt.key()->symbolLayer( llayer )->ogrFeatureStyle( mmsf, musf );
3956 if ( !styleString.isEmpty() )
3958 OGR_F_SetStyleString( ogrFeature.get(), styleString.toLocal8Bit().constData() );
3959 if ( !writeFeature(
mLayer, ogrFeature.get() ) )
3972 *
errorMessage += QObject::tr(
"\nOnly %1 of %2 features written." ).arg( nTotalFeatures - nErrors ).arg( nTotalFeatures );
3989 return 1000 / scale;
4006 return scale / 1000;
4014 mRenderer = createSymbologyRenderer( sourceRenderer );
4020 mRenderer->startRender( mRenderContext, fields );
4023 void QgsVectorFileWriter::stopRender()
4030 mRenderer->stopRender( mRenderContext );
4033 std::unique_ptr<QgsFeatureRenderer> QgsVectorFileWriter::createSymbologyRenderer(
QgsFeatureRenderer *sourceRenderer )
const
4039 if ( !sourceRenderer )
4044 return std::unique_ptr< QgsFeatureRenderer >( sourceRenderer->
clone() );
4051 const QSet<QString> rendererAttributes = renderer->
usedAttributes( context );
4052 for (
const QString &attr : rendererAttributes )
4057 attList.append( index );
4063 QStringList QgsVectorFileWriter::concatenateOptions(
const QMap<QString, QgsVectorFileWriter::Option *> &options )
4066 QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
4068 for ( it = options.constBegin(); it != options.constEnd(); ++it )
4071 switch ( option->
type )
4078 list.append( QStringLiteral(
"%1=%2" ).arg( it.key() ).arg( opt->
defaultValue ) );
4088 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
defaultValue ) );
4098 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
defaultValue ) );
4107 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
mValue ) );
4118 OGRSFDriverH hDriver =
nullptr;
4121 return QgsVectorFileWriter::EditionCapabilities();
4122 QString drvName = OGR_Dr_GetName( hDriver );
4123 QgsVectorFileWriter::EditionCapabilities caps = QgsVectorFileWriter::EditionCapabilities();
4124 if ( OGR_DS_TestCapability( hDS.get(), ODsCCreateLayer ) )
4129 if ( !( drvName == QLatin1String(
"ESRI Shapefile" ) && QFile::exists( datasetName ) ) )
4132 if ( OGR_DS_TestCapability( hDS.get(), ODsCDeleteLayer ) )
4136 int layer_count = OGR_DS_GetLayerCount( hDS.get() );
4139 OGRLayerH hLayer = OGR_DS_GetLayer( hDS.get(), 0 );
4142 if ( OGR_L_TestCapability( hLayer, OLCSequentialWrite ) )
4145 if ( OGR_L_TestCapability( hLayer, OLCCreateField ) )
4156 const QString &layerNameIn )
4158 OGRSFDriverH hDriver =
nullptr;
4163 QString layerName( layerNameIn );
4164 if ( layerName.isEmpty() )
4165 layerName = QFileInfo( datasetName ).baseName();
4167 return OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
4172 const QString &layerName,
4176 OGRSFDriverH hDriver =
nullptr;
4180 OGRLayerH hLayer = OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
4186 OGRFeatureDefnH defn = OGR_L_GetLayerDefn( hLayer );
4187 const auto constAttributes = attributes;
4188 for (
int idx : constAttributes )
4191 if ( OGR_FD_GetFieldIndex( defn, fld.
name().toUtf8().constData() ) < 0 )
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.
static void registerOgrDrivers()
Register OGR drivers ensuring this only happens once.
This class represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
static Q_INVOKABLE QgsCoordinateReferenceSystem fromEpsgId(long epsg)
Creates a CRS from a given EPSG ID.
Q_GADGET QgsUnitTypes::DistanceUnit mapUnits
Contains information about the context in which a coordinate transform is executed.
Custom exception class for Coordinate Reference System related exceptions.
virtual QString dataSourceUri(bool expandAuthConfig=false) const
Gets the data source specification.
Class for storing the component parts of a RDBMS data source URI (e.g.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
virtual QgsFeatureRenderer * clone() const =0
Create a deep copy of this renderer.
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.
@ SymbolLevels
Rendering with symbol levels (i.e. implements symbols(), symbolForFeature())
virtual QSet< QString > usedAttributes(const QgsRenderContext &context) const =0
Returns a list of attributes required by 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.
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.
QVariant::Type subType() const
If the field is a collection, gets its element's type.
Container of fields for a vector layer.
int count() const
Returns number of items.
int size() const
Returns number of items.
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
A geometry is the spatial representation of a feature.
const QgsAbstractGeometry * constGet() const SIP_HOLDGIL
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
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.
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.
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.
DistanceUnit
Units of distance.
RenderUnit
Rendering size units.
@ RenderMillimeters
Millimeters.
@ RenderMapUnits
Map units.
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.
QgsLayerMetadata layerMetadata
Layer metadata to save for the exported vector file.
SaveVectorOptions()
Constructor.
QString layerName
Layer name. If let empty, it will be derived from the filename.
QgsRectangle filterExtent
If not empty, only features intersecting the extent will be saved.
QgsVectorFileWriter::FieldValueConverter * fieldValueConverter
Field value converter.
QStringList layerOptions
List of OGR layer creation options.
QgsVectorFileWriter::SymbologyExport symbologyExport
Symbology to export.
bool includeZ
Sets to true to include z dimension in output. This option is only valid if overrideGeometryType is s...
bool saveMetadata
Set to true to save layer metadata for the exported vector file.
QgsVectorFileWriter::ActionOnExistingFile actionOnExistingFile
Action on existing file.
QgsAttributeList attributes
Attributes to export (empty means all unless skipAttributeCreation is set)
bool onlySelectedFeatures
Write only selected features of layer.
bool skipAttributeCreation
Only write geometries.
double symbologyScale
Scale of symbology.
QStringList datasourceOptions
List of OGR data source creation options.
QgsWkbTypes::Type overrideGeometryType
Set to a valid geometry type to override the default geometry type for the layer.
QgsFeedback * feedback
Optional feedback object allowing cancellation of layer save.
A convenience class for writing vector layers to disk based formats (e.g.
static QgsVectorFileWriter::WriterError writeAsVectorFormatV3(QgsVectorLayer *layer, const QString &fileName, const QgsCoordinateTransformContext &transformContext, const QgsVectorFileWriter::SaveVectorOptions &options, QString *errorMessage=nullptr, QString *newFilename=nullptr, QString *newLayer=nullptr)
Writes a layer out to a vector file.
QString lastError() const override
Returns the most recent error encountered by the sink, e.g.
@ CanAddNewFieldsToExistingLayer
Flag to indicate that new fields can be added to an existing layer. Imply CanAppendToExistingLayer.
@ CanAppendToExistingLayer
Flag to indicate that new features can be added to an existing layer.
@ CanAddNewLayer
Flag to indicate that a new layer can be added to the dataset.
@ CanDeleteLayer
Flag to indicate that an existing layer can be deleted.
static QgsVectorFileWriter::EditionCapabilities editionCapabilities(const QString &datasetName)
Returns edition capabilities for an existing dataset name.
static QgsVectorFileWriter * create(const QString &fileName, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &srs, const QgsCoordinateTransformContext &transformContext, const QgsVectorFileWriter::SaveVectorOptions &options, QgsFeatureSink::SinkFlags sinkFlags=QgsFeatureSink::SinkFlags(), QString *newFilename=nullptr, QString *newLayer=nullptr)
Create a new vector file writer.
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a single feature to the sink.
static bool supportsFeatureStyles(const QString &driverName)
Returns true if the specified driverName supports feature styles.
bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a list of features to the sink.
double mSymbologyScale
Scale for symbology export (e.g. for symbols units in map units)
OGRGeometryH createEmptyGeometry(QgsWkbTypes::Type wkbType)
QMap< int, int > mAttrIdxToOgrIdx
Map attribute indizes to OGR field indexes.
@ ErrAttributeTypeUnsupported
@ Canceled
Writing was interrupted by manual cancellation.
@ ErrAttributeCreationFailed
@ ErrSavingMetadata
Metadata saving failed.
gdal::ogr_datasource_unique_ptr mDS
static Q_DECL_DEPRECATED QgsVectorFileWriter::WriterError writeAsVectorFormatV2(QgsVectorLayer *layer, const QString &fileName, const QgsCoordinateTransformContext &transformContext, const QgsVectorFileWriter::SaveVectorOptions &options, QString *newFilename=nullptr, QString *newLayer=nullptr, QString *errorMessage=nullptr)
Writes a layer out to a vector file.
~QgsVectorFileWriter() override
Close opened shapefile for writing.
static bool targetLayerExists(const QString &datasetName, const QString &layerName)
Returns whether the target layer already exists.
double symbologyScale() const
Returns the reference scale for output.
static QStringList defaultLayerOptions(const QString &driverName)
Returns a list of the default layer options for a specified driver.
SymbologyExport mSymbologyExport
static QString driverForExtension(const QString &extension)
Returns the OGR driver name for a specified file extension.
static QList< QgsVectorFileWriter::FilterFormatDetails > supportedFiltersAndFormats(VectorFormatOptions options=SortRecommended)
Returns a list or pairs, with format filter string as first element and OGR format key as second elem...
OGRSpatialReferenceH mOgrRef
static bool driverMetadata(const QString &driverName, MetaData &driverMetadata)
QgsVectorFileWriter::WriterError hasError()
Checks whether there were any errors in constructor.
static bool deleteShapeFile(const QString &fileName)
Delete a shapefile (and its accompanying shx / dbf / prj / qix / qpj / cpg / sbn / sbx / idm / ind)
static QString filterForDriver(const QString &driverName)
Creates a filter for an OGR driver key.
QgsWkbTypes::Type mWkbType
Geometry type which is being used.
static OGRwkbGeometryType ogrTypeFromWkbType(QgsWkbTypes::Type type)
Gets the ogr geometry type from an internal QGIS wkb type enum.
@ SkipNonSpatialFormats
Filter out any formats which do not have spatial support (e.g. those which cannot save geometries)
static bool areThereNewFieldsToCreate(const QString &datasetName, const QString &layerName, QgsVectorLayer *layer, const QgsAttributeList &attributes)
Returns whether there are among the attributes specified some that do not exist yet in the layer.
static QList< QgsVectorFileWriter::DriverDetails > ogrDriverList(VectorFormatOptions options=SortRecommended)
Returns the driver list that can be used for dialogs.
static Q_DECL_DEPRECATED QgsVectorFileWriter::WriterError writeAsVectorFormat(QgsVectorLayer *layer, const QString &fileName, const QString &fileEncoding, const QgsCoordinateReferenceSystem &destCRS=QgsCoordinateReferenceSystem(), const QString &driverName="GPKG", bool onlySelected=false, QString *errorMessage=nullptr, const QStringList &datasourceOptions=QStringList(), const QStringList &layerOptions=QStringList(), bool skipAttributeCreation=false, QString *newFilename=nullptr, QgsVectorFileWriter::SymbologyExport symbologyExport=QgsVectorFileWriter::NoSymbology, double symbologyScale=1.0, const QgsRectangle *filterExtent=nullptr, QgsWkbTypes::Type overrideGeometryType=QgsWkbTypes::Unknown, bool forceMulti=false, bool includeZ=false, const QgsAttributeList &attributes=QgsAttributeList(), QgsVectorFileWriter::FieldValueConverter *fieldValueConverter=nullptr, QString *newLayer=nullptr)
Write contents of vector layer to an (OGR supported) vector format.
WriterError mError
Contains error value if construction was not successful.
FieldNameSource
Source for exported field names.
@ PreferAlias
Use the field alias as the exported field name, wherever one is set. Otherwise use the original field...
@ Original
Use original field names.
static QStringList defaultDatasetOptions(const QString &driverName)
Returns a list of the default dataset options for a specified driver.
static QStringList supportedFormatExtensions(VectorFormatOptions options=SortRecommended)
Returns a list of file extensions for supported formats, e.g "shp", "gpkg".
QString errorMessage()
Retrieves error message.
static QString convertCodecNameForEncodingOption(const QString &codecName)
Converts codec name to string passed to ENCODING layer creation option of OGR Shapefile.
FieldValueConverter * mFieldValueConverter
Field value converter.
bool addFeatureWithStyle(QgsFeature &feature, QgsFeatureRenderer *renderer, QgsUnitTypes::DistanceUnit outputUnit=QgsUnitTypes::DistanceMeters)
Adds a feature to the currently opened data source, using the style from a specified renderer.
QgsVectorFileWriter::SymbologyExport symbologyExport() const
void setSymbologyScale(double scale)
Set reference scale for output.
Q_DECL_DEPRECATED QgsVectorFileWriter(const QString &vectorFileName, const QString &fileEncoding, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &srs=QgsCoordinateReferenceSystem(), const QString &driverName="GPKG", const QStringList &datasourceOptions=QStringList(), const QStringList &layerOptions=QStringList(), QString *newFilename=nullptr, QgsVectorFileWriter::SymbologyExport symbologyExport=QgsVectorFileWriter::NoSymbology, QgsFeatureSink::SinkFlags sinkFlags=QgsFeatureSink::SinkFlags(), QString *newLayer=nullptr, const QgsCoordinateTransformContext &transformContext=QgsCoordinateTransformContext(), FieldNameSource fieldNameSource=Original)
Create a new vector file writer.
QMap< QgsSymbolLayer *, QString > mSymbolLayerTable
static QString fileFilterString(VectorFormatOptions options=SortRecommended)
Returns filter string that can be used for dialogs.
ActionOnExistingFile
Combination of CanAddNewLayer, CanAppendToExistingLayer, CanAddNewFieldsToExistingLayer or CanDeleteL...
@ CreateOrOverwriteLayer
Create or overwrite layer.
@ CreateOrOverwriteFile
Create or overwrite file.
@ AppendToLayerNoNewFields
Append features to existing layer, but do not create new fields.
@ AppendToLayerAddFields
Append features to existing layer, and create new fields if needed.
Represents a vector layer which manages a vector based data sets.
Q_INVOKABLE QgsWkbTypes::Type wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
long long featureCount(const QString &legendKey) const
Number of features rendered with specified legend key.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
int selectedFeatureCount() const
Returns the number of features that are selected in this layer.
Q_INVOKABLE const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
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.
QgsFeatureRenderer * renderer()
Returns the feature renderer used for rendering the features in the layer in 2D map views.
static bool isMultiType(Type type) SIP_HOLDGIL
Returns true if the WKB type is a multi type.
static bool hasM(Type type) SIP_HOLDGIL
Tests whether a WKB type contains m values.
Type
The WKB type describes the number of dimensions a geometry has.
static Type to25D(Type type) SIP_HOLDGIL
Will convert the 25D version of the flat type if supported or Unknown if not supported.
static Type singleType(Type type) SIP_HOLDGIL
Returns the single type for a WKB type.
static Type flatType(Type type) SIP_HOLDGIL
Returns the flat type for a WKB type.
static Type multiType(Type type) SIP_HOLDGIL
Returns the multi type for a WKB type.
static Type addZ(Type type) SIP_HOLDGIL
Adds the z dimension to a WKB type and returns the new type.
static bool hasZ(Type type) SIP_HOLDGIL
Tests whether a WKB type contains the z-dimension.
std::unique_ptr< std::remove_pointer< OGRFeatureH >::type, OGRFeatureDeleter > ogr_feature_unique_ptr
Scoped OGR feature.
std::unique_ptr< std::remove_pointer< OGRDataSourceH >::type, OGRDataSourceDeleter > ogr_datasource_unique_ptr
Scoped OGR data source.
std::unique_ptr< std::remove_pointer< OGRFieldDefnH >::type, OGRFldDeleter > ogr_field_def_unique_ptr
Scoped OGR field definition.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
#define Q_NOWARN_DEPRECATED_POP
#define Q_NOWARN_DEPRECATED_PUSH
QList< QgsFeature > QgsFeatureList
QList< int > QgsAttributeList
#define QgsDebugMsgLevel(str, level)
QList< QgsSymbolLevel > QgsSymbolLevelOrder
QList< QgsSymbolLevelItem > QgsSymbolLevel
QList< QgsSymbol * > QgsSymbolList
Details of available driver formats.
QString longName
Descriptive, user friendly name for the driver.
QString driverName
Unique driver name.