34 #include "qgssettings.h"
45 #include <QTextStream>
49 #include <QRegularExpression>
55 #include <ogr_srs_api.h>
56 #include <cpl_error.h>
58 #include <cpl_string.h>
77 const QString &vectorFileName,
78 const QString &fileEncoding,
82 const QString &driverName,
83 const QStringList &datasourceOptions,
84 const QStringList &layerOptions,
87 QgsFeatureSink::SinkFlags sinkFlags,
97 init( vectorFileName, fileEncoding, fields, geometryType,
98 srs, driverName, datasourceOptions, layerOptions, newFilename,
nullptr,
103 const QString &vectorFileName,
104 const QString &fileEncoding,
108 const QString &driverName,
109 const QStringList &datasourceOptions,
110 const QStringList &layerOptions,
111 QString *newFilename,
114 const QString &layerName,
118 QgsFeatureSink::SinkFlags sinkFlags,
122 , mWkbType( geometryType )
123 , mSymbologyExport( symbologyExport )
124 , mSymbologyScale( 1.0 )
126 init( vectorFileName, fileEncoding, fields, geometryType, srs, driverName,
127 datasourceOptions, layerOptions, newFilename, fieldValueConverter,
128 layerName, action, newLayer, sinkFlags, transformContext, fieldNameSource );
132 const QString &fileName,
138 QgsFeatureSink::SinkFlags sinkFlags,
139 QString *newFilename,
153 if ( driverName == QLatin1String(
"MapInfo MIF" ) )
157 GDALDriverH gdalDriver = GDALGetDriverByName( driverName.toLocal8Bit().constData() );
165 return CSLFetchBoolean(
driverMetadata, GDAL_DCAP_FEATURE_STYLES,
false );
168 void QgsVectorFileWriter::init( QString vectorFileName,
169 QString fileEncoding,
173 const QString &driverName,
174 QStringList datasourceOptions,
175 QStringList layerOptions,
176 QString *newFilename,
177 FieldValueConverter *fieldValueConverter,
178 const QString &layerNameIn,
179 ActionOnExistingFile action,
180 QString *newLayer, SinkFlags sinkFlags,
185 if ( vectorFileName.isEmpty() )
192 if ( driverName == QLatin1String(
"MapInfo MIF" ) )
196 else if ( driverName == QLatin1String(
"SpatiaLite" ) )
199 if ( !datasourceOptions.contains( QStringLiteral(
"SPATIALITE=YES" ) ) )
201 datasourceOptions.append( QStringLiteral(
"SPATIALITE=YES" ) );
204 else if ( driverName == QLatin1String(
"DBF file" ) )
207 if ( !layerOptions.contains( QStringLiteral(
"SHPT=NULL" ) ) )
209 layerOptions.append( QStringLiteral(
"SHPT=NULL" ) );
218 #if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,3,1)
219 QString fidFieldName;
222 for (
const QString &layerOption : layerOptions )
224 if ( layerOption.startsWith( QLatin1String(
"FID=" ) ) )
226 fidFieldName = layerOption.mid( 4 );
230 if ( fidFieldName.isEmpty() )
231 fidFieldName = QStringLiteral(
"fid" );
236 OGRSFDriverH poDriver;
239 poDriver = OGRGetDriverByName(
mOgrDriverName.toLocal8Bit().constData() );
243 mErrorMessage = QObject::tr(
"OGR driver for '%1' not found (OGR error: %2)" )
245 QString::fromUtf8( CPLGetLastErrorMsg() ) );
255 if ( layerOptions.join( QString() ).toUpper().indexOf( QLatin1String(
"ENCODING=" ) ) == -1 )
260 if ( driverName == QLatin1String(
"ESRI Shapefile" ) && !vectorFileName.endsWith( QLatin1String(
".shp" ), Qt::CaseInsensitive ) )
262 vectorFileName += QLatin1String(
".shp" );
264 else if ( driverName == QLatin1String(
"DBF file" ) && !vectorFileName.endsWith( QLatin1String(
".dbf" ), Qt::CaseInsensitive ) )
266 vectorFileName += QLatin1String(
".dbf" );
276 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
277 QStringList allExts = metadata.ext.split(
' ', QString::SkipEmptyParts );
279 QStringList allExts = metadata.ext.split(
' ', Qt::SkipEmptyParts );
282 const auto constAllExts = allExts;
283 for (
const QString &ext : constAllExts )
285 if ( vectorFileName.endsWith(
'.' + ext, Qt::CaseInsensitive ) )
294 vectorFileName +=
'.' + allExts[0];
300 if ( vectorFileName.endsWith( QLatin1String(
".gdb" ), Qt::CaseInsensitive ) )
302 QDir dir( vectorFileName );
305 QFileInfoList fileList = dir.entryInfoList(
306 QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files, QDir::DirsFirst );
307 const auto constFileList = fileList;
308 for (
const QFileInfo &info : constFileList )
310 QFile::remove( info.absoluteFilePath() );
313 QDir().rmdir( vectorFileName );
317 QFile::remove( vectorFileName );
322 if ( metadataFound && !metadata.compulsoryEncoding.isEmpty() )
324 if ( fileEncoding.compare( metadata.compulsoryEncoding, Qt::CaseInsensitive ) != 0 )
326 QgsDebugMsgLevel( QStringLiteral(
"forced %1 encoding for %2" ).arg( metadata.compulsoryEncoding, driverName ), 2 );
327 fileEncoding = metadata.compulsoryEncoding;
332 char **options =
nullptr;
333 if ( !datasourceOptions.isEmpty() )
335 options =
new char *[ datasourceOptions.size() + 1 ];
336 for (
int i = 0; i < datasourceOptions.size(); i++ )
338 QgsDebugMsgLevel( QStringLiteral(
"-dsco=%1" ).arg( datasourceOptions[i] ), 2 );
339 options[i] = CPLStrdup( datasourceOptions[i].toLocal8Bit().constData() );
341 options[ datasourceOptions.size()] =
nullptr;
347 mDS.reset( OGR_Dr_CreateDataSource( poDriver, vectorFileName.toUtf8().constData(), options ) );
349 mDS.reset( OGROpen( vectorFileName.toUtf8().constData(), TRUE,
nullptr ) );
353 for (
int i = 0; i < datasourceOptions.size(); i++ )
354 CPLFree( options[i] );
363 mErrorMessage = QObject::tr(
"Creation of data source failed (OGR error: %1)" )
364 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
366 mErrorMessage = QObject::tr(
"Opening of data source in update mode failed (OGR error: %1)" )
367 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
371 QString layerName( layerNameIn );
372 if ( layerName.isEmpty() )
373 layerName = QFileInfo( vectorFileName ).baseName();
377 const int layer_count = OGR_DS_GetLayerCount(
mDS.get() );
378 for (
int i = 0; i < layer_count; i++ )
380 OGRLayerH hLayer = OGR_DS_GetLayer(
mDS.get(), i );
381 if ( EQUAL( OGR_L_GetName( hLayer ), layerName.toUtf8().constData() ) )
383 if ( OGR_DS_DeleteLayer(
mDS.get(), i ) != OGRERR_NONE )
386 mErrorMessage = QObject::tr(
"Overwriting of existing layer failed (OGR error: %1)" )
387 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
401 QgsDebugMsgLevel( QStringLiteral(
"Opened data source in update mode" ), 2 );
405 mCodec = QTextCodec::codecForName( fileEncoding.toLocal8Bit().constData() );
408 QgsDebugMsg(
"error finding QTextCodec for " + fileEncoding );
410 QgsSettings settings;
411 QString enc = settings.value( QStringLiteral(
"UI/encoding" ),
"System" ).toString();
412 mCodec = QTextCodec::codecForName( enc.toLocal8Bit().constData() );
415 QgsDebugMsg(
"error finding QTextCodec for " + enc );
416 mCodec = QTextCodec::codecForLocale();
422 if ( driverName == QLatin1String(
"KML" ) || driverName == QLatin1String(
"LIBKML" ) || driverName == QLatin1String(
"GPX" ) )
424 if ( srs.
authid() != QLatin1String(
"EPSG:4326" ) )
437 mOgrRef = OSRNewSpatialReference( srsWkt.toLocal8Bit().constData() );
438 #if GDAL_VERSION_MAJOR >= 3
441 OSRSetAxisMappingStrategy(
mOgrRef, OAMS_TRADITIONAL_GIS_ORDER );
450 int optIndex = layerOptions.indexOf( QLatin1String(
"FEATURE_DATASET=" ) );
451 if ( optIndex != -1 )
453 layerOptions.removeAt( optIndex );
456 if ( !layerOptions.isEmpty() )
458 options =
new char *[ layerOptions.size() + 1 ];
459 for (
int i = 0; i < layerOptions.size(); i++ )
462 options[i] = CPLStrdup( layerOptions[i].toLocal8Bit().constData() );
464 options[ layerOptions.size()] =
nullptr;
468 CPLSetConfigOption(
"SHAPE_ENCODING",
"" );
472 mLayer = OGR_DS_CreateLayer(
mDS.get(), layerName.toUtf8().constData(),
mOgrRef, wkbType, options );
475 *newLayer = OGR_L_GetName(
mLayer );
476 if ( driverName == QLatin1String(
"GPX" ) )
483 if ( !EQUAL( layerName.toUtf8().constData(),
"track_points" ) &&
484 !EQUAL( layerName.toUtf8().constData(),
"route_points" ) )
486 *newLayer = QStringLiteral(
"waypoints" );
493 const char *pszForceGPXTrack
494 = CSLFetchNameValue( options,
"FORCE_GPX_TRACK" );
495 if ( pszForceGPXTrack && CPLTestBool( pszForceGPXTrack ) )
496 *newLayer = QStringLiteral(
"tracks" );
498 *newLayer = QStringLiteral(
"routes" );
505 const char *pszForceGPXRoute
506 = CSLFetchNameValue( options,
"FORCE_GPX_ROUTE" );
507 if ( pszForceGPXRoute && CPLTestBool( pszForceGPXRoute ) )
508 *newLayer = QStringLiteral(
"routes" );
510 *newLayer = QStringLiteral(
"tracks" );
520 else if ( driverName == QLatin1String(
"DGN" ) )
522 mLayer = OGR_DS_GetLayerByName(
mDS.get(),
"elements" );
526 mLayer = OGR_DS_GetLayerByName(
mDS.get(), layerName.toUtf8().constData() );
531 for (
int i = 0; i < layerOptions.size(); i++ )
532 CPLFree( options[i] );
541 QString layerName = vectorFileName.left( vectorFileName.indexOf( QLatin1String(
".shp" ), Qt::CaseInsensitive ) );
542 QFile prjFile( layerName +
".qpj" );
543 if ( prjFile.exists() )
551 mErrorMessage = QObject::tr(
"Creation of layer failed (OGR error: %1)" )
552 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
554 mErrorMessage = QObject::tr(
"Opening of layer failed (OGR error: %1)" )
555 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
560 OGRFeatureDefnH defn = OGR_L_GetLayerDefn(
mLayer );
569 QSet<int> existingIdxs;
579 for (
int fldIdx = 0; fldIdx < fields.
count(); ++fldIdx )
583 if ( fieldValueConverter )
585 attrField = fieldValueConverter->fieldDefinition( fields.
at( fldIdx ) );
590 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( attrField.
name() ) );
599 switch ( fieldNameSource )
602 name = attrField.
name();
606 name = !attrField.
alias().isEmpty() ? attrField.
alias() : attrField.
name();
610 OGRFieldType ogrType = OFTString;
611 int ogrWidth = attrField.
length();
612 int ogrPrecision = attrField.
precision();
613 if ( ogrPrecision > 0 )
616 switch ( attrField.
type() )
618 case QVariant::LongLong:
620 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
621 if ( pszDataTypes && strstr( pszDataTypes,
"Integer64" ) )
622 ogrType = OFTInteger64;
625 ogrWidth = ogrWidth > 0 && ogrWidth <= 20 ? ogrWidth : 20;
629 case QVariant::String:
631 if ( ( ogrWidth <= 0 || ogrWidth > 255 ) &&
mOgrDriverName == QLatin1String(
"ESRI Shapefile" ) )
636 ogrType = OFTInteger;
637 ogrWidth = ogrWidth > 0 && ogrWidth <= 10 ? ogrWidth : 10;
642 ogrType = OFTInteger;
647 case QVariant::Double:
648 #if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,3,1)
649 if (
mOgrDriverName == QLatin1String(
"GPKG" ) && attrField.
precision() == 0 && attrField.
name().compare( fidFieldName, Qt::CaseInsensitive ) == 0 )
652 ogrType = OFTInteger64;
675 case QVariant::DateTime:
683 ogrType = OFTDateTime;
687 case QVariant::ByteArray:
691 case QVariant::StringList:
693 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
694 if ( pszDataTypes && strstr( pszDataTypes,
"StringList" ) )
696 ogrType = OFTStringList;
697 mSupportedListSubTypes.insert( QVariant::String );
709 if ( attrField.
subType() == QVariant::String )
711 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
712 if ( pszDataTypes && strstr( pszDataTypes,
"StringList" ) )
714 ogrType = OFTStringList;
715 mSupportedListSubTypes.insert( QVariant::String );
724 else if ( attrField.
subType() == QVariant::Int )
726 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
727 if ( pszDataTypes && strstr( pszDataTypes,
"IntegerList" ) )
729 ogrType = OFTIntegerList;
730 mSupportedListSubTypes.insert( QVariant::Int );
739 else if ( attrField.
subType() == QVariant::Double )
741 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
742 if ( pszDataTypes && strstr( pszDataTypes,
"RealList" ) )
744 ogrType = OFTRealList;
745 mSupportedListSubTypes.insert( QVariant::Double );
754 else if ( attrField.
subType() == QVariant::LongLong )
756 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
757 if ( pszDataTypes && strstr( pszDataTypes,
"Integer64List" ) )
759 ogrType = OFTInteger64List;
760 mSupportedListSubTypes.insert( QVariant::LongLong );
774 mErrorMessage = QObject::tr(
"Unsupported type for field %1" )
775 .arg( attrField.
name() );
780 if (
mOgrDriverName == QLatin1String(
"SQLite" ) && name.compare( QLatin1String(
"ogc_fid" ), Qt::CaseInsensitive ) == 0 )
783 for ( i = 0; i < 10; i++ )
785 name = QStringLiteral(
"ogc_fid%1" ).arg( i );
788 for ( j = 0; j < fields.
size() && name.compare( fields.
at( j ).
name(), Qt::CaseInsensitive ) != 0; j++ )
791 if ( j == fields.
size() )
797 mErrorMessage = QObject::tr(
"No available replacement for internal fieldname ogc_fid found" ).arg( attrField.
name() );
802 QgsMessageLog::logMessage( QObject::tr(
"Reserved attribute name ogc_fid replaced with %1" ).arg( name ), QObject::tr(
"OGR" ) );
809 OGR_Fld_SetWidth( fld.get(), ogrWidth );
812 if ( ogrPrecision >= 0 )
814 OGR_Fld_SetPrecision( fld.get(), ogrPrecision );
817 switch ( attrField.
type() )
820 OGR_Fld_SetSubType( fld.get(), OFSTBoolean );
828 " type " + QString( QVariant::typeToName( attrField.
type() ) ) +
829 " width " + QString::number( ogrWidth ) +
830 " precision " + QString::number( ogrPrecision ), 2 );
831 if ( OGR_L_CreateField(
mLayer, fld.get(),
true ) != OGRERR_NONE )
834 mErrorMessage = QObject::tr(
"Creation of field %1 failed (OGR error: %2)" )
835 .arg( attrField.
name(),
836 QString::fromUtf8( CPLGetLastErrorMsg() ) );
841 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( name ) );
842 QgsDebugMsgLevel( QStringLiteral(
"returned field index for %1: %2" ).arg( name ).arg( ogrIdx ), 2 );
843 if ( ogrIdx < 0 || existingIdxs.contains( ogrIdx ) )
846 ogrIdx = OGR_FD_GetFieldCount( defn ) - 1;
851 mErrorMessage = QObject::tr(
"Created field %1 not found (OGR error: %2)" )
852 .arg( attrField.
name(),
853 QString::fromUtf8( CPLGetLastErrorMsg() ) );
859 existingIdxs.insert( ogrIdx );
867 for (
int fldIdx = 0; fldIdx < fields.
count(); ++fldIdx )
870 QString name( attrField.
name() );
871 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( name ) );
883 int fidIdx = fields.
lookupField( QStringLiteral(
"FID" ) );
894 *newFilename = vectorFileName;
897 mUsingTransaction =
true;
898 if ( OGRERR_NONE != OGR_L_StartTransaction(
mLayer ) )
900 mUsingTransaction =
false;
910 class QgsVectorFileWriterMetadataContainer
914 QgsVectorFileWriterMetadataContainer()
916 QMap<QString, QgsVectorFileWriter::Option *> datasetOptions;
917 QMap<QString, QgsVectorFileWriter::Option *> layerOptions;
920 datasetOptions.clear();
921 layerOptions.clear();
923 driverMetadata.insert( QStringLiteral(
"AVCE00" ),
925 QStringLiteral(
"Arc/Info ASCII Coverage" ),
926 QObject::tr(
"Arc/Info ASCII Coverage" ),
927 QStringLiteral(
"*.e00" ),
928 QStringLiteral(
"e00" ),
935 #if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,3,0)
939 datasetOptions.clear();
940 layerOptions.clear();
943 QObject::tr(
"New BNA files are created by the "
944 "systems default line termination conventions. "
945 "This may be overridden here." ),
947 << QStringLiteral(
"CRLF" )
948 << QStringLiteral(
"LF" ),
954 QObject::tr(
"By default, BNA files are created in multi-line format. "
955 "For each record, the first line contains the identifiers and the "
956 "type/number of coordinates to follow. Each following line contains "
957 "a pair of coordinates." ),
962 QObject::tr(
"BNA records may contain from 2 to 4 identifiers per record. "
963 "Some software packages only support a precise number of identifiers. "
964 "You can override the default value (2) by a precise value." ),
966 << QStringLiteral(
"2" )
967 << QStringLiteral(
"3" )
968 << QStringLiteral(
"4" )
969 << QStringLiteral(
"NB_SOURCE_FIELDS" ),
970 QStringLiteral(
"2" )
974 QObject::tr(
"The BNA writer will try to recognize ellipses and circles when writing a polygon. "
975 "This will only work if the feature has previously been read from a BNA file. "
976 "As some software packages do not support ellipses/circles in BNA data file, "
977 "it may be useful to tell the writer by specifying ELLIPSES_AS_ELLIPSES=NO not "
978 "to export them as such, but keep them as polygons." ),
983 QObject::tr(
"Limit the number of coordinate pairs per line in multiline format." ),
988 QObject::tr(
"Set the number of decimal for coordinates. Default value is 10." ),
992 driverMetadata.insert( QStringLiteral(
"BNA" ),
994 QStringLiteral(
"Atlas BNA" ),
995 QObject::tr(
"Atlas BNA" ),
996 QStringLiteral(
"*.bna" ),
997 QStringLiteral(
"bna" ),
1005 datasetOptions.clear();
1006 layerOptions.clear();
1009 QObject::tr(
"By default when creating new .csv files they "
1010 "are created with the line termination conventions "
1011 "of the local platform (CR/LF on Win32 or LF on all other systems). "
1012 "This may be overridden through the use of the LINEFORMAT option." ),
1014 << QStringLiteral(
"CRLF" )
1015 << QStringLiteral(
"LF" ),
1021 QObject::tr(
"By default, the geometry of a feature written to a .csv file is discarded. "
1022 "It is possible to export the geometry in its WKT representation by "
1023 "specifying GEOMETRY=AS_WKT. It is also possible to export point geometries "
1024 "into their X,Y,Z components by specifying GEOMETRY=AS_XYZ, GEOMETRY=AS_XY "
1025 "or GEOMETRY=AS_YX." ),
1027 << QStringLiteral(
"AS_WKT" )
1028 << QStringLiteral(
"AS_XYZ" )
1029 << QStringLiteral(
"AS_XY" )
1030 << QStringLiteral(
"AS_YX" ),
1036 QObject::tr(
"Create the associated .csvt file to describe the type of each "
1037 "column of the layer and its optional width and precision." ),
1042 QObject::tr(
"Field separator character." ),
1044 << QStringLiteral(
"COMMA" )
1045 << QStringLiteral(
"SEMICOLON" )
1046 << QStringLiteral(
"TAB" ),
1047 QStringLiteral(
"COMMA" )
1051 QObject::tr(
"Double-quote strings. IF_AMBIGUOUS means that string values that look like numbers will be quoted." ),
1053 << QStringLiteral(
"IF_NEEDED" )
1054 << QStringLiteral(
"IF_AMBIGUOUS" )
1055 << QStringLiteral(
"ALWAYS" ),
1056 QStringLiteral(
"IF_AMBIGUOUS" )
1060 QObject::tr(
"Write a UTF-8 Byte Order Mark (BOM) at the start of the file." ),
1064 driverMetadata.insert( QStringLiteral(
"CSV" ),
1066 QStringLiteral(
"Comma Separated Value [CSV]" ),
1067 QObject::tr(
"Comma Separated Value [CSV]" ),
1068 QStringLiteral(
"*.csv" ),
1069 QStringLiteral(
"csv" ),
1075 #if defined(GDAL_COMPUTE_VERSION) && GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,1,0)
1077 datasetOptions.clear();
1078 layerOptions.clear();
1080 driverMetadata.insert( QStringLiteral(
"FlatGeobuf" ),
1082 QStringLiteral(
"FlatGeobuf" ),
1083 QObject::tr(
"FlatGeobuf" ),
1084 QStringLiteral(
"*.fgb" ),
1085 QStringLiteral(
"fgb" ),
1088 QStringLiteral(
"UTF-8" )
1094 datasetOptions.clear();
1095 layerOptions.clear();
1098 QObject::tr(
"Override the type of shapefile created. "
1099 "Can be one of NULL for a simple .dbf file with no .shp file, POINT, "
1100 "ARC, POLYGON or MULTIPOINT for 2D, or POINTZ, ARCZ, POLYGONZ or "
1101 "MULTIPOINTZ for 3D;" ) +
1102 QObject::tr(
" POINTM, ARCM, POLYGONM or MULTIPOINTM for measured geometries"
1103 " and POINTZM, ARCZM, POLYGONZM or MULTIPOINTZM for 3D measured"
1105 QObject::tr(
" MULTIPATCH files are supported since GDAL 2.2." ) +
1108 << QStringLiteral(
"NULL" )
1109 << QStringLiteral(
"POINT" )
1110 << QStringLiteral(
"ARC" )
1111 << QStringLiteral(
"POLYGON" )
1112 << QStringLiteral(
"MULTIPOINT" )
1113 << QStringLiteral(
"POINTZ" )
1114 << QStringLiteral(
"ARCZ" )
1115 << QStringLiteral(
"POLYGONZ" )
1116 << QStringLiteral(
"MULTIPOINTZ" )
1117 << QStringLiteral(
"POINTM" )
1118 << QStringLiteral(
"ARCM" )
1119 << QStringLiteral(
"POLYGONM" )
1120 << QStringLiteral(
"MULTIPOINTM" )
1121 << QStringLiteral(
"POINTZM" )
1122 << QStringLiteral(
"ARCZM" )
1123 << QStringLiteral(
"POLYGONZM" )
1124 << QStringLiteral(
"MULTIPOINTZM" )
1125 << QStringLiteral(
"MULTIPATCH" )
1135 QObject::tr(
"Set the encoding value in the DBF file. "
1136 "The default value is LDID/87. It is not clear "
1137 "what other values may be appropriate." ),
1145 QObject::tr(
"Set to YES to resize fields to their optimal size." ),
1149 driverMetadata.insert( QStringLiteral(
"ESRI" ),
1151 QStringLiteral(
"ESRI Shapefile" ),
1152 QObject::tr(
"ESRI Shapefile" ),
1153 QStringLiteral(
"*.shp" ),
1154 QStringLiteral(
"shp" ),
1161 datasetOptions.clear();
1162 layerOptions.clear();
1164 driverMetadata.insert( QStringLiteral(
"DBF File" ),
1166 QStringLiteral(
"DBF File" ),
1167 QObject::tr(
"DBF File" ),
1168 QStringLiteral(
"*.dbf" ),
1169 QStringLiteral(
"dbf" ),
1176 datasetOptions.clear();
1177 layerOptions.clear();
1179 driverMetadata.insert( QStringLiteral(
"FMEObjects Gateway" ),
1181 QStringLiteral(
"FMEObjects Gateway" ),
1182 QObject::tr(
"FMEObjects Gateway" ),
1183 QStringLiteral(
"*.fdd" ),
1184 QStringLiteral(
"fdd" ),
1191 datasetOptions.clear();
1192 layerOptions.clear();
1195 QObject::tr(
"Set to YES to write a bbox property with the bounding box "
1196 "of the geometries at the feature and feature collection level." ),
1201 QObject::tr(
"Maximum number of figures after decimal separator to write in coordinates. "
1202 "Defaults to 15. Truncation will occur to remove trailing zeros." ),
1207 QObject::tr(
"Whether to use RFC 7946 standard. "
1208 "If disabled GeoJSON 2008 initial version will be used. "
1209 "Default is NO (thus GeoJSON 2008). See also Documentation (via Help button)" ),
1213 driverMetadata.insert( QStringLiteral(
"GeoJSON" ),
1215 QStringLiteral(
"GeoJSON" ),
1216 QObject::tr(
"GeoJSON" ),
1217 QStringLiteral(
"*.geojson" ),
1218 QStringLiteral(
"geojson" ),
1221 QStringLiteral(
"UTF-8" )
1226 datasetOptions.clear();
1227 layerOptions.clear();
1230 QObject::tr(
"Maximum number of figures after decimal separator to write in coordinates. "
1231 "Defaults to 15. Truncation will occur to remove trailing zeros." ),
1236 QObject::tr(
"Whether to start records with the RS=0x1E character (RFC 8142 standard). "
1237 "Defaults to NO: Newline Delimited JSON (geojsonl). \n"
1238 "If set to YES: RFC 8142 standard: GeoJSON Text Sequences (geojsons)." ),
1242 driverMetadata.insert( QStringLiteral(
"GeoJSONSeq" ),
1244 QStringLiteral(
"GeoJSON - Newline Delimited" ),
1245 QObject::tr(
"GeoJSON - Newline Delimited" ),
1246 QStringLiteral(
"*.geojsonl *.geojsons *.json" ),
1247 QStringLiteral(
"json" ),
1250 QStringLiteral(
"UTF-8" )
1255 datasetOptions.clear();
1256 layerOptions.clear();
1259 QObject::tr(
"whether the document must be in RSS 2.0 or Atom 1.0 format. "
1260 "Default value : RSS" ),
1262 << QStringLiteral(
"RSS" )
1263 << QStringLiteral(
"ATOM" ),
1264 QStringLiteral(
"RSS" )
1268 QObject::tr(
"The encoding of location information. Default value : SIMPLE. "
1269 "W3C_GEO only supports point geometries. "
1270 "SIMPLE or W3C_GEO only support geometries in geographic WGS84 coordinates." ),
1272 << QStringLiteral(
"SIMPLE" )
1273 << QStringLiteral(
"GML" )
1274 << QStringLiteral(
"W3C_GEO" ),
1275 QStringLiteral(
"SIMPLE" )
1279 QObject::tr(
"If defined to YES, extension fields will be written. "
1280 "If the field name not found in the base schema matches "
1281 "the foo_bar pattern, foo will be considered as the namespace "
1282 "of the element, and a <foo:bar> element will be written. "
1283 "Otherwise, elements will be written in the <ogr:> namespace." ),
1288 QObject::tr(
"If defined to NO, only <entry> or <item> elements will be written. "
1289 "The user will have to provide the appropriate header and footer of the document." ),
1294 QObject::tr(
"XML content that will be put between the <channel> element and the "
1295 "first <item> element for a RSS document, or between the xml tag and "
1296 "the first <entry> element for an Atom document." ),
1301 QObject::tr(
"Value put inside the <title> element in the header. "
1302 "If not provided, a dummy value will be used as that element is compulsory." ),
1307 QObject::tr(
"Value put inside the <description> element in the header. "
1308 "If not provided, a dummy value will be used as that element is compulsory." ),
1313 QObject::tr(
"Value put inside the <link> element in the header. "
1314 "If not provided, a dummy value will be used as that element is compulsory." ),
1319 QObject::tr(
"Value put inside the <updated> element in the header. "
1320 "Should be formatted as a XML datetime. "
1321 "If not provided, a dummy value will be used as that element is compulsory." ),
1326 QObject::tr(
"Value put inside the <author><name> element in the header. "
1327 "If not provided, a dummy value will be used as that element is compulsory." ),
1332 QObject::tr(
"Value put inside the <id> element in the header. "
1333 "If not provided, a dummy value will be used as that element is compulsory." ),
1337 driverMetadata.insert( QStringLiteral(
"GeoRSS" ),
1339 QStringLiteral(
"GeoRSS" ),
1340 QObject::tr(
"GeoRSS" ),
1341 QStringLiteral(
"*.xml" ),
1342 QStringLiteral(
"xml" ),
1345 QStringLiteral(
"UTF-8" )
1350 datasetOptions.clear();
1351 layerOptions.clear();
1354 QObject::tr(
"If provided, this URI will be inserted as the schema location. "
1355 "Note that the schema file isn't actually accessed by OGR, so it "
1356 "is up to the user to ensure it will match the schema of the OGR "
1357 "produced GML data file." ),
1362 QObject::tr(
"This writes a GML application schema file to a corresponding "
1363 ".xsd file (with the same basename). If INTERNAL is used the "
1364 "schema is written within the GML file, but this is experimental "
1365 "and almost certainly not valid XML. "
1366 "OFF disables schema generation (and is implicit if XSISCHEMAURI is used)." ),
1368 << QStringLiteral(
"EXTERNAL" )
1369 << QStringLiteral(
"INTERNAL" )
1370 << QStringLiteral(
"OFF" ),
1371 QStringLiteral(
"EXTERNAL" )
1375 QObject::tr(
"This is the prefix for the application target namespace." ),
1376 QStringLiteral(
"ogr" )
1380 QObject::tr(
"Can be set to TRUE to avoid writing the prefix of the "
1381 "application target namespace in the GML file." ),
1386 QObject::tr(
"Defaults to 'http://ogr.maptools.org/'. "
1387 "This is the application target namespace." ),
1388 QStringLiteral(
"http://ogr.maptools.org/" )
1392 QObject::tr(
"If not specified, GML2 will be used." ),
1394 << QStringLiteral(
"GML3" )
1395 << QStringLiteral(
"GML3Deegree" )
1396 << QStringLiteral(
"GML3.2" ),
1402 QObject::tr(
"Only valid when FORMAT=GML3/GML3Degree/GML3.2. Default to YES. "
1403 "If YES, SRS with EPSG authority will be written with the "
1404 "'urn:ogc:def:crs:EPSG::' prefix. In the case the SRS is a "
1405 "geographic SRS without explicit AXIS order, but that the same "
1406 "SRS authority code imported with ImportFromEPSGA() should be "
1407 "treated as lat/long, then the function will take care of coordinate "
1408 "order swapping. If set to NO, SRS with EPSG authority will be "
1409 "written with the 'EPSG:' prefix, even if they are in lat/long order." ),
1414 QObject::tr(
"only valid when FORMAT=GML3/GML3Degree/GML3.2) Default to YES. "
1415 "If set to NO, the <gml:boundedBy> element will not be written for "
1421 QObject::tr(
"Default to YES. If YES, the output will be indented with spaces "
1422 "for more readability, but at the expense of file size." ),
1427 driverMetadata.insert( QStringLiteral(
"GML" ),
1429 QStringLiteral(
"Geography Markup Language [GML]" ),
1430 QObject::tr(
"Geography Markup Language [GML]" ),
1431 QStringLiteral(
"*.gml" ),
1432 QStringLiteral(
"gml" ),
1435 QStringLiteral(
"UTF-8" )
1440 datasetOptions.clear();
1441 layerOptions.clear();
1444 QObject::tr(
"Human-readable identifier (e.g. short name) for the layer content" ),
1449 QObject::tr(
"Human-readable description for the layer content" ),
1454 QObject::tr(
"Name for the feature identifier column" ),
1455 QStringLiteral(
"fid" )
1459 QObject::tr(
"Name for the geometry column" ),
1460 QStringLiteral(
"geom" )
1464 QObject::tr(
"If a spatial index must be created." ),
1468 driverMetadata.insert( QStringLiteral(
"GPKG" ),
1470 QStringLiteral(
"GeoPackage" ),
1471 QObject::tr(
"GeoPackage" ),
1472 QStringLiteral(
"*.gpkg" ),
1473 QStringLiteral(
"gpkg" ),
1476 QStringLiteral(
"UTF-8" )
1481 datasetOptions.clear();
1482 layerOptions.clear();
1484 driverMetadata.insert( QStringLiteral(
"GMT" ),
1486 QStringLiteral(
"Generic Mapping Tools [GMT]" ),
1487 QObject::tr(
"Generic Mapping Tools [GMT]" ),
1488 QStringLiteral(
"*.gmt" ),
1489 QStringLiteral(
"gmt" ),
1496 datasetOptions.clear();
1497 layerOptions.clear();
1500 QObject::tr(
"By default when writing a layer whose features are of "
1501 "type wkbLineString, the GPX driver chooses to write "
1502 "them as routes. If FORCE_GPX_TRACK=YES is specified, "
1503 "they will be written as tracks." ),
1508 QObject::tr(
"By default when writing a layer whose features are of "
1509 "type wkbMultiLineString, the GPX driver chooses to write "
1510 "them as tracks. If FORCE_GPX_ROUTE=YES is specified, "
1511 "they will be written as routes, provided that the multilines "
1512 "are composed of only one single line." ),
1517 QObject::tr(
"If GPX_USE_EXTENSIONS=YES is specified, "
1518 "extra fields will be written inside the <extensions> tag." ),
1523 QObject::tr(
"Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS_URL "
1524 "is set. The namespace value used for extension tags. By default, 'ogr'." ),
1525 QStringLiteral(
"ogr" )
1529 QObject::tr(
"Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS "
1530 "is set. The namespace URI. By default, 'http://osgeo.org/gdal'." ),
1531 QStringLiteral(
"http://osgeo.org/gdal" )
1535 QObject::tr(
"By default files are created with the line termination "
1536 "conventions of the local platform (CR/LF on win32 or LF "
1537 "on all other systems). This may be overridden through use "
1538 "of the LINEFORMAT layer creation option which may have a value "
1539 "of CRLF (DOS format) or LF (Unix format)." ),
1541 << QStringLiteral(
"CRLF" )
1542 << QStringLiteral(
"LF" ),
1547 driverMetadata.insert( QStringLiteral(
"GPX" ),
1549 QStringLiteral(
"GPS eXchange Format [GPX]" ),
1550 QObject::tr(
"GPS eXchange Format [GPX]" ),
1551 QStringLiteral(
"*.gpx" ),
1552 QStringLiteral(
"gpx" ),
1555 QStringLiteral(
"UTF-8" )
1560 datasetOptions.clear();
1561 layerOptions.clear();
1563 driverMetadata.insert( QStringLiteral(
"Interlis 1" ),
1565 QStringLiteral(
"INTERLIS 1" ),
1566 QObject::tr(
"INTERLIS 1" ),
1567 QStringLiteral(
"*.itf *.xml *.ili" ),
1568 QStringLiteral(
"ili" ),
1575 datasetOptions.clear();
1576 layerOptions.clear();
1578 driverMetadata.insert( QStringLiteral(
"Interlis 2" ),
1580 QStringLiteral(
"INTERLIS 2" ),
1581 QObject::tr(
"INTERLIS 2" ),
1582 QStringLiteral(
"*.xtf *.xml *.ili" ),
1583 QStringLiteral(
"ili" ),
1590 datasetOptions.clear();
1591 layerOptions.clear();
1594 QObject::tr(
"Allows you to specify the field to use for the KML <name> element." ),
1595 QStringLiteral(
"Name" )
1599 QObject::tr(
"Allows you to specify the field to use for the KML <description> element." ),
1600 QStringLiteral(
"Description" )
1604 QObject::tr(
"Allows you to specify the AltitudeMode to use for KML geometries. "
1605 "This will only affect 3D geometries and must be one of the valid KML options." ),
1607 << QStringLiteral(
"clampToGround" )
1608 << QStringLiteral(
"relativeToGround" )
1609 << QStringLiteral(
"absolute" ),
1610 QStringLiteral(
"relativeToGround" )
1614 QObject::tr(
"The DOCUMENT_ID datasource creation option can be used to specified "
1615 "the id of the root <Document> node. The default value is root_doc." ),
1616 QStringLiteral(
"root_doc" )
1619 driverMetadata.insert( QStringLiteral(
"KML" ),
1621 QStringLiteral(
"Keyhole Markup Language [KML]" ),
1622 QObject::tr(
"Keyhole Markup Language [KML]" ),
1623 QStringLiteral(
"*.kml" ),
1624 QStringLiteral(
"kml" ),
1627 QStringLiteral(
"UTF-8" )
1632 datasetOptions.clear();
1633 layerOptions.clear();
1635 auto insertMapInfoOptions = []( QMap<QString, QgsVectorFileWriter::Option *> &datasetOptions, QMap<QString, QgsVectorFileWriter::Option *> &layerOptions )
1638 QObject::tr(
"Use this to turn on 'quick spatial index mode'. "
1639 "In this mode writing files can be about 5 times faster, "
1640 "but spatial queries can be up to 30 times slower." ),
1642 << QStringLiteral(
"QUICK" )
1643 << QStringLiteral(
"OPTIMIZED" ),
1644 QStringLiteral(
"QUICK" ),
1649 QObject::tr(
"(multiples of 512): Block size for .map files. Defaults "
1650 "to 512. MapInfo 15.2 and above creates .tab files with a "
1651 "blocksize of 16384 bytes. Any MapInfo version should be "
1652 "able to handle block sizes from 512 to 32256." ),
1656 QObject::tr(
"xmin,ymin,xmax,ymax: Define custom layer bounds to increase the "
1657 "accuracy of the coordinates. Note: the geometry of written "
1658 "features must be within the defined box." ),
1662 insertMapInfoOptions( datasetOptions, layerOptions );
1664 driverMetadata.insert( QStringLiteral(
"MapInfo File" ),
1666 QStringLiteral(
"Mapinfo" ),
1667 QObject::tr(
"Mapinfo TAB" ),
1668 QStringLiteral(
"*.tab" ),
1669 QStringLiteral(
"tab" ),
1674 datasetOptions.clear();
1675 layerOptions.clear();
1676 insertMapInfoOptions( datasetOptions, layerOptions );
1679 driverMetadata.insert( QStringLiteral(
"MapInfo MIF" ),
1681 QStringLiteral(
"Mapinfo" ),
1682 QObject::tr(
"Mapinfo MIF" ),
1683 QStringLiteral(
"*.mif" ),
1684 QStringLiteral(
"mif" ),
1691 datasetOptions.clear();
1692 layerOptions.clear();
1695 QObject::tr(
"Determine whether 2D (seed_2d.dgn) or 3D (seed_3d.dgn) "
1696 "seed file should be used. This option is ignored if the SEED option is provided." ),
1701 QObject::tr(
"Override the seed file to use." ),
1706 QObject::tr(
"Indicate whether the whole seed file should be copied. "
1707 "If not, only the first three elements will be copied." ),
1712 QObject::tr(
"Indicates whether the color table should be copied from the seed file." ),
1717 QObject::tr(
"Override the master unit name from the seed file with "
1718 "the provided one or two character unit name." ),
1723 QObject::tr(
"Override the sub unit name from the seed file with the provided "
1724 "one or two character unit name." ),
1729 QObject::tr(
"Override the number of subunits per master unit. "
1730 "By default the seed file value is used." ),
1735 QObject::tr(
"Override the number of UORs (Units of Resolution) "
1736 "per sub unit. By default the seed file value is used." ),
1741 QObject::tr(
"ORIGIN=x,y,z: Override the origin of the design plane. "
1742 "By default the origin from the seed file is used." ),
1746 driverMetadata.insert( QStringLiteral(
"DGN" ),
1748 QStringLiteral(
"Microstation DGN" ),
1749 QObject::tr(
"Microstation DGN" ),
1750 QStringLiteral(
"*.dgn" ),
1751 QStringLiteral(
"dgn" ),
1758 datasetOptions.clear();
1759 layerOptions.clear();
1762 QObject::tr(
"Should update files be incorporated into the base data on the fly." ),
1764 << QStringLiteral(
"APPLY" )
1765 << QStringLiteral(
"IGNORE" ),
1766 QStringLiteral(
"APPLY" )
1770 QObject::tr(
"Should multipoint soundings be split into many single point sounding features. "
1771 "Multipoint geometries are not well handled by many formats, "
1772 "so it can be convenient to split single sounding features with many points "
1773 "into many single point features." ),
1778 QObject::tr(
"Should a DEPTH attribute be added on SOUNDG features and assign the depth "
1779 "of the sounding. This should only be enabled when SPLIT_MULTIPOINT is "
1785 QObject::tr(
"Should all the low level geometry primitives be returned as special "
1786 "IsolatedNode, ConnectedNode, Edge and Face layers." ),
1791 QObject::tr(
"If enabled, numeric attributes assigned an empty string as a value will "
1792 "be preserved as a special numeric value. This option should not generally "
1793 "be needed, but may be useful when translated S-57 to S-57 losslessly." ),
1798 QObject::tr(
"Should LNAM and LNAM_REFS fields be attached to features capturing "
1799 "the feature to feature relationships in the FFPT group of the S-57 file." ),
1804 QObject::tr(
"Should additional attributes relating features to their underlying "
1805 "geometric primitives be attached. These are the values of the FSPT group, "
1806 "and are primarily needed when doing S-57 to S-57 translations." ),
1811 QObject::tr(
"Should attribute values be recoded to UTF-8 from the character encoding "
1812 "specified in the S57 DSSI record." ),
1818 driverMetadata.insert( QStringLiteral(
"S57" ),
1820 QStringLiteral(
"S-57 Base file" ),
1821 QObject::tr(
"S-57 Base file" ),
1822 QStringLiteral(
"*.000" ),
1823 QStringLiteral(
"000" ),
1830 datasetOptions.clear();
1831 layerOptions.clear();
1833 driverMetadata.insert( QStringLiteral(
"SDTS" ),
1835 QStringLiteral(
"Spatial Data Transfer Standard [SDTS]" ),
1836 QObject::tr(
"Spatial Data Transfer Standard [SDTS]" ),
1837 QStringLiteral(
"*catd.ddf" ),
1838 QStringLiteral(
"ddf" ),
1845 datasetOptions.clear();
1846 layerOptions.clear();
1849 QObject::tr(
"Can be used to avoid creating the geometry_columns and spatial_ref_sys "
1850 "tables in a new database. By default these metadata tables are created "
1851 "when a new database is created." ),
1857 QStringLiteral(
"NO" )
1862 QStringLiteral(
"NO" )
1866 QObject::tr(
"Controls the format used for the geometry column. Defaults to WKB. "
1867 "This is generally more space and processing efficient, but harder "
1868 "to inspect or use in simple applications than WKT (Well Known Text)." ),
1870 << QStringLiteral(
"WKB" )
1871 << QStringLiteral(
"WKT" ),
1872 QStringLiteral(
"WKB" )
1876 QObject::tr(
"Controls whether layer and field names will be laundered for easier use "
1877 "in SQLite. Laundered names will be converted to lower case and some special "
1878 "characters(' - #) will be changed to underscores." ),
1883 QStringLiteral(
"NO" )
1887 QStringLiteral(
"NO" )
1895 QObject::tr(
"column_name1[,column_name2, …] A list of (String) columns that "
1896 "must be compressed with ZLib DEFLATE algorithm. This might be beneficial "
1897 "for databases that have big string blobs. However, use with care, since "
1898 "the value of such columns will be seen as compressed binary content with "
1899 "other SQLite utilities (or previous OGR versions). With OGR, when inserting, "
1900 "modifying or querying compressed columns, compression/decompression is "
1901 "done transparently. However, such columns cannot be (easily) queried with "
1902 "an attribute filter or WHERE clause. Note: in table definition, such columns "
1903 "have the 'VARCHAR_deflate' declaration type." ),
1907 driverMetadata.insert( QStringLiteral(
"SQLite" ),
1909 QStringLiteral(
"SQLite" ),
1910 QObject::tr(
"SQLite" ),
1911 QStringLiteral(
"*.sqlite" ),
1912 QStringLiteral(
"sqlite" ),
1915 QStringLiteral(
"UTF-8" )
1920 datasetOptions.clear();
1921 layerOptions.clear();
1924 QObject::tr(
"Can be used to avoid creating the geometry_columns and spatial_ref_sys "
1925 "tables in a new database. By default these metadata tables are created "
1926 "when a new database is created." ),
1931 QStringLiteral(
"YES" )
1935 QObject::tr(
"Insert the content of the EPSG CSV files into the spatial_ref_sys table. "
1936 "Set to NO for regular SQLite databases." ),
1941 QStringLiteral(
"SPATIALITE" )
1945 QObject::tr(
"Controls whether layer and field names will be laundered for easier use "
1946 "in SQLite. Laundered names will be converted to lower case and some special "
1947 "characters(' - #) will be changed to underscores." ),
1952 QObject::tr(
"If the database is of the SpatiaLite flavor, and if OGR is linked "
1953 "against libspatialite, this option can be used to control if a spatial "
1954 "index must be created." ),
1959 QObject::tr(
"If the format of the geometry BLOB is of the SpatiaLite flavor, "
1960 "this option can be used to control if the compressed format for "
1961 "geometries (LINESTRINGs, POLYGONs) must be used." ),
1966 QObject::tr(
"Used to force the SRID number of the SRS associated with the layer. "
1967 "When this option isn't specified and that a SRS is associated with the "
1968 "layer, a search is made in the spatial_ref_sys to find a match for the "
1969 "SRS, and, if there is no match, a new entry is inserted for the SRS in "
1970 "the spatial_ref_sys table. When the SRID option is specified, this "
1971 "search (and the eventual insertion of a new entry) will not be done: "
1972 "the specified SRID is used as such." ),
1977 QObject::tr(
"column_name1[,column_name2, …] A list of (String) columns that "
1978 "must be compressed with ZLib DEFLATE algorithm. This might be beneficial "
1979 "for databases that have big string blobs. However, use with care, since "
1980 "the value of such columns will be seen as compressed binary content with "
1981 "other SQLite utilities (or previous OGR versions). With OGR, when inserting, "
1982 "modifying or queryings compressed columns, compression/decompression is "
1983 "done transparently. However, such columns cannot be (easily) queried with "
1984 "an attribute filter or WHERE clause. Note: in table definition, such columns "
1985 "have the 'VARCHAR_deflate' declaration type." ),
1989 driverMetadata.insert( QStringLiteral(
"SpatiaLite" ),
1991 QStringLiteral(
"SpatiaLite" ),
1992 QObject::tr(
"SpatiaLite" ),
1993 QStringLiteral(
"*.sqlite" ),
1994 QStringLiteral(
"sqlite" ),
1997 QStringLiteral(
"UTF-8" )
2001 datasetOptions.clear();
2002 layerOptions.clear();
2005 QObject::tr(
"Override the header file used - in place of header.dxf." ),
2010 QObject::tr(
"Override the trailer file used - in place of trailer.dxf." ),
2014 driverMetadata.insert( QStringLiteral(
"DXF" ),
2016 QStringLiteral(
"AutoCAD DXF" ),
2017 QObject::tr(
"AutoCAD DXF" ),
2018 QStringLiteral(
"*.dxf" ),
2019 QStringLiteral(
"dxf" ),
2026 datasetOptions.clear();
2027 layerOptions.clear();
2030 QObject::tr(
"Indicates the GeoConcept export file extension. "
2031 "TXT was used by earlier releases of GeoConcept. GXT is currently used." ),
2033 << QStringLiteral(
"GXT" )
2034 << QStringLiteral(
"TXT" ),
2035 QStringLiteral(
"GXT" )
2039 QObject::tr(
"Path to the GCT: the GCT file describes the GeoConcept types definitions: "
2040 "In this file, every line must start with //# followed by a keyword. "
2041 "Lines starting with // are comments." ),
2046 QObject::tr(
"Defines the feature to be created. The TYPE corresponds to one of the Name "
2047 "found in the GCT file for a type section. The SUBTYPE corresponds to one of "
2048 "the Name found in the GCT file for a sub-type section within the previous "
2053 driverMetadata.insert( QStringLiteral(
"Geoconcept" ),
2055 QStringLiteral(
"Geoconcept" ),
2056 QObject::tr(
"Geoconcept" ),
2057 QStringLiteral(
"*.gxt *.txt" ),
2058 QStringLiteral(
"gxt" ),
2065 datasetOptions.clear();
2066 layerOptions.clear();
2069 QObject::tr(
"When this option is set, the new layer will be created inside the named "
2070 "FeatureDataset folder. If the folder does not already exist, it will be created." ),
2075 QObject::tr(
"Set name of geometry column in new layer. Defaults to 'SHAPE'." ),
2076 QStringLiteral(
"SHAPE" )
2080 QObject::tr(
"Name of the OID column to create. Defaults to 'OBJECTID'." ),
2081 QStringLiteral(
"OBJECTID" )
2084 driverMetadata.insert( QStringLiteral(
"FileGDB" ),
2086 QStringLiteral(
"ESRI FileGDB" ),
2087 QObject::tr(
"ESRI FileGDB" ),
2088 QStringLiteral(
"*.gdb" ),
2089 QStringLiteral(
"gdb" ),
2092 QStringLiteral(
"UTF-8" )
2097 datasetOptions.clear();
2098 layerOptions.clear();
2101 QObject::tr(
"By default, the driver will try to detect the data type of fields. If set "
2102 "to STRING, all fields will be of String type." ),
2104 << QStringLiteral(
"AUTO" )
2105 << QStringLiteral(
"STRING" ),
2106 QStringLiteral(
"AUTO" ),
2111 QObject::tr(
"By default, the driver will read the first lines of each sheet to detect "
2112 "if the first line might be the name of columns. If set to FORCE, the driver "
2113 "will consider the first line as the header line. If set to "
2114 "DISABLE, it will be considered as the first feature. Otherwise "
2115 "auto-detection will occur." ),
2117 << QStringLiteral(
"FORCE" )
2118 << QStringLiteral(
"DISABLE" )
2119 << QStringLiteral(
"AUTO" ),
2120 QStringLiteral(
"AUTO" ),
2124 driverMetadata.insert( QStringLiteral(
"XLSX" ),
2126 QStringLiteral(
"MS Office Open XML spreadsheet" ),
2127 QObject::tr(
"MS Office Open XML spreadsheet [XLSX]" ),
2128 QStringLiteral(
"*.xlsx" ),
2129 QStringLiteral(
"xlsx" ),
2132 QStringLiteral(
"UTF-8" )
2137 datasetOptions.clear();
2138 layerOptions.clear();
2141 QObject::tr(
"By default, the driver will try to detect the data type of fields. If set "
2142 "to STRING, all fields will be of String type." ),
2144 << QStringLiteral(
"AUTO" )
2145 << QStringLiteral(
"STRING" ),
2146 QStringLiteral(
"AUTO" ),
2151 QObject::tr(
"By default, the driver will read the first lines of each sheet to detect "
2152 "if the first line might be the name of columns. If set to FORCE, the driver "
2153 "will consider the first line as the header line. If set to "
2154 "DISABLE, it will be considered as the first feature. Otherwise "
2155 "auto-detection will occur." ),
2157 << QStringLiteral(
"FORCE" )
2158 << QStringLiteral(
"DISABLE" )
2159 << QStringLiteral(
"AUTO" ),
2160 QStringLiteral(
"AUTO" ),
2164 driverMetadata.insert( QStringLiteral(
"ODS" ),
2166 QStringLiteral(
"Open Document Spreadsheet" ),
2167 QObject::tr(
"Open Document Spreadsheet [ODS]" ),
2168 QStringLiteral(
"*.ods" ),
2169 QStringLiteral(
"ods" ),
2172 QStringLiteral(
"UTF-8" )
2177 datasetOptions.clear();
2178 layerOptions.clear();
2181 QObject::tr(
"Line termination character sequence." ),
2183 << QStringLiteral(
"CRLF" )
2184 << QStringLiteral(
"LF" ),
2185 QStringLiteral(
"LF" ),
2191 QObject::tr(
"Format of geometry columns." ),
2193 << QStringLiteral(
"geometry" )
2194 << QStringLiteral(
"geography" ),
2195 QStringLiteral(
"geometry" ),
2200 QObject::tr(
"Controls whether layer and field names will be laundered for easier use. "
2201 "Laundered names will be converted to lower case and some special "
2202 "characters(' - #) will be changed to underscores." ),
2207 QObject::tr(
"Name for the geometry column. Defaults to wkb_geometry "
2208 "for GEOM_TYPE=geometry or the_geog for GEOM_TYPE=geography" ) ) );
2211 QObject::tr(
"Name of schema into which to create the new table" ) ) );
2214 QObject::tr(
"Whether to explicitly emit the CREATE SCHEMA statement to create the specified schema." ),
2219 QObject::tr(
"Whether to explicitly recreate the table if necessary." ),
2224 QObject::tr(
"Whether to explicitly destroy tables before recreating them." ),
2226 << QStringLiteral(
"YES" )
2227 << QStringLiteral(
"NO" )
2228 << QStringLiteral(
"IF_EXISTS" ),
2229 QStringLiteral(
"YES" ),
2234 QObject::tr(
"Used to force the SRID number of the SRS associated with the layer. "
2235 "When this option isn't specified and that a SRS is associated with the "
2236 "layer, a search is made in the spatial_ref_sys to find a match for the "
2237 "SRS, and, if there is no match, a new entry is inserted for the SRS in "
2238 "the spatial_ref_sys table. When the SRID option is specified, this "
2239 "search (and the eventual insertion of a new entry) will not be done: "
2240 "the specified SRID is used as such." ),
2245 QObject::tr(
"Can be set to 2.0 or 2.2 for PostGIS 2.0/2.2 compatibility. "
2246 "Important to set it correctly if using non-linear geometry types" ),
2247 QStringLiteral(
"2.2" )
2250 driverMetadata.insert( QStringLiteral(
"PGDUMP" ),
2252 QStringLiteral(
"PostgreSQL SQL dump" ),
2253 QObject::tr(
"PostgreSQL SQL dump" ),
2254 QStringLiteral(
"*.sql" ),
2255 QStringLiteral(
"sql" ),
2258 QStringLiteral(
"UTF-8" )
2264 QgsVectorFileWriterMetadataContainer(
const QgsVectorFileWriterMetadataContainer &other ) =
delete;
2265 QgsVectorFileWriterMetadataContainer &operator=(
const QgsVectorFileWriterMetadataContainer &other ) =
delete;
2266 ~QgsVectorFileWriterMetadataContainer()
2268 for (
auto it = driverMetadata.constBegin(); it != driverMetadata.constEnd(); ++it )
2270 for (
auto optionIt = it.value().driverOptions.constBegin(); optionIt != it.value().driverOptions.constEnd(); ++optionIt )
2271 delete optionIt.value();
2272 for (
auto optionIt = it.value().layerOptions.constBegin(); optionIt != it.value().layerOptions.constEnd(); ++optionIt )
2273 delete optionIt.value();
2277 QMap<QString, QgsVectorFileWriter::MetaData> driverMetadata;
2284 static QgsVectorFileWriterMetadataContainer sDriverMetadata;
2285 QMap<QString, MetaData>::ConstIterator it = sDriverMetadata.driverMetadata.constBegin();
2287 for ( ; it != sDriverMetadata.driverMetadata.constEnd(); ++it )
2289 if ( it.key() == QLatin1String(
"PGDUMP" ) &&
2290 driverName != QLatin1String(
"PGDUMP" ) &&
2291 driverName != QLatin1String(
"PostgreSQL SQL dump" ) )
2296 if ( it.key().startsWith( driverName ) || it.value().longName.startsWith( driverName ) )
2311 return QStringList();
2320 return QStringList();
2327 OGRwkbGeometryType ogrType =
static_cast<OGRwkbGeometryType
>( type );
2353 QgsFeatureList::iterator fIt = features.begin();
2355 for ( ; fIt != features.end(); ++fIt )
2380 QString styleString;
2381 QString currentStyle;
2383 QgsSymbolList::const_iterator symbolIt = symbols.constBegin();
2384 for ( ; symbolIt != symbols.constEnd(); ++symbolIt )
2386 int nSymbolLayers = ( *symbolIt )->symbolLayerCount();
2387 for (
int i = 0; i < nSymbolLayers; ++i )
2390 QMap< QgsSymbolLayer *, QString >::const_iterator it =
mSymbolLayerTable.find( ( *symbolIt )->symbolLayer( i ) );
2396 double mmsf = mmScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
2397 double musf = mapUnitScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
2399 currentStyle = ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf );
2403 if ( symbolIt != symbols.constBegin() || i != 0 )
2405 styleString.append(
';' );
2407 styleString.append( currentStyle );
2411 OGR_F_SetStyleString( poFeature.get(), currentStyle.toLocal8Bit().constData() );
2412 if ( !writeFeature(
mLayer, poFeature.get() ) )
2419 OGR_F_SetStyleString( poFeature.get(), styleString.toLocal8Bit().constData() );
2424 if ( !writeFeature(
mLayer, poFeature.get() ) )
2441 if ( fid > std::numeric_limits<int>::max() )
2443 QgsDebugMsg( QStringLiteral(
"feature id %1 too large." ).arg( fid ) );
2444 OGRErr err = OGR_F_SetFID( poFeature.get(),
static_cast<long>( fid ) );
2445 if ( err != OGRERR_NONE )
2447 QgsDebugMsg( QStringLiteral(
"Failed to set feature id to %1: %2 (OGR error: %3)" )
2448 .arg( feature.
id() )
2449 .arg( err ).arg( CPLGetLastErrorMsg() )
2457 int fldIdx = it.key();
2458 int ogrField = it.value();
2460 QVariant attrValue = feature.
attribute( fldIdx );
2463 if ( !attrValue.isValid() || attrValue.isNull() )
2472 #ifdef OGRNullMarker
2473 OGR_F_SetFieldNull( poFeature.get(), ogrField );
2488 mErrorMessage = QObject::tr(
"Error converting value (%1) for attribute field %2: %3" )
2489 .arg( feature.
attribute( fldIdx ).toString(),
2499 OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
2501 case QVariant::LongLong:
2502 OGR_F_SetFieldInteger64( poFeature.get(), ogrField, attrValue.toLongLong() );
2504 case QVariant::Bool:
2505 OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
2507 case QVariant::String:
2508 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toString() ).constData() );
2510 case QVariant::Double:
2511 OGR_F_SetFieldDouble( poFeature.get(), ogrField, attrValue.toDouble() );
2513 case QVariant::Date:
2514 OGR_F_SetFieldDateTime( poFeature.get(), ogrField,
2515 attrValue.toDate().year(),
2516 attrValue.toDate().month(),
2517 attrValue.toDate().day(),
2520 case QVariant::DateTime:
2523 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toDateTime().toString( QStringLiteral(
"yyyy/MM/dd hh:mm:ss.zzz" ) ) ).constData() );
2527 OGR_F_SetFieldDateTime( poFeature.get(), ogrField,
2528 attrValue.toDateTime().date().year(),
2529 attrValue.toDateTime().date().month(),
2530 attrValue.toDateTime().date().day(),
2531 attrValue.toDateTime().time().hour(),
2532 attrValue.toDateTime().time().minute(),
2533 attrValue.toDateTime().time().second(),
2537 case QVariant::Time:
2540 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toString() ).constData() );
2544 OGR_F_SetFieldDateTime( poFeature.get(), ogrField,
2546 attrValue.toTime().hour(),
2547 attrValue.toTime().minute(),
2548 attrValue.toTime().second(),
2553 case QVariant::ByteArray:
2555 const QByteArray ba = attrValue.toByteArray();
2556 OGR_F_SetFieldBinary( poFeature.get(), ogrField, ba.size(),
const_cast< GByte *
>(
reinterpret_cast< const GByte *
>( ba.data() ) ) );
2560 case QVariant::Invalid:
2563 case QVariant::StringList:
2565 QStringList list = attrValue.toStringList();
2566 if ( mSupportedListSubTypes.contains( QVariant::String ) )
2568 int count = list.count();
2569 char **lst =
new char *[count + 1];
2573 for (
const QString &
string : list )
2575 lst[pos] = CPLStrdup(
mCodec->fromUnicode(
string ).data() );
2579 lst[count] =
nullptr;
2580 OGR_F_SetFieldStringList( poFeature.get(), ogrField, lst );
2585 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( list.join(
',' ) ).constData() );
2590 case QVariant::List:
2594 QStringList list = attrValue.toStringList();
2595 if ( mSupportedListSubTypes.contains( QVariant::String ) )
2597 int count = list.count();
2598 char **lst =
new char *[count + 1];
2602 for (
const QString &
string : list )
2604 lst[pos] = CPLStrdup(
mCodec->fromUnicode(
string ).data() );
2608 lst[count] =
nullptr;
2609 OGR_F_SetFieldStringList( poFeature.get(), ogrField, lst );
2614 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( list.join(
',' ) ).constData() );
2620 const QVariantList list = attrValue.toList();
2621 if ( mSupportedListSubTypes.contains( QVariant::Int ) )
2623 const int count = list.count();
2624 int *lst =
new int[count];
2628 for (
const QVariant &value : list )
2630 lst[pos] = value.toInt();
2634 OGR_F_SetFieldIntegerList( poFeature.get(), ogrField, count, lst );
2639 QStringList strings;
2640 strings.reserve( list.size() );
2641 for (
const QVariant &value : list )
2643 strings << QString::number( value.toInt() );
2645 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
2651 const QVariantList list = attrValue.toList();
2652 if ( mSupportedListSubTypes.contains( QVariant::Double ) )
2654 const int count = list.count();
2655 double *lst =
new double[count];
2659 for (
const QVariant &value : list )
2661 lst[pos] = value.toDouble();
2665 OGR_F_SetFieldDoubleList( poFeature.get(), ogrField, count, lst );
2670 QStringList strings;
2671 strings.reserve( list.size() );
2672 for (
const QVariant &value : list )
2674 strings << QString::number( value.toDouble() );
2676 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
2682 const QVariantList list = attrValue.toList();
2683 if ( mSupportedListSubTypes.contains( QVariant::LongLong ) )
2685 const int count = list.count();
2686 long long *lst =
new long long[count];
2690 for (
const QVariant &value : list )
2692 lst[pos] = value.toLongLong();
2696 OGR_F_SetFieldInteger64List( poFeature.get(), ogrField, count, lst );
2701 QStringList strings;
2702 strings.reserve( list.size() );
2703 for (
const QVariant &value : list )
2705 strings << QString::number( value.toLongLong() );
2707 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
2715 mErrorMessage = QObject::tr(
"Invalid variant type for field %1[%2]: received %3 with type %4" )
2718 .arg( attrValue.typeName(),
2719 attrValue.toString() );
2732 if ( mCoordinateTransform )
2737 geom.
transform( *mCoordinateTransform );
2755 OGRGeometryH mGeom2 =
nullptr;
2801 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
2802 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
2808 QByteArray wkb( geom.
asWkb() );
2809 OGRErr err = OGR_G_ImportFromWkb( mGeom2,
reinterpret_cast<unsigned char *
>(
const_cast<char *
>( wkb.constData() ) ), wkb.length() );
2810 if ( err != OGRERR_NONE )
2812 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
2813 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
2820 OGR_F_SetGeometryDirectly( poFeature.get(), mGeom2 );
2826 OGRErr err = OGR_G_ImportFromWkb( ogrGeom,
reinterpret_cast<unsigned char *
>(
const_cast<char *
>( wkb.constData() ) ), wkb.length() );
2827 if ( err != OGRERR_NONE )
2829 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
2830 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
2837 OGR_F_SetGeometryDirectly( poFeature.get(), ogrGeom );
2852 for (
int i = 0; i < attributes.size(); i++ )
2854 if ( omap.find( i ) != omap.end() )
2859 bool QgsVectorFileWriter::writeFeature( OGRLayerH layer, OGRFeatureH feature )
2861 if ( OGR_L_CreateFeature( layer, feature ) != OGRERR_NONE )
2863 mErrorMessage = QObject::tr(
"Feature creation error (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
2873 if ( mUsingTransaction )
2875 if ( OGRERR_NONE != OGR_L_CommitTransaction(
mLayer ) )
2877 QgsDebugMsg( QStringLiteral(
"Error while committing transaction on OGRLayer." ) );
2881 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,1,0) && GDAL_VERSION_NUM <= GDAL_COMPUTE_VERSION(3,1,3)
2885 QString drvName = GDALGetDriverShortName( GDALGetDatasetDriver(
mDS.get() ) );
2886 if ( drvName == QLatin1String(
"XLSX" ) ||
2887 drvName == QLatin1String(
"ODS" ) )
2889 CPLSetThreadLocalConfigOption(
"CPL_CREATE_ZIP64",
"NO" );
2891 CPLSetThreadLocalConfigOption(
"CPL_CREATE_ZIP64",
nullptr );
2900 OSRDestroySpatialReference(
mOgrRef );
2906 const QString &fileName,
2907 const QString &fileEncoding,
2909 const QString &driverName,
2911 QString *errorMessage,
2912 const QStringList &datasourceOptions,
2913 const QStringList &layerOptions,
2914 bool skipAttributeCreation,
2915 QString *newFilename,
2917 double symbologyScale,
2927 if ( destCRS.
isValid() && layer )
2953 const QString &fileName,
2954 const QString &fileEncoding,
2956 const QString &driverName,
2958 QString *errorMessage,
2959 const QStringList &datasourceOptions,
2960 const QStringList &layerOptions,
2961 bool skipAttributeCreation,
2962 QString *newFilename,
2964 double symbologyScale,
2995 : driverName( QStringLiteral(
"GPKG" ) )
3003 if ( !layer || !layer->
isValid() )
3010 details.sourceCrs = layer->
crs();
3011 details.sourceWkbType = layer->
wkbType();
3012 details.sourceFields = layer->
fields();
3021 if ( details.storageType == QLatin1String(
"ESRI Shapefile" ) )
3029 details.geometryTypeScanIterator = layer->
getFeatures( req );
3033 details.renderContext.setExpressionContext( details.expressionContext );
3034 details.renderContext.setRendererScale( options.
symbologyScale );
3036 details.shallTransform =
false;
3041 details.shallTransform =
true;
3046 details.outputCrs = details.sourceCrs;
3049 details.destWkbType = details.sourceWkbType;
3063 details.attributes.clear();
3064 else if ( details.attributes.isEmpty() )
3066 const QgsAttributeList allAttributes = details.sourceFields.allAttributesList();
3067 for (
int idx : allAttributes )
3069 QgsField fld = details.sourceFields.at( idx );
3070 if ( details.providerType == QLatin1String(
"oracle" ) && fld.
typeName().contains( QLatin1String(
"SDO_GEOMETRY" ) ) )
3072 details.attributes.append( idx );
3076 if ( !details.attributes.isEmpty() )
3078 for (
int attrIdx : std::as_const( details.attributes ) )
3080 details.outputFields.append( details.sourceFields.at( attrIdx ) );
3086 if ( details.providerType == QLatin1String(
"spatialite" ) )
3088 for (
int i = 0; i < details.outputFields.size(); i++ )
3090 if ( details.outputFields.at( i ).type() == QVariant::LongLong )
3095 if ( std::max( std::llabs( min.toLongLong() ), std::llabs( max.toLongLong() ) ) < std::numeric_limits<int>::max() )
3097 details.outputFields[i].setType( QVariant::Int );
3105 addRendererAttributes( details.renderer.get(), details.renderContext, details.sourceFields, details.attributes );
3115 bool useFilterRect =
true;
3116 if ( details.shallTransform )
3125 useFilterRect =
false;
3128 if ( useFilterRect )
3134 details.filterRectEngine->prepareGeometry();
3136 details.sourceFeatureIterator = layer->
getFeatures( req );
3150 int lastProgressReport = 0;
3151 long long total = details.featureCount;
3154 if ( details.providerType == QLatin1String(
"ogr" ) && !details.dataSourceUri.isEmpty() )
3156 QString srcFileName( details.providerUriParams.value( QStringLiteral(
"path" ) ).toString() );
3157 if ( QFile::exists( srcFileName ) && QFileInfo( fileName ).canonicalFilePath() == QFileInfo( srcFileName ).canonicalFilePath() )
3161 if ( !( ( options.
driverName == QLatin1String(
"GPKG" ) ||
3162 options.
driverName == QLatin1String(
"SpatiaLite" ) ||
3163 options.
driverName == QLatin1String(
"SQLite" ) ) &&
3164 options.
layerName != details.providerUriParams.value( QStringLiteral(
"layerName" ) ) ) )
3167 *
errorMessage = QObject::tr(
"Cannot overwrite a OGR layer in place" );
3187 int newProgress =
static_cast<int>( ( 5.0 * scanned ) / total );
3188 if ( newProgress != lastProgressReport )
3190 lastProgressReport = newProgress;
3205 QString tempNewFilename;
3206 QString tempNewLayer;
3208 std::unique_ptr< QgsVectorFileWriter > writer(
create( fileName, details.outputFields, destWkbType, details.outputCrs, transformContext, options, QgsFeatureSink::SinkFlags(), &tempNewFilename, &tempNewLayer ) );
3212 *newFilename = tempNewFilename;
3215 *newLayer = tempNewLayer;
3255 int n = 0, errors = 0;
3264 writer->startRender( details.renderer.get(), details.sourceFields );
3266 writer->resetMap( details.attributes );
3268 writer->mFields = details.sourceFields;
3272 int initialProgress = lastProgressReport;
3273 while ( details.sourceFeatureIterator.nextFeature( fet ) )
3284 int newProgress =
static_cast<int>( initialProgress + ( ( 100.0 - initialProgress ) * saved ) / total );
3285 if ( newProgress < 100 && newProgress != lastProgressReport )
3287 lastProgressReport = newProgress;
3292 if ( details.shallTransform )
3305 QString msg = QObject::tr(
"Failed to transform a point while drawing a feature with ID '%1'. Writing stopped. (Exception: %2)" )
3306 .arg( fet.
id() ).arg( e.
what() );
3323 if ( !writer->addFeatureWithStyle( fet, writer->mRenderer.get(), mapUnits ) )
3330 *
errorMessage = QObject::tr(
"Feature write errors:" );
3336 if ( errors > 1000 )
3340 *
errorMessage += QObject::tr(
"Stopping after %1 errors" ).arg( errors );
3350 writer->stopRender();
3354 *
errorMessage += QObject::tr(
"\nOnly %1 of %2 features written." ).arg( n - errors ).arg( n );
3359 bool metadataFailure =
false;
3364 {QStringLiteral(
"path" ), tempNewFilename },
3365 {QStringLiteral(
"layerName" ), tempNewLayer }
3379 metadataFailure =
true;
3390 metadataFailure =
true;
3398 const QString &fileName,
3400 QString *newFilename,
3404 QgsVectorFileWriter::PreparedWriterDetails details;
3405 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
3413 const QString &fileName,
3416 QString *newFilename,
3420 QgsVectorFileWriter::PreparedWriterDetails details;
3421 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
3430 QgsVectorFileWriter::PreparedWriterDetails details;
3431 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
3440 QFileInfo fi( fileName );
3441 QDir dir = fi.dir();
3444 for (
const char *suffix : {
".shp",
".shx",
".dbf",
".prj",
".qix",
".qpj",
".cpg",
".sbn",
".sbx",
".idm",
".ind" } )
3446 filter << fi.completeBaseName() + suffix;
3450 const auto constEntryList = dir.entryList( filter );
3451 for (
const QString &file : constEntryList )
3453 QFile f( dir.canonicalPath() +
'/' + file );
3456 QgsDebugMsg( QStringLiteral(
"Removing file %1 failed: %2" ).arg( file, f.errorString() ) );
3472 static QReadWriteLock sFilterLock;
3473 static QMap< VectorFormatOptions, QList< QgsVectorFileWriter::FilterFormatDetails > > sFilters;
3477 const auto it = sFilters.constFind( options );
3478 if ( it != sFilters.constEnd() )
3482 QList< QgsVectorFileWriter::FilterFormatDetails > results;
3485 int const drvCount = OGRGetDriverCount();
3487 for (
int i = 0; i < drvCount; ++i )
3489 OGRSFDriverH drv = OGRGetDriver( i );
3492 QString drvName = OGR_Dr_GetName( drv );
3494 GDALDriverH gdalDriver = GDALGetDriverByName( drvName.toLocal8Bit().constData() );
3495 char **metadata =
nullptr;
3498 metadata = GDALGetMetadata( gdalDriver,
nullptr );
3501 bool nonSpatialFormat = CSLFetchBoolean( metadata, GDAL_DCAP_NONSPATIAL,
false );
3503 if ( OGR_Dr_TestCapability( drv,
"CreateDataSource" ) != 0 )
3508 if ( nonSpatialFormat )
3513 if ( filterString.isEmpty() )
3520 globs = metadata.
glob.toLower().split(
' ' );
3526 details.
globs = globs;
3535 if ( options & SortRecommended )
3537 if ( a.driverName == QLatin1String(
"GPKG" ) )
3539 else if ( b.driverName == QLatin1String(
"GPKG" ) )
3541 else if ( a.driverName == QLatin1String(
"ESRI Shapefile" ) )
3543 else if ( b.driverName == QLatin1String(
"ESRI Shapefile" ) )
3550 sFilters.insert( options, results );
3557 QSet< QString > extensions;
3559 const QRegularExpression rx( QStringLiteral(
"\\*\\.(.*)$" ) );
3563 for (
const QString &glob : format.globs )
3565 const QRegularExpressionMatch match = rx.match( glob );
3566 if ( !match.hasMatch() )
3569 const QString matched = match.captured( 1 );
3570 extensions.insert( matched );
3574 QStringList extensionList = qgis::setToList( extensions );
3576 std::sort( extensionList.begin(), extensionList.end(), [options](
const QString & a,
const QString & b ) ->
bool
3578 if ( options & SortRecommended )
3580 if ( a == QLatin1String(
"gpkg" ) )
3582 else if ( b == QLatin1String(
"gpkg" ) )
3584 else if ( a == QLatin1String(
"shp" ) )
3586 else if ( b == QLatin1String(
"shp" ) )
3590 return a.toLower().localeAwareCompare( b.toLower() ) < 0;
3593 return extensionList;
3598 QList< QgsVectorFileWriter::DriverDetails > results;
3601 const int drvCount = OGRGetDriverCount();
3603 QStringList writableDrivers;
3604 for (
int i = 0; i < drvCount; ++i )
3606 OGRSFDriverH drv = OGRGetDriver( i );
3609 QString drvName = OGR_Dr_GetName( drv );
3615 if ( drvName == QLatin1String(
"ODS" ) || drvName == QLatin1String(
"XLSX" ) || drvName == QLatin1String(
"XLS" ) )
3619 if ( drvName == QLatin1String(
"ESRI Shapefile" ) )
3621 writableDrivers << QStringLiteral(
"DBF file" );
3623 if ( OGR_Dr_TestCapability( drv,
"CreateDataSource" ) != 0 )
3626 if ( drvName == QLatin1String(
"MapInfo File" ) )
3628 writableDrivers << QStringLiteral(
"MapInfo MIF" );
3630 else if ( drvName == QLatin1String(
"SQLite" ) )
3637 QString option = QStringLiteral(
"SPATIALITE=YES" );
3638 char *options[2] = { CPLStrdup( option.toLocal8Bit().constData() ),
nullptr };
3639 OGRSFDriverH poDriver;
3641 poDriver = OGRGetDriverByName( drvName.toLocal8Bit().constData() );
3644 gdal::ogr_datasource_unique_ptr ds( OGR_Dr_CreateDataSource( poDriver, QStringLiteral(
"/vsimem/spatialitetest.sqlite" ).toUtf8().constData(), options ) );
3647 writableDrivers << QStringLiteral(
"SpatiaLite" );
3648 OGR_Dr_DeleteDataSource( poDriver, QStringLiteral(
"/vsimem/spatialitetest.sqlite" ).toUtf8().constData() );
3651 CPLFree( options[0] );
3653 writableDrivers << drvName;
3658 results.reserve( writableDrivers.count() );
3659 for (
const QString &drvName : std::as_const( writableDrivers ) )
3673 if ( options & SortRecommended )
3675 if ( a.driverName == QLatin1String(
"GPKG" ) )
3677 else if ( b.driverName == QLatin1String(
"GPKG" ) )
3679 else if ( a.driverName == QLatin1String(
"ESRI Shapefile" ) )
3681 else if ( b.driverName == QLatin1String(
"ESRI Shapefile" ) )
3685 return a.
longName.toLower().localeAwareCompare( b.
longName.toLower() ) < 0;
3692 QString ext = extension.trimmed();
3693 if ( ext.isEmpty() )
3696 if ( ext.startsWith(
'.' ) )
3700 int const drvCount = GDALGetDriverCount();
3702 for (
int i = 0; i < drvCount; ++i )
3704 GDALDriverH drv = GDALGetDriver( i );
3710 QString drvName = GDALGetDriverShortName( drv );
3711 QStringList driverExtensions = QString( GDALGetMetadataItem( drv, GDAL_DMD_EXTENSIONS,
nullptr ) ).split(
' ' );
3713 const auto constDriverExtensions = driverExtensions;
3714 for (
const QString &driver : constDriverExtensions )
3716 if ( driver.compare( ext, Qt::CaseInsensitive ) == 0 )
3727 QString filterString;
3731 if ( !filterString.isEmpty() )
3732 filterString += QLatin1String(
";;" );
3734 filterString += details.filterString;
3736 return filterString;
3745 return QStringLiteral(
"%1 (%2 %3)" ).arg( metadata.
trLongName,
3746 metadata.
glob.toLower(),
3747 metadata.
glob.toUpper() );
3752 if ( codecName == QLatin1String(
"System" ) )
3753 return QStringLiteral(
"LDID/0" );
3755 QRegExp re = QRegExp( QString(
"(CP|windows-|ISO[ -])(.+)" ), Qt::CaseInsensitive );
3756 if ( re.exactMatch( codecName ) )
3758 QString
c = re.cap( 2 ).remove(
'-' );
3760 ( void )
c.toInt( &isNumber );
3788 OGRStyleTableH ogrStyleTable = OGR_STBL_Create();
3789 OGRStyleMgrH styleManager = OGR_SM_Create( ogrStyleTable );
3792 int nTotalLevels = 0;
3794 QgsSymbolList::iterator symbolIt = symbolList.begin();
3795 for ( ; symbolIt != symbolList.end(); ++symbolIt )
3797 double mmsf = mmScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
3798 double musf = mapUnitScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
3800 int nLevels = ( *symbolIt )->symbolLayerCount();
3801 for (
int i = 0; i < nLevels; ++i )
3803 mSymbolLayerTable.insert( ( *symbolIt )->symbolLayer( i ), QString::number( nTotalLevels ) );
3804 OGR_SM_AddStyle( styleManager, QString::number( nTotalLevels ).toLocal8Bit(),
3805 ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf ).toLocal8Bit() );
3809 OGR_DS_SetStyleTableDirectly( ds, ogrStyleTable );
3815 if ( !details.renderer )
3820 QHash< QgsSymbol *, QList<QgsFeature> > features;
3829 startRender( details.renderer.get(), details.sourceFields );
3849 QString msg = QObject::tr(
"Failed to transform, writing stopped. (Exception: %1)" )
3860 featureSymbol = mRenderer->symbolForFeature( fet, mRenderContext );
3861 if ( !featureSymbol )
3866 QHash< QgsSymbol *, QList<QgsFeature> >::iterator it = features.find( featureSymbol );
3867 if ( it == features.end() )
3869 it = features.insert( featureSymbol, QList<QgsFeature>() );
3871 it.value().append( fet );
3876 QgsSymbolList symbols = mRenderer->symbols( mRenderContext );
3877 for (
int i = 0; i < symbols.count(); i++ )
3883 if ( level < 0 || level >= 1000 )
3886 while ( level >= levels.count() )
3888 levels[level].append( item );
3893 int nTotalFeatures = 0;
3896 for (
int l = 0; l < levels.count(); l++ )
3899 for (
int i = 0; i < level.count(); i++ )
3902 QHash< QgsSymbol *, QList<QgsFeature> >::iterator levelIt = features.find( item.
symbol() );
3903 if ( levelIt == features.end() )
3909 double mmsf = mmScaleFactor(
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
3910 double musf = mapUnitScaleFactor(
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
3912 int llayer = item.
layer();
3913 QList<QgsFeature> &featureList = levelIt.value();
3914 QList<QgsFeature>::iterator featureIt = featureList.begin();
3915 for ( ; featureIt != featureList.end(); ++featureIt )
3925 QString styleString = levelIt.key()->symbolLayer( llayer )->ogrFeatureStyle( mmsf, musf );
3926 if ( !styleString.isEmpty() )
3928 OGR_F_SetStyleString( ogrFeature.get(), styleString.toLocal8Bit().constData() );
3929 if ( !writeFeature(
mLayer, ogrFeature.get() ) )
3942 *
errorMessage += QObject::tr(
"\nOnly %1 of %2 features written." ).arg( nTotalFeatures - nErrors ).arg( nTotalFeatures );
3959 return 1000 / scale;
3976 return scale / 1000;
3984 mRenderer = createSymbologyRenderer( sourceRenderer );
3990 mRenderer->startRender( mRenderContext, fields );
3993 void QgsVectorFileWriter::stopRender()
4000 mRenderer->stopRender( mRenderContext );
4003 std::unique_ptr<QgsFeatureRenderer> QgsVectorFileWriter::createSymbologyRenderer(
QgsFeatureRenderer *sourceRenderer )
const
4009 if ( !sourceRenderer )
4014 return std::unique_ptr< QgsFeatureRenderer >( sourceRenderer->
clone() );
4021 const QSet<QString> rendererAttributes = renderer->
usedAttributes( context );
4022 for (
const QString &attr : rendererAttributes )
4027 attList.append( index );
4033 QStringList QgsVectorFileWriter::concatenateOptions(
const QMap<QString, QgsVectorFileWriter::Option *> &options )
4036 QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
4038 for ( it = options.constBegin(); it != options.constEnd(); ++it )
4041 switch ( option->
type )
4048 list.append( QStringLiteral(
"%1=%2" ).arg( it.key() ).arg( opt->
defaultValue ) );
4058 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
defaultValue ) );
4068 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
defaultValue ) );
4077 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
mValue ) );
4088 OGRSFDriverH hDriver =
nullptr;
4091 return QgsVectorFileWriter::EditionCapabilities();
4092 QString drvName = OGR_Dr_GetName( hDriver );
4093 QgsVectorFileWriter::EditionCapabilities caps = QgsVectorFileWriter::EditionCapabilities();
4094 if ( OGR_DS_TestCapability( hDS.get(), ODsCCreateLayer ) )
4099 if ( !( drvName == QLatin1String(
"ESRI Shapefile" ) && QFile::exists( datasetName ) ) )
4102 if ( OGR_DS_TestCapability( hDS.get(), ODsCDeleteLayer ) )
4106 int layer_count = OGR_DS_GetLayerCount( hDS.get() );
4109 OGRLayerH hLayer = OGR_DS_GetLayer( hDS.get(), 0 );
4112 if ( OGR_L_TestCapability( hLayer, OLCSequentialWrite ) )
4115 if ( OGR_L_TestCapability( hLayer, OLCCreateField ) )
4126 const QString &layerNameIn )
4128 OGRSFDriverH hDriver =
nullptr;
4133 QString layerName( layerNameIn );
4134 if ( layerName.isEmpty() )
4135 layerName = QFileInfo( datasetName ).baseName();
4137 return OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
4142 const QString &layerName,
4146 OGRSFDriverH hDriver =
nullptr;
4150 OGRLayerH hLayer = OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
4156 OGRFeatureDefnH defn = OGR_L_GetLayerDefn( hLayer );
4157 const auto constAttributes = attributes;
4158 for (
int idx : constAttributes )
4161 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.
QString authid() const
Returns the authority identifier for the CRS.
@ WKT_PREFERRED_GDAL
Preferred format for conversion of CRS to WKT for use with the GDAL library.
QString toWkt(WktVariant variant=WKT1_GDAL, bool multiline=false, int indentationWidth=4) const
Returns a WKT representation of this CRS.
Q_GADGET QgsUnitTypes::DistanceUnit mapUnits
Contains information about the context in which a coordinate transform is executed.
Custom exception class for Coordinate Reference System related exceptions.
virtual QString dataSourceUri(bool expandAuthConfig=false) const
Gets the data source specification.
Class for storing the component parts of a RDBMS data source URI (e.g.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
virtual QgsFeatureRenderer * clone() const =0
Create a deep copy of this renderer.
virtual QgsSymbolList symbolsForFeature(const QgsFeature &feature, QgsRenderContext &context) const
Returns list of symbols used for rendering the feature.
virtual QgsSymbolList symbols(QgsRenderContext &context) const
Returns list of symbols used by the renderer.
bool usingSymbolLevels() const
virtual QgsFeatureRenderer::Capabilities capabilities()
Returns details about internals of this renderer.
@ SymbolLevels
Rendering with symbol levels (i.e. implements symbols(), symbolForFeature())
virtual QSet< QString > usedAttributes(const QgsRenderContext &context) const =0
Returns a list of attributes required by this renderer.
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Sets feature IDs that should be fetched.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
QgsFeatureRequest & setFilterRect(const QgsRectangle &rectangle)
Sets the rectangle from which features will be taken.
@ RegeneratePrimaryKey
This flag indicates, that a primary key field cannot be guaranteed to be unique and the sink should i...
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
void initAttributes(int fieldCount)
Initialize this feature with the given number of fields.
bool hasGeometry() const
Returns true if the feature has an associated geometry.
QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
bool isCanceled() const SIP_HOLDGIL
Tells whether the operation has been canceled already.
void setProgress(double progress)
Sets the current progress for the feedback object.
Encapsulate a field in an attribute table or data source.
QString typeName() const
Gets the field type.
bool convertCompatible(QVariant &v, QString *errorMessage=nullptr) const
Converts the provided variant to a compatible format.
QVariant::Type subType() const
If the field is a collection, gets its element's type.
Container of fields for a vector layer.
int count() const
Returns number of items.
int size() const
Returns number of items.
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
A geometry is the spatial representation of a feature.
const QgsAbstractGeometry * constGet() const SIP_HOLDGIL
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
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.
OperationResult transform(const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection direction=QgsCoordinateTransform::ForwardTransform, bool transformZ=false) SIP_THROW(QgsCsException)
Transforms this geometry as described by the coordinate transform ct.
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.
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.
int renderingPass() const
Specifies the rendering pass in which this symbol layer should be rendered.
int layer() const
The layer of this symbol level.
QgsSymbol * symbol() const
The symbol of this symbol level.
Abstract base class for all rendered symbols.
QgsSymbolLayer * symbolLayer(int layer)
Returns the symbol layer at the specified index.
int symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
DistanceUnit
Units of distance.
RenderUnit
Rendering size units.
@ RenderMillimeters
Millimeters.
@ RenderMapUnits
Map units.
Interface to convert raw field values to their user-friendly value.
virtual QVariant convert(int fieldIdxInLayer, const QVariant &value)
Convert the provided value, for field fieldIdxInLayer.
virtual QgsVectorFileWriter::FieldValueConverter * clone() const
Creates a clone of the FieldValueConverter.
virtual QgsField fieldDefinition(const QgsField &field)
Returns a possibly modified field definition.
QgsVectorFileWriter::OptionType type
Options to pass to writeAsVectorFormat()
QString fileEncoding
Encoding to use.
bool forceMulti
Sets to true to force creation of multi* geometries.
FieldNameSource fieldNameSource
Source for exported field names.
QString driverName
OGR driver to use.
QgsCoordinateTransform ct
Transform to reproject exported geometries with, or invalid transform for no transformation.
QgsLayerMetadata layerMetadata
Layer metadata to save for the exported vector file.
SaveVectorOptions()
Constructor.
QString layerName
Layer name. If let empty, it will be derived from the filename.
QgsRectangle filterExtent
If not empty, only features intersecting the extent will be saved.
QgsVectorFileWriter::FieldValueConverter * fieldValueConverter
Field value converter.
QStringList layerOptions
List of OGR layer creation options.
QgsVectorFileWriter::SymbologyExport symbologyExport
Symbology to export.
bool includeZ
Sets to true to include z dimension in output. This option is only valid if overrideGeometryType is s...
bool saveMetadata
Set to true to save layer metadata for the exported vector file.
QgsVectorFileWriter::ActionOnExistingFile actionOnExistingFile
Action on existing file.
QgsAttributeList attributes
Attributes to export (empty means all unless skipAttributeCreation is set)
bool onlySelectedFeatures
Write only selected features of layer.
bool skipAttributeCreation
Only write geometries.
double symbologyScale
Scale of symbology.
QStringList datasourceOptions
List of OGR data source creation options.
QgsWkbTypes::Type overrideGeometryType
Set to a valid geometry type to override the default geometry type for the layer.
QgsFeedback * feedback
Optional feedback object allowing cancellation of layer save.
A convenience class for writing vector layers to disk based formats (e.g.
static QgsVectorFileWriter::WriterError writeAsVectorFormatV3(QgsVectorLayer *layer, const QString &fileName, const QgsCoordinateTransformContext &transformContext, const QgsVectorFileWriter::SaveVectorOptions &options, QString *errorMessage=nullptr, QString *newFilename=nullptr, QString *newLayer=nullptr)
Writes a layer out to a vector file.
QString lastError() const override
Returns the most recent error encountered by the sink, e.g.
@ CanAddNewFieldsToExistingLayer
Flag to indicate that new fields can be added to an existing layer. Imply CanAppendToExistingLayer.
@ CanAppendToExistingLayer
Flag to indicate that new features can be added to an existing layer.
@ CanAddNewLayer
Flag to indicate that a new layer can be added to the dataset.
@ CanDeleteLayer
Flag to indicate that an existing layer can be deleted.
static QgsVectorFileWriter::EditionCapabilities editionCapabilities(const QString &datasetName)
Returns edition capabilities for an existing dataset name.
static QgsVectorFileWriter * create(const QString &fileName, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &srs, const QgsCoordinateTransformContext &transformContext, const QgsVectorFileWriter::SaveVectorOptions &options, QgsFeatureSink::SinkFlags sinkFlags=QgsFeatureSink::SinkFlags(), QString *newFilename=nullptr, QString *newLayer=nullptr)
Create a new vector file writer.
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a single feature to the sink.
static bool supportsFeatureStyles(const QString &driverName)
Returns true if the specified driverName supports feature styles.
bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a list of features to the sink.
double mSymbologyScale
Scale for symbology export (e.g. for symbols units in map units)
OGRGeometryH createEmptyGeometry(QgsWkbTypes::Type wkbType)
QMap< int, int > mAttrIdxToOgrIdx
Map attribute indizes to OGR field indexes.
@ ErrAttributeTypeUnsupported
@ Canceled
Writing was interrupted by manual cancellation.
@ ErrAttributeCreationFailed
@ ErrSavingMetadata
Metadata saving failed.
gdal::ogr_datasource_unique_ptr mDS
static Q_DECL_DEPRECATED QgsVectorFileWriter::WriterError writeAsVectorFormatV2(QgsVectorLayer *layer, const QString &fileName, const QgsCoordinateTransformContext &transformContext, const QgsVectorFileWriter::SaveVectorOptions &options, QString *newFilename=nullptr, QString *newLayer=nullptr, QString *errorMessage=nullptr)
Writes a layer out to a vector file.
~QgsVectorFileWriter() override
Close opened shapefile for writing.
static bool targetLayerExists(const QString &datasetName, const QString &layerName)
Returns whether the target layer already exists.
double symbologyScale() const
Returns the reference scale for output.
static QStringList defaultLayerOptions(const QString &driverName)
Returns a list of the default layer options for a specified driver.
SymbologyExport mSymbologyExport
static QString driverForExtension(const QString &extension)
Returns the OGR driver name for a specified file extension.
static QList< QgsVectorFileWriter::FilterFormatDetails > supportedFiltersAndFormats(VectorFormatOptions options=SortRecommended)
Returns a list or pairs, with format filter string as first element and OGR format key as second elem...
OGRSpatialReferenceH mOgrRef
static bool driverMetadata(const QString &driverName, MetaData &driverMetadata)
QgsVectorFileWriter::WriterError hasError()
Checks whether there were any errors in constructor.
static bool deleteShapeFile(const QString &fileName)
Delete a shapefile (and its accompanying shx / dbf / prj / qix / qpj / cpg / sbn / sbx / idm / ind)
static QString filterForDriver(const QString &driverName)
Creates a filter for an OGR driver key.
QgsWkbTypes::Type mWkbType
Geometry type which is being used.
static OGRwkbGeometryType ogrTypeFromWkbType(QgsWkbTypes::Type type)
Gets the ogr geometry type from an internal QGIS wkb type enum.
@ SkipNonSpatialFormats
Filter out any formats which do not have spatial support (e.g. those which cannot save geometries)
static bool areThereNewFieldsToCreate(const QString &datasetName, const QString &layerName, QgsVectorLayer *layer, const QgsAttributeList &attributes)
Returns whether there are among the attributes specified some that do not exist yet in the layer.
static QList< QgsVectorFileWriter::DriverDetails > ogrDriverList(VectorFormatOptions options=SortRecommended)
Returns the driver list that can be used for dialogs.
static Q_DECL_DEPRECATED QgsVectorFileWriter::WriterError writeAsVectorFormat(QgsVectorLayer *layer, const QString &fileName, const QString &fileEncoding, const QgsCoordinateReferenceSystem &destCRS=QgsCoordinateReferenceSystem(), const QString &driverName="GPKG", bool onlySelected=false, QString *errorMessage=nullptr, const QStringList &datasourceOptions=QStringList(), const QStringList &layerOptions=QStringList(), bool skipAttributeCreation=false, QString *newFilename=nullptr, QgsVectorFileWriter::SymbologyExport symbologyExport=QgsVectorFileWriter::NoSymbology, double symbologyScale=1.0, const QgsRectangle *filterExtent=nullptr, QgsWkbTypes::Type overrideGeometryType=QgsWkbTypes::Unknown, bool forceMulti=false, bool includeZ=false, const QgsAttributeList &attributes=QgsAttributeList(), QgsVectorFileWriter::FieldValueConverter *fieldValueConverter=nullptr, QString *newLayer=nullptr)
Write contents of vector layer to an (OGR supported) vector format.
WriterError mError
Contains error value if construction was not successful.
FieldNameSource
Source for exported field names.
@ PreferAlias
Use the field alias as the exported field name, wherever one is set. Otherwise use the original field...
@ Original
Use original field names.
static QStringList defaultDatasetOptions(const QString &driverName)
Returns a list of the default dataset options for a specified driver.
static QStringList supportedFormatExtensions(VectorFormatOptions options=SortRecommended)
Returns a list of file extensions for supported formats, e.g "shp", "gpkg".
QString errorMessage()
Retrieves error message.
static QString convertCodecNameForEncodingOption(const QString &codecName)
Converts codec name to string passed to ENCODING layer creation option of OGR Shapefile.
FieldValueConverter * mFieldValueConverter
Field value converter.
bool addFeatureWithStyle(QgsFeature &feature, QgsFeatureRenderer *renderer, QgsUnitTypes::DistanceUnit outputUnit=QgsUnitTypes::DistanceMeters)
Adds a feature to the currently opened data source, using the style from a specified renderer.
QgsVectorFileWriter::SymbologyExport symbologyExport() const
void setSymbologyScale(double scale)
Set reference scale for output.
Q_DECL_DEPRECATED QgsVectorFileWriter(const QString &vectorFileName, const QString &fileEncoding, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &srs=QgsCoordinateReferenceSystem(), const QString &driverName="GPKG", const QStringList &datasourceOptions=QStringList(), const QStringList &layerOptions=QStringList(), QString *newFilename=nullptr, QgsVectorFileWriter::SymbologyExport symbologyExport=QgsVectorFileWriter::NoSymbology, QgsFeatureSink::SinkFlags sinkFlags=QgsFeatureSink::SinkFlags(), QString *newLayer=nullptr, const QgsCoordinateTransformContext &transformContext=QgsCoordinateTransformContext(), FieldNameSource fieldNameSource=Original)
Create a new vector file writer.
QMap< QgsSymbolLayer *, QString > mSymbolLayerTable
static QString fileFilterString(VectorFormatOptions options=SortRecommended)
Returns filter string that can be used for dialogs.
ActionOnExistingFile
Combination of CanAddNewLayer, CanAppendToExistingLayer, CanAddNewFieldsToExistingLayer or CanDeleteL...
@ CreateOrOverwriteLayer
Create or overwrite layer.
@ CreateOrOverwriteFile
Create or overwrite file.
@ AppendToLayerNoNewFields
Append features to existing layer, but do not create new fields.
@ AppendToLayerAddFields
Append features to existing layer, and create new fields if needed.
Represents a vector layer which manages a vector based data sets.
Q_INVOKABLE QgsWkbTypes::Type wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
long long featureCount(const QString &legendKey) const
Number of features rendered with specified legend key.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
int selectedFeatureCount() const
Returns the number of features that are selected in this layer.
Q_INVOKABLE const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
void minimumAndMaximumValue(int index, QVariant &minimum, QVariant &maximum) const
Calculates both the minimum and maximum value for an attribute column.
QgsFeatureRenderer * renderer()
Returns the feature renderer used for rendering the features in the layer in 2D map views.
static bool isMultiType(Type type) SIP_HOLDGIL
Returns true if the WKB type is a multi type.
static bool hasM(Type type) SIP_HOLDGIL
Tests whether a WKB type contains m values.
Type
The WKB type describes the number of dimensions a geometry has.
static Type to25D(Type type) SIP_HOLDGIL
Will convert the 25D version of the flat type if supported or Unknown if not supported.
static Type singleType(Type type) SIP_HOLDGIL
Returns the single type for a WKB type.
static Type flatType(Type type) SIP_HOLDGIL
Returns the flat type for a WKB type.
static Type multiType(Type type) SIP_HOLDGIL
Returns the multi type for a WKB type.
static Type addZ(Type type) SIP_HOLDGIL
Adds the z dimension to a WKB type and returns the new type.
static bool hasZ(Type type) SIP_HOLDGIL
Tests whether a WKB type contains the z-dimension.
std::unique_ptr< std::remove_pointer< OGRFeatureH >::type, OGRFeatureDeleter > ogr_feature_unique_ptr
Scoped OGR feature.
std::unique_ptr< std::remove_pointer< OGRDataSourceH >::type, OGRDataSourceDeleter > ogr_datasource_unique_ptr
Scoped OGR data source.
std::unique_ptr< std::remove_pointer< OGRFieldDefnH >::type, OGRFldDeleter > ogr_field_def_unique_ptr
Scoped OGR field definition.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
#define Q_NOWARN_DEPRECATED_POP
#define Q_NOWARN_DEPRECATED_PUSH
QList< QgsFeature > QgsFeatureList
#define FID_TO_NUMBER(fid)
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.