50#include <QRegularExpression>
51#include <QJsonDocument>
57#include <ogr_srs_api.h>
60#include <cpl_string.h>
79 const QString &vectorFileName,
80 const QString &fileEncoding,
84 const QString &driverName,
85 const QStringList &datasourceOptions,
86 const QStringList &layerOptions,
89 QgsFeatureSink::SinkFlags sinkFlags,
99 init( vectorFileName, fileEncoding, fields, geometryType,
100 srs, driverName, datasourceOptions, layerOptions, newFilename,
nullptr,
105 const QString &vectorFileName,
106 const QString &fileEncoding,
110 const QString &driverName,
111 const QStringList &datasourceOptions,
112 const QStringList &layerOptions,
113 QString *newFilename,
116 const QString &layerName,
120 QgsFeatureSink::SinkFlags sinkFlags,
124 , mWkbType( geometryType )
125 , mSymbologyExport( symbologyExport )
126 , mSymbologyScale( 1.0 )
128 init( vectorFileName, fileEncoding, fields, geometryType, srs, driverName,
129 datasourceOptions, layerOptions, newFilename, fieldValueConverter,
130 layerName, action, newLayer, sinkFlags, transformContext, fieldNameSource );
134 const QString &fileName,
140 QgsFeatureSink::SinkFlags sinkFlags,
141 QString *newFilename,
155 if ( driverName == QLatin1String(
"MapInfo MIF" ) )
159 GDALDriverH gdalDriver = GDALGetDriverByName( driverName.toLocal8Bit().constData() );
167 return CSLFetchBoolean(
driverMetadata, GDAL_DCAP_FEATURE_STYLES,
false );
170void QgsVectorFileWriter::init( QString vectorFileName,
171 QString fileEncoding,
175 const QString &driverName,
176 QStringList datasourceOptions,
177 QStringList layerOptions,
178 QString *newFilename,
179 FieldValueConverter *fieldValueConverter,
180 const QString &layerNameIn,
181 ActionOnExistingFile action,
182 QString *newLayer, SinkFlags sinkFlags,
187 if ( vectorFileName.isEmpty() )
194 if ( driverName == QLatin1String(
"MapInfo MIF" ) )
198 else if ( driverName == QLatin1String(
"SpatiaLite" ) )
201 if ( !datasourceOptions.contains( QStringLiteral(
"SPATIALITE=YES" ) ) )
203 datasourceOptions.append( QStringLiteral(
"SPATIALITE=YES" ) );
206 else if ( driverName == QLatin1String(
"DBF file" ) )
209 if ( !layerOptions.contains( QStringLiteral(
"SHPT=NULL" ) ) )
211 layerOptions.append( QStringLiteral(
"SHPT=NULL" ) );
220#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,3,1)
221 QString fidFieldName;
224 for (
const QString &layerOption : layerOptions )
226 if ( layerOption.startsWith( QLatin1String(
"FID=" ) ) )
228 fidFieldName = layerOption.mid( 4 );
232 if ( fidFieldName.isEmpty() )
233 fidFieldName = QStringLiteral(
"fid" );
238 OGRSFDriverH poDriver;
241 poDriver = OGRGetDriverByName(
mOgrDriverName.toLocal8Bit().constData() );
245 mErrorMessage = QObject::tr(
"OGR driver for '%1' not found (OGR error: %2)" )
247 QString::fromUtf8( CPLGetLastErrorMsg() ) );
257 if ( layerOptions.join( QString() ).toUpper().indexOf( QLatin1String(
"ENCODING=" ) ) == -1 )
262 if ( driverName == QLatin1String(
"ESRI Shapefile" ) && !vectorFileName.endsWith( QLatin1String(
".shp" ), Qt::CaseInsensitive ) )
264 vectorFileName += QLatin1String(
".shp" );
266 else if ( driverName == QLatin1String(
"DBF file" ) && !vectorFileName.endsWith( QLatin1String(
".dbf" ), Qt::CaseInsensitive ) )
268 vectorFileName += QLatin1String(
".dbf" );
278#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
279 QStringList allExts = metadata.ext.split(
' ', QString::SkipEmptyParts );
281 QStringList allExts = metadata.ext.split(
' ', Qt::SkipEmptyParts );
284 const auto constAllExts = allExts;
285 for (
const QString &ext : constAllExts )
287 if ( vectorFileName.endsWith(
'.' + ext, Qt::CaseInsensitive ) )
296 vectorFileName +=
'.' + allExts[0];
302 if ( vectorFileName.endsWith( QLatin1String(
".gdb" ), Qt::CaseInsensitive ) )
304 QDir dir( vectorFileName );
307 QFileInfoList fileList = dir.entryInfoList(
308 QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files, QDir::DirsFirst );
309 const auto constFileList = fileList;
310 for (
const QFileInfo &info : constFileList )
312 QFile::remove( info.absoluteFilePath() );
315 QDir().rmdir( vectorFileName );
319 QFile::remove( vectorFileName );
324 if ( metadataFound && !metadata.compulsoryEncoding.isEmpty() )
326 if ( fileEncoding.compare( metadata.compulsoryEncoding, Qt::CaseInsensitive ) != 0 )
328 QgsDebugMsgLevel( QStringLiteral(
"forced %1 encoding for %2" ).arg( metadata.compulsoryEncoding, driverName ), 2 );
329 fileEncoding = metadata.compulsoryEncoding;
334 char **options =
nullptr;
335 if ( !datasourceOptions.isEmpty() )
337 options =
new char *[ datasourceOptions.size() + 1 ];
338 for (
int i = 0; i < datasourceOptions.size(); i++ )
340 QgsDebugMsgLevel( QStringLiteral(
"-dsco=%1" ).arg( datasourceOptions[i] ), 2 );
341 options[i] = CPLStrdup( datasourceOptions[i].toLocal8Bit().constData() );
343 options[ datasourceOptions.size()] =
nullptr;
350 mDS.reset( OGR_Dr_CreateDataSource( poDriver, vectorFileName.toUtf8().constData(), options ) );
352 mDS.reset( OGROpen( vectorFileName.toUtf8().constData(), TRUE,
nullptr ) );
356 for (
int i = 0; i < datasourceOptions.size(); i++ )
357 CPLFree( options[i] );
366 mErrorMessage = QObject::tr(
"Creation of data source failed (OGR error: %1)" )
367 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
369 mErrorMessage = QObject::tr(
"Opening of data source in update mode failed (OGR error: %1)" )
370 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
374 QString layerName( layerNameIn );
375 if ( layerName.isEmpty() )
376 layerName = QFileInfo( vectorFileName ).baseName();
380 const int layer_count = OGR_DS_GetLayerCount(
mDS.get() );
381 for (
int i = 0; i < layer_count; i++ )
383 OGRLayerH hLayer = OGR_DS_GetLayer(
mDS.get(), i );
384 if ( EQUAL( OGR_L_GetName( hLayer ), layerName.toUtf8().constData() ) )
386 if ( OGR_DS_DeleteLayer(
mDS.get(), i ) != OGRERR_NONE )
389 mErrorMessage = QObject::tr(
"Overwriting of existing layer failed (OGR error: %1)" )
390 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
404 QgsDebugMsgLevel( QStringLiteral(
"Opened data source in update mode" ), 2 );
408 mCodec = QTextCodec::codecForName( fileEncoding.toLocal8Bit().constData() );
411 QgsDebugMsg(
"error finding QTextCodec for " + fileEncoding );
414 QString enc = settings.
value( QStringLiteral(
"UI/encoding" ),
"System" ).toString();
415 mCodec = QTextCodec::codecForName( enc.toLocal8Bit().constData() );
418 QgsDebugMsg(
"error finding QTextCodec for " + enc );
419 mCodec = QTextCodec::codecForLocale();
425 if ( driverName == QLatin1String(
"KML" ) || driverName == QLatin1String(
"LIBKML" ) || driverName == QLatin1String(
"GPX" ) )
427 if ( srs.
authid() != QLatin1String(
"EPSG:4326" ) )
442 int optIndex = layerOptions.indexOf( QLatin1String(
"FEATURE_DATASET=" ) );
443 if ( optIndex != -1 )
445 layerOptions.removeAt( optIndex );
448 if ( !layerOptions.isEmpty() )
450 options =
new char *[ layerOptions.size() + 1 ];
451 for (
int i = 0; i < layerOptions.size(); i++ )
454 options[i] = CPLStrdup( layerOptions[i].toLocal8Bit().constData() );
456 options[ layerOptions.size()] =
nullptr;
460 CPLSetConfigOption(
"SHAPE_ENCODING",
"" );
464 mLayer = OGR_DS_CreateLayer(
mDS.get(), layerName.toUtf8().constData(),
mOgrRef, wkbType, options );
467 *newLayer = OGR_L_GetName(
mLayer );
468 if ( driverName == QLatin1String(
"GPX" ) )
475 if ( !EQUAL( layerName.toUtf8().constData(),
"track_points" ) &&
476 !EQUAL( layerName.toUtf8().constData(),
"route_points" ) )
478 *newLayer = QStringLiteral(
"waypoints" );
485 const char *pszForceGPXTrack
486 = CSLFetchNameValue( options,
"FORCE_GPX_TRACK" );
487 if ( pszForceGPXTrack && CPLTestBool( pszForceGPXTrack ) )
488 *newLayer = QStringLiteral(
"tracks" );
490 *newLayer = QStringLiteral(
"routes" );
497 const char *pszForceGPXRoute
498 = CSLFetchNameValue( options,
"FORCE_GPX_ROUTE" );
499 if ( pszForceGPXRoute && CPLTestBool( pszForceGPXRoute ) )
500 *newLayer = QStringLiteral(
"routes" );
502 *newLayer = QStringLiteral(
"tracks" );
512 else if ( driverName == QLatin1String(
"DGN" ) )
514 mLayer = OGR_DS_GetLayerByName(
mDS.get(),
"elements" );
518 mLayer = OGR_DS_GetLayerByName(
mDS.get(), layerName.toUtf8().constData() );
523 for (
int i = 0; i < layerOptions.size(); i++ )
524 CPLFree( options[i] );
533 QString layerName = vectorFileName.left( vectorFileName.indexOf( QLatin1String(
".shp" ), Qt::CaseInsensitive ) );
534 QFile prjFile( layerName +
".qpj" );
535 if ( prjFile.exists() )
543 mErrorMessage = QObject::tr(
"Creation of layer failed (OGR error: %1)" )
544 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
546 mErrorMessage = QObject::tr(
"Opening of layer failed (OGR error: %1)" )
547 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
552 OGRFeatureDefnH defn = OGR_L_GetLayerDefn(
mLayer );
561 QSet<int> existingIdxs;
571 for (
int fldIdx = 0; fldIdx < fields.
count(); ++fldIdx )
575 if ( fieldValueConverter )
577 attrField = fieldValueConverter->fieldDefinition( fields.
at( fldIdx ) );
582 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( attrField.
name() ) );
591 switch ( fieldNameSource )
594 name = attrField.
name();
598 name = !attrField.
alias().isEmpty() ? attrField.
alias() : attrField.
name();
602 OGRFieldType ogrType = OFTString;
603 OGRFieldSubType ogrSubType = OFSTNone;
604 int ogrWidth = attrField.
length();
605 int ogrPrecision = attrField.
precision();
606 if ( ogrPrecision > 0 )
609 switch ( attrField.
type() )
611 case QVariant::LongLong:
613 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
614 if ( pszDataTypes && strstr( pszDataTypes,
"Integer64" ) )
615 ogrType = OFTInteger64;
618 ogrWidth = ogrWidth > 0 && ogrWidth <= 20 ? ogrWidth : 20;
622 case QVariant::String:
624 if ( ( ogrWidth <= 0 || ogrWidth > 255 ) &&
mOgrDriverName == QLatin1String(
"ESRI Shapefile" ) )
629 ogrType = OFTInteger;
630 ogrWidth = ogrWidth > 0 && ogrWidth <= 10 ? ogrWidth : 10;
635 ogrType = OFTInteger;
636 ogrSubType = OFSTBoolean;
641 case QVariant::Double:
642#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,3,1)
643 if (
mOgrDriverName == QLatin1String(
"GPKG" ) && attrField.
precision() == 0 && attrField.
name().compare( fidFieldName, Qt::CaseInsensitive ) == 0 )
646 ogrType = OFTInteger64;
669 case QVariant::DateTime:
677 ogrType = OFTDateTime;
681 case QVariant::ByteArray:
685 case QVariant::StringList:
691 ogrSubType = OFSTJSON;
695 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
696 if ( pszDataTypes && strstr( pszDataTypes,
"StringList" ) )
698 ogrType = OFTStringList;
699 mSupportedListSubTypes.insert( QVariant::String );
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;
914class 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" ),
1080 datasetOptions.clear();
1081 layerOptions.clear();
1083 driverMetadata.insert( QStringLiteral(
"FlatGeobuf" ),
1085 QStringLiteral(
"FlatGeobuf" ),
1086 QObject::tr(
"FlatGeobuf" ),
1087 QStringLiteral(
"*.fgb" ),
1088 QStringLiteral(
"fgb" ),
1091 QStringLiteral(
"UTF-8" )
1096 datasetOptions.clear();
1097 layerOptions.clear();
1100 QObject::tr(
"Override the type of shapefile created. "
1101 "Can be one of NULL for a simple .dbf file with no .shp file, POINT, "
1102 "ARC, POLYGON or MULTIPOINT for 2D, or POINTZ, ARCZ, POLYGONZ or "
1103 "MULTIPOINTZ for 3D;" ) +
1104 QObject::tr(
" POINTM, ARCM, POLYGONM or MULTIPOINTM for measured geometries"
1105 " and POINTZM, ARCZM, POLYGONZM or MULTIPOINTZM for 3D measured"
1107 QObject::tr(
" MULTIPATCH files are supported since GDAL 2.2." ) +
1110 << QStringLiteral(
"NULL" )
1111 << QStringLiteral(
"POINT" )
1112 << QStringLiteral(
"ARC" )
1113 << QStringLiteral(
"POLYGON" )
1114 << QStringLiteral(
"MULTIPOINT" )
1115 << QStringLiteral(
"POINTZ" )
1116 << QStringLiteral(
"ARCZ" )
1117 << QStringLiteral(
"POLYGONZ" )
1118 << QStringLiteral(
"MULTIPOINTZ" )
1119 << QStringLiteral(
"POINTM" )
1120 << QStringLiteral(
"ARCM" )
1121 << QStringLiteral(
"POLYGONM" )
1122 << QStringLiteral(
"MULTIPOINTM" )
1123 << QStringLiteral(
"POINTZM" )
1124 << QStringLiteral(
"ARCZM" )
1125 << QStringLiteral(
"POLYGONZM" )
1126 << QStringLiteral(
"MULTIPOINTZM" )
1127 << QStringLiteral(
"MULTIPATCH" )
1137 QObject::tr(
"Set the encoding value in the DBF file. "
1138 "The default value is LDID/87. It is not clear "
1139 "what other values may be appropriate." ),
1147 QObject::tr(
"Set to YES to resize fields to their optimal size." ),
1151 driverMetadata.insert( QStringLiteral(
"ESRI" ),
1153 QStringLiteral(
"ESRI Shapefile" ),
1154 QObject::tr(
"ESRI Shapefile" ),
1155 QStringLiteral(
"*.shp" ),
1156 QStringLiteral(
"shp" ),
1163 datasetOptions.clear();
1164 layerOptions.clear();
1166 driverMetadata.insert( QStringLiteral(
"DBF File" ),
1168 QStringLiteral(
"DBF File" ),
1169 QObject::tr(
"DBF File" ),
1170 QStringLiteral(
"*.dbf" ),
1171 QStringLiteral(
"dbf" ),
1178 datasetOptions.clear();
1179 layerOptions.clear();
1181 driverMetadata.insert( QStringLiteral(
"FMEObjects Gateway" ),
1183 QStringLiteral(
"FMEObjects Gateway" ),
1184 QObject::tr(
"FMEObjects Gateway" ),
1185 QStringLiteral(
"*.fdd" ),
1186 QStringLiteral(
"fdd" ),
1193 datasetOptions.clear();
1194 layerOptions.clear();
1197 QObject::tr(
"Set to YES to write a bbox property with the bounding box "
1198 "of the geometries at the feature and feature collection level." ),
1203 QObject::tr(
"Maximum number of figures after decimal separator to write in coordinates. "
1204 "Defaults to 15. Truncation will occur to remove trailing zeros." ),
1209 QObject::tr(
"Whether to use RFC 7946 standard. "
1210 "If disabled GeoJSON 2008 initial version will be used. "
1211 "Default is NO (thus GeoJSON 2008). See also Documentation (via Help button)" ),
1215 driverMetadata.insert( QStringLiteral(
"GeoJSON" ),
1217 QStringLiteral(
"GeoJSON" ),
1218 QObject::tr(
"GeoJSON" ),
1219 QStringLiteral(
"*.geojson" ),
1220 QStringLiteral(
"geojson" ),
1223 QStringLiteral(
"UTF-8" )
1228 datasetOptions.clear();
1229 layerOptions.clear();
1232 QObject::tr(
"Maximum number of figures after decimal separator to write in coordinates. "
1233 "Defaults to 15. Truncation will occur to remove trailing zeros." ),
1238 QObject::tr(
"Whether to start records with the RS=0x1E character (RFC 8142 standard). "
1239 "Defaults to NO: Newline Delimited JSON (geojsonl). \n"
1240 "If set to YES: RFC 8142 standard: GeoJSON Text Sequences (geojsons)." ),
1244 driverMetadata.insert( QStringLiteral(
"GeoJSONSeq" ),
1246 QStringLiteral(
"GeoJSON - Newline Delimited" ),
1247 QObject::tr(
"GeoJSON - Newline Delimited" ),
1248 QStringLiteral(
"*.geojsonl *.geojsons *.json" ),
1249 QStringLiteral(
"json" ),
1252 QStringLiteral(
"UTF-8" )
1257 datasetOptions.clear();
1258 layerOptions.clear();
1261 QObject::tr(
"whether the document must be in RSS 2.0 or Atom 1.0 format. "
1262 "Default value : RSS" ),
1264 << QStringLiteral(
"RSS" )
1265 << QStringLiteral(
"ATOM" ),
1266 QStringLiteral(
"RSS" )
1270 QObject::tr(
"The encoding of location information. Default value : SIMPLE. "
1271 "W3C_GEO only supports point geometries. "
1272 "SIMPLE or W3C_GEO only support geometries in geographic WGS84 coordinates." ),
1274 << QStringLiteral(
"SIMPLE" )
1275 << QStringLiteral(
"GML" )
1276 << QStringLiteral(
"W3C_GEO" ),
1277 QStringLiteral(
"SIMPLE" )
1281 QObject::tr(
"If defined to YES, extension fields will be written. "
1282 "If the field name not found in the base schema matches "
1283 "the foo_bar pattern, foo will be considered as the namespace "
1284 "of the element, and a <foo:bar> element will be written. "
1285 "Otherwise, elements will be written in the <ogr:> namespace." ),
1290 QObject::tr(
"If defined to NO, only <entry> or <item> elements will be written. "
1291 "The user will have to provide the appropriate header and footer of the document." ),
1296 QObject::tr(
"XML content that will be put between the <channel> element and the "
1297 "first <item> element for a RSS document, or between the xml tag and "
1298 "the first <entry> element for an Atom document." ),
1303 QObject::tr(
"Value put inside the <title> element in the header. "
1304 "If not provided, a dummy value will be used as that element is compulsory." ),
1309 QObject::tr(
"Value put inside the <description> element in the header. "
1310 "If not provided, a dummy value will be used as that element is compulsory." ),
1315 QObject::tr(
"Value put inside the <link> element in the header. "
1316 "If not provided, a dummy value will be used as that element is compulsory." ),
1321 QObject::tr(
"Value put inside the <updated> element in the header. "
1322 "Should be formatted as a XML datetime. "
1323 "If not provided, a dummy value will be used as that element is compulsory." ),
1328 QObject::tr(
"Value put inside the <author><name> element in the header. "
1329 "If not provided, a dummy value will be used as that element is compulsory." ),
1334 QObject::tr(
"Value put inside the <id> element in the header. "
1335 "If not provided, a dummy value will be used as that element is compulsory." ),
1339 driverMetadata.insert( QStringLiteral(
"GeoRSS" ),
1341 QStringLiteral(
"GeoRSS" ),
1342 QObject::tr(
"GeoRSS" ),
1343 QStringLiteral(
"*.xml" ),
1344 QStringLiteral(
"xml" ),
1347 QStringLiteral(
"UTF-8" )
1352 datasetOptions.clear();
1353 layerOptions.clear();
1356 QObject::tr(
"If provided, this URI will be inserted as the schema location. "
1357 "Note that the schema file isn't actually accessed by OGR, so it "
1358 "is up to the user to ensure it will match the schema of the OGR "
1359 "produced GML data file." ),
1364 QObject::tr(
"This writes a GML application schema file to a corresponding "
1365 ".xsd file (with the same basename). If INTERNAL is used the "
1366 "schema is written within the GML file, but this is experimental "
1367 "and almost certainly not valid XML. "
1368 "OFF disables schema generation (and is implicit if XSISCHEMAURI is used)." ),
1370 << QStringLiteral(
"EXTERNAL" )
1371 << QStringLiteral(
"INTERNAL" )
1372 << QStringLiteral(
"OFF" ),
1373 QStringLiteral(
"EXTERNAL" )
1377 QObject::tr(
"This is the prefix for the application target namespace." ),
1378 QStringLiteral(
"ogr" )
1382 QObject::tr(
"Can be set to TRUE to avoid writing the prefix of the "
1383 "application target namespace in the GML file." ),
1388 QObject::tr(
"Defaults to 'http://ogr.maptools.org/'. "
1389 "This is the application target namespace." ),
1390 QStringLiteral(
"http://ogr.maptools.org/" )
1394 QObject::tr(
"If not specified, GML2 will be used." ),
1396 << QStringLiteral(
"GML3" )
1397 << QStringLiteral(
"GML3Deegree" )
1398 << QStringLiteral(
"GML3.2" ),
1404 QObject::tr(
"Only valid when FORMAT=GML3/GML3Degree/GML3.2. Default to YES. "
1405 "If YES, SRS with EPSG authority will be written with the "
1406 "'urn:ogc:def:crs:EPSG::' prefix. In the case the SRS is a "
1407 "geographic SRS without explicit AXIS order, but that the same "
1408 "SRS authority code imported with ImportFromEPSGA() should be "
1409 "treated as lat/long, then the function will take care of coordinate "
1410 "order swapping. If set to NO, SRS with EPSG authority will be "
1411 "written with the 'EPSG:' prefix, even if they are in lat/long order." ),
1416 QObject::tr(
"only valid when FORMAT=GML3/GML3Degree/GML3.2) Default to YES. "
1417 "If set to NO, the <gml:boundedBy> element will not be written for "
1423 QObject::tr(
"Default to YES. If YES, the output will be indented with spaces "
1424 "for more readability, but at the expense of file size." ),
1429 driverMetadata.insert( QStringLiteral(
"GML" ),
1431 QStringLiteral(
"Geography Markup Language [GML]" ),
1432 QObject::tr(
"Geography Markup Language [GML]" ),
1433 QStringLiteral(
"*.gml" ),
1434 QStringLiteral(
"gml" ),
1437 QStringLiteral(
"UTF-8" )
1442 datasetOptions.clear();
1443 layerOptions.clear();
1446 QObject::tr(
"Human-readable identifier (e.g. short name) for the layer content" ),
1451 QObject::tr(
"Human-readable description for the layer content" ),
1456 QObject::tr(
"Name for the feature identifier column" ),
1457 QStringLiteral(
"fid" )
1461 QObject::tr(
"Name for the geometry column" ),
1462 QStringLiteral(
"geom" )
1466 QObject::tr(
"If a spatial index must be created." ),
1470 driverMetadata.insert( QStringLiteral(
"GPKG" ),
1472 QStringLiteral(
"GeoPackage" ),
1473 QObject::tr(
"GeoPackage" ),
1474 QStringLiteral(
"*.gpkg" ),
1475 QStringLiteral(
"gpkg" ),
1478 QStringLiteral(
"UTF-8" )
1483 datasetOptions.clear();
1484 layerOptions.clear();
1486 driverMetadata.insert( QStringLiteral(
"GMT" ),
1488 QStringLiteral(
"Generic Mapping Tools [GMT]" ),
1489 QObject::tr(
"Generic Mapping Tools [GMT]" ),
1490 QStringLiteral(
"*.gmt" ),
1491 QStringLiteral(
"gmt" ),
1498 datasetOptions.clear();
1499 layerOptions.clear();
1502 QObject::tr(
"By default when writing a layer whose features are of "
1503 "type wkbLineString, the GPX driver chooses to write "
1504 "them as routes. If FORCE_GPX_TRACK=YES is specified, "
1505 "they will be written as tracks." ),
1510 QObject::tr(
"By default when writing a layer whose features are of "
1511 "type wkbMultiLineString, the GPX driver chooses to write "
1512 "them as tracks. If FORCE_GPX_ROUTE=YES is specified, "
1513 "they will be written as routes, provided that the multilines "
1514 "are composed of only one single line." ),
1519 QObject::tr(
"If GPX_USE_EXTENSIONS=YES is specified, "
1520 "extra fields will be written inside the <extensions> tag." ),
1525 QObject::tr(
"Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS_URL "
1526 "is set. The namespace value used for extension tags. By default, 'ogr'." ),
1527 QStringLiteral(
"ogr" )
1531 QObject::tr(
"Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS "
1532 "is set. The namespace URI. By default, 'http://osgeo.org/gdal'." ),
1533 QStringLiteral(
"http://osgeo.org/gdal" )
1537 QObject::tr(
"By default files are created with the line termination "
1538 "conventions of the local platform (CR/LF on win32 or LF "
1539 "on all other systems). This may be overridden through use "
1540 "of the LINEFORMAT layer creation option which may have a value "
1541 "of CRLF (DOS format) or LF (Unix format)." ),
1543 << QStringLiteral(
"CRLF" )
1544 << QStringLiteral(
"LF" ),
1549 driverMetadata.insert( QStringLiteral(
"GPX" ),
1551 QStringLiteral(
"GPS eXchange Format [GPX]" ),
1552 QObject::tr(
"GPS eXchange Format [GPX]" ),
1553 QStringLiteral(
"*.gpx" ),
1554 QStringLiteral(
"gpx" ),
1557 QStringLiteral(
"UTF-8" )
1562 datasetOptions.clear();
1563 layerOptions.clear();
1565 driverMetadata.insert( QStringLiteral(
"Interlis 1" ),
1567 QStringLiteral(
"INTERLIS 1" ),
1568 QObject::tr(
"INTERLIS 1" ),
1569 QStringLiteral(
"*.itf *.xml *.ili" ),
1570 QStringLiteral(
"ili" ),
1577 datasetOptions.clear();
1578 layerOptions.clear();
1580 driverMetadata.insert( QStringLiteral(
"Interlis 2" ),
1582 QStringLiteral(
"INTERLIS 2" ),
1583 QObject::tr(
"INTERLIS 2" ),
1584 QStringLiteral(
"*.xtf *.xml *.ili" ),
1585 QStringLiteral(
"ili" ),
1592 datasetOptions.clear();
1593 layerOptions.clear();
1596 QObject::tr(
"Allows you to specify the field to use for the KML <name> element." ),
1597 QStringLiteral(
"Name" )
1601 QObject::tr(
"Allows you to specify the field to use for the KML <description> element." ),
1602 QStringLiteral(
"Description" )
1606 QObject::tr(
"Allows you to specify the AltitudeMode to use for KML geometries. "
1607 "This will only affect 3D geometries and must be one of the valid KML options." ),
1609 << QStringLiteral(
"clampToGround" )
1610 << QStringLiteral(
"relativeToGround" )
1611 << QStringLiteral(
"absolute" ),
1612 QStringLiteral(
"relativeToGround" )
1616 QObject::tr(
"The DOCUMENT_ID datasource creation option can be used to specified "
1617 "the id of the root <Document> node. The default value is root_doc." ),
1618 QStringLiteral(
"root_doc" )
1621 driverMetadata.insert( QStringLiteral(
"KML" ),
1623 QStringLiteral(
"Keyhole Markup Language [KML]" ),
1624 QObject::tr(
"Keyhole Markup Language [KML]" ),
1625 QStringLiteral(
"*.kml" ),
1626 QStringLiteral(
"kml" ),
1629 QStringLiteral(
"UTF-8" )
1634 datasetOptions.clear();
1635 layerOptions.clear();
1637 auto insertMapInfoOptions = []( QMap<QString, QgsVectorFileWriter::Option *> &datasetOptions, QMap<QString, QgsVectorFileWriter::Option *> &layerOptions )
1640 QObject::tr(
"Use this to turn on 'quick spatial index mode'. "
1641 "In this mode writing files can be about 5 times faster, "
1642 "but spatial queries can be up to 30 times slower." ),
1644 << QStringLiteral(
"QUICK" )
1645 << QStringLiteral(
"OPTIMIZED" ),
1646 QStringLiteral(
"QUICK" ),
1651 QObject::tr(
"(multiples of 512): Block size for .map files. Defaults "
1652 "to 512. MapInfo 15.2 and above creates .tab files with a "
1653 "blocksize of 16384 bytes. Any MapInfo version should be "
1654 "able to handle block sizes from 512 to 32256." ),
1658 QObject::tr(
"xmin,ymin,xmax,ymax: Define custom layer bounds to increase the "
1659 "accuracy of the coordinates. Note: the geometry of written "
1660 "features must be within the defined box." ),
1664 insertMapInfoOptions( datasetOptions, layerOptions );
1666 driverMetadata.insert( QStringLiteral(
"MapInfo File" ),
1668 QStringLiteral(
"Mapinfo" ),
1669 QObject::tr(
"Mapinfo TAB" ),
1670 QStringLiteral(
"*.tab" ),
1671 QStringLiteral(
"tab" ),
1676 datasetOptions.clear();
1677 layerOptions.clear();
1678 insertMapInfoOptions( datasetOptions, layerOptions );
1681 driverMetadata.insert( QStringLiteral(
"MapInfo MIF" ),
1683 QStringLiteral(
"Mapinfo" ),
1684 QObject::tr(
"Mapinfo MIF" ),
1685 QStringLiteral(
"*.mif" ),
1686 QStringLiteral(
"mif" ),
1693 datasetOptions.clear();
1694 layerOptions.clear();
1697 QObject::tr(
"Determine whether 2D (seed_2d.dgn) or 3D (seed_3d.dgn) "
1698 "seed file should be used. This option is ignored if the SEED option is provided." ),
1703 QObject::tr(
"Override the seed file to use." ),
1708 QObject::tr(
"Indicate whether the whole seed file should be copied. "
1709 "If not, only the first three elements will be copied." ),
1714 QObject::tr(
"Indicates whether the color table should be copied from the seed file." ),
1719 QObject::tr(
"Override the master unit name from the seed file with "
1720 "the provided one or two character unit name." ),
1725 QObject::tr(
"Override the sub unit name from the seed file with the provided "
1726 "one or two character unit name." ),
1731 QObject::tr(
"Override the number of subunits per master unit. "
1732 "By default the seed file value is used." ),
1737 QObject::tr(
"Override the number of UORs (Units of Resolution) "
1738 "per sub unit. By default the seed file value is used." ),
1743 QObject::tr(
"ORIGIN=x,y,z: Override the origin of the design plane. "
1744 "By default the origin from the seed file is used." ),
1748 driverMetadata.insert( QStringLiteral(
"DGN" ),
1750 QStringLiteral(
"Microstation DGN" ),
1751 QObject::tr(
"Microstation DGN" ),
1752 QStringLiteral(
"*.dgn" ),
1753 QStringLiteral(
"dgn" ),
1760 datasetOptions.clear();
1761 layerOptions.clear();
1764 QObject::tr(
"Should update files be incorporated into the base data on the fly." ),
1766 << QStringLiteral(
"APPLY" )
1767 << QStringLiteral(
"IGNORE" ),
1768 QStringLiteral(
"APPLY" )
1772 QObject::tr(
"Should multipoint soundings be split into many single point sounding features. "
1773 "Multipoint geometries are not well handled by many formats, "
1774 "so it can be convenient to split single sounding features with many points "
1775 "into many single point features." ),
1780 QObject::tr(
"Should a DEPTH attribute be added on SOUNDG features and assign the depth "
1781 "of the sounding. This should only be enabled when SPLIT_MULTIPOINT is "
1787 QObject::tr(
"Should all the low level geometry primitives be returned as special "
1788 "IsolatedNode, ConnectedNode, Edge and Face layers." ),
1793 QObject::tr(
"If enabled, numeric attributes assigned an empty string as a value will "
1794 "be preserved as a special numeric value. This option should not generally "
1795 "be needed, but may be useful when translated S-57 to S-57 losslessly." ),
1800 QObject::tr(
"Should LNAM and LNAM_REFS fields be attached to features capturing "
1801 "the feature to feature relationships in the FFPT group of the S-57 file." ),
1806 QObject::tr(
"Should additional attributes relating features to their underlying "
1807 "geometric primitives be attached. These are the values of the FSPT group, "
1808 "and are primarily needed when doing S-57 to S-57 translations." ),
1813 QObject::tr(
"Should attribute values be recoded to UTF-8 from the character encoding "
1814 "specified in the S57 DSSI record." ),
1820 driverMetadata.insert( QStringLiteral(
"S57" ),
1822 QStringLiteral(
"S-57 Base file" ),
1823 QObject::tr(
"S-57 Base file" ),
1824 QStringLiteral(
"*.000" ),
1825 QStringLiteral(
"000" ),
1832 datasetOptions.clear();
1833 layerOptions.clear();
1835 driverMetadata.insert( QStringLiteral(
"SDTS" ),
1837 QStringLiteral(
"Spatial Data Transfer Standard [SDTS]" ),
1838 QObject::tr(
"Spatial Data Transfer Standard [SDTS]" ),
1839 QStringLiteral(
"*catd.ddf" ),
1840 QStringLiteral(
"ddf" ),
1847 datasetOptions.clear();
1848 layerOptions.clear();
1851 QObject::tr(
"Can be used to avoid creating the geometry_columns and spatial_ref_sys "
1852 "tables in a new database. By default these metadata tables are created "
1853 "when a new database is created." ),
1859 QStringLiteral(
"NO" )
1864 QStringLiteral(
"NO" )
1868 QObject::tr(
"Controls the format used for the geometry column. Defaults to WKB. "
1869 "This is generally more space and processing efficient, but harder "
1870 "to inspect or use in simple applications than WKT (Well Known Text)." ),
1872 << QStringLiteral(
"WKB" )
1873 << QStringLiteral(
"WKT" ),
1874 QStringLiteral(
"WKB" )
1878 QObject::tr(
"Controls whether layer and field names will be laundered for easier use "
1879 "in SQLite. Laundered names will be converted to lower case and some special "
1880 "characters(' - #) will be changed to underscores." ),
1885 QStringLiteral(
"NO" )
1889 QStringLiteral(
"NO" )
1897 QObject::tr(
"column_name1[,column_name2, …] A list of (String) columns that "
1898 "must be compressed with ZLib DEFLATE algorithm. This might be beneficial "
1899 "for databases that have big string blobs. However, use with care, since "
1900 "the value of such columns will be seen as compressed binary content with "
1901 "other SQLite utilities (or previous OGR versions). With OGR, when inserting, "
1902 "modifying or querying compressed columns, compression/decompression is "
1903 "done transparently. However, such columns cannot be (easily) queried with "
1904 "an attribute filter or WHERE clause. Note: in table definition, such columns "
1905 "have the 'VARCHAR_deflate' declaration type." ),
1909 driverMetadata.insert( QStringLiteral(
"SQLite" ),
1911 QStringLiteral(
"SQLite" ),
1912 QObject::tr(
"SQLite" ),
1913 QStringLiteral(
"*.sqlite" ),
1914 QStringLiteral(
"sqlite" ),
1917 QStringLiteral(
"UTF-8" )
1922 datasetOptions.clear();
1923 layerOptions.clear();
1926 QObject::tr(
"Can be used to avoid creating the geometry_columns and spatial_ref_sys "
1927 "tables in a new database. By default these metadata tables are created "
1928 "when a new database is created." ),
1933 QStringLiteral(
"YES" )
1937 QObject::tr(
"Insert the content of the EPSG CSV files into the spatial_ref_sys table. "
1938 "Set to NO for regular SQLite databases." ),
1943 QStringLiteral(
"SPATIALITE" )
1947 QObject::tr(
"Controls whether layer and field names will be laundered for easier use "
1948 "in SQLite. Laundered names will be converted to lower case and some special "
1949 "characters(' - #) will be changed to underscores." ),
1954 QObject::tr(
"If the database is of the SpatiaLite flavor, and if OGR is linked "
1955 "against libspatialite, this option can be used to control if a spatial "
1956 "index must be created." ),
1961 QObject::tr(
"If the format of the geometry BLOB is of the SpatiaLite flavor, "
1962 "this option can be used to control if the compressed format for "
1963 "geometries (LINESTRINGs, POLYGONs) must be used." ),
1968 QObject::tr(
"Used to force the SRID number of the SRS associated with the layer. "
1969 "When this option isn't specified and that a SRS is associated with the "
1970 "layer, a search is made in the spatial_ref_sys to find a match for the "
1971 "SRS, and, if there is no match, a new entry is inserted for the SRS in "
1972 "the spatial_ref_sys table. When the SRID option is specified, this "
1973 "search (and the eventual insertion of a new entry) will not be done: "
1974 "the specified SRID is used as such." ),
1979 QObject::tr(
"column_name1[,column_name2, …] A list of (String) columns that "
1980 "must be compressed with ZLib DEFLATE algorithm. This might be beneficial "
1981 "for databases that have big string blobs. However, use with care, since "
1982 "the value of such columns will be seen as compressed binary content with "
1983 "other SQLite utilities (or previous OGR versions). With OGR, when inserting, "
1984 "modifying or queryings compressed columns, compression/decompression is "
1985 "done transparently. However, such columns cannot be (easily) queried with "
1986 "an attribute filter or WHERE clause. Note: in table definition, such columns "
1987 "have the 'VARCHAR_deflate' declaration type." ),
1991 driverMetadata.insert( QStringLiteral(
"SpatiaLite" ),
1993 QStringLiteral(
"SpatiaLite" ),
1994 QObject::tr(
"SpatiaLite" ),
1995 QStringLiteral(
"*.sqlite" ),
1996 QStringLiteral(
"sqlite" ),
1999 QStringLiteral(
"UTF-8" )
2003 datasetOptions.clear();
2004 layerOptions.clear();
2007 QObject::tr(
"Override the header file used - in place of header.dxf." ),
2012 QObject::tr(
"Override the trailer file used - in place of trailer.dxf." ),
2016 driverMetadata.insert( QStringLiteral(
"DXF" ),
2018 QStringLiteral(
"AutoCAD DXF" ),
2019 QObject::tr(
"AutoCAD DXF" ),
2020 QStringLiteral(
"*.dxf" ),
2021 QStringLiteral(
"dxf" ),
2028 datasetOptions.clear();
2029 layerOptions.clear();
2032 QObject::tr(
"Indicates the GeoConcept export file extension. "
2033 "TXT was used by earlier releases of GeoConcept. GXT is currently used." ),
2035 << QStringLiteral(
"GXT" )
2036 << QStringLiteral(
"TXT" ),
2037 QStringLiteral(
"GXT" )
2041 QObject::tr(
"Path to the GCT: the GCT file describes the GeoConcept types definitions: "
2042 "In this file, every line must start with //# followed by a keyword. "
2043 "Lines starting with // are comments." ),
2048 QObject::tr(
"Defines the feature to be created. The TYPE corresponds to one of the Name "
2049 "found in the GCT file for a type section. The SUBTYPE corresponds to one of "
2050 "the Name found in the GCT file for a sub-type section within the previous "
2055 driverMetadata.insert( QStringLiteral(
"Geoconcept" ),
2057 QStringLiteral(
"Geoconcept" ),
2058 QObject::tr(
"Geoconcept" ),
2059 QStringLiteral(
"*.gxt *.txt" ),
2060 QStringLiteral(
"gxt" ),
2067 datasetOptions.clear();
2068 layerOptions.clear();
2071 QObject::tr(
"When this option is set, the new layer will be created inside the named "
2072 "FeatureDataset folder. If the folder does not already exist, it will be created." ),
2077 QObject::tr(
"Set name of geometry column in new layer. Defaults to 'SHAPE'." ),
2078 QStringLiteral(
"SHAPE" )
2082 QObject::tr(
"Name of the OID column to create. Defaults to 'OBJECTID'." ),
2083 QStringLiteral(
"OBJECTID" )
2086 driverMetadata.insert( QStringLiteral(
"FileGDB" ),
2088 QStringLiteral(
"ESRI FileGDB" ),
2089 QObject::tr(
"ESRI FileGDB" ),
2090 QStringLiteral(
"*.gdb" ),
2091 QStringLiteral(
"gdb" ),
2094 QStringLiteral(
"UTF-8" )
2099 datasetOptions.clear();
2100 layerOptions.clear();
2103 QObject::tr(
"By default, the driver will try to detect the data type of fields. If set "
2104 "to STRING, all fields will be of String type." ),
2106 << QStringLiteral(
"AUTO" )
2107 << QStringLiteral(
"STRING" ),
2108 QStringLiteral(
"AUTO" ),
2113 QObject::tr(
"By default, the driver will read the first lines of each sheet to detect "
2114 "if the first line might be the name of columns. If set to FORCE, the driver "
2115 "will consider the first line as the header line. If set to "
2116 "DISABLE, it will be considered as the first feature. Otherwise "
2117 "auto-detection will occur." ),
2119 << QStringLiteral(
"FORCE" )
2120 << QStringLiteral(
"DISABLE" )
2121 << QStringLiteral(
"AUTO" ),
2122 QStringLiteral(
"AUTO" ),
2126 driverMetadata.insert( QStringLiteral(
"XLSX" ),
2128 QStringLiteral(
"MS Office Open XML spreadsheet" ),
2129 QObject::tr(
"MS Office Open XML spreadsheet [XLSX]" ),
2130 QStringLiteral(
"*.xlsx" ),
2131 QStringLiteral(
"xlsx" ),
2134 QStringLiteral(
"UTF-8" )
2139 datasetOptions.clear();
2140 layerOptions.clear();
2143 QObject::tr(
"By default, the driver will try to detect the data type of fields. If set "
2144 "to STRING, all fields will be of String type." ),
2146 << QStringLiteral(
"AUTO" )
2147 << QStringLiteral(
"STRING" ),
2148 QStringLiteral(
"AUTO" ),
2153 QObject::tr(
"By default, the driver will read the first lines of each sheet to detect "
2154 "if the first line might be the name of columns. If set to FORCE, the driver "
2155 "will consider the first line as the header line. If set to "
2156 "DISABLE, it will be considered as the first feature. Otherwise "
2157 "auto-detection will occur." ),
2159 << QStringLiteral(
"FORCE" )
2160 << QStringLiteral(
"DISABLE" )
2161 << QStringLiteral(
"AUTO" ),
2162 QStringLiteral(
"AUTO" ),
2166 driverMetadata.insert( QStringLiteral(
"ODS" ),
2168 QStringLiteral(
"Open Document Spreadsheet" ),
2169 QObject::tr(
"Open Document Spreadsheet [ODS]" ),
2170 QStringLiteral(
"*.ods" ),
2171 QStringLiteral(
"ods" ),
2174 QStringLiteral(
"UTF-8" )
2179 datasetOptions.clear();
2180 layerOptions.clear();
2183 QObject::tr(
"Line termination character sequence." ),
2185 << QStringLiteral(
"CRLF" )
2186 << QStringLiteral(
"LF" ),
2187 QStringLiteral(
"LF" ),
2193 QObject::tr(
"Format of geometry columns." ),
2195 << QStringLiteral(
"geometry" )
2196 << QStringLiteral(
"geography" ),
2197 QStringLiteral(
"geometry" ),
2202 QObject::tr(
"Controls whether layer and field names will be laundered for easier use. "
2203 "Laundered names will be converted to lower case and some special "
2204 "characters(' - #) will be changed to underscores." ),
2209 QObject::tr(
"Name for the geometry column. Defaults to wkb_geometry "
2210 "for GEOM_TYPE=geometry or the_geog for GEOM_TYPE=geography" ) ) );
2213 QObject::tr(
"Name of schema into which to create the new table" ) ) );
2216 QObject::tr(
"Whether to explicitly emit the CREATE SCHEMA statement to create the specified schema." ),
2221 QObject::tr(
"Whether to explicitly recreate the table if necessary." ),
2226 QObject::tr(
"Whether to explicitly destroy tables before recreating them." ),
2228 << QStringLiteral(
"YES" )
2229 << QStringLiteral(
"NO" )
2230 << QStringLiteral(
"IF_EXISTS" ),
2231 QStringLiteral(
"YES" ),
2236 QObject::tr(
"Used to force the SRID number of the SRS associated with the layer. "
2237 "When this option isn't specified and that a SRS is associated with the "
2238 "layer, a search is made in the spatial_ref_sys to find a match for the "
2239 "SRS, and, if there is no match, a new entry is inserted for the SRS in "
2240 "the spatial_ref_sys table. When the SRID option is specified, this "
2241 "search (and the eventual insertion of a new entry) will not be done: "
2242 "the specified SRID is used as such." ),
2247 QObject::tr(
"Can be set to 2.0 or 2.2 for PostGIS 2.0/2.2 compatibility. "
2248 "Important to set it correctly if using non-linear geometry types" ),
2249 QStringLiteral(
"2.2" )
2252 driverMetadata.insert( QStringLiteral(
"PGDUMP" ),
2254 QStringLiteral(
"PostgreSQL SQL dump" ),
2255 QObject::tr(
"PostgreSQL SQL dump" ),
2256 QStringLiteral(
"*.sql" ),
2257 QStringLiteral(
"sql" ),
2260 QStringLiteral(
"UTF-8" )
2266 QgsVectorFileWriterMetadataContainer(
const QgsVectorFileWriterMetadataContainer &other ) =
delete;
2267 QgsVectorFileWriterMetadataContainer &operator=(
const QgsVectorFileWriterMetadataContainer &other ) =
delete;
2268 ~QgsVectorFileWriterMetadataContainer()
2270 for (
auto it = driverMetadata.constBegin(); it != driverMetadata.constEnd(); ++it )
2272 for (
auto optionIt = it.value().driverOptions.constBegin(); optionIt != it.value().driverOptions.constEnd(); ++optionIt )
2273 delete optionIt.value();
2274 for (
auto optionIt = it.value().layerOptions.constBegin(); optionIt != it.value().layerOptions.constEnd(); ++optionIt )
2275 delete optionIt.value();
2279 QMap<QString, QgsVectorFileWriter::MetaData> driverMetadata;
2286 static QgsVectorFileWriterMetadataContainer sDriverMetadata;
2287 QMap<QString, MetaData>::ConstIterator it = sDriverMetadata.driverMetadata.constBegin();
2289 for ( ; it != sDriverMetadata.driverMetadata.constEnd(); ++it )
2291 if ( it.key() == QLatin1String(
"PGDUMP" ) &&
2292 driverName != QLatin1String(
"PGDUMP" ) &&
2293 driverName != QLatin1String(
"PostgreSQL SQL dump" ) )
2298 if ( it.key().startsWith( driverName ) || it.value().longName.startsWith( driverName ) )
2313 return QStringList();
2322 return QStringList();
2329 OGRwkbGeometryType ogrType =
static_cast<OGRwkbGeometryType
>( type );
2355 QgsFeatureList::iterator fIt = features.begin();
2357 for ( ; fIt != features.end(); ++fIt )
2382 QString styleString;
2383 QString currentStyle;
2385 QgsSymbolList::const_iterator symbolIt = symbols.constBegin();
2386 for ( ; symbolIt != symbols.constEnd(); ++symbolIt )
2388 int nSymbolLayers = ( *symbolIt )->symbolLayerCount();
2389 for (
int i = 0; i < nSymbolLayers; ++i )
2392 QMap< QgsSymbolLayer *, QString >::const_iterator it =
mSymbolLayerTable.find( ( *symbolIt )->symbolLayer( i ) );
2398 double mmsf = mmScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
2399 double musf = mapUnitScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
2401 currentStyle = ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf );
2405 if ( symbolIt != symbols.constBegin() || i != 0 )
2407 styleString.append(
';' );
2409 styleString.append( currentStyle );
2413 OGR_F_SetStyleString( poFeature.get(), currentStyle.toLocal8Bit().constData() );
2414 if ( !writeFeature(
mLayer, poFeature.get() ) )
2421 OGR_F_SetStyleString( poFeature.get(), styleString.toLocal8Bit().constData() );
2426 if ( !writeFeature(
mLayer, poFeature.get() ) )
2445 int fldIdx = it.key();
2446 int ogrField = it.value();
2448 QVariant attrValue = feature.
attribute( fldIdx );
2453 OGR_F_UnsetField( poFeature.get(), ogrField );
2466 OGR_F_SetFieldNull( poFeature.get(), ogrField );
2481 mErrorMessage = QObject::tr(
"Error converting value (%1) for attribute field %2: %3" )
2482 .arg( feature.
attribute( fldIdx ).toString(),
2492 OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
2494 case QVariant::LongLong:
2495 OGR_F_SetFieldInteger64( poFeature.get(), ogrField, attrValue.toLongLong() );
2497 case QVariant::Bool:
2498 OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
2500 case QVariant::String:
2501 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toString() ).constData() );
2503 case QVariant::Double:
2504 OGR_F_SetFieldDouble( poFeature.get(), ogrField, attrValue.toDouble() );
2506 case QVariant::Date:
2507 OGR_F_SetFieldDateTime( poFeature.get(), ogrField,
2508 attrValue.toDate().year(),
2509 attrValue.toDate().month(),
2510 attrValue.toDate().day(),
2513 case QVariant::DateTime:
2516 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toDateTime().toString( QStringLiteral(
"yyyy/MM/dd hh:mm:ss.zzz" ) ) ).constData() );
2520 OGR_F_SetFieldDateTime( poFeature.get(), ogrField,
2521 attrValue.toDateTime().date().year(),
2522 attrValue.toDateTime().date().month(),
2523 attrValue.toDateTime().date().day(),
2524 attrValue.toDateTime().time().hour(),
2525 attrValue.toDateTime().time().minute(),
2526 attrValue.toDateTime().time().second(),
2530 case QVariant::Time:
2533 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toString() ).constData() );
2537 OGR_F_SetFieldDateTime( poFeature.get(), ogrField,
2539 attrValue.toTime().hour(),
2540 attrValue.toTime().minute(),
2541 attrValue.toTime().second(),
2546 case QVariant::ByteArray:
2548 const QByteArray ba = attrValue.toByteArray();
2549 OGR_F_SetFieldBinary( poFeature.get(), ogrField, ba.size(),
const_cast< GByte *
>(
reinterpret_cast< const GByte *
>( ba.data() ) ) );
2553 case QVariant::Invalid:
2556 case QVariant::StringList:
2561 const QJsonDocument doc = QJsonDocument::fromVariant( attrValue );
2563 if ( !doc.isNull() )
2565 jsonString = QString::fromUtf8( doc.toJson( QJsonDocument::Compact ).constData() );
2567 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( jsonString.constData() ) );
2571 QStringList list = attrValue.toStringList();
2572 if ( mSupportedListSubTypes.contains( QVariant::String ) )
2574 int count = list.count();
2575 char **lst =
new char *[count + 1];
2579 for (
const QString &
string : list )
2581 lst[pos] = CPLStrdup(
mCodec->fromUnicode(
string ).data() );
2585 lst[count] =
nullptr;
2586 OGR_F_SetFieldStringList( poFeature.get(), ogrField, lst );
2591 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( list.join(
',' ) ).constData() );
2596 case QVariant::List:
2600 const QJsonDocument doc = QJsonDocument::fromVariant( attrValue );
2602 if ( !doc.isNull() )
2604 jsonString = QString::fromUtf8( doc.toJson( QJsonDocument::Compact ).data() );
2606 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( jsonString.constData() ) );
2613 QStringList list = attrValue.toStringList();
2614 if ( mSupportedListSubTypes.contains( QVariant::String ) )
2616 int count = list.count();
2617 char **lst =
new char *[count + 1];
2621 for (
const QString &
string : list )
2623 lst[pos] = CPLStrdup(
mCodec->fromUnicode(
string ).data() );
2627 lst[count] =
nullptr;
2628 OGR_F_SetFieldStringList( poFeature.get(), ogrField, lst );
2633 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( list.join(
',' ) ).constData() );
2639 const QVariantList list = attrValue.toList();
2640 if ( mSupportedListSubTypes.contains( QVariant::Int ) )
2642 const int count = list.count();
2643 int *lst =
new int[count];
2647 for (
const QVariant &value : list )
2649 lst[pos] = value.toInt();
2653 OGR_F_SetFieldIntegerList( poFeature.get(), ogrField, count, lst );
2658 QStringList strings;
2659 strings.reserve( list.size() );
2660 for (
const QVariant &value : list )
2662 strings << QString::number( value.toInt() );
2664 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
2670 const QVariantList list = attrValue.toList();
2671 if ( mSupportedListSubTypes.contains( QVariant::Double ) )
2673 const int count = list.count();
2674 double *lst =
new double[count];
2678 for (
const QVariant &value : list )
2680 lst[pos] = value.toDouble();
2684 OGR_F_SetFieldDoubleList( poFeature.get(), ogrField, count, lst );
2689 QStringList strings;
2690 strings.reserve( list.size() );
2691 for (
const QVariant &value : list )
2693 strings << QString::number( value.toDouble() );
2695 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
2701 const QVariantList list = attrValue.toList();
2702 if ( mSupportedListSubTypes.contains( QVariant::LongLong ) )
2704 const int count = list.count();
2705 long long *lst =
new long long[count];
2709 for (
const QVariant &value : list )
2711 lst[pos] = value.toLongLong();
2715 OGR_F_SetFieldInteger64List( poFeature.get(), ogrField, count, lst );
2720 QStringList strings;
2721 strings.reserve( list.size() );
2722 for (
const QVariant &value : list )
2724 strings << QString::number( value.toLongLong() );
2726 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
2734 mErrorMessage = QObject::tr(
"Invalid variant type for field %1[%2]: received %3 with type %4" )
2737 .arg( attrValue.typeName(),
2738 attrValue.toString() );
2751 if ( mCoordinateTransform )
2756 geom.
transform( *mCoordinateTransform );
2774 OGRGeometryH mGeom2 =
nullptr;
2820 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
2821 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
2827 QByteArray wkb( geom.
asWkb() );
2828 OGRErr err = OGR_G_ImportFromWkb( mGeom2,
reinterpret_cast<unsigned char *
>(
const_cast<char *
>( wkb.constData() ) ), wkb.length() );
2829 if ( err != OGRERR_NONE )
2831 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
2832 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
2839 OGR_F_SetGeometryDirectly( poFeature.get(), mGeom2 );
2845 OGRErr err = OGR_G_ImportFromWkb( ogrGeom,
reinterpret_cast<unsigned char *
>(
const_cast<char *
>( wkb.constData() ) ), wkb.length() );
2846 if ( err != OGRERR_NONE )
2848 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
2849 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
2856 OGR_F_SetGeometryDirectly( poFeature.get(), ogrGeom );
2871 for (
int i = 0; i < attributes.size(); i++ )
2873 if ( omap.find( i ) != omap.end() )
2878bool QgsVectorFileWriter::writeFeature( OGRLayerH layer, OGRFeatureH feature )
2880 if ( OGR_L_CreateFeature( layer, feature ) != OGRERR_NONE )
2882 mErrorMessage = QObject::tr(
"Feature creation error (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
2892 if ( mUsingTransaction )
2894 if ( OGRERR_NONE != OGR_L_CommitTransaction(
mLayer ) )
2896 QgsDebugMsg( QStringLiteral(
"Error while committing transaction on OGRLayer." ) );
2909 const QString &fileName,
2910 const QString &fileEncoding,
2912 const QString &driverName,
2914 QString *errorMessage,
2915 const QStringList &datasourceOptions,
2916 const QStringList &layerOptions,
2917 bool skipAttributeCreation,
2918 QString *newFilename,
2920 double symbologyScale,
2930 if ( destCRS.
isValid() && layer )
2956 const QString &fileName,
2957 const QString &fileEncoding,
2959 const QString &driverName,
2961 QString *errorMessage,
2962 const QStringList &datasourceOptions,
2963 const QStringList &layerOptions,
2964 bool skipAttributeCreation,
2965 QString *newFilename,
2967 double symbologyScale,
2998 : driverName( QStringLiteral(
"GPKG" ) )
3006 if ( !layer || !layer->
isValid() )
3013 details.sourceCrs = layer->
crs();
3014 details.sourceWkbType = layer->
wkbType();
3015 details.sourceFields = layer->
fields();
3024 if ( details.storageType == QLatin1String(
"ESRI Shapefile" ) )
3032 details.geometryTypeScanIterator = layer->
getFeatures( req );
3036 details.renderContext.setExpressionContext( details.expressionContext );
3037 details.renderContext.setRendererScale( options.
symbologyScale );
3039 details.shallTransform =
false;
3044 details.shallTransform =
true;
3049 details.outputCrs = details.sourceCrs;
3052 details.destWkbType = details.sourceWkbType;
3066 details.attributes.clear();
3067 else if ( details.attributes.isEmpty() )
3069 const QgsAttributeList allAttributes = details.sourceFields.allAttributesList();
3070 for (
int idx : allAttributes )
3072 QgsField fld = details.sourceFields.at( idx );
3073 if ( details.providerType == QLatin1String(
"oracle" ) && fld.
typeName().contains( QLatin1String(
"SDO_GEOMETRY" ) ) )
3075 details.attributes.append( idx );
3079 if ( !details.attributes.isEmpty() )
3081 for (
int attrIdx : std::as_const( details.attributes ) )
3083 if ( details.sourceFields.exists( attrIdx ) )
3087 details.outputFields.append(
field );
3091 QgsDebugMsg( QStringLiteral(
"No such source field with index '%1' available." ).arg( attrIdx ) );
3098 if ( details.providerType == QLatin1String(
"spatialite" ) )
3100 for (
int i = 0; i < details.outputFields.size(); i++ )
3102 if ( details.outputFields.at( i ).type() == QVariant::LongLong )
3107 if ( std::max( std::llabs( min.toLongLong() ), std::llabs( max.toLongLong() ) ) < std::numeric_limits<int>::max() )
3109 details.outputFields[i].setType( QVariant::Int );
3117 addRendererAttributes( details.renderer.get(), details.renderContext, details.sourceFields, details.attributes );
3127 bool useFilterRect =
true;
3128 if ( details.shallTransform )
3135 filterRect = extentTransform.
transformBoundingBox( filterRect, Qgis::TransformDirection::Reverse );
3139 useFilterRect =
false;
3142 if ( useFilterRect )
3148 details.filterRectEngine->prepareGeometry();
3150 details.sourceFeatureIterator = layer->
getFeatures( req );
3164 int lastProgressReport = 0;
3165 long long total = details.featureCount;
3168 if ( details.providerType == QLatin1String(
"ogr" ) && !details.dataSourceUri.isEmpty() )
3170 QString srcFileName( details.providerUriParams.value( QStringLiteral(
"path" ) ).toString() );
3171 if ( QFile::exists( srcFileName ) && QFileInfo( fileName ).canonicalFilePath() == QFileInfo( srcFileName ).canonicalFilePath() )
3175 if ( !( ( options.
driverName == QLatin1String(
"GPKG" ) ||
3176 options.
driverName == QLatin1String(
"SpatiaLite" ) ||
3177 options.
driverName == QLatin1String(
"SQLite" ) ) &&
3178 options.
layerName != details.providerUriParams.value( QStringLiteral(
"layerName" ) ) ) )
3181 *
errorMessage = QObject::tr(
"Cannot overwrite a OGR layer in place" );
3201 int newProgress =
static_cast<int>( ( 5.0 * scanned ) / total );
3202 if ( newProgress != lastProgressReport )
3204 lastProgressReport = newProgress;
3219 QString tempNewFilename;
3220 QString tempNewLayer;
3222 std::unique_ptr< QgsVectorFileWriter > writer(
create( fileName, details.outputFields, destWkbType, details.outputCrs, transformContext, options, QgsFeatureSink::SinkFlags(), &tempNewFilename, &tempNewLayer ) );
3226 *newFilename = tempNewFilename;
3229 *newLayer = tempNewLayer;
3269 int n = 0, errors = 0;
3278 writer->startRender( details.renderer.get(), details.sourceFields );
3280 writer->resetMap( details.attributes );
3282 writer->mFields = details.sourceFields;
3286 int initialProgress = lastProgressReport;
3287 while ( details.sourceFeatureIterator.nextFeature( fet ) )
3298 int newProgress =
static_cast<int>( initialProgress + ( ( 100.0 - initialProgress ) * saved ) / total );
3299 if ( newProgress < 100 && newProgress != lastProgressReport )
3301 lastProgressReport = newProgress;
3306 if ( details.shallTransform )
3319 QString msg = QObject::tr(
"Failed to transform a point while drawing a feature with ID '%1'. Writing stopped. (Exception: %2)" )
3320 .arg( fet.
id() ).arg( e.
what() );
3337 if ( !writer->addFeatureWithStyle( fet, writer->mRenderer.get(), mapUnits ) )
3344 *
errorMessage = QObject::tr(
"Feature write errors:" );
3350 if ( errors > 1000 )
3354 *
errorMessage += QObject::tr(
"Stopping after %n error(s)",
nullptr, errors );
3364 writer->stopRender();
3368 *
errorMessage += QObject::tr(
"\nOnly %1 of %2 features written." ).arg( n - errors ).arg( n );
3373 bool metadataFailure =
false;
3378 {QStringLiteral(
"path" ), tempNewFilename },
3379 {QStringLiteral(
"layerName" ), tempNewLayer }
3393 metadataFailure =
true;
3404 metadataFailure =
true;
3412 const QString &fileName,
3414 QString *newFilename,
3418 QgsVectorFileWriter::PreparedWriterDetails details;
3419 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
3427 const QString &fileName,
3430 QString *newFilename,
3434 QgsVectorFileWriter::PreparedWriterDetails details;
3435 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
3444 QgsVectorFileWriter::PreparedWriterDetails details;
3445 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
3454 QFileInfo fi( fileName );
3455 QDir dir = fi.dir();
3458 for (
const char *suffix : {
".shp",
".shx",
".dbf",
".prj",
".qix",
".qpj",
".cpg",
".sbn",
".sbx",
".idm",
".ind" } )
3460 filter << fi.completeBaseName() + suffix;
3464 const auto constEntryList = dir.entryList( filter );
3465 for (
const QString &file : constEntryList )
3467 QFile f( dir.canonicalPath() +
'/' + file );
3470 QgsDebugMsg( QStringLiteral(
"Removing file %1 failed: %2" ).arg( file, f.errorString() ) );
3486 static QReadWriteLock sFilterLock;
3487 static QMap< VectorFormatOptions, QList< QgsVectorFileWriter::FilterFormatDetails > > sFilters;
3491 const auto it = sFilters.constFind( options );
3492 if ( it != sFilters.constEnd() )
3496 QList< QgsVectorFileWriter::FilterFormatDetails > results;
3499 int const drvCount = OGRGetDriverCount();
3501 for (
int i = 0; i < drvCount; ++i )
3503 OGRSFDriverH drv = OGRGetDriver( i );
3506 QString drvName = OGR_Dr_GetName( drv );
3508 GDALDriverH gdalDriver = GDALGetDriverByName( drvName.toLocal8Bit().constData() );
3509 char **metadata =
nullptr;
3512 metadata = GDALGetMetadata( gdalDriver,
nullptr );
3515 bool nonSpatialFormat = CSLFetchBoolean( metadata, GDAL_DCAP_NONSPATIAL,
false );
3517 if ( OGR_Dr_TestCapability( drv,
"CreateDataSource" ) != 0 )
3522 if ( nonSpatialFormat )
3527 if ( filterString.isEmpty() )
3534 globs = metadata.
glob.toLower().split(
' ' );
3540 details.
globs = globs;
3549 if ( options & SortRecommended )
3551 if ( a.driverName == QLatin1String(
"GPKG" ) )
3553 else if ( b.driverName == QLatin1String(
"GPKG" ) )
3555 else if ( a.driverName == QLatin1String(
"ESRI Shapefile" ) )
3557 else if ( b.driverName == QLatin1String(
"ESRI Shapefile" ) )
3564 sFilters.insert( options, results );
3571 QSet< QString > extensions;
3573 const QRegularExpression rx( QStringLiteral(
"\\*\\.(.*)$" ) );
3577 for (
const QString &glob : format.globs )
3579 const QRegularExpressionMatch match = rx.match( glob );
3580 if ( !match.hasMatch() )
3583 const QString matched = match.captured( 1 );
3584 extensions.insert( matched );
3588 QStringList extensionList( extensions.constBegin(), extensions.constEnd() );
3590 std::sort( extensionList.begin(), extensionList.end(), [options](
const QString & a,
const QString & b ) ->
bool
3592 if ( options & SortRecommended )
3594 if ( a == QLatin1String(
"gpkg" ) )
3596 else if ( b == QLatin1String(
"gpkg" ) )
3598 else if ( a == QLatin1String(
"shp" ) )
3600 else if ( b == QLatin1String(
"shp" ) )
3604 return a.toLower().localeAwareCompare( b.toLower() ) < 0;
3607 return extensionList;
3612 QList< QgsVectorFileWriter::DriverDetails > results;
3615 const int drvCount = OGRGetDriverCount();
3617 QStringList writableDrivers;
3618 for (
int i = 0; i < drvCount; ++i )
3620 OGRSFDriverH drv = OGRGetDriver( i );
3623 QString drvName = OGR_Dr_GetName( drv );
3629 if ( drvName == QLatin1String(
"ODS" ) || drvName == QLatin1String(
"XLSX" ) || drvName == QLatin1String(
"XLS" ) )
3633 if ( drvName == QLatin1String(
"ESRI Shapefile" ) )
3635 writableDrivers << QStringLiteral(
"DBF file" );
3637 if ( OGR_Dr_TestCapability( drv,
"CreateDataSource" ) != 0 )
3640 if ( drvName == QLatin1String(
"MapInfo File" ) )
3642 writableDrivers << QStringLiteral(
"MapInfo MIF" );
3644 else if ( drvName == QLatin1String(
"SQLite" ) )
3651 QString option = QStringLiteral(
"SPATIALITE=YES" );
3652 char *options[2] = { CPLStrdup( option.toLocal8Bit().constData() ),
nullptr };
3653 OGRSFDriverH poDriver;
3655 poDriver = OGRGetDriverByName( drvName.toLocal8Bit().constData() );
3658 gdal::ogr_datasource_unique_ptr ds( OGR_Dr_CreateDataSource( poDriver, QStringLiteral(
"/vsimem/spatialitetest.sqlite" ).toUtf8().constData(), options ) );
3661 writableDrivers << QStringLiteral(
"SpatiaLite" );
3662 OGR_Dr_DeleteDataSource( poDriver, QStringLiteral(
"/vsimem/spatialitetest.sqlite" ).toUtf8().constData() );
3665 CPLFree( options[0] );
3667 writableDrivers << drvName;
3672 results.reserve( writableDrivers.count() );
3673 for (
const QString &drvName : std::as_const( writableDrivers ) )
3687 if ( options & SortRecommended )
3689 if ( a.driverName == QLatin1String(
"GPKG" ) )
3691 else if ( b.driverName == QLatin1String(
"GPKG" ) )
3693 else if ( a.driverName == QLatin1String(
"ESRI Shapefile" ) )
3695 else if ( b.driverName == QLatin1String(
"ESRI Shapefile" ) )
3699 return a.
longName.toLower().localeAwareCompare( b.
longName.toLower() ) < 0;
3706 QString ext = extension.trimmed();
3707 if ( ext.isEmpty() )
3710 if ( ext.startsWith(
'.' ) )
3714 int const drvCount = GDALGetDriverCount();
3716 for (
int i = 0; i < drvCount; ++i )
3718 GDALDriverH drv = GDALGetDriver( i );
3724 QString drvName = GDALGetDriverShortName( drv );
3725 QStringList driverExtensions = QString( GDALGetMetadataItem( drv, GDAL_DMD_EXTENSIONS,
nullptr ) ).split(
' ' );
3727 const auto constDriverExtensions = driverExtensions;
3728 for (
const QString &driver : constDriverExtensions )
3730 if ( driver.compare( ext, Qt::CaseInsensitive ) == 0 )
3741 QString filterString;
3745 if ( !filterString.isEmpty() )
3746 filterString += QLatin1String(
";;" );
3748 filterString += details.filterString;
3750 return filterString;
3759 return QStringLiteral(
"%1 (%2 %3)" ).arg( metadata.
trLongName,
3760 metadata.
glob.toLower(),
3761 metadata.
glob.toUpper() );
3766 if ( codecName == QLatin1String(
"System" ) )
3767 return QStringLiteral(
"LDID/0" );
3769 const QRegularExpression re( QRegularExpression::anchoredPattern( QString(
"(CP|windows-|ISO[ -])(.+)" ) ), QRegularExpression::CaseInsensitiveOption );
3770 const QRegularExpressionMatch match = re.match( codecName );
3771 if ( match.hasMatch() )
3773 QString
c = match.captured( 2 ).remove(
'-' );
3775 ( void )
c.toInt( &isNumber );
3803 OGRStyleTableH ogrStyleTable = OGR_STBL_Create();
3804 OGRStyleMgrH styleManager = OGR_SM_Create( ogrStyleTable );
3807 int nTotalLevels = 0;
3809 QgsSymbolList::iterator symbolIt = symbolList.begin();
3810 for ( ; symbolIt != symbolList.end(); ++symbolIt )
3812 double mmsf = mmScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
3813 double musf = mapUnitScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
3815 int nLevels = ( *symbolIt )->symbolLayerCount();
3816 for (
int i = 0; i < nLevels; ++i )
3818 mSymbolLayerTable.insert( ( *symbolIt )->symbolLayer( i ), QString::number( nTotalLevels ) );
3819 OGR_SM_AddStyle( styleManager, QString::number( nTotalLevels ).toLocal8Bit(),
3820 ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf ).toLocal8Bit() );
3824 OGR_DS_SetStyleTableDirectly( ds, ogrStyleTable );
3830 if ( !details.renderer )
3835 QHash< QgsSymbol *, QList<QgsFeature> > features;
3844 startRender( details.renderer.get(), details.sourceFields );
3864 QString msg = QObject::tr(
"Failed to transform, writing stopped. (Exception: %1)" )
3875 featureSymbol = mRenderer->symbolForFeature( fet, mRenderContext );
3876 if ( !featureSymbol )
3881 QHash< QgsSymbol *, QList<QgsFeature> >::iterator it = features.find( featureSymbol );
3882 if ( it == features.end() )
3884 it = features.insert( featureSymbol, QList<QgsFeature>() );
3886 it.value().append( fet );
3891 QgsSymbolList symbols = mRenderer->symbols( mRenderContext );
3892 for (
int i = 0; i < symbols.count(); i++ )
3898 if ( level < 0 || level >= 1000 )
3901 while ( level >= levels.count() )
3903 levels[level].append( item );
3908 int nTotalFeatures = 0;
3911 for (
int l = 0; l < levels.count(); l++ )
3914 for (
int i = 0; i < level.count(); i++ )
3917 QHash< QgsSymbol *, QList<QgsFeature> >::iterator levelIt = features.find( item.
symbol() );
3918 if ( levelIt == features.end() )
3924 double mmsf = mmScaleFactor(
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
3925 double musf = mapUnitScaleFactor(
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
3927 int llayer = item.
layer();
3928 QList<QgsFeature> &featureList = levelIt.value();
3929 QList<QgsFeature>::iterator featureIt = featureList.begin();
3930 for ( ; featureIt != featureList.end(); ++featureIt )
3940 QString styleString = levelIt.key()->symbolLayer( llayer )->ogrFeatureStyle( mmsf, musf );
3941 if ( !styleString.isEmpty() )
3943 OGR_F_SetStyleString( ogrFeature.get(), styleString.toLocal8Bit().constData() );
3944 if ( !writeFeature(
mLayer, ogrFeature.get() ) )
3957 *
errorMessage += QObject::tr(
"\nOnly %1 of %2 features written." ).arg( nTotalFeatures - nErrors ).arg( nTotalFeatures );
3974 return 1000 / scale;
3991 return scale / 1000;
3999 mRenderer = createSymbologyRenderer( sourceRenderer );
4005 mRenderer->startRender( mRenderContext, fields );
4008void QgsVectorFileWriter::stopRender()
4015 mRenderer->stopRender( mRenderContext );
4018std::unique_ptr<QgsFeatureRenderer> QgsVectorFileWriter::createSymbologyRenderer(
QgsFeatureRenderer *sourceRenderer )
const
4024 if ( !sourceRenderer )
4029 return std::unique_ptr< QgsFeatureRenderer >( sourceRenderer->
clone() );
4036 const QSet<QString> rendererAttributes = renderer->
usedAttributes( context );
4037 for (
const QString &attr : rendererAttributes )
4042 attList.append( index );
4048QStringList QgsVectorFileWriter::concatenateOptions(
const QMap<QString, QgsVectorFileWriter::Option *> &options )
4051 QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
4053 for ( it = options.constBegin(); it != options.constEnd(); ++it )
4056 switch ( option->
type )
4063 list.append( QStringLiteral(
"%1=%2" ).arg( it.key() ).arg( opt->
defaultValue ) );
4073 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
defaultValue ) );
4083 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
defaultValue ) );
4092 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
mValue ) );
4103 OGRSFDriverH hDriver =
nullptr;
4106 return QgsVectorFileWriter::EditionCapabilities();
4107 QString drvName = OGR_Dr_GetName( hDriver );
4108 QgsVectorFileWriter::EditionCapabilities caps = QgsVectorFileWriter::EditionCapabilities();
4109 if ( OGR_DS_TestCapability( hDS.get(), ODsCCreateLayer ) )
4114 if ( !( drvName == QLatin1String(
"ESRI Shapefile" ) && QFile::exists( datasetName ) ) )
4117 if ( OGR_DS_TestCapability( hDS.get(), ODsCDeleteLayer ) )
4121 int layer_count = OGR_DS_GetLayerCount( hDS.get() );
4124 OGRLayerH hLayer = OGR_DS_GetLayer( hDS.get(), 0 );
4127 if ( OGR_L_TestCapability( hLayer, OLCSequentialWrite ) )
4130 if ( OGR_L_TestCapability( hLayer, OLCCreateField ) )
4141 const QString &layerNameIn )
4143 OGRSFDriverH hDriver =
nullptr;
4148 QString layerName( layerNameIn );
4149 if ( layerName.isEmpty() )
4150 layerName = QFileInfo( datasetName ).baseName();
4152 return OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
4157 const QString &layerName,
4161 OGRSFDriverH hDriver =
nullptr;
4165 OGRLayerH hLayer = OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
4171 OGRFeatureDefnH defn = OGR_L_GetLayerDefn( hLayer );
4172 const auto constAttributes = attributes;
4173 for (
int idx : constAttributes )
4176 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 QgsSymbolList symbolsForFeature(const QgsFeature &feature, QgsRenderContext &context) const
Returns list of symbols used for rendering the feature.
virtual QgsSymbolList symbols(QgsRenderContext &context) const
Returns list of symbols used by the renderer.
bool usingSymbolLevels() const
virtual QgsFeatureRenderer::Capabilities capabilities()
Returns details about internals of this renderer.
virtual QSet< QString > usedAttributes(const QgsRenderContext &context) const =0
Returns a list of attributes required by this renderer.
@ SymbolLevels
Rendering with symbol levels (i.e. implements symbols(), symbolForFeature())
virtual QgsFeatureRenderer * clone() const =0
Create a deep copy of this renderer.
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Sets the feature IDs that should be fetched.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
QgsFeatureRequest & setFilterRect(const QgsRectangle &rectangle)
Sets the rectangle from which features will be taken.
@ RegeneratePrimaryKey
This flag indicates, that a primary key field cannot be guaranteed to be unique and the sink should i...
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
void initAttributes(int fieldCount)
Initialize this feature with the given number of fields.
bool hasGeometry() const
Returns true if the feature has an associated geometry.
bool isUnsetValue(int fieldIdx) const
Returns true if the attribute at the specified index is an unset value.
QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
bool isCanceled() const SIP_HOLDGIL
Tells whether the operation has been canceled already.
void setProgress(double progress)
Sets the current progress for the feedback object.
Encapsulate a field in an attribute table or data source.
QString typeName() const
Gets the field type.
bool convertCompatible(QVariant &v, QString *errorMessage=nullptr) const
Converts the provided variant to a compatible format.
void setName(const QString &name)
Set the field name.
QVariant::Type subType() const
If the field is a collection, gets its element's type.
Container of fields for a vector layer.
int count() const
Returns number of items.
int size() const
Returns number of items.
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
A geometry is the spatial representation of a feature.
const QgsAbstractGeometry * constGet() const SIP_HOLDGIL
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
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.
static bool isNull(const QVariant &variant)
Returns true if the specified variant should be considered a NULL value.
Interface to convert raw field values to their user-friendly value.
virtual QVariant convert(int fieldIdxInLayer, const QVariant &value)
Convert the provided value, for field fieldIdxInLayer.
virtual QgsVectorFileWriter::FieldValueConverter * clone() const
Creates a clone of the FieldValueConverter.
virtual QgsField fieldDefinition(const QgsField &field)
Returns a possibly modified field definition.
QgsVectorFileWriter::OptionType type
Options to pass to writeAsVectorFormat()
QString fileEncoding
Encoding to use.
bool forceMulti
Sets to true to force creation of multi* geometries.
FieldNameSource fieldNameSource
Source for exported field names.
QString driverName
OGR driver to use.
QgsCoordinateTransform ct
Transform to reproject exported geometries with, or invalid transform for no transformation.
QStringList attributesExportNames
Attributes export names.
QgsLayerMetadata layerMetadata
Layer metadata to save for the exported vector file.
SaveVectorOptions()
Constructor.
QString layerName
Layer name. If let empty, it will be derived from the filename.
QgsRectangle filterExtent
If not empty, only features intersecting the extent will be saved.
QgsVectorFileWriter::FieldValueConverter * fieldValueConverter
Field value converter.
QStringList layerOptions
List of OGR layer creation options.
QgsVectorFileWriter::SymbologyExport symbologyExport
Symbology to export.
bool includeZ
Sets to true to include z dimension in output. This option is only valid if overrideGeometryType is s...
bool saveMetadata
Set to true to save layer metadata for the exported vector file.
QgsVectorFileWriter::ActionOnExistingFile actionOnExistingFile
Action on existing file.
QgsAttributeList attributes
Attributes to export (empty means all unless skipAttributeCreation is set)
bool onlySelectedFeatures
Write only selected features of layer.
bool skipAttributeCreation
Only write geometries.
double symbologyScale
Scale of symbology.
QStringList datasourceOptions
List of OGR data source creation options.
QgsWkbTypes::Type overrideGeometryType
Set to a valid geometry type to override the default geometry type for the layer.
QgsFeedback * feedback
Optional feedback object allowing cancellation of layer save.
A convenience class for writing vector layers to disk based formats (e.g.
static QgsVectorFileWriter::WriterError writeAsVectorFormatV3(QgsVectorLayer *layer, const QString &fileName, const QgsCoordinateTransformContext &transformContext, const QgsVectorFileWriter::SaveVectorOptions &options, QString *errorMessage=nullptr, QString *newFilename=nullptr, QString *newLayer=nullptr)
Writes a layer out to a vector file.
QString lastError() const override
Returns the most recent error encountered by the sink, e.g.
@ CanAddNewFieldsToExistingLayer
Flag to indicate that new fields can be added to an existing layer. Imply CanAppendToExistingLayer.
@ CanAppendToExistingLayer
Flag to indicate that new features can be added to an existing layer.
@ CanAddNewLayer
Flag to indicate that a new layer can be added to the dataset.
@ CanDeleteLayer
Flag to indicate that an existing layer can be deleted.
static QgsVectorFileWriter::EditionCapabilities editionCapabilities(const QString &datasetName)
Returns edition capabilities for an existing dataset name.
static QgsVectorFileWriter * create(const QString &fileName, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &srs, const QgsCoordinateTransformContext &transformContext, const QgsVectorFileWriter::SaveVectorOptions &options, QgsFeatureSink::SinkFlags sinkFlags=QgsFeatureSink::SinkFlags(), QString *newFilename=nullptr, QString *newLayer=nullptr)
Create a new vector file writer.
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a single feature to the sink.
static bool supportsFeatureStyles(const QString &driverName)
Returns true if the specified driverName supports feature styles.
bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a list of features to the sink.
double mSymbologyScale
Scale for symbology export (e.g. for symbols units in map units)
OGRGeometryH createEmptyGeometry(QgsWkbTypes::Type wkbType)
QMap< int, int > mAttrIdxToOgrIdx
Map attribute indizes to OGR field indexes.
@ ErrAttributeTypeUnsupported
@ Canceled
Writing was interrupted by manual cancellation.
@ ErrAttributeCreationFailed
@ ErrSavingMetadata
Metadata saving failed.
gdal::ogr_datasource_unique_ptr mDS
static Q_DECL_DEPRECATED QgsVectorFileWriter::WriterError writeAsVectorFormatV2(QgsVectorLayer *layer, const QString &fileName, const QgsCoordinateTransformContext &transformContext, const QgsVectorFileWriter::SaveVectorOptions &options, QString *newFilename=nullptr, QString *newLayer=nullptr, QString *errorMessage=nullptr)
Writes a layer out to a vector file.
~QgsVectorFileWriter() override
Close opened shapefile for writing.
static bool targetLayerExists(const QString &datasetName, const QString &layerName)
Returns whether the target layer already exists.
double symbologyScale() const
Returns the reference scale for output.
static QStringList defaultLayerOptions(const QString &driverName)
Returns a list of the default layer options for a specified driver.
SymbologyExport mSymbologyExport
static QString driverForExtension(const QString &extension)
Returns the OGR driver name for a specified file extension.
static QList< QgsVectorFileWriter::FilterFormatDetails > supportedFiltersAndFormats(VectorFormatOptions options=SortRecommended)
Returns a list or pairs, with format filter string as first element and OGR format key as second elem...
OGRSpatialReferenceH mOgrRef
static bool driverMetadata(const QString &driverName, MetaData &driverMetadata)
static bool deleteShapeFile(const QString &fileName)
Delete a shapefile (and its accompanying shx / dbf / prj / qix / qpj / cpg / sbn / sbx / idm / ind)
static QString filterForDriver(const QString &driverName)
Creates a filter for an OGR driver key.
QgsWkbTypes::Type mWkbType
Geometry type which is being used.
QgsVectorFileWriter::WriterError hasError() const
Checks whether there were any errors in constructor.
static OGRwkbGeometryType ogrTypeFromWkbType(QgsWkbTypes::Type type)
Gets the ogr geometry type from an internal QGIS wkb type enum.
@ SkipNonSpatialFormats
Filter out any formats which do not have spatial support (e.g. those which cannot save geometries)
static bool areThereNewFieldsToCreate(const QString &datasetName, const QString &layerName, QgsVectorLayer *layer, const QgsAttributeList &attributes)
Returns whether there are among the attributes specified some that do not exist yet in the layer.
static QList< QgsVectorFileWriter::DriverDetails > ogrDriverList(VectorFormatOptions options=SortRecommended)
Returns the driver list that can be used for dialogs.
static Q_DECL_DEPRECATED QgsVectorFileWriter::WriterError writeAsVectorFormat(QgsVectorLayer *layer, const QString &fileName, const QString &fileEncoding, const QgsCoordinateReferenceSystem &destCRS=QgsCoordinateReferenceSystem(), const QString &driverName="GPKG", bool onlySelected=false, QString *errorMessage=nullptr, const QStringList &datasourceOptions=QStringList(), const QStringList &layerOptions=QStringList(), bool skipAttributeCreation=false, QString *newFilename=nullptr, QgsVectorFileWriter::SymbologyExport symbologyExport=QgsVectorFileWriter::NoSymbology, double symbologyScale=1.0, const QgsRectangle *filterExtent=nullptr, QgsWkbTypes::Type overrideGeometryType=QgsWkbTypes::Unknown, bool forceMulti=false, bool includeZ=false, const QgsAttributeList &attributes=QgsAttributeList(), QgsVectorFileWriter::FieldValueConverter *fieldValueConverter=nullptr, QString *newLayer=nullptr)
Write contents of vector layer to an (OGR supported) vector format.
WriterError mError
Contains error value if construction was not successful.
FieldNameSource
Source for exported field names.
@ PreferAlias
Use the field alias as the exported field name, wherever one is set. Otherwise use the original field...
@ Original
Use original field names.
static QStringList defaultDatasetOptions(const QString &driverName)
Returns a list of the default dataset options for a specified driver.
static QStringList supportedFormatExtensions(VectorFormatOptions options=SortRecommended)
Returns a list of file extensions for supported formats, e.g "shp", "gpkg".
static QString convertCodecNameForEncodingOption(const QString &codecName)
Converts codec name to string passed to ENCODING layer creation option of OGR Shapefile.
FieldValueConverter * mFieldValueConverter
Field value converter.
bool addFeatureWithStyle(QgsFeature &feature, QgsFeatureRenderer *renderer, QgsUnitTypes::DistanceUnit outputUnit=QgsUnitTypes::DistanceMeters)
Adds a feature to the currently opened data source, using the style from a specified renderer.
QString errorMessage() const
Retrieves error message.
QgsVectorFileWriter::SymbologyExport symbologyExport() const
void setSymbologyScale(double scale)
Set reference scale for output.
Q_DECL_DEPRECATED QgsVectorFileWriter(const QString &vectorFileName, const QString &fileEncoding, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &srs=QgsCoordinateReferenceSystem(), const QString &driverName="GPKG", const QStringList &datasourceOptions=QStringList(), const QStringList &layerOptions=QStringList(), QString *newFilename=nullptr, QgsVectorFileWriter::SymbologyExport symbologyExport=QgsVectorFileWriter::NoSymbology, QgsFeatureSink::SinkFlags sinkFlags=QgsFeatureSink::SinkFlags(), QString *newLayer=nullptr, const QgsCoordinateTransformContext &transformContext=QgsCoordinateTransformContext(), FieldNameSource fieldNameSource=Original)
Create a new vector file writer.
QMap< QgsSymbolLayer *, QString > mSymbolLayerTable
static QString fileFilterString(VectorFormatOptions options=SortRecommended)
Returns filter string that can be used for dialogs.
ActionOnExistingFile
Combination of CanAddNewLayer, CanAppendToExistingLayer, CanAddNewFieldsToExistingLayer or CanDeleteL...
@ CreateOrOverwriteLayer
Create or overwrite layer.
@ CreateOrOverwriteFile
Create or overwrite file.
@ AppendToLayerNoNewFields
Append features to existing layer, but do not create new fields.
@ AppendToLayerAddFields
Append features to existing layer, and create new fields if needed.
Represents a vector layer which manages a vector based data sets.
Q_INVOKABLE QgsWkbTypes::Type wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
long long featureCount(const QString &legendKey) const
Number of features rendered with specified legend key.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
int selectedFeatureCount() const
Returns the number of features that are selected in this layer.
Q_INVOKABLE const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
QgsFeatureRenderer * renderer()
Returns the feature renderer used for rendering the features in the layer in 2D map views.
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
void minimumAndMaximumValue(int index, QVariant &minimum, QVariant &maximum) const
Calculates both the minimum and maximum value for an attribute column.
static 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.