50#include <QRegularExpression>
51#include <QJsonDocument>
57#include <ogr_srs_api.h>
60#include <cpl_string.h>
79 const QString &vectorFileName,
80 const QString &fileEncoding,
84 const QString &driverName,
85 const QStringList &datasourceOptions,
86 const QStringList &layerOptions,
89 QgsFeatureSink::SinkFlags sinkFlags,
99 init( vectorFileName, fileEncoding, fields, geometryType,
100 srs, driverName, datasourceOptions, layerOptions, newFilename,
nullptr,
105 const QString &vectorFileName,
106 const QString &fileEncoding,
110 const QString &driverName,
111 const QStringList &datasourceOptions,
112 const QStringList &layerOptions,
113 QString *newFilename,
116 const QString &layerName,
120 QgsFeatureSink::SinkFlags sinkFlags,
124 , mWkbType( geometryType )
125 , mSymbologyExport( symbologyExport )
126 , mSymbologyScale( 1.0 )
128 init( vectorFileName, fileEncoding, fields, geometryType, srs, driverName,
129 datasourceOptions, layerOptions, newFilename, fieldValueConverter,
130 layerName, action, newLayer, sinkFlags, transformContext, fieldNameSource );
134 const QString &fileName,
140 QgsFeatureSink::SinkFlags sinkFlags,
141 QString *newFilename,
155 if ( driverName == QLatin1String(
"MapInfo MIF" ) )
159 GDALDriverH gdalDriver = GDALGetDriverByName( driverName.toLocal8Bit().constData() );
167 return CSLFetchBoolean(
driverMetadata, GDAL_DCAP_FEATURE_STYLES,
false );
170void QgsVectorFileWriter::init( QString vectorFileName,
171 QString fileEncoding,
175 const QString &driverName,
176 QStringList datasourceOptions,
177 QStringList layerOptions,
178 QString *newFilename,
179 FieldValueConverter *fieldValueConverter,
180 const QString &layerNameIn,
181 ActionOnExistingFile action,
182 QString *newLayer, SinkFlags sinkFlags,
187 if ( vectorFileName.isEmpty() )
194 if ( driverName == QLatin1String(
"MapInfo MIF" ) )
198 else if ( driverName == QLatin1String(
"SpatiaLite" ) )
201 if ( !datasourceOptions.contains( QStringLiteral(
"SPATIALITE=YES" ) ) )
203 datasourceOptions.append( QStringLiteral(
"SPATIALITE=YES" ) );
206 else if ( driverName == QLatin1String(
"DBF file" ) )
209 if ( !layerOptions.contains( QStringLiteral(
"SHPT=NULL" ) ) )
211 layerOptions.append( QStringLiteral(
"SHPT=NULL" ) );
220#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,3,1)
221 QString fidFieldName;
224 for (
const QString &layerOption : layerOptions )
226 if ( layerOption.startsWith( QLatin1String(
"FID=" ) ) )
228 fidFieldName = layerOption.mid( 4 );
232 if ( fidFieldName.isEmpty() )
233 fidFieldName = QStringLiteral(
"fid" );
238 OGRSFDriverH poDriver;
241 poDriver = OGRGetDriverByName(
mOgrDriverName.toLocal8Bit().constData() );
245 mErrorMessage = QObject::tr(
"OGR driver for '%1' not found (OGR error: %2)" )
247 QString::fromUtf8( CPLGetLastErrorMsg() ) );
257 if ( layerOptions.join( QString() ).toUpper().indexOf( QLatin1String(
"ENCODING=" ) ) == -1 )
262 if ( driverName == QLatin1String(
"ESRI Shapefile" ) && !vectorFileName.endsWith( QLatin1String(
".shp" ), Qt::CaseInsensitive ) )
264 vectorFileName += QLatin1String(
".shp" );
266 else if ( driverName == QLatin1String(
"DBF file" ) && !vectorFileName.endsWith( QLatin1String(
".dbf" ), Qt::CaseInsensitive ) )
268 vectorFileName += QLatin1String(
".dbf" );
278#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
279 QStringList allExts = metadata.ext.split(
' ', QString::SkipEmptyParts );
281 QStringList allExts = metadata.ext.split(
' ', Qt::SkipEmptyParts );
284 const auto constAllExts = allExts;
285 for (
const QString &ext : constAllExts )
287 if ( vectorFileName.endsWith(
'.' + ext, Qt::CaseInsensitive ) )
296 vectorFileName +=
'.' + allExts[0];
302 if ( vectorFileName.endsWith( QLatin1String(
".gdb" ), Qt::CaseInsensitive ) )
304 QDir dir( vectorFileName );
307 QFileInfoList fileList = dir.entryInfoList(
308 QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files, QDir::DirsFirst );
309 const auto constFileList = fileList;
310 for (
const QFileInfo &info : constFileList )
312 QFile::remove( info.absoluteFilePath() );
315 QDir().rmdir( vectorFileName );
319 QFile::remove( vectorFileName );
324 if ( metadataFound && !metadata.compulsoryEncoding.isEmpty() )
326 if ( fileEncoding.compare( metadata.compulsoryEncoding, Qt::CaseInsensitive ) != 0 )
328 QgsDebugMsgLevel( QStringLiteral(
"forced %1 encoding for %2" ).arg( metadata.compulsoryEncoding, driverName ), 2 );
329 fileEncoding = metadata.compulsoryEncoding;
334 char **options =
nullptr;
335 if ( !datasourceOptions.isEmpty() )
337 options =
new char *[ datasourceOptions.size() + 1 ];
338 for (
int i = 0; i < datasourceOptions.size(); i++ )
340 QgsDebugMsgLevel( QStringLiteral(
"-dsco=%1" ).arg( datasourceOptions[i] ), 2 );
341 options[i] = CPLStrdup( datasourceOptions[i].toLocal8Bit().constData() );
343 options[ datasourceOptions.size()] =
nullptr;
350 mDS.reset( OGR_Dr_CreateDataSource( poDriver, vectorFileName.toUtf8().constData(), options ) );
352 mDS.reset( OGROpen( vectorFileName.toUtf8().constData(), TRUE,
nullptr ) );
356 for (
int i = 0; i < datasourceOptions.size(); i++ )
357 CPLFree( options[i] );
366 mErrorMessage = QObject::tr(
"Creation of data source failed (OGR error: %1)" )
367 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
369 mErrorMessage = QObject::tr(
"Opening of data source in update mode failed (OGR error: %1)" )
370 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
374 QString layerName( layerNameIn );
375 if ( layerName.isEmpty() )
376 layerName = QFileInfo( vectorFileName ).baseName();
380 const int layer_count = OGR_DS_GetLayerCount(
mDS.get() );
381 for (
int i = 0; i < layer_count; i++ )
383 OGRLayerH hLayer = OGR_DS_GetLayer(
mDS.get(), i );
384 if ( EQUAL( OGR_L_GetName( hLayer ), layerName.toUtf8().constData() ) )
386 if ( OGR_DS_DeleteLayer(
mDS.get(), i ) != OGRERR_NONE )
389 mErrorMessage = QObject::tr(
"Overwriting of existing layer failed (OGR error: %1)" )
390 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
404 QgsDebugMsgLevel( QStringLiteral(
"Opened data source in update mode" ), 2 );
408 mCodec = QTextCodec::codecForName( fileEncoding.toLocal8Bit().constData() );
411 QgsDebugMsg(
"error finding QTextCodec for " + fileEncoding );
414 QString enc = settings.
value( QStringLiteral(
"UI/encoding" ),
"System" ).toString();
415 mCodec = QTextCodec::codecForName( enc.toLocal8Bit().constData() );
418 QgsDebugMsg(
"error finding QTextCodec for " + enc );
419 mCodec = QTextCodec::codecForLocale();
425 if ( driverName == QLatin1String(
"KML" ) || driverName == QLatin1String(
"LIBKML" ) || driverName == QLatin1String(
"GPX" ) )
427 if ( srs.
authid() != QLatin1String(
"EPSG:4326" ) )
442 int optIndex = layerOptions.indexOf( QLatin1String(
"FEATURE_DATASET=" ) );
443 if ( optIndex != -1 )
445 layerOptions.removeAt( optIndex );
448 if ( !layerOptions.isEmpty() )
450 options =
new char *[ layerOptions.size() + 1 ];
451 for (
int i = 0; i < layerOptions.size(); i++ )
454 options[i] = CPLStrdup( layerOptions[i].toLocal8Bit().constData() );
456 options[ layerOptions.size()] =
nullptr;
460 CPLSetConfigOption(
"SHAPE_ENCODING",
"" );
464 mLayer = OGR_DS_CreateLayer(
mDS.get(), layerName.toUtf8().constData(),
mOgrRef, wkbType, options );
467 *newLayer = OGR_L_GetName(
mLayer );
468 if ( driverName == QLatin1String(
"GPX" ) )
475 if ( !EQUAL( layerName.toUtf8().constData(),
"track_points" ) &&
476 !EQUAL( layerName.toUtf8().constData(),
"route_points" ) )
478 *newLayer = QStringLiteral(
"waypoints" );
485 const char *pszForceGPXTrack
486 = CSLFetchNameValue( options,
"FORCE_GPX_TRACK" );
487 if ( pszForceGPXTrack && CPLTestBool( pszForceGPXTrack ) )
488 *newLayer = QStringLiteral(
"tracks" );
490 *newLayer = QStringLiteral(
"routes" );
497 const char *pszForceGPXRoute
498 = CSLFetchNameValue( options,
"FORCE_GPX_ROUTE" );
499 if ( pszForceGPXRoute && CPLTestBool( pszForceGPXRoute ) )
500 *newLayer = QStringLiteral(
"routes" );
502 *newLayer = QStringLiteral(
"tracks" );
512 else if ( driverName == QLatin1String(
"DGN" ) )
514 mLayer = OGR_DS_GetLayerByName(
mDS.get(),
"elements" );
518 mLayer = OGR_DS_GetLayerByName(
mDS.get(), layerName.toUtf8().constData() );
523 for (
int i = 0; i < layerOptions.size(); i++ )
524 CPLFree( options[i] );
533 QString layerName = vectorFileName.left( vectorFileName.indexOf( QLatin1String(
".shp" ), Qt::CaseInsensitive ) );
534 QFile prjFile( layerName +
".qpj" );
535 if ( prjFile.exists() )
543 mErrorMessage = QObject::tr(
"Creation of layer failed (OGR error: %1)" )
544 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
546 mErrorMessage = QObject::tr(
"Opening of layer failed (OGR error: %1)" )
547 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
552 OGRFeatureDefnH defn = OGR_L_GetLayerDefn(
mLayer );
561 QSet<int> existingIdxs;
571 for (
int fldIdx = 0; fldIdx < fields.
count(); ++fldIdx )
575 if ( fieldValueConverter )
577 attrField = fieldValueConverter->fieldDefinition( fields.
at( fldIdx ) );
582 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( attrField.
name() ) );
591 switch ( fieldNameSource )
594 name = attrField.
name();
598 name = !attrField.
alias().isEmpty() ? attrField.
alias() : attrField.
name();
602 OGRFieldType ogrType = OFTString;
603 OGRFieldSubType ogrSubType = OFSTNone;
604 int ogrWidth = attrField.
length();
605 int ogrPrecision = attrField.
precision();
606 if ( ogrPrecision > 0 )
609 switch ( attrField.
type() )
611 case QVariant::LongLong:
613 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
614 if ( pszDataTypes && strstr( pszDataTypes,
"Integer64" ) )
615 ogrType = OFTInteger64;
618 ogrWidth = ogrWidth > 0 && ogrWidth <= 20 ? ogrWidth : 20;
622 case QVariant::String:
624 if ( ( ogrWidth <= 0 || ogrWidth > 255 ) &&
mOgrDriverName == QLatin1String(
"ESRI Shapefile" ) )
629 ogrType = OFTInteger;
630 ogrWidth = ogrWidth > 0 && ogrWidth <= 10 ? ogrWidth : 10;
635 ogrType = OFTInteger;
636 ogrSubType = OFSTBoolean;
641 case QVariant::Double:
642#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,3,1)
643 if (
mOgrDriverName == QLatin1String(
"GPKG" ) && attrField.
precision() == 0 && attrField.
name().compare( fidFieldName, Qt::CaseInsensitive ) == 0 )
646 ogrType = OFTInteger64;
669 case QVariant::DateTime:
677 ogrType = OFTDateTime;
681 case QVariant::ByteArray:
685 case QVariant::StringList:
691 ogrSubType = OFSTJSON;
695 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
696 if ( pszDataTypes && strstr( pszDataTypes,
"StringList" ) )
698 ogrType = OFTStringList;
699 mSupportedListSubTypes.insert( QVariant::String );
714 ogrSubType = OFSTJSON;
719 if ( attrField.
subType() == QVariant::String )
721 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
722 if ( pszDataTypes && strstr( pszDataTypes,
"StringList" ) )
724 ogrType = OFTStringList;
725 mSupportedListSubTypes.insert( QVariant::String );
734 else if ( attrField.
subType() == QVariant::Int )
736 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
737 if ( pszDataTypes && strstr( pszDataTypes,
"IntegerList" ) )
739 ogrType = OFTIntegerList;
740 mSupportedListSubTypes.insert( QVariant::Int );
749 else if ( attrField.
subType() == QVariant::Double )
751 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
752 if ( pszDataTypes && strstr( pszDataTypes,
"RealList" ) )
754 ogrType = OFTRealList;
755 mSupportedListSubTypes.insert( QVariant::Double );
764 else if ( attrField.
subType() == QVariant::LongLong )
766 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
767 if ( pszDataTypes && strstr( pszDataTypes,
"Integer64List" ) )
769 ogrType = OFTInteger64List;
770 mSupportedListSubTypes.insert( QVariant::LongLong );
784 mErrorMessage = QObject::tr(
"Unsupported type for field %1" )
785 .arg( attrField.
name() );
790 if (
mOgrDriverName == QLatin1String(
"SQLite" ) && name.compare( QLatin1String(
"ogc_fid" ), Qt::CaseInsensitive ) == 0 )
793 for ( i = 0; i < 10; i++ )
795 name = QStringLiteral(
"ogc_fid%1" ).arg( i );
798 for ( j = 0; j < fields.
size() && name.compare( fields.
at( j ).
name(), Qt::CaseInsensitive ) != 0; j++ )
801 if ( j == fields.
size() )
807 mErrorMessage = QObject::tr(
"No available replacement for internal fieldname ogc_fid found" ).arg( attrField.
name() );
812 QgsMessageLog::logMessage( QObject::tr(
"Reserved attribute name ogc_fid replaced with %1" ).arg( name ), QObject::tr(
"OGR" ) );
819 OGR_Fld_SetWidth( fld.get(), ogrWidth );
822 if ( ogrPrecision >= 0 )
824 OGR_Fld_SetPrecision( fld.get(), ogrPrecision );
827 if ( ogrSubType != OFSTNone )
828 OGR_Fld_SetSubType( fld.get(), ogrSubType );
832 " type " + QString( QVariant::typeToName( attrField.
type() ) ) +
833 " width " + QString::number( ogrWidth ) +
834 " precision " + QString::number( ogrPrecision ), 2 );
835 if ( OGR_L_CreateField(
mLayer, fld.get(),
true ) != OGRERR_NONE )
838 mErrorMessage = QObject::tr(
"Creation of field %1 failed (OGR error: %2)" )
839 .arg( attrField.
name(),
840 QString::fromUtf8( CPLGetLastErrorMsg() ) );
845 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( name ) );
846 QgsDebugMsgLevel( QStringLiteral(
"returned field index for %1: %2" ).arg( name ).arg( ogrIdx ), 2 );
847 if ( ogrIdx < 0 || existingIdxs.contains( ogrIdx ) )
850 ogrIdx = OGR_FD_GetFieldCount( defn ) - 1;
855 mErrorMessage = QObject::tr(
"Created field %1 not found (OGR error: %2)" )
856 .arg( attrField.
name(),
857 QString::fromUtf8( CPLGetLastErrorMsg() ) );
863 existingIdxs.insert( ogrIdx );
871 for (
int fldIdx = 0; fldIdx < fields.
count(); ++fldIdx )
874 QString name( attrField.
name() );
875 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( name ) );
887 int fidIdx = fields.
lookupField( QStringLiteral(
"FID" ) );
898 *newFilename = vectorFileName;
901 mUsingTransaction =
true;
902 if ( OGRERR_NONE != OGR_L_StartTransaction(
mLayer ) )
904 mUsingTransaction =
false;
914class QgsVectorFileWriterMetadataContainer
918 QgsVectorFileWriterMetadataContainer()
920 QMap<QString, QgsVectorFileWriter::Option *> datasetOptions;
921 QMap<QString, QgsVectorFileWriter::Option *> layerOptions;
924 datasetOptions.clear();
925 layerOptions.clear();
928 QObject::tr(
"Compression method." ),
930 << QStringLiteral(
"UNCOMPRESSED" )
931 << QStringLiteral(
"ZSTD" )
932 << QStringLiteral(
"LZ4" ),
933 QStringLiteral(
"LZ4" ),
938 QObject::tr(
"Geometry encoding." ),
940 << QStringLiteral(
"GEOARROW" )
941 << QStringLiteral(
"WKB" )
942 << QStringLiteral(
"WKT" ),
943 QStringLiteral(
"GEOARROW" ),
948 QObject::tr(
"Maximum number of rows per batch." ),
953 QObject::tr(
"Name for the feature identifier column" ),
958 QObject::tr(
"Name for the geometry column" ),
959 QStringLiteral(
"geometry" )
962 driverMetadata.insert( QStringLiteral(
"Arrow" ),
964 QStringLiteral(
"(Geo)Arrow" ),
965 QObject::tr(
"(Geo)Arrow" ),
966 QStringLiteral(
"*.arrow *.feather *.arrows *.ipc" ),
967 QStringLiteral(
"arrow" ),
970 QStringLiteral(
"UTF-8" )
975 datasetOptions.clear();
976 layerOptions.clear();
978 driverMetadata.insert( QStringLiteral(
"AVCE00" ),
980 QStringLiteral(
"Arc/Info ASCII Coverage" ),
981 QObject::tr(
"Arc/Info ASCII Coverage" ),
982 QStringLiteral(
"*.e00" ),
983 QStringLiteral(
"e00" ),
990#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,3,0)
994 datasetOptions.clear();
995 layerOptions.clear();
998 QObject::tr(
"New BNA files are created by the "
999 "systems default line termination conventions. "
1000 "This may be overridden here." ),
1002 << QStringLiteral(
"CRLF" )
1003 << QStringLiteral(
"LF" ),
1009 QObject::tr(
"By default, BNA files are created in multi-line format. "
1010 "For each record, the first line contains the identifiers and the "
1011 "type/number of coordinates to follow. Each following line contains "
1012 "a pair of coordinates." ),
1017 QObject::tr(
"BNA records may contain from 2 to 4 identifiers per record. "
1018 "Some software packages only support a precise number of identifiers. "
1019 "You can override the default value (2) by a precise value." ),
1021 << QStringLiteral(
"2" )
1022 << QStringLiteral(
"3" )
1023 << QStringLiteral(
"4" )
1024 << QStringLiteral(
"NB_SOURCE_FIELDS" ),
1025 QStringLiteral(
"2" )
1029 QObject::tr(
"The BNA writer will try to recognize ellipses and circles when writing a polygon. "
1030 "This will only work if the feature has previously been read from a BNA file. "
1031 "As some software packages do not support ellipses/circles in BNA data file, "
1032 "it may be useful to tell the writer by specifying ELLIPSES_AS_ELLIPSES=NO not "
1033 "to export them as such, but keep them as polygons." ),
1038 QObject::tr(
"Limit the number of coordinate pairs per line in multiline format." ),
1043 QObject::tr(
"Set the number of decimal for coordinates. Default value is 10." ),
1047 driverMetadata.insert( QStringLiteral(
"BNA" ),
1049 QStringLiteral(
"Atlas BNA" ),
1050 QObject::tr(
"Atlas BNA" ),
1051 QStringLiteral(
"*.bna" ),
1052 QStringLiteral(
"bna" ),
1060 datasetOptions.clear();
1061 layerOptions.clear();
1064 QObject::tr(
"By default when creating new .csv files they "
1065 "are created with the line termination conventions "
1066 "of the local platform (CR/LF on Win32 or LF on all other systems). "
1067 "This may be overridden through the use of the LINEFORMAT option." ),
1069 << QStringLiteral(
"CRLF" )
1070 << QStringLiteral(
"LF" ),
1076 QObject::tr(
"By default, the geometry of a feature written to a .csv file is discarded. "
1077 "It is possible to export the geometry in its WKT representation by "
1078 "specifying GEOMETRY=AS_WKT. It is also possible to export point geometries "
1079 "into their X,Y,Z components by specifying GEOMETRY=AS_XYZ, GEOMETRY=AS_XY "
1080 "or GEOMETRY=AS_YX." ),
1082 << QStringLiteral(
"AS_WKT" )
1083 << QStringLiteral(
"AS_XYZ" )
1084 << QStringLiteral(
"AS_XY" )
1085 << QStringLiteral(
"AS_YX" ),
1091 QObject::tr(
"Create the associated .csvt file to describe the type of each "
1092 "column of the layer and its optional width and precision." ),
1097 QObject::tr(
"Field separator character." ),
1099 << QStringLiteral(
"COMMA" )
1100 << QStringLiteral(
"SEMICOLON" )
1101 << QStringLiteral(
"TAB" ),
1102 QStringLiteral(
"COMMA" )
1106 QObject::tr(
"Double-quote strings. IF_AMBIGUOUS means that string values that look like numbers will be quoted." ),
1108 << QStringLiteral(
"IF_NEEDED" )
1109 << QStringLiteral(
"IF_AMBIGUOUS" )
1110 << QStringLiteral(
"ALWAYS" ),
1111 QStringLiteral(
"IF_AMBIGUOUS" )
1115 QObject::tr(
"Write a UTF-8 Byte Order Mark (BOM) at the start of the file." ),
1119 driverMetadata.insert( QStringLiteral(
"CSV" ),
1121 QStringLiteral(
"Comma Separated Value [CSV]" ),
1122 QObject::tr(
"Comma Separated Value [CSV]" ),
1123 QStringLiteral(
"*.csv" ),
1124 QStringLiteral(
"csv" ),
1131 datasetOptions.clear();
1132 layerOptions.clear();
1134 driverMetadata.insert( QStringLiteral(
"FlatGeobuf" ),
1136 QStringLiteral(
"FlatGeobuf" ),
1137 QObject::tr(
"FlatGeobuf" ),
1138 QStringLiteral(
"*.fgb" ),
1139 QStringLiteral(
"fgb" ),
1142 QStringLiteral(
"UTF-8" )
1147 datasetOptions.clear();
1148 layerOptions.clear();
1151 QObject::tr(
"Override the type of shapefile created. "
1152 "Can be one of NULL for a simple .dbf file with no .shp file, POINT, "
1153 "ARC, POLYGON or MULTIPOINT for 2D, or POINTZ, ARCZ, POLYGONZ or "
1154 "MULTIPOINTZ for 3D;" ) +
1155 QObject::tr(
" POINTM, ARCM, POLYGONM or MULTIPOINTM for measured geometries"
1156 " and POINTZM, ARCZM, POLYGONZM or MULTIPOINTZM for 3D measured"
1158 QObject::tr(
" MULTIPATCH files are supported since GDAL 2.2." ) +
1161 << QStringLiteral(
"NULL" )
1162 << QStringLiteral(
"POINT" )
1163 << QStringLiteral(
"ARC" )
1164 << QStringLiteral(
"POLYGON" )
1165 << QStringLiteral(
"MULTIPOINT" )
1166 << QStringLiteral(
"POINTZ" )
1167 << QStringLiteral(
"ARCZ" )
1168 << QStringLiteral(
"POLYGONZ" )
1169 << QStringLiteral(
"MULTIPOINTZ" )
1170 << QStringLiteral(
"POINTM" )
1171 << QStringLiteral(
"ARCM" )
1172 << QStringLiteral(
"POLYGONM" )
1173 << QStringLiteral(
"MULTIPOINTM" )
1174 << QStringLiteral(
"POINTZM" )
1175 << QStringLiteral(
"ARCZM" )
1176 << QStringLiteral(
"POLYGONZM" )
1177 << QStringLiteral(
"MULTIPOINTZM" )
1178 << QStringLiteral(
"MULTIPATCH" )
1188 QObject::tr(
"Set the encoding value in the DBF file. "
1189 "The default value is LDID/87. It is not clear "
1190 "what other values may be appropriate." ),
1198 QObject::tr(
"Set to YES to resize fields to their optimal size." ),
1202 driverMetadata.insert( QStringLiteral(
"ESRI" ),
1204 QStringLiteral(
"ESRI Shapefile" ),
1205 QObject::tr(
"ESRI Shapefile" ),
1206 QStringLiteral(
"*.shp" ),
1207 QStringLiteral(
"shp" ),
1214 datasetOptions.clear();
1215 layerOptions.clear();
1217 driverMetadata.insert( QStringLiteral(
"DBF File" ),
1219 QStringLiteral(
"DBF File" ),
1220 QObject::tr(
"DBF File" ),
1221 QStringLiteral(
"*.dbf" ),
1222 QStringLiteral(
"dbf" ),
1229 datasetOptions.clear();
1230 layerOptions.clear();
1232 driverMetadata.insert( QStringLiteral(
"FMEObjects Gateway" ),
1234 QStringLiteral(
"FMEObjects Gateway" ),
1235 QObject::tr(
"FMEObjects Gateway" ),
1236 QStringLiteral(
"*.fdd" ),
1237 QStringLiteral(
"fdd" ),
1244 datasetOptions.clear();
1245 layerOptions.clear();
1248 QObject::tr(
"Set to YES to write a bbox property with the bounding box "
1249 "of the geometries at the feature and feature collection level." ),
1254 QObject::tr(
"Maximum number of figures after decimal separator to write in coordinates. "
1255 "Defaults to 15. Truncation will occur to remove trailing zeros." ),
1260 QObject::tr(
"Whether to use RFC 7946 standard. "
1261 "If disabled GeoJSON 2008 initial version will be used. "
1262 "Default is NO (thus GeoJSON 2008). See also Documentation (via Help button)" ),
1266 driverMetadata.insert( QStringLiteral(
"GeoJSON" ),
1268 QStringLiteral(
"GeoJSON" ),
1269 QObject::tr(
"GeoJSON" ),
1270 QStringLiteral(
"*.geojson" ),
1271 QStringLiteral(
"geojson" ),
1274 QStringLiteral(
"UTF-8" )
1279 datasetOptions.clear();
1280 layerOptions.clear();
1283 QObject::tr(
"Maximum number of figures after decimal separator to write in coordinates. "
1284 "Defaults to 15. Truncation will occur to remove trailing zeros." ),
1289 QObject::tr(
"Whether to start records with the RS=0x1E character (RFC 8142 standard). "
1290 "Defaults to NO: Newline Delimited JSON (geojsonl). \n"
1291 "If set to YES: RFC 8142 standard: GeoJSON Text Sequences (geojsons)." ),
1295 driverMetadata.insert( QStringLiteral(
"GeoJSONSeq" ),
1297 QStringLiteral(
"GeoJSON - Newline Delimited" ),
1298 QObject::tr(
"GeoJSON - Newline Delimited" ),
1299 QStringLiteral(
"*.geojsonl *.geojsons *.json" ),
1300 QStringLiteral(
"json" ),
1303 QStringLiteral(
"UTF-8" )
1308 datasetOptions.clear();
1309 layerOptions.clear();
1312 QObject::tr(
"whether the document must be in RSS 2.0 or Atom 1.0 format. "
1313 "Default value : RSS" ),
1315 << QStringLiteral(
"RSS" )
1316 << QStringLiteral(
"ATOM" ),
1317 QStringLiteral(
"RSS" )
1321 QObject::tr(
"The encoding of location information. Default value : SIMPLE. "
1322 "W3C_GEO only supports point geometries. "
1323 "SIMPLE or W3C_GEO only support geometries in geographic WGS84 coordinates." ),
1325 << QStringLiteral(
"SIMPLE" )
1326 << QStringLiteral(
"GML" )
1327 << QStringLiteral(
"W3C_GEO" ),
1328 QStringLiteral(
"SIMPLE" )
1332 QObject::tr(
"If defined to YES, extension fields will be written. "
1333 "If the field name not found in the base schema matches "
1334 "the foo_bar pattern, foo will be considered as the namespace "
1335 "of the element, and a <foo:bar> element will be written. "
1336 "Otherwise, elements will be written in the <ogr:> namespace." ),
1341 QObject::tr(
"If defined to NO, only <entry> or <item> elements will be written. "
1342 "The user will have to provide the appropriate header and footer of the document." ),
1347 QObject::tr(
"XML content that will be put between the <channel> element and the "
1348 "first <item> element for a RSS document, or between the xml tag and "
1349 "the first <entry> element for an Atom document." ),
1354 QObject::tr(
"Value put inside the <title> element in the header. "
1355 "If not provided, a dummy value will be used as that element is compulsory." ),
1360 QObject::tr(
"Value put inside the <description> element in the header. "
1361 "If not provided, a dummy value will be used as that element is compulsory." ),
1366 QObject::tr(
"Value put inside the <link> element in the header. "
1367 "If not provided, a dummy value will be used as that element is compulsory." ),
1372 QObject::tr(
"Value put inside the <updated> element in the header. "
1373 "Should be formatted as a XML datetime. "
1374 "If not provided, a dummy value will be used as that element is compulsory." ),
1379 QObject::tr(
"Value put inside the <author><name> element in the header. "
1380 "If not provided, a dummy value will be used as that element is compulsory." ),
1385 QObject::tr(
"Value put inside the <id> element in the header. "
1386 "If not provided, a dummy value will be used as that element is compulsory." ),
1390 driverMetadata.insert( QStringLiteral(
"GeoRSS" ),
1392 QStringLiteral(
"GeoRSS" ),
1393 QObject::tr(
"GeoRSS" ),
1394 QStringLiteral(
"*.xml" ),
1395 QStringLiteral(
"xml" ),
1398 QStringLiteral(
"UTF-8" )
1403 datasetOptions.clear();
1404 layerOptions.clear();
1407 QObject::tr(
"If provided, this URI will be inserted as the schema location. "
1408 "Note that the schema file isn't actually accessed by OGR, so it "
1409 "is up to the user to ensure it will match the schema of the OGR "
1410 "produced GML data file." ),
1415 QObject::tr(
"This writes a GML application schema file to a corresponding "
1416 ".xsd file (with the same basename). If INTERNAL is used the "
1417 "schema is written within the GML file, but this is experimental "
1418 "and almost certainly not valid XML. "
1419 "OFF disables schema generation (and is implicit if XSISCHEMAURI is used)." ),
1421 << QStringLiteral(
"EXTERNAL" )
1422 << QStringLiteral(
"INTERNAL" )
1423 << QStringLiteral(
"OFF" ),
1424 QStringLiteral(
"EXTERNAL" )
1428 QObject::tr(
"This is the prefix for the application target namespace." ),
1429 QStringLiteral(
"ogr" )
1433 QObject::tr(
"Can be set to TRUE to avoid writing the prefix of the "
1434 "application target namespace in the GML file." ),
1439 QObject::tr(
"Defaults to 'http://ogr.maptools.org/'. "
1440 "This is the application target namespace." ),
1441 QStringLiteral(
"http://ogr.maptools.org/" )
1445 QObject::tr(
"GML version to use." ),
1447 << QStringLiteral(
"GML2" )
1448 << QStringLiteral(
"GML3" )
1449 << QStringLiteral(
"GML3Deegree" )
1450 << QStringLiteral(
"GML3.2" ),
1451 QStringLiteral(
"GML3.2" )
1455 QObject::tr(
"Only valid when FORMAT=GML3/GML3Degree/GML3.2. Default to YES. "
1456 "If YES, SRS with EPSG authority will be written with the "
1457 "'urn:ogc:def:crs:EPSG::' prefix. In the case the SRS is a "
1458 "geographic SRS without explicit AXIS order, but that the same "
1459 "SRS authority code imported with ImportFromEPSGA() should be "
1460 "treated as lat/long, then the function will take care of coordinate "
1461 "order swapping. If set to NO, SRS with EPSG authority will be "
1462 "written with the 'EPSG:' prefix, even if they are in lat/long order." ),
1467 QObject::tr(
"only valid when FORMAT=GML3/GML3Degree/GML3.2) Default to YES. "
1468 "If set to NO, the <gml:boundedBy> element will not be written for "
1474 QObject::tr(
"Default to YES. If YES, the output will be indented with spaces "
1475 "for more readability, but at the expense of file size." ),
1480 driverMetadata.insert( QStringLiteral(
"GML" ),
1482 QStringLiteral(
"Geography Markup Language [GML]" ),
1483 QObject::tr(
"Geography Markup Language [GML]" ),
1484 QStringLiteral(
"*.gml" ),
1485 QStringLiteral(
"gml" ),
1488 QStringLiteral(
"UTF-8" )
1493 datasetOptions.clear();
1494 layerOptions.clear();
1497 QObject::tr(
"Human-readable identifier (e.g. short name) for the layer content" ),
1502 QObject::tr(
"Human-readable description for the layer content" ),
1507 QObject::tr(
"Name for the feature identifier column" ),
1508 QStringLiteral(
"fid" )
1512 QObject::tr(
"Name for the geometry column" ),
1513 QStringLiteral(
"geom" )
1517 QObject::tr(
"If a spatial index must be created." ),
1521 driverMetadata.insert( QStringLiteral(
"GPKG" ),
1523 QStringLiteral(
"GeoPackage" ),
1524 QObject::tr(
"GeoPackage" ),
1525 QStringLiteral(
"*.gpkg" ),
1526 QStringLiteral(
"gpkg" ),
1529 QStringLiteral(
"UTF-8" )
1534 datasetOptions.clear();
1535 layerOptions.clear();
1537 driverMetadata.insert( QStringLiteral(
"GMT" ),
1539 QStringLiteral(
"Generic Mapping Tools [GMT]" ),
1540 QObject::tr(
"Generic Mapping Tools [GMT]" ),
1541 QStringLiteral(
"*.gmt" ),
1542 QStringLiteral(
"gmt" ),
1549 datasetOptions.clear();
1550 layerOptions.clear();
1553 QObject::tr(
"By default when writing a layer whose features are of "
1554 "type wkbLineString, the GPX driver chooses to write "
1555 "them as routes. If FORCE_GPX_TRACK=YES is specified, "
1556 "they will be written as tracks." ),
1561 QObject::tr(
"By default when writing a layer whose features are of "
1562 "type wkbMultiLineString, the GPX driver chooses to write "
1563 "them as tracks. If FORCE_GPX_ROUTE=YES is specified, "
1564 "they will be written as routes, provided that the multilines "
1565 "are composed of only one single line." ),
1570 QObject::tr(
"If GPX_USE_EXTENSIONS=YES is specified, "
1571 "extra fields will be written inside the <extensions> tag." ),
1576 QObject::tr(
"Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS_URL "
1577 "is set. The namespace value used for extension tags. By default, 'ogr'." ),
1578 QStringLiteral(
"ogr" )
1582 QObject::tr(
"Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS "
1583 "is set. The namespace URI. By default, 'http://osgeo.org/gdal'." ),
1584 QStringLiteral(
"http://osgeo.org/gdal" )
1588 QObject::tr(
"By default files are created with the line termination "
1589 "conventions of the local platform (CR/LF on win32 or LF "
1590 "on all other systems). This may be overridden through use "
1591 "of the LINEFORMAT layer creation option which may have a value "
1592 "of CRLF (DOS format) or LF (Unix format)." ),
1594 << QStringLiteral(
"CRLF" )
1595 << QStringLiteral(
"LF" ),
1600 driverMetadata.insert( QStringLiteral(
"GPX" ),
1602 QStringLiteral(
"GPS eXchange Format [GPX]" ),
1603 QObject::tr(
"GPS eXchange Format [GPX]" ),
1604 QStringLiteral(
"*.gpx" ),
1605 QStringLiteral(
"gpx" ),
1608 QStringLiteral(
"UTF-8" )
1613 datasetOptions.clear();
1614 layerOptions.clear();
1616 driverMetadata.insert( QStringLiteral(
"Interlis 1" ),
1618 QStringLiteral(
"INTERLIS 1" ),
1619 QObject::tr(
"INTERLIS 1" ),
1620 QStringLiteral(
"*.itf *.xml *.ili" ),
1621 QStringLiteral(
"ili" ),
1628 datasetOptions.clear();
1629 layerOptions.clear();
1631 driverMetadata.insert( QStringLiteral(
"Interlis 2" ),
1633 QStringLiteral(
"INTERLIS 2" ),
1634 QObject::tr(
"INTERLIS 2" ),
1635 QStringLiteral(
"*.xtf *.xml *.ili" ),
1636 QStringLiteral(
"ili" ),
1643 datasetOptions.clear();
1644 layerOptions.clear();
1647 QObject::tr(
"Allows you to specify the field to use for the KML <name> element." ),
1648 QStringLiteral(
"Name" )
1652 QObject::tr(
"Allows you to specify the field to use for the KML <description> element." ),
1653 QStringLiteral(
"Description" )
1657 QObject::tr(
"Allows you to specify the AltitudeMode to use for KML geometries. "
1658 "This will only affect 3D geometries and must be one of the valid KML options." ),
1660 << QStringLiteral(
"clampToGround" )
1661 << QStringLiteral(
"relativeToGround" )
1662 << QStringLiteral(
"absolute" ),
1663 QStringLiteral(
"relativeToGround" )
1667 QObject::tr(
"The DOCUMENT_ID datasource creation option can be used to specified "
1668 "the id of the root <Document> node. The default value is root_doc." ),
1669 QStringLiteral(
"root_doc" )
1672 driverMetadata.insert( QStringLiteral(
"KML" ),
1674 QStringLiteral(
"Keyhole Markup Language [KML]" ),
1675 QObject::tr(
"Keyhole Markup Language [KML]" ),
1676 QStringLiteral(
"*.kml" ),
1677 QStringLiteral(
"kml" ),
1680 QStringLiteral(
"UTF-8" )
1685 datasetOptions.clear();
1686 layerOptions.clear();
1688 auto insertMapInfoOptions = []( QMap<QString, QgsVectorFileWriter::Option *> &datasetOptions, QMap<QString, QgsVectorFileWriter::Option *> &layerOptions )
1691 QObject::tr(
"Use this to turn on 'quick spatial index mode'. "
1692 "In this mode writing files can be about 5 times faster, "
1693 "but spatial queries can be up to 30 times slower." ),
1695 << QStringLiteral(
"QUICK" )
1696 << QStringLiteral(
"OPTIMIZED" ),
1697 QStringLiteral(
"QUICK" ),
1702 QObject::tr(
"(multiples of 512): Block size for .map files. Defaults "
1703 "to 512. MapInfo 15.2 and above creates .tab files with a "
1704 "blocksize of 16384 bytes. Any MapInfo version should be "
1705 "able to handle block sizes from 512 to 32256." ),
1709 QObject::tr(
"xmin,ymin,xmax,ymax: Define custom layer bounds to increase the "
1710 "accuracy of the coordinates. Note: the geometry of written "
1711 "features must be within the defined box." ),
1715 insertMapInfoOptions( datasetOptions, layerOptions );
1717 driverMetadata.insert( QStringLiteral(
"MapInfo File" ),
1719 QStringLiteral(
"Mapinfo" ),
1720 QObject::tr(
"Mapinfo TAB" ),
1721 QStringLiteral(
"*.tab" ),
1722 QStringLiteral(
"tab" ),
1727 datasetOptions.clear();
1728 layerOptions.clear();
1729 insertMapInfoOptions( datasetOptions, layerOptions );
1732 driverMetadata.insert( QStringLiteral(
"MapInfo MIF" ),
1734 QStringLiteral(
"Mapinfo" ),
1735 QObject::tr(
"Mapinfo MIF" ),
1736 QStringLiteral(
"*.mif" ),
1737 QStringLiteral(
"mif" ),
1744 datasetOptions.clear();
1745 layerOptions.clear();
1748 QObject::tr(
"Determine whether 2D (seed_2d.dgn) or 3D (seed_3d.dgn) "
1749 "seed file should be used. This option is ignored if the SEED option is provided." ),
1754 QObject::tr(
"Override the seed file to use." ),
1759 QObject::tr(
"Indicate whether the whole seed file should be copied. "
1760 "If not, only the first three elements will be copied." ),
1765 QObject::tr(
"Indicates whether the color table should be copied from the seed file." ),
1770 QObject::tr(
"Override the master unit name from the seed file with "
1771 "the provided one or two character unit name." ),
1776 QObject::tr(
"Override the sub unit name from the seed file with the provided "
1777 "one or two character unit name." ),
1782 QObject::tr(
"Override the number of subunits per master unit. "
1783 "By default the seed file value is used." ),
1788 QObject::tr(
"Override the number of UORs (Units of Resolution) "
1789 "per sub unit. By default the seed file value is used." ),
1794 QObject::tr(
"ORIGIN=x,y,z: Override the origin of the design plane. "
1795 "By default the origin from the seed file is used." ),
1799 driverMetadata.insert( QStringLiteral(
"DGN" ),
1801 QStringLiteral(
"Microstation DGN" ),
1802 QObject::tr(
"Microstation DGN" ),
1803 QStringLiteral(
"*.dgn" ),
1804 QStringLiteral(
"dgn" ),
1811 datasetOptions.clear();
1812 layerOptions.clear();
1815 QObject::tr(
"Should update files be incorporated into the base data on the fly." ),
1817 << QStringLiteral(
"APPLY" )
1818 << QStringLiteral(
"IGNORE" ),
1819 QStringLiteral(
"APPLY" )
1823 QObject::tr(
"Should multipoint soundings be split into many single point sounding features. "
1824 "Multipoint geometries are not well handled by many formats, "
1825 "so it can be convenient to split single sounding features with many points "
1826 "into many single point features." ),
1831 QObject::tr(
"Should a DEPTH attribute be added on SOUNDG features and assign the depth "
1832 "of the sounding. This should only be enabled when SPLIT_MULTIPOINT is "
1838 QObject::tr(
"Should all the low level geometry primitives be returned as special "
1839 "IsolatedNode, ConnectedNode, Edge and Face layers." ),
1844 QObject::tr(
"If enabled, numeric attributes assigned an empty string as a value will "
1845 "be preserved as a special numeric value. This option should not generally "
1846 "be needed, but may be useful when translated S-57 to S-57 losslessly." ),
1851 QObject::tr(
"Should LNAM and LNAM_REFS fields be attached to features capturing "
1852 "the feature to feature relationships in the FFPT group of the S-57 file." ),
1857 QObject::tr(
"Should additional attributes relating features to their underlying "
1858 "geometric primitives be attached. These are the values of the FSPT group, "
1859 "and are primarily needed when doing S-57 to S-57 translations." ),
1864 QObject::tr(
"Should attribute values be recoded to UTF-8 from the character encoding "
1865 "specified in the S57 DSSI record." ),
1871 driverMetadata.insert( QStringLiteral(
"S57" ),
1873 QStringLiteral(
"S-57 Base file" ),
1874 QObject::tr(
"S-57 Base file" ),
1875 QStringLiteral(
"*.000" ),
1876 QStringLiteral(
"000" ),
1883 datasetOptions.clear();
1884 layerOptions.clear();
1886 driverMetadata.insert( QStringLiteral(
"SDTS" ),
1888 QStringLiteral(
"Spatial Data Transfer Standard [SDTS]" ),
1889 QObject::tr(
"Spatial Data Transfer Standard [SDTS]" ),
1890 QStringLiteral(
"*catd.ddf" ),
1891 QStringLiteral(
"ddf" ),
1898 datasetOptions.clear();
1899 layerOptions.clear();
1902 QObject::tr(
"Can be used to avoid creating the geometry_columns and spatial_ref_sys "
1903 "tables in a new database. By default these metadata tables are created "
1904 "when a new database is created." ),
1910 QStringLiteral(
"NO" )
1915 QStringLiteral(
"NO" )
1919 QObject::tr(
"Controls the format used for the geometry column. Defaults to WKB. "
1920 "This is generally more space and processing efficient, but harder "
1921 "to inspect or use in simple applications than WKT (Well Known Text)." ),
1923 << QStringLiteral(
"WKB" )
1924 << QStringLiteral(
"WKT" ),
1925 QStringLiteral(
"WKB" )
1929 QObject::tr(
"Controls whether layer and field names will be laundered for easier use "
1930 "in SQLite. Laundered names will be converted to lower case and some special "
1931 "characters(' - #) will be changed to underscores." ),
1936 QStringLiteral(
"NO" )
1940 QStringLiteral(
"NO" )
1948 QObject::tr(
"column_name1[,column_name2, …] A list of (String) columns that "
1949 "must be compressed with ZLib DEFLATE algorithm. This might be beneficial "
1950 "for databases that have big string blobs. However, use with care, since "
1951 "the value of such columns will be seen as compressed binary content with "
1952 "other SQLite utilities (or previous OGR versions). With OGR, when inserting, "
1953 "modifying or querying compressed columns, compression/decompression is "
1954 "done transparently. However, such columns cannot be (easily) queried with "
1955 "an attribute filter or WHERE clause. Note: in table definition, such columns "
1956 "have the 'VARCHAR_deflate' declaration type." ),
1960 driverMetadata.insert( QStringLiteral(
"SQLite" ),
1962 QStringLiteral(
"SQLite" ),
1963 QObject::tr(
"SQLite" ),
1964 QStringLiteral(
"*.sqlite" ),
1965 QStringLiteral(
"sqlite" ),
1968 QStringLiteral(
"UTF-8" )
1973 datasetOptions.clear();
1974 layerOptions.clear();
1977 QObject::tr(
"Can be used to avoid creating the geometry_columns and spatial_ref_sys "
1978 "tables in a new database. By default these metadata tables are created "
1979 "when a new database is created." ),
1984 QStringLiteral(
"YES" )
1988 QObject::tr(
"Insert the content of the EPSG CSV files into the spatial_ref_sys table. "
1989 "Set to NO for regular SQLite databases." ),
1994 QStringLiteral(
"SPATIALITE" )
1998 QObject::tr(
"Controls whether layer and field names will be laundered for easier use "
1999 "in SQLite. Laundered names will be converted to lower case and some special "
2000 "characters(' - #) will be changed to underscores." ),
2005 QObject::tr(
"If the database is of the SpatiaLite flavor, and if OGR is linked "
2006 "against libspatialite, this option can be used to control if a spatial "
2007 "index must be created." ),
2012 QObject::tr(
"If the format of the geometry BLOB is of the SpatiaLite flavor, "
2013 "this option can be used to control if the compressed format for "
2014 "geometries (LINESTRINGs, POLYGONs) must be used." ),
2019 QObject::tr(
"Used to force the SRID number of the SRS associated with the layer. "
2020 "When this option isn't specified and that a SRS is associated with the "
2021 "layer, a search is made in the spatial_ref_sys to find a match for the "
2022 "SRS, and, if there is no match, a new entry is inserted for the SRS in "
2023 "the spatial_ref_sys table. When the SRID option is specified, this "
2024 "search (and the eventual insertion of a new entry) will not be done: "
2025 "the specified SRID is used as such." ),
2030 QObject::tr(
"column_name1[,column_name2, …] A list of (String) columns that "
2031 "must be compressed with ZLib DEFLATE algorithm. This might be beneficial "
2032 "for databases that have big string blobs. However, use with care, since "
2033 "the value of such columns will be seen as compressed binary content with "
2034 "other SQLite utilities (or previous OGR versions). With OGR, when inserting, "
2035 "modifying or queryings compressed columns, compression/decompression is "
2036 "done transparently. However, such columns cannot be (easily) queried with "
2037 "an attribute filter or WHERE clause. Note: in table definition, such columns "
2038 "have the 'VARCHAR_deflate' declaration type." ),
2042 driverMetadata.insert( QStringLiteral(
"SpatiaLite" ),
2044 QStringLiteral(
"SpatiaLite" ),
2045 QObject::tr(
"SpatiaLite" ),
2046 QStringLiteral(
"*.sqlite" ),
2047 QStringLiteral(
"sqlite" ),
2050 QStringLiteral(
"UTF-8" )
2054 datasetOptions.clear();
2055 layerOptions.clear();
2058 QObject::tr(
"Override the header file used - in place of header.dxf." ),
2063 QObject::tr(
"Override the trailer file used - in place of trailer.dxf." ),
2067 driverMetadata.insert( QStringLiteral(
"DXF" ),
2069 QStringLiteral(
"AutoCAD DXF" ),
2070 QObject::tr(
"AutoCAD DXF" ),
2071 QStringLiteral(
"*.dxf" ),
2072 QStringLiteral(
"dxf" ),
2079 datasetOptions.clear();
2080 layerOptions.clear();
2083 QObject::tr(
"Indicates the GeoConcept export file extension. "
2084 "TXT was used by earlier releases of GeoConcept. GXT is currently used." ),
2086 << QStringLiteral(
"GXT" )
2087 << QStringLiteral(
"TXT" ),
2088 QStringLiteral(
"GXT" )
2092 QObject::tr(
"Path to the GCT: the GCT file describes the GeoConcept types definitions: "
2093 "In this file, every line must start with //# followed by a keyword. "
2094 "Lines starting with // are comments." ),
2099 QObject::tr(
"Defines the feature to be created. The TYPE corresponds to one of the Name "
2100 "found in the GCT file for a type section. The SUBTYPE corresponds to one of "
2101 "the Name found in the GCT file for a sub-type section within the previous "
2106 driverMetadata.insert( QStringLiteral(
"Geoconcept" ),
2108 QStringLiteral(
"Geoconcept" ),
2109 QObject::tr(
"Geoconcept" ),
2110 QStringLiteral(
"*.gxt *.txt" ),
2111 QStringLiteral(
"gxt" ),
2118 datasetOptions.clear();
2119 layerOptions.clear();
2122 QObject::tr(
"When this option is set, the new layer will be created inside the named "
2123 "FeatureDataset folder. If the folder does not already exist, it will be created." ),
2128 QObject::tr(
"Set layer name alias." ),
2133 QObject::tr(
"Set name of geometry column in new layer. Defaults to 'SHAPE'." ),
2134 QStringLiteral(
"SHAPE" )
2138 QObject::tr(
"Whether the values of the geometry column can be NULL. Can be set to NO so that geometry is required. Default to 'YES'." ),
2143 QObject::tr(
"Name of the OID column to create. Defaults to 'OBJECTID'." ),
2144 QStringLiteral(
"OBJECTID" )
2160 QObject::tr(
"A list of strings of format field_name=fgdb_field_type (separated by comma) to force the FileGDB column type of fields to be created." ),
2165 QObject::tr(
"XML documentation for the layer." ),
2169 QObject::tr(
"Customize how data is stored. By default text in UTF-8 and data up to 1TB." ),
2170 {QStringLiteral(
"DEFAULTS" ), QStringLiteral(
"MAX_FILE_SIZE_4GB" ), QStringLiteral(
"MAX_FILE_SIZE_256TB" )},
2171 QStringLiteral(
"DEFAULTS" ),
2176 QObject::tr(
" Defaults to NO (through CreateLayer() API). When this option is set, a Shape_Area and Shape_Length special fields will be created for polygonal layers (Shape_Length only for linear layers). These fields will automatically be populated with the feature’s area or length whenever a new feature is added to the dataset or an existing feature is amended. When using ogr2ogr with a source layer that has Shape_Area/Shape_Length special fields, and this option is not explicitly specified, it will be automatically set, so that the resulting FileGeodatabase has those fields properly tagged." ),
2180 driverMetadata.insert( QStringLiteral(
"OpenFileGDB" ),
2182 QStringLiteral(
"ESRI File Geodatabase" ),
2183 QObject::tr(
"ESRI File Geodatabase" ),
2184 QStringLiteral(
"*.gdb" ),
2185 QStringLiteral(
"gdb" ),
2188 QStringLiteral(
"UTF-8" )
2193 datasetOptions.clear();
2194 layerOptions.clear();
2197 QObject::tr(
"When this option is set, the new layer will be created inside the named "
2198 "FeatureDataset folder. If the folder does not already exist, it will be created." ),
2203 QObject::tr(
"Set name of geometry column in new layer. Defaults to 'SHAPE'." ),
2204 QStringLiteral(
"SHAPE" )
2208 QObject::tr(
"Name of the OID column to create. Defaults to 'OBJECTID'." ),
2209 QStringLiteral(
"OBJECTID" )
2212 driverMetadata.insert( QStringLiteral(
"FileGDB" ),
2214 QStringLiteral(
"ESRI FileGDB" ),
2215 QObject::tr(
"ESRI FileGDB" ),
2216 QStringLiteral(
"*.gdb" ),
2217 QStringLiteral(
"gdb" ),
2220 QStringLiteral(
"UTF-8" )
2225 datasetOptions.clear();
2226 layerOptions.clear();
2229 QObject::tr(
"By default, the driver will try to detect the data type of fields. If set "
2230 "to STRING, all fields will be of String type." ),
2232 << QStringLiteral(
"AUTO" )
2233 << QStringLiteral(
"STRING" ),
2234 QStringLiteral(
"AUTO" ),
2239 QObject::tr(
"By default, the driver will read the first lines of each sheet to detect "
2240 "if the first line might be the name of columns. If set to FORCE, the driver "
2241 "will consider the first line as the header line. If set to "
2242 "DISABLE, it will be considered as the first feature. Otherwise "
2243 "auto-detection will occur." ),
2245 << QStringLiteral(
"FORCE" )
2246 << QStringLiteral(
"DISABLE" )
2247 << QStringLiteral(
"AUTO" ),
2248 QStringLiteral(
"AUTO" ),
2252 driverMetadata.insert( QStringLiteral(
"XLSX" ),
2254 QStringLiteral(
"MS Office Open XML spreadsheet" ),
2255 QObject::tr(
"MS Office Open XML spreadsheet [XLSX]" ),
2256 QStringLiteral(
"*.xlsx" ),
2257 QStringLiteral(
"xlsx" ),
2260 QStringLiteral(
"UTF-8" )
2265 datasetOptions.clear();
2266 layerOptions.clear();
2269 QObject::tr(
"By default, the driver will try to detect the data type of fields. If set "
2270 "to STRING, all fields will be of String type." ),
2272 << QStringLiteral(
"AUTO" )
2273 << QStringLiteral(
"STRING" ),
2274 QStringLiteral(
"AUTO" ),
2279 QObject::tr(
"By default, the driver will read the first lines of each sheet to detect "
2280 "if the first line might be the name of columns. If set to FORCE, the driver "
2281 "will consider the first line as the header line. If set to "
2282 "DISABLE, it will be considered as the first feature. Otherwise "
2283 "auto-detection will occur." ),
2285 << QStringLiteral(
"FORCE" )
2286 << QStringLiteral(
"DISABLE" )
2287 << QStringLiteral(
"AUTO" ),
2288 QStringLiteral(
"AUTO" ),
2292 driverMetadata.insert( QStringLiteral(
"ODS" ),
2294 QStringLiteral(
"Open Document Spreadsheet" ),
2295 QObject::tr(
"Open Document Spreadsheet [ODS]" ),
2296 QStringLiteral(
"*.ods" ),
2297 QStringLiteral(
"ods" ),
2300 QStringLiteral(
"UTF-8" )
2305 datasetOptions.clear();
2306 layerOptions.clear();
2309 QObject::tr(
"Compression method." ),
2311 << QStringLiteral(
"UNCOMPRESSED" )
2312 << QStringLiteral(
"SNAPPY" ),
2313 QStringLiteral(
"SNAPPY" ),
2318 QObject::tr(
"Geometry encoding." ),
2320 << QStringLiteral(
"WKB" )
2321 << QStringLiteral(
"WKT" )
2322 << QStringLiteral(
"GEOARROW" ),
2323 QStringLiteral(
"WKB" ),
2328 QObject::tr(
"Maximum number of rows per group." ),
2333 QObject::tr(
"Name for the feature identifier column" ),
2338 QObject::tr(
"Name for the geometry column" ),
2339 QStringLiteral(
"geometry" )
2343 QObject::tr(
"Name of the coordinate system for the edges." ),
2345 << QStringLiteral(
"PLANAR" )
2346 << QStringLiteral(
"SPHERICAL" ),
2347 QStringLiteral(
"PLANAR" ),
2351 driverMetadata.insert( QStringLiteral(
"Parquet" ),
2353 QStringLiteral(
"(Geo)Parquet" ),
2354 QObject::tr(
"(Geo)Parquet" ),
2355 QStringLiteral(
"*.parquet" ),
2356 QStringLiteral(
"parquet" ),
2359 QStringLiteral(
"UTF-8" )
2364 datasetOptions.clear();
2365 layerOptions.clear();
2368 QObject::tr(
"Line termination character sequence." ),
2370 << QStringLiteral(
"CRLF" )
2371 << QStringLiteral(
"LF" ),
2372 QStringLiteral(
"LF" ),
2378 QObject::tr(
"Format of geometry columns." ),
2380 << QStringLiteral(
"geometry" )
2381 << QStringLiteral(
"geography" ),
2382 QStringLiteral(
"geometry" ),
2387 QObject::tr(
"Controls whether layer and field names will be laundered for easier use. "
2388 "Laundered names will be converted to lower case and some special "
2389 "characters(' - #) will be changed to underscores." ),
2394 QObject::tr(
"Name for the geometry column. Defaults to wkb_geometry "
2395 "for GEOM_TYPE=geometry or the_geog for GEOM_TYPE=geography" ) ) );
2398 QObject::tr(
"Name of schema into which to create the new table" ) ) );
2401 QObject::tr(
"Whether to explicitly emit the CREATE SCHEMA statement to create the specified schema." ),
2406 QObject::tr(
"Whether to explicitly recreate the table if necessary." ),
2411 QObject::tr(
"Whether to explicitly destroy tables before recreating them." ),
2413 << QStringLiteral(
"YES" )
2414 << QStringLiteral(
"NO" )
2415 << QStringLiteral(
"IF_EXISTS" ),
2416 QStringLiteral(
"YES" ),
2421 QObject::tr(
"Used to force the SRID number of the SRS associated with the layer. "
2422 "When this option isn't specified and that a SRS is associated with the "
2423 "layer, a search is made in the spatial_ref_sys to find a match for the "
2424 "SRS, and, if there is no match, a new entry is inserted for the SRS in "
2425 "the spatial_ref_sys table. When the SRID option is specified, this "
2426 "search (and the eventual insertion of a new entry) will not be done: "
2427 "the specified SRID is used as such." ),
2432 QObject::tr(
"Can be set to 2.0 or 2.2 for PostGIS 2.0/2.2 compatibility. "
2433 "Important to set it correctly if using non-linear geometry types" ),
2434 QStringLiteral(
"2.2" )
2437 driverMetadata.insert( QStringLiteral(
"PGDUMP" ),
2439 QStringLiteral(
"PostgreSQL SQL dump" ),
2440 QObject::tr(
"PostgreSQL SQL dump" ),
2441 QStringLiteral(
"*.sql" ),
2442 QStringLiteral(
"sql" ),
2445 QStringLiteral(
"UTF-8" )
2451 QgsVectorFileWriterMetadataContainer(
const QgsVectorFileWriterMetadataContainer &other ) =
delete;
2452 QgsVectorFileWriterMetadataContainer &operator=(
const QgsVectorFileWriterMetadataContainer &other ) =
delete;
2453 ~QgsVectorFileWriterMetadataContainer()
2455 for (
auto it = driverMetadata.constBegin(); it != driverMetadata.constEnd(); ++it )
2457 for (
auto optionIt = it.value().driverOptions.constBegin(); optionIt != it.value().driverOptions.constEnd(); ++optionIt )
2458 delete optionIt.value();
2459 for (
auto optionIt = it.value().layerOptions.constBegin(); optionIt != it.value().layerOptions.constEnd(); ++optionIt )
2460 delete optionIt.value();
2464 QMap<QString, QgsVectorFileWriter::MetaData> driverMetadata;
2471 static QgsVectorFileWriterMetadataContainer sDriverMetadata;
2472 QMap<QString, MetaData>::ConstIterator it = sDriverMetadata.driverMetadata.constBegin();
2474 for ( ; it != sDriverMetadata.driverMetadata.constEnd(); ++it )
2476 if ( it.key() == QLatin1String(
"PGDUMP" ) &&
2477 driverName != QLatin1String(
"PGDUMP" ) &&
2478 driverName != QLatin1String(
"PostgreSQL SQL dump" ) )
2483 if ( it.key().startsWith( driverName ) || it.value().longName.startsWith( driverName ) )
2498 return QStringList();
2507 return QStringList();
2514 OGRwkbGeometryType ogrType =
static_cast<OGRwkbGeometryType
>( type );
2540 QgsFeatureList::iterator fIt = features.begin();
2542 for ( ; fIt != features.end(); ++fIt )
2567 QString styleString;
2568 QString currentStyle;
2570 QgsSymbolList::const_iterator symbolIt = symbols.constBegin();
2571 for ( ; symbolIt != symbols.constEnd(); ++symbolIt )
2573 int nSymbolLayers = ( *symbolIt )->symbolLayerCount();
2574 for (
int i = 0; i < nSymbolLayers; ++i )
2577 QMap< QgsSymbolLayer *, QString >::const_iterator it =
mSymbolLayerTable.find( ( *symbolIt )->symbolLayer( i ) );
2583 double mmsf = mmScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
2584 double musf = mapUnitScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
2586 currentStyle = ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf );
2590 if ( symbolIt != symbols.constBegin() || i != 0 )
2592 styleString.append(
';' );
2594 styleString.append( currentStyle );
2598 OGR_F_SetStyleString( poFeature.get(), currentStyle.toLocal8Bit().constData() );
2599 if ( !writeFeature(
mLayer, poFeature.get() ) )
2606 OGR_F_SetStyleString( poFeature.get(), styleString.toLocal8Bit().constData() );
2611 if ( !writeFeature(
mLayer, poFeature.get() ) )
2630 int fldIdx = it.key();
2631 int ogrField = it.value();
2633 QVariant attrValue = feature.
attribute( fldIdx );
2638 OGR_F_UnsetField( poFeature.get(), ogrField );
2651 OGR_F_SetFieldNull( poFeature.get(), ogrField );
2666 mErrorMessage = QObject::tr(
"Error converting value (%1) for attribute field %2: %3" )
2667 .arg( feature.
attribute( fldIdx ).toString(),
2677 OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
2679 case QVariant::LongLong:
2680 OGR_F_SetFieldInteger64( poFeature.get(), ogrField, attrValue.toLongLong() );
2682 case QVariant::Bool:
2683 OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
2685 case QVariant::String:
2686 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toString() ).constData() );
2688 case QVariant::Double:
2689 OGR_F_SetFieldDouble( poFeature.get(), ogrField, attrValue.toDouble() );
2691 case QVariant::Date:
2692 OGR_F_SetFieldDateTime( poFeature.get(), ogrField,
2693 attrValue.toDate().year(),
2694 attrValue.toDate().month(),
2695 attrValue.toDate().day(),
2698 case QVariant::DateTime:
2701 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toDateTime().toString( QStringLiteral(
"yyyy/MM/dd hh:mm:ss.zzz" ) ) ).constData() );
2705 const QDateTime dt = attrValue.toDateTime();
2706 const QDate date = dt.date();
2707 const QTime time = dt.time();
2708 OGR_F_SetFieldDateTimeEx( poFeature.get(), ogrField,
2714 static_cast<float>( time.second() +
static_cast< double >( time.msec() ) / 1000 ),
2718 case QVariant::Time:
2721 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toString() ).constData() );
2725 const QTime time = attrValue.toTime();
2726 OGR_F_SetFieldDateTimeEx( poFeature.get(), ogrField,
2730 static_cast<float>( time.second() +
static_cast< double >( time.msec() ) / 1000 ),
2735 case QVariant::ByteArray:
2737 const QByteArray ba = attrValue.toByteArray();
2738 OGR_F_SetFieldBinary( poFeature.get(), ogrField, ba.size(),
const_cast< GByte *
>(
reinterpret_cast< const GByte *
>( ba.data() ) ) );
2742 case QVariant::Invalid:
2745 case QVariant::StringList:
2750 const QJsonDocument doc = QJsonDocument::fromVariant( attrValue );
2752 if ( !doc.isNull() )
2754 jsonString = QString::fromUtf8( doc.toJson( QJsonDocument::Compact ).constData() );
2756 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( jsonString.constData() ) );
2760 QStringList list = attrValue.toStringList();
2761 if ( mSupportedListSubTypes.contains( QVariant::String ) )
2763 int count = list.count();
2764 char **lst =
new char *[count + 1];
2768 for (
const QString &
string : list )
2770 lst[pos] = CPLStrdup(
mCodec->fromUnicode(
string ).data() );
2774 lst[count] =
nullptr;
2775 OGR_F_SetFieldStringList( poFeature.get(), ogrField, lst );
2780 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( list.join(
',' ) ).constData() );
2785 case QVariant::List:
2789 const QJsonDocument doc = QJsonDocument::fromVariant( attrValue );
2791 if ( !doc.isNull() )
2793 jsonString = QString::fromUtf8( doc.toJson( QJsonDocument::Compact ).data() );
2795 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( jsonString.constData() ) );
2802 QStringList list = attrValue.toStringList();
2803 if ( mSupportedListSubTypes.contains( QVariant::String ) )
2805 int count = list.count();
2806 char **lst =
new char *[count + 1];
2810 for (
const QString &
string : list )
2812 lst[pos] = CPLStrdup(
mCodec->fromUnicode(
string ).data() );
2816 lst[count] =
nullptr;
2817 OGR_F_SetFieldStringList( poFeature.get(), ogrField, lst );
2822 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( list.join(
',' ) ).constData() );
2828 const QVariantList list = attrValue.toList();
2829 if ( mSupportedListSubTypes.contains( QVariant::Int ) )
2831 const int count = list.count();
2832 int *lst =
new int[count];
2836 for (
const QVariant &value : list )
2838 lst[pos] = value.toInt();
2842 OGR_F_SetFieldIntegerList( poFeature.get(), ogrField, count, lst );
2847 QStringList strings;
2848 strings.reserve( list.size() );
2849 for (
const QVariant &value : list )
2851 strings << QString::number( value.toInt() );
2853 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
2859 const QVariantList list = attrValue.toList();
2860 if ( mSupportedListSubTypes.contains( QVariant::Double ) )
2862 const int count = list.count();
2863 double *lst =
new double[count];
2867 for (
const QVariant &value : list )
2869 lst[pos] = value.toDouble();
2873 OGR_F_SetFieldDoubleList( poFeature.get(), ogrField, count, lst );
2878 QStringList strings;
2879 strings.reserve( list.size() );
2880 for (
const QVariant &value : list )
2882 strings << QString::number( value.toDouble() );
2884 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
2890 const QVariantList list = attrValue.toList();
2891 if ( mSupportedListSubTypes.contains( QVariant::LongLong ) )
2893 const int count = list.count();
2894 long long *lst =
new long long[count];
2898 for (
const QVariant &value : list )
2900 lst[pos] = value.toLongLong();
2904 OGR_F_SetFieldInteger64List( poFeature.get(), ogrField, count, lst );
2909 QStringList strings;
2910 strings.reserve( list.size() );
2911 for (
const QVariant &value : list )
2913 strings << QString::number( value.toLongLong() );
2915 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
2923 mErrorMessage = QObject::tr(
"Invalid variant type for field %1[%2]: received %3 with type %4" )
2926 .arg( attrValue.typeName(),
2927 attrValue.toString() );
2940 if ( mCoordinateTransform )
2945 geom.
transform( *mCoordinateTransform );
2963 OGRGeometryH mGeom2 =
nullptr;
2992 geom.
get()->
addZValue( std::numeric_limits<double>::quiet_NaN() );
2999 geom.
get()->
addMValue( std::numeric_limits<double>::quiet_NaN() );
3019 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
3020 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
3026 QgsAbstractGeometry::WkbFlags wkbFlags;
3030 QByteArray wkb( geom.
asWkb( wkbFlags ) );
3031 OGRErr err = OGR_G_ImportFromWkb( mGeom2,
reinterpret_cast<unsigned char *
>(
const_cast<char *
>( wkb.constData() ) ), wkb.length() );
3032 if ( err != OGRERR_NONE )
3034 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
3035 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
3042 OGR_F_SetGeometryDirectly( poFeature.get(), mGeom2 );
3050 QByteArray wkb( geom.
asWkb( wkbFlags ) );
3052 OGRErr err = OGR_G_ImportFromWkb( ogrGeom,
reinterpret_cast<unsigned char *
>(
const_cast<char *
>( wkb.constData() ) ), wkb.length() );
3053 if ( err != OGRERR_NONE )
3055 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
3056 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
3063 OGR_F_SetGeometryDirectly( poFeature.get(), ogrGeom );
3078 for (
int i = 0; i < attributes.size(); i++ )
3080 if ( omap.find( i ) != omap.end() )
3085bool QgsVectorFileWriter::writeFeature( OGRLayerH layer, OGRFeatureH feature )
3087 if ( OGR_L_CreateFeature( layer, feature ) != OGRERR_NONE )
3089 mErrorMessage = QObject::tr(
"Feature creation error (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
3099 if ( mUsingTransaction )
3101 if ( OGRERR_NONE != OGR_L_CommitTransaction(
mLayer ) )
3103 QgsDebugMsg( QStringLiteral(
"Error while committing transaction on OGRLayer." ) );
3116 const QString &fileName,
3117 const QString &fileEncoding,
3119 const QString &driverName,
3121 QString *errorMessage,
3122 const QStringList &datasourceOptions,
3123 const QStringList &layerOptions,
3124 bool skipAttributeCreation,
3125 QString *newFilename,
3127 double symbologyScale,
3137 if ( destCRS.
isValid() && layer )
3163 const QString &fileName,
3164 const QString &fileEncoding,
3166 const QString &driverName,
3168 QString *errorMessage,
3169 const QStringList &datasourceOptions,
3170 const QStringList &layerOptions,
3171 bool skipAttributeCreation,
3172 QString *newFilename,
3174 double symbologyScale,
3205 : driverName( QStringLiteral(
"GPKG" ) )
3213 if ( !layer || !layer->
isValid() )
3220 details.sourceCrs = layer->
crs();
3221 details.sourceWkbType = layer->
wkbType();
3222 details.sourceFields = layer->
fields();
3231 if ( details.storageType == QLatin1String(
"ESRI Shapefile" ) )
3239 details.geometryTypeScanIterator = layer->
getFeatures( req );
3243 details.renderContext.setExpressionContext( details.expressionContext );
3244 details.renderContext.setRendererScale( options.
symbologyScale );
3246 details.shallTransform =
false;
3251 details.shallTransform =
true;
3256 details.outputCrs = details.sourceCrs;
3259 details.destWkbType = details.sourceWkbType;
3273 details.attributes.clear();
3274 else if ( details.attributes.isEmpty() )
3276 const QgsAttributeList allAttributes = details.sourceFields.allAttributesList();
3277 for (
int idx : allAttributes )
3279 QgsField fld = details.sourceFields.at( idx );
3280 if ( details.providerType == QLatin1String(
"oracle" ) && fld.
typeName().contains( QLatin1String(
"SDO_GEOMETRY" ) ) )
3282 details.attributes.append( idx );
3286 if ( !details.attributes.isEmpty() )
3288 for (
int attrIdx : std::as_const( details.attributes ) )
3290 if ( details.sourceFields.exists( attrIdx ) )
3294 details.outputFields.append(
field );
3298 QgsDebugMsg( QStringLiteral(
"No such source field with index '%1' available." ).arg( attrIdx ) );
3305 if ( details.providerType == QLatin1String(
"spatialite" ) )
3307 for (
int i = 0; i < details.outputFields.size(); i++ )
3309 if ( details.outputFields.at( i ).type() == QVariant::LongLong )
3314 if ( std::max( std::llabs( min.toLongLong() ), std::llabs( max.toLongLong() ) ) < std::numeric_limits<int>::max() )
3316 details.outputFields[i].setType( QVariant::Int );
3324 addRendererAttributes( details.renderer.get(), details.renderContext, details.sourceFields, details.attributes );
3334 bool useFilterRect =
true;
3335 if ( details.shallTransform )
3346 useFilterRect =
false;
3349 if ( useFilterRect )
3355 details.filterRectEngine->prepareGeometry();
3357 details.sourceFeatureIterator = layer->
getFeatures( req );
3371 int lastProgressReport = 0;
3372 long long total = details.featureCount;
3375 if ( details.providerType == QLatin1String(
"ogr" ) && !details.dataSourceUri.isEmpty() )
3377 QString srcFileName( details.providerUriParams.value( QStringLiteral(
"path" ) ).toString() );
3378 if ( QFile::exists( srcFileName ) && QFileInfo( fileName ).canonicalFilePath() == QFileInfo( srcFileName ).canonicalFilePath() )
3382 if ( !( ( options.
driverName == QLatin1String(
"GPKG" ) ||
3383 options.
driverName == QLatin1String(
"SpatiaLite" ) ||
3384 options.
driverName == QLatin1String(
"SQLite" ) ) &&
3385 options.
layerName != details.providerUriParams.value( QStringLiteral(
"layerName" ) ) ) )
3388 *
errorMessage = QObject::tr(
"Cannot overwrite a OGR layer in place" );
3408 int newProgress =
static_cast<int>( ( 5.0 * scanned ) / total );
3409 if ( newProgress != lastProgressReport )
3411 lastProgressReport = newProgress;
3426 QString tempNewFilename;
3427 QString tempNewLayer;
3429 std::unique_ptr< QgsVectorFileWriter > writer(
create( fileName, details.outputFields, destWkbType, details.outputCrs, transformContext, options, QgsFeatureSink::SinkFlags(), &tempNewFilename, &tempNewLayer ) );
3433 *newFilename = tempNewFilename;
3436 *newLayer = tempNewLayer;
3476 int n = 0, errors = 0;
3485 writer->startRender( details.renderer.get(), details.sourceFields );
3487 writer->resetMap( details.attributes );
3489 writer->mFields = details.sourceFields;
3493 int initialProgress = lastProgressReport;
3494 while ( details.sourceFeatureIterator.nextFeature( fet ) )
3505 int newProgress =
static_cast<int>( initialProgress + ( ( 100.0 - initialProgress ) * saved ) / total );
3506 if ( newProgress < 100 && newProgress != lastProgressReport )
3508 lastProgressReport = newProgress;
3513 if ( details.shallTransform )
3526 QString msg = QObject::tr(
"Failed to transform a point while drawing a feature with ID '%1'. Writing stopped. (Exception: %2)" )
3527 .arg( fet.
id() ).arg( e.
what() );
3544 if ( !writer->addFeatureWithStyle( fet, writer->mRenderer.get(), mapUnits ) )
3551 *
errorMessage = QObject::tr(
"Feature write errors:" );
3557 if ( errors > 1000 )
3561 *
errorMessage += QObject::tr(
"Stopping after %n error(s)",
nullptr, errors );
3571 writer->stopRender();
3575 *
errorMessage += QObject::tr(
"\nOnly %1 of %2 features written." ).arg( n - errors ).arg( n );
3580 bool metadataFailure =
false;
3585 {QStringLiteral(
"path" ), tempNewFilename },
3586 {QStringLiteral(
"layerName" ), tempNewLayer }
3600 metadataFailure =
true;
3611 metadataFailure =
true;
3619 const QString &fileName,
3621 QString *newFilename,
3625 QgsVectorFileWriter::PreparedWriterDetails details;
3626 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
3634 const QString &fileName,
3637 QString *newFilename,
3641 QgsVectorFileWriter::PreparedWriterDetails details;
3642 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
3651 QgsVectorFileWriter::PreparedWriterDetails details;
3652 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
3661 QFileInfo fi( fileName );
3662 QDir dir = fi.dir();
3665 for (
const char *suffix : {
".shp",
".shx",
".dbf",
".prj",
".qix",
".qpj",
".cpg",
".sbn",
".sbx",
".idm",
".ind" } )
3667 filter << fi.completeBaseName() + suffix;
3671 const auto constEntryList = dir.entryList( filter );
3672 for (
const QString &file : constEntryList )
3674 QFile f( dir.canonicalPath() +
'/' + file );
3677 QgsDebugMsg( QStringLiteral(
"Removing file %1 failed: %2" ).arg( file, f.errorString() ) );
3693 static QReadWriteLock sFilterLock;
3694 static QMap< VectorFormatOptions, QList< QgsVectorFileWriter::FilterFormatDetails > > sFilters;
3698 const auto it = sFilters.constFind( options );
3699 if ( it != sFilters.constEnd() )
3703 QList< QgsVectorFileWriter::FilterFormatDetails > results;
3706 int const drvCount = OGRGetDriverCount();
3708 for (
int i = 0; i < drvCount; ++i )
3710 OGRSFDriverH drv = OGRGetDriver( i );
3713 QString drvName = OGR_Dr_GetName( drv );
3715 GDALDriverH gdalDriver = GDALGetDriverByName( drvName.toLocal8Bit().constData() );
3716 char **metadata =
nullptr;
3719 metadata = GDALGetMetadata( gdalDriver,
nullptr );
3722 bool nonSpatialFormat = CSLFetchBoolean( metadata, GDAL_DCAP_NONSPATIAL,
false );
3724 if ( OGR_Dr_TestCapability( drv,
"CreateDataSource" ) != 0 )
3729 if ( nonSpatialFormat )
3734 if ( filterString.isEmpty() )
3741 globs = metadata.
glob.toLower().split(
' ' );
3747 details.
globs = globs;
3756 if ( options & SortRecommended )
3758 if ( a.driverName == QLatin1String(
"GPKG" ) )
3760 else if ( b.driverName == QLatin1String(
"GPKG" ) )
3762 else if ( a.driverName == QLatin1String(
"ESRI Shapefile" ) )
3764 else if ( b.driverName == QLatin1String(
"ESRI Shapefile" ) )
3771 sFilters.insert( options, results );
3778 QSet< QString > extensions;
3780 const QRegularExpression rx( QStringLiteral(
"\\*\\.(.*)$" ) );
3784 for (
const QString &glob : format.globs )
3786 const QRegularExpressionMatch match = rx.match( glob );
3787 if ( !match.hasMatch() )
3790 const QString matched = match.captured( 1 );
3791 extensions.insert( matched );
3795 QStringList extensionList( extensions.constBegin(), extensions.constEnd() );
3797 std::sort( extensionList.begin(), extensionList.end(), [options](
const QString & a,
const QString & b ) ->
bool
3799 if ( options & SortRecommended )
3801 if ( a == QLatin1String(
"gpkg" ) )
3803 else if ( b == QLatin1String(
"gpkg" ) )
3805 else if ( a == QLatin1String(
"shp" ) )
3807 else if ( b == QLatin1String(
"shp" ) )
3811 return a.toLower().localeAwareCompare( b.toLower() ) < 0;
3814 return extensionList;
3819 QList< QgsVectorFileWriter::DriverDetails > results;
3822 const int drvCount = OGRGetDriverCount();
3824 QStringList writableDrivers;
3825 for (
int i = 0; i < drvCount; ++i )
3827 OGRSFDriverH drv = OGRGetDriver( i );
3830 QString drvName = OGR_Dr_GetName( drv );
3836 if ( drvName == QLatin1String(
"ODS" ) || drvName == QLatin1String(
"XLSX" ) || drvName == QLatin1String(
"XLS" ) )
3840 if ( drvName == QLatin1String(
"ESRI Shapefile" ) )
3842 writableDrivers << QStringLiteral(
"DBF file" );
3844 if ( OGR_Dr_TestCapability( drv,
"CreateDataSource" ) != 0 )
3847 if ( drvName == QLatin1String(
"MapInfo File" ) )
3849 writableDrivers << QStringLiteral(
"MapInfo MIF" );
3851 else if ( drvName == QLatin1String(
"SQLite" ) )
3858 QString option = QStringLiteral(
"SPATIALITE=YES" );
3859 char *options[2] = { CPLStrdup( option.toLocal8Bit().constData() ),
nullptr };
3860 OGRSFDriverH poDriver;
3862 poDriver = OGRGetDriverByName( drvName.toLocal8Bit().constData() );
3865 gdal::ogr_datasource_unique_ptr ds( OGR_Dr_CreateDataSource( poDriver, QStringLiteral(
"/vsimem/spatialitetest.sqlite" ).toUtf8().constData(), options ) );
3868 writableDrivers << QStringLiteral(
"SpatiaLite" );
3869 OGR_Dr_DeleteDataSource( poDriver, QStringLiteral(
"/vsimem/spatialitetest.sqlite" ).toUtf8().constData() );
3872 CPLFree( options[0] );
3874 writableDrivers << drvName;
3879 results.reserve( writableDrivers.count() );
3880 for (
const QString &drvName : std::as_const( writableDrivers ) )
3894 if ( options & SortRecommended )
3896 if ( a.driverName == QLatin1String(
"GPKG" ) )
3898 else if ( b.driverName == QLatin1String(
"GPKG" ) )
3900 else if ( a.driverName == QLatin1String(
"ESRI Shapefile" ) )
3902 else if ( b.driverName == QLatin1String(
"ESRI Shapefile" ) )
3906 return a.
longName.toLower().localeAwareCompare( b.
longName.toLower() ) < 0;
3913 QString ext = extension.trimmed();
3914 if ( ext.isEmpty() )
3917 if ( ext.startsWith(
'.' ) )
3921 int const drvCount = GDALGetDriverCount();
3923 for (
int i = 0; i < drvCount; ++i )
3925 GDALDriverH drv = GDALGetDriver( i );
3931 QString drvName = GDALGetDriverShortName( drv );
3932 QStringList driverExtensions = QString( GDALGetMetadataItem( drv, GDAL_DMD_EXTENSIONS,
nullptr ) ).split(
' ' );
3934 const auto constDriverExtensions = driverExtensions;
3935 for (
const QString &driver : constDriverExtensions )
3937 if ( driver.compare( ext, Qt::CaseInsensitive ) == 0 )
3948 QString filterString;
3952 if ( !filterString.isEmpty() )
3953 filterString += QLatin1String(
";;" );
3955 filterString += details.filterString;
3957 return filterString;
3966 return QStringLiteral(
"%1 (%2 %3)" ).arg( metadata.
trLongName,
3967 metadata.
glob.toLower(),
3968 metadata.
glob.toUpper() );
3973 if ( codecName == QLatin1String(
"System" ) )
3974 return QStringLiteral(
"LDID/0" );
3976 const QRegularExpression re( QRegularExpression::anchoredPattern( QString(
"(CP|windows-|ISO[ -])(.+)" ) ), QRegularExpression::CaseInsensitiveOption );
3977 const QRegularExpressionMatch match = re.match( codecName );
3978 if ( match.hasMatch() )
3980 QString
c = match.captured( 2 ).remove(
'-' );
3982 ( void )
c.toInt( &isNumber );
4010 OGRStyleTableH ogrStyleTable = OGR_STBL_Create();
4011 OGRStyleMgrH styleManager = OGR_SM_Create( ogrStyleTable );
4014 int nTotalLevels = 0;
4016 QgsSymbolList::iterator symbolIt = symbolList.begin();
4017 for ( ; symbolIt != symbolList.end(); ++symbolIt )
4019 double mmsf = mmScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
4020 double musf = mapUnitScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
4022 int nLevels = ( *symbolIt )->symbolLayerCount();
4023 for (
int i = 0; i < nLevels; ++i )
4025 mSymbolLayerTable.insert( ( *symbolIt )->symbolLayer( i ), QString::number( nTotalLevels ) );
4026 OGR_SM_AddStyle( styleManager, QString::number( nTotalLevels ).toLocal8Bit(),
4027 ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf ).toLocal8Bit() );
4031 OGR_DS_SetStyleTableDirectly( ds, ogrStyleTable );
4037 if ( !details.renderer )
4042 QHash< QgsSymbol *, QList<QgsFeature> > features;
4051 startRender( details.renderer.get(), details.sourceFields );
4071 QString msg = QObject::tr(
"Failed to transform, writing stopped. (Exception: %1)" )
4082 featureSymbol = mRenderer->symbolForFeature( fet, mRenderContext );
4083 if ( !featureSymbol )
4088 QHash< QgsSymbol *, QList<QgsFeature> >::iterator it = features.find( featureSymbol );
4089 if ( it == features.end() )
4091 it = features.insert( featureSymbol, QList<QgsFeature>() );
4093 it.value().append( fet );
4098 QgsSymbolList symbols = mRenderer->symbols( mRenderContext );
4099 for (
int i = 0; i < symbols.count(); i++ )
4105 if ( level < 0 || level >= 1000 )
4108 while ( level >= levels.count() )
4110 levels[level].append( item );
4115 int nTotalFeatures = 0;
4118 for (
int l = 0; l < levels.count(); l++ )
4121 for (
int i = 0; i < level.count(); i++ )
4124 QHash< QgsSymbol *, QList<QgsFeature> >::iterator levelIt = features.find( item.
symbol() );
4125 if ( levelIt == features.end() )
4131 double mmsf = mmScaleFactor(
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
4132 double musf = mapUnitScaleFactor(
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
4134 int llayer = item.
layer();
4135 QList<QgsFeature> &featureList = levelIt.value();
4136 QList<QgsFeature>::iterator featureIt = featureList.begin();
4137 for ( ; featureIt != featureList.end(); ++featureIt )
4147 QString styleString = levelIt.key()->symbolLayer( llayer )->ogrFeatureStyle( mmsf, musf );
4148 if ( !styleString.isEmpty() )
4150 OGR_F_SetStyleString( ogrFeature.get(), styleString.toLocal8Bit().constData() );
4151 if ( !writeFeature(
mLayer, ogrFeature.get() ) )
4164 *
errorMessage += QObject::tr(
"\nOnly %1 of %2 features written." ).arg( nTotalFeatures - nErrors ).arg( nTotalFeatures );
4181 return 1000 / scale;
4198 return scale / 1000;
4206 mRenderer = createSymbologyRenderer( sourceRenderer );
4212 mRenderer->startRender( mRenderContext, fields );
4215void QgsVectorFileWriter::stopRender()
4222 mRenderer->stopRender( mRenderContext );
4225std::unique_ptr<QgsFeatureRenderer> QgsVectorFileWriter::createSymbologyRenderer(
QgsFeatureRenderer *sourceRenderer )
const
4231 if ( !sourceRenderer )
4236 return std::unique_ptr< QgsFeatureRenderer >( sourceRenderer->
clone() );
4243 const QSet<QString> rendererAttributes = renderer->
usedAttributes( context );
4244 for (
const QString &attr : rendererAttributes )
4249 attList.append( index );
4255QStringList QgsVectorFileWriter::concatenateOptions(
const QMap<QString, QgsVectorFileWriter::Option *> &options )
4258 QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
4260 for ( it = options.constBegin(); it != options.constEnd(); ++it )
4263 switch ( option->
type )
4270 list.append( QStringLiteral(
"%1=%2" ).arg( it.key() ).arg( opt->
defaultValue ) );
4280 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
defaultValue ) );
4290 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
defaultValue ) );
4299 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
mValue ) );
4310 OGRSFDriverH hDriver =
nullptr;
4313 return QgsVectorFileWriter::EditionCapabilities();
4314 QString drvName = OGR_Dr_GetName( hDriver );
4315 QgsVectorFileWriter::EditionCapabilities caps = QgsVectorFileWriter::EditionCapabilities();
4316 if ( OGR_DS_TestCapability( hDS.get(), ODsCCreateLayer ) )
4321 if ( !( drvName == QLatin1String(
"ESRI Shapefile" ) && QFile::exists( datasetName ) ) )
4324 if ( OGR_DS_TestCapability( hDS.get(), ODsCDeleteLayer ) )
4328 int layer_count = OGR_DS_GetLayerCount( hDS.get() );
4331 OGRLayerH hLayer = OGR_DS_GetLayer( hDS.get(), 0 );
4334 if ( OGR_L_TestCapability( hLayer, OLCSequentialWrite ) )
4337 if ( OGR_L_TestCapability( hLayer, OLCCreateField ) )
4348 const QString &layerNameIn )
4350 OGRSFDriverH hDriver =
nullptr;
4355 QString layerName( layerNameIn );
4356 if ( layerName.isEmpty() )
4357 layerName = QFileInfo( datasetName ).baseName();
4359 return OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
4364 const QString &layerName,
4368 OGRSFDriverH hDriver =
nullptr;
4372 OGRLayerH hLayer = OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
4378 OGRFeatureDefnH defn = OGR_L_GetLayerDefn( hLayer );
4379 const auto constAttributes = attributes;
4380 for (
int idx : constAttributes )
4383 if ( OGR_FD_GetFieldIndex( defn, fld.
name().toUtf8().constData() ) < 0 )
@ Reverse
Reverse/inverse transform (from destination to source)
virtual bool addZValue(double zValue=0)=0
Adds a z-dimension to the geometry, initialized to a preset value.
virtual bool dropMValue()=0
Drops any measure values which exist in the geometry.
virtual bool addMValue(double mValue=0)=0
Adds a measure to the geometry, initialized to a preset value.
virtual bool dropZValue()=0
Drops any z-dimensions which exist in the geometry.
@ FlagExportTrianglesAsPolygons
Triangles should be exported as polygon geometries.
@ FlagExportNanAsDoubleMin
Use -DOUBLE_MAX to represent NaN (since QGIS 3.30)
static void registerOgrDrivers()
Register OGR drivers ensuring this only happens once.
This class represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
static Q_INVOKABLE QgsCoordinateReferenceSystem fromEpsgId(long epsg)
Creates a CRS from a given EPSG ID.
QgsUnitTypes::DistanceUnit mapUnits
Contains information about the context in which a coordinate transform is executed.
Custom exception class for Coordinate Reference System related exceptions.
virtual QString dataSourceUri(bool expandAuthConfig=false) const
Gets the data source specification.
Class for storing the component parts of a RDBMS data source URI (e.g.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
virtual QgsSymbolList symbolsForFeature(const QgsFeature &feature, QgsRenderContext &context) const
Returns list of symbols used for rendering the feature.
virtual QgsSymbolList symbols(QgsRenderContext &context) const
Returns list of symbols used by the renderer.
bool usingSymbolLevels() const
virtual QgsFeatureRenderer::Capabilities capabilities()
Returns details about internals of this renderer.
virtual QSet< QString > usedAttributes(const QgsRenderContext &context) const =0
Returns a list of attributes required by this renderer.
@ SymbolLevels
Rendering with symbol levels (i.e. implements symbols(), symbolForFeature())
virtual QgsFeatureRenderer * clone() const =0
Create a deep copy of this renderer.
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Sets the feature IDs that should be fetched.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
QgsFeatureRequest & setFilterRect(const QgsRectangle &rectangle)
Sets the rectangle from which features will be taken.
@ RegeneratePrimaryKey
This flag indicates, that a primary key field cannot be guaranteed to be unique and the sink should i...
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
void initAttributes(int fieldCount)
Initialize this feature with the given number of fields.
bool hasGeometry() const
Returns true if the feature has an associated geometry.
bool isUnsetValue(int fieldIdx) const
Returns true if the attribute at the specified index is an unset value.
QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
bool isCanceled() const
Tells whether the operation has been canceled already.
void setProgress(double progress)
Sets the current progress for the feedback object.
Encapsulate a field in an attribute table or data source.
QString typeName() const
Gets the field type.
bool convertCompatible(QVariant &v, QString *errorMessage=nullptr) const
Converts the provided variant to a compatible format.
void setName(const QString &name)
Set the field name.
QVariant::Type subType() const
If the field is a collection, gets its element's type.
Container of fields for a vector layer.
int count() const
Returns number of items.
int size() const
Returns number of items.
void clear()
Removes all fields.
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.
QgsWkbTypes::Type wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false)
Transforms this geometry as described by the coordinate transform ct.
QgsAbstractGeometry * get()
Returns a modifiable (non-const) reference to the underlying abstract geometry primitive.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry)
Creates and returns a new geometry engine representing the specified geometry.
bool convertToMultiType()
Converts single type geometry into multitype geometry e.g.
QByteArray asWkb(QgsAbstractGeometry::WkbFlags flags=QgsAbstractGeometry::WkbFlags()) const
Export the geometry to WKB.
static void warning(const QString &msg)
Goes to qWarning.
QString providerType() const
Returns the provider type (provider key) for this layer.
QgsCoordinateReferenceSystem crs
QgsCoordinateTransformContext transformContext() const
Returns the layer data provider coordinate transform context or a default transform context if the la...
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
Custom exception class which is raised when an operation is not supported.
static OGRSpatialReferenceH crsToOGRSpatialReference(const QgsCoordinateReferenceSystem &crs)
Returns a OGRSpatialReferenceH corresponding to the specified crs object.
static int OGRTZFlagFromQt(const QDateTime &datetime)
Gets the value of OGRField::Date::TZFlag from the timezone of a QDateTime.
QVariantMap decodeUri(const QString &providerKey, const QString &uri)
Breaks a provider data source URI into its component paths (e.g.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
QString encodeUri(const QString &providerKey, const QVariantMap &parts)
Reassembles a provider data source URI from its component paths (e.g.
bool saveLayerMetadata(const QString &providerKey, const QString &uri, const QgsLayerMetadata &metadata, QString &errorMessage)
Saves metadata to the layer corresponding to the specified uri.
The QgsReadWriteLocker class is a convenience class that simplifies locking and unlocking QReadWriteL...
void changeMode(Mode mode)
Change the mode of the lock to mode.
A rectangle specified with double values.
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()).
Contains information about the context of a rendering operation.
QgsExpressionContext & expressionContext()
Gets the expression context.
void setRendererScale(double scale)
Sets the renderer map scale.
This class is a composition of two QSettings instances:
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
int renderingPass() const
Specifies the rendering pass in which this symbol layer should be rendered.
int layer() const
The layer of this symbol level.
QgsSymbol * symbol() const
The symbol of this symbol level.
Abstract base class for all rendered symbols.
QgsSymbolLayer * symbolLayer(int layer)
Returns the symbol layer at the specified index.
int symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
DistanceUnit
Units of distance.
RenderUnit
Rendering size units.
@ RenderMillimeters
Millimeters.
@ RenderMapUnits
Map units.
static bool isNull(const QVariant &variant)
Returns true if the specified variant should be considered a NULL value.
Interface to convert raw field values to their user-friendly value.
virtual QVariant convert(int fieldIdxInLayer, const QVariant &value)
Convert the provided value, for field fieldIdxInLayer.
virtual QgsVectorFileWriter::FieldValueConverter * clone() const
Creates a clone of the FieldValueConverter.
virtual QgsField fieldDefinition(const QgsField &field)
Returns a possibly modified field definition.
QgsVectorFileWriter::OptionType type
Options to pass to writeAsVectorFormat()
QString fileEncoding
Encoding to use.
bool forceMulti
Sets to true to force creation of multi* geometries.
FieldNameSource fieldNameSource
Source for exported field names.
QString driverName
OGR driver to use.
QgsCoordinateTransform ct
Transform to reproject exported geometries with, or invalid transform for no transformation.
QStringList attributesExportNames
Attributes export names.
QgsLayerMetadata layerMetadata
Layer metadata to save for the exported vector file.
SaveVectorOptions()
Constructor.
QString layerName
Layer name. If let empty, it will be derived from the filename.
QgsRectangle filterExtent
If not empty, only features intersecting the extent will be saved.
QgsVectorFileWriter::FieldValueConverter * fieldValueConverter
Field value converter.
QStringList layerOptions
List of OGR layer creation options.
QgsVectorFileWriter::SymbologyExport symbologyExport
Symbology to export.
bool includeZ
Sets to true to include z dimension in output. This option is only valid if overrideGeometryType is s...
bool saveMetadata
Set to true to save layer metadata for the exported vector file.
QgsVectorFileWriter::ActionOnExistingFile actionOnExistingFile
Action on existing file.
QgsAttributeList attributes
Attributes to export (empty means all unless skipAttributeCreation is set)
bool onlySelectedFeatures
Write only selected features of layer.
bool skipAttributeCreation
Only write geometries.
double symbologyScale
Scale of symbology.
QStringList datasourceOptions
List of OGR data source creation options.
QgsWkbTypes::Type overrideGeometryType
Set to a valid geometry type to override the default geometry type for the layer.
QgsFeedback * feedback
Optional feedback object allowing cancellation of layer save.
A convenience class for writing vector layers to disk based formats (e.g.
static QgsVectorFileWriter::WriterError writeAsVectorFormatV3(QgsVectorLayer *layer, const QString &fileName, const QgsCoordinateTransformContext &transformContext, const QgsVectorFileWriter::SaveVectorOptions &options, QString *errorMessage=nullptr, QString *newFilename=nullptr, QString *newLayer=nullptr)
Writes a layer out to a vector file.
QString lastError() const override
Returns the most recent error encountered by the sink, e.g.
@ CanAddNewFieldsToExistingLayer
Flag to indicate that new fields can be added to an existing layer. Imply CanAppendToExistingLayer.
@ CanAppendToExistingLayer
Flag to indicate that new features can be added to an existing layer.
@ CanAddNewLayer
Flag to indicate that a new layer can be added to the dataset.
@ CanDeleteLayer
Flag to indicate that an existing layer can be deleted.
static QgsVectorFileWriter::EditionCapabilities editionCapabilities(const QString &datasetName)
Returns edition capabilities for an existing dataset name.
static QgsVectorFileWriter * create(const QString &fileName, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &srs, const QgsCoordinateTransformContext &transformContext, const QgsVectorFileWriter::SaveVectorOptions &options, QgsFeatureSink::SinkFlags sinkFlags=QgsFeatureSink::SinkFlags(), QString *newFilename=nullptr, QString *newLayer=nullptr)
Create a new vector file writer.
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a single feature to the sink.
static bool supportsFeatureStyles(const QString &driverName)
Returns true if the specified driverName supports feature styles.
bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a list of features to the sink.
double mSymbologyScale
Scale for symbology export (e.g. for symbols units in map units)
OGRGeometryH createEmptyGeometry(QgsWkbTypes::Type wkbType)
QMap< int, int > mAttrIdxToOgrIdx
Map attribute indizes to OGR field indexes.
@ ErrAttributeTypeUnsupported
@ Canceled
Writing was interrupted by manual cancellation.
@ ErrAttributeCreationFailed
@ ErrSavingMetadata
Metadata saving failed.
gdal::ogr_datasource_unique_ptr mDS
static Q_DECL_DEPRECATED QgsVectorFileWriter::WriterError writeAsVectorFormatV2(QgsVectorLayer *layer, const QString &fileName, const QgsCoordinateTransformContext &transformContext, const QgsVectorFileWriter::SaveVectorOptions &options, QString *newFilename=nullptr, QString *newLayer=nullptr, QString *errorMessage=nullptr)
Writes a layer out to a vector file.
~QgsVectorFileWriter() override
Close opened shapefile for writing.
static bool targetLayerExists(const QString &datasetName, const QString &layerName)
Returns whether the target layer already exists.
double symbologyScale() const
Returns the reference scale for output.
static QStringList defaultLayerOptions(const QString &driverName)
Returns a list of the default layer options for a specified driver.
SymbologyExport mSymbologyExport
static QString driverForExtension(const QString &extension)
Returns the OGR driver name for a specified file extension.
static QList< QgsVectorFileWriter::FilterFormatDetails > supportedFiltersAndFormats(VectorFormatOptions options=SortRecommended)
Returns a list or pairs, with format filter string as first element and OGR format key as second elem...
OGRSpatialReferenceH mOgrRef
static bool driverMetadata(const QString &driverName, MetaData &driverMetadata)
static bool deleteShapeFile(const QString &fileName)
Delete a shapefile (and its accompanying shx / dbf / prj / qix / qpj / cpg / sbn / sbx / idm / ind)
static QString filterForDriver(const QString &driverName)
Creates a filter for an OGR driver key.
QgsWkbTypes::Type mWkbType
Geometry type which is being used.
QgsVectorFileWriter::WriterError hasError() const
Checks whether there were any errors in constructor.
static OGRwkbGeometryType ogrTypeFromWkbType(QgsWkbTypes::Type type)
Gets the ogr geometry type from an internal QGIS wkb type enum.
@ SkipNonSpatialFormats
Filter out any formats which do not have spatial support (e.g. those which cannot save geometries)
static bool areThereNewFieldsToCreate(const QString &datasetName, const QString &layerName, QgsVectorLayer *layer, const QgsAttributeList &attributes)
Returns whether there are among the attributes specified some that do not exist yet in the layer.
static QList< QgsVectorFileWriter::DriverDetails > ogrDriverList(VectorFormatOptions options=SortRecommended)
Returns the driver list that can be used for dialogs.
static Q_DECL_DEPRECATED QgsVectorFileWriter::WriterError writeAsVectorFormat(QgsVectorLayer *layer, const QString &fileName, const QString &fileEncoding, const QgsCoordinateReferenceSystem &destCRS=QgsCoordinateReferenceSystem(), const QString &driverName="GPKG", bool onlySelected=false, QString *errorMessage=nullptr, const QStringList &datasourceOptions=QStringList(), const QStringList &layerOptions=QStringList(), bool skipAttributeCreation=false, QString *newFilename=nullptr, QgsVectorFileWriter::SymbologyExport symbologyExport=QgsVectorFileWriter::NoSymbology, double symbologyScale=1.0, const QgsRectangle *filterExtent=nullptr, QgsWkbTypes::Type overrideGeometryType=QgsWkbTypes::Unknown, bool forceMulti=false, bool includeZ=false, const QgsAttributeList &attributes=QgsAttributeList(), QgsVectorFileWriter::FieldValueConverter *fieldValueConverter=nullptr, QString *newLayer=nullptr)
Write contents of vector layer to an (OGR supported) vector format.
WriterError mError
Contains error value if construction was not successful.
FieldNameSource
Source for exported field names.
@ PreferAlias
Use the field alias as the exported field name, wherever one is set. Otherwise use the original field...
@ Original
Use original field names.
static QStringList defaultDatasetOptions(const QString &driverName)
Returns a list of the default dataset options for a specified driver.
static QStringList supportedFormatExtensions(VectorFormatOptions options=SortRecommended)
Returns a list of file extensions for supported formats, e.g "shp", "gpkg".
static QString convertCodecNameForEncodingOption(const QString &codecName)
Converts codec name to string passed to ENCODING layer creation option of OGR Shapefile.
FieldValueConverter * mFieldValueConverter
Field value converter.
bool addFeatureWithStyle(QgsFeature &feature, QgsFeatureRenderer *renderer, QgsUnitTypes::DistanceUnit outputUnit=QgsUnitTypes::DistanceMeters)
Adds a feature to the currently opened data source, using the style from a specified renderer.
QString errorMessage() const
Retrieves error message.
QgsVectorFileWriter::SymbologyExport symbologyExport() const
void setSymbologyScale(double scale)
Set reference scale for output.
Q_DECL_DEPRECATED QgsVectorFileWriter(const QString &vectorFileName, const QString &fileEncoding, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &srs=QgsCoordinateReferenceSystem(), const QString &driverName="GPKG", const QStringList &datasourceOptions=QStringList(), const QStringList &layerOptions=QStringList(), QString *newFilename=nullptr, QgsVectorFileWriter::SymbologyExport symbologyExport=QgsVectorFileWriter::NoSymbology, QgsFeatureSink::SinkFlags sinkFlags=QgsFeatureSink::SinkFlags(), QString *newLayer=nullptr, const QgsCoordinateTransformContext &transformContext=QgsCoordinateTransformContext(), FieldNameSource fieldNameSource=Original)
Create a new vector file writer.
QMap< QgsSymbolLayer *, QString > mSymbolLayerTable
static QString fileFilterString(VectorFormatOptions options=SortRecommended)
Returns filter string that can be used for dialogs.
ActionOnExistingFile
Combination of CanAddNewLayer, CanAppendToExistingLayer, CanAddNewFieldsToExistingLayer or CanDeleteL...
@ CreateOrOverwriteLayer
Create or overwrite layer.
@ CreateOrOverwriteFile
Create or overwrite file.
@ AppendToLayerNoNewFields
Append features to existing layer, but do not create new fields.
@ AppendToLayerAddFields
Append features to existing layer, and create new fields if needed.
Represents a vector layer which manages a vector based data sets.
Q_INVOKABLE QgsWkbTypes::Type wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
long long featureCount(const QString &legendKey) const
Number of features rendered with specified legend key.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
int selectedFeatureCount() const
Returns the number of features that are selected in this layer.
Q_INVOKABLE const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
QgsFeatureRenderer * renderer()
Returns the feature renderer used for rendering the features in the layer in 2D map views.
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
void minimumAndMaximumValue(int index, QVariant &minimum, QVariant &maximum) const
Calculates both the minimum and maximum value for an attribute column.
static Type to25D(Type type)
Will convert the 25D version of the flat type if supported or Unknown if not supported.
Type
The WKB type describes the number of dimensions a geometry has.
static bool hasZ(Type type)
Tests whether a WKB type contains the z-dimension.
static bool hasM(Type type)
Tests whether a WKB type contains m values.
static Type multiType(Type type)
Returns the multi type for a WKB type.
static Type addZ(Type type)
Adds the z dimension to a WKB type and returns the new type.
static Type flatType(Type type)
Returns the flat type for a WKB type.
static Type singleType(Type type)
Returns the single type for a WKB type.
static bool isMultiType(Type type)
Returns true if the WKB type is a multi type.
std::unique_ptr< std::remove_pointer< OGRFeatureH >::type, OGRFeatureDeleter > ogr_feature_unique_ptr
Scoped OGR feature.
std::unique_ptr< std::remove_pointer< OGRDataSourceH >::type, OGRDataSourceDeleter > ogr_datasource_unique_ptr
Scoped OGR data source.
std::unique_ptr< std::remove_pointer< OGRFieldDefnH >::type, OGRFldDeleter > ogr_field_def_unique_ptr
Scoped OGR field definition.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
#define Q_NOWARN_DEPRECATED_POP
#define Q_NOWARN_DEPRECATED_PUSH
QList< QgsFeature > QgsFeatureList
QList< int > QgsAttributeList
#define QgsDebugMsgLevel(str, level)
QList< QgsSymbolLevel > QgsSymbolLevelOrder
QList< QgsSymbolLevelItem > QgsSymbolLevel
QList< QgsSymbol * > QgsSymbolList
Details of available driver formats.
QString longName
Descriptive, user friendly name for the driver.
QString driverName
Unique driver name.