45 #include <QTextStream>
49 #include <QRegularExpression>
55 #include <ogr_srs_api.h>
56 #include <cpl_error.h>
58 #include <cpl_string.h>
77 const QString &vectorFileName,
78 const QString &fileEncoding,
82 const QString &driverName,
83 const QStringList &datasourceOptions,
84 const QStringList &layerOptions,
87 QgsFeatureSink::SinkFlags sinkFlags,
97 init( vectorFileName, fileEncoding, fields, geometryType,
98 srs, driverName, datasourceOptions, layerOptions, newFilename,
nullptr,
103 const QString &vectorFileName,
104 const QString &fileEncoding,
108 const QString &driverName,
109 const QStringList &datasourceOptions,
110 const QStringList &layerOptions,
111 QString *newFilename,
114 const QString &layerName,
118 QgsFeatureSink::SinkFlags sinkFlags,
122 , mWkbType( geometryType )
123 , mSymbologyExport( symbologyExport )
124 , mSymbologyScale( 1.0 )
126 init( vectorFileName, fileEncoding, fields, geometryType, srs, driverName,
127 datasourceOptions, layerOptions, newFilename, fieldValueConverter,
128 layerName, action, newLayer, sinkFlags, transformContext, fieldNameSource );
132 const QString &fileName,
138 QgsFeatureSink::SinkFlags sinkFlags,
139 QString *newFilename,
153 if ( driverName == QLatin1String(
"MapInfo MIF" ) )
157 GDALDriverH gdalDriver = GDALGetDriverByName( driverName.toLocal8Bit().constData() );
165 return CSLFetchBoolean(
driverMetadata, GDAL_DCAP_FEATURE_STYLES,
false );
168 void QgsVectorFileWriter::init( QString vectorFileName,
169 QString fileEncoding,
173 const QString &driverName,
174 QStringList datasourceOptions,
175 QStringList layerOptions,
176 QString *newFilename,
177 FieldValueConverter *fieldValueConverter,
178 const QString &layerNameIn,
179 ActionOnExistingFile action,
180 QString *newLayer, SinkFlags sinkFlags,
185 if ( vectorFileName.isEmpty() )
192 if ( driverName == QLatin1String(
"MapInfo MIF" ) )
196 else if ( driverName == QLatin1String(
"SpatiaLite" ) )
199 if ( !datasourceOptions.contains( QStringLiteral(
"SPATIALITE=YES" ) ) )
201 datasourceOptions.append( QStringLiteral(
"SPATIALITE=YES" ) );
204 else if ( driverName == QLatin1String(
"DBF file" ) )
207 if ( !layerOptions.contains( QStringLiteral(
"SHPT=NULL" ) ) )
209 layerOptions.append( QStringLiteral(
"SHPT=NULL" ) );
218 #if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,3,1)
219 QString fidFieldName;
222 for (
const QString &layerOption : layerOptions )
224 if ( layerOption.startsWith( QLatin1String(
"FID=" ) ) )
226 fidFieldName = layerOption.mid( 4 );
230 if ( fidFieldName.isEmpty() )
231 fidFieldName = QStringLiteral(
"fid" );
236 OGRSFDriverH poDriver;
239 poDriver = OGRGetDriverByName(
mOgrDriverName.toLocal8Bit().constData() );
243 mErrorMessage = QObject::tr(
"OGR driver for '%1' not found (OGR error: %2)" )
245 QString::fromUtf8( CPLGetLastErrorMsg() ) );
255 if ( layerOptions.join( QString() ).toUpper().indexOf( QLatin1String(
"ENCODING=" ) ) == -1 )
260 if ( driverName == QLatin1String(
"ESRI Shapefile" ) && !vectorFileName.endsWith( QLatin1String(
".shp" ), Qt::CaseInsensitive ) )
262 vectorFileName += QLatin1String(
".shp" );
264 else if ( driverName == QLatin1String(
"DBF file" ) && !vectorFileName.endsWith( QLatin1String(
".dbf" ), Qt::CaseInsensitive ) )
266 vectorFileName += QLatin1String(
".dbf" );
276 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
277 QStringList allExts = metadata.ext.split(
' ', QString::SkipEmptyParts );
279 QStringList allExts = metadata.ext.split(
' ', Qt::SkipEmptyParts );
282 const auto constAllExts = allExts;
283 for (
const QString &ext : constAllExts )
285 if ( vectorFileName.endsWith(
'.' + ext, Qt::CaseInsensitive ) )
294 vectorFileName +=
'.' + allExts[0];
300 if ( vectorFileName.endsWith( QLatin1String(
".gdb" ), Qt::CaseInsensitive ) )
302 QDir dir( vectorFileName );
305 QFileInfoList fileList = dir.entryInfoList(
306 QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files, QDir::DirsFirst );
307 const auto constFileList = fileList;
308 for (
const QFileInfo &info : constFileList )
310 QFile::remove( info.absoluteFilePath() );
313 QDir().rmdir( vectorFileName );
317 QFile::remove( vectorFileName );
322 if ( metadataFound && !metadata.compulsoryEncoding.isEmpty() )
324 if ( fileEncoding.compare( metadata.compulsoryEncoding, Qt::CaseInsensitive ) != 0 )
326 QgsDebugMsgLevel( QStringLiteral(
"forced %1 encoding for %2" ).arg( metadata.compulsoryEncoding, driverName ), 2 );
327 fileEncoding = metadata.compulsoryEncoding;
332 char **options =
nullptr;
333 if ( !datasourceOptions.isEmpty() )
335 options =
new char *[ datasourceOptions.size() + 1 ];
336 for (
int i = 0; i < datasourceOptions.size(); i++ )
338 QgsDebugMsgLevel( QStringLiteral(
"-dsco=%1" ).arg( datasourceOptions[i] ), 2 );
339 options[i] = CPLStrdup( datasourceOptions[i].toLocal8Bit().constData() );
341 options[ datasourceOptions.size()] =
nullptr;
347 mDS.reset( OGR_Dr_CreateDataSource( poDriver, vectorFileName.toUtf8().constData(), options ) );
349 mDS.reset( OGROpen( vectorFileName.toUtf8().constData(), TRUE,
nullptr ) );
353 for (
int i = 0; i < datasourceOptions.size(); i++ )
354 CPLFree( options[i] );
363 mErrorMessage = QObject::tr(
"Creation of data source failed (OGR error: %1)" )
364 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
366 mErrorMessage = QObject::tr(
"Opening of data source in update mode failed (OGR error: %1)" )
367 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
371 QString layerName( layerNameIn );
372 if ( layerName.isEmpty() )
373 layerName = QFileInfo( vectorFileName ).baseName();
377 const int layer_count = OGR_DS_GetLayerCount(
mDS.get() );
378 for (
int i = 0; i < layer_count; i++ )
380 OGRLayerH hLayer = OGR_DS_GetLayer(
mDS.get(), i );
381 if ( EQUAL( OGR_L_GetName( hLayer ), layerName.toUtf8().constData() ) )
383 if ( OGR_DS_DeleteLayer(
mDS.get(), i ) != OGRERR_NONE )
386 mErrorMessage = QObject::tr(
"Overwriting of existing layer failed (OGR error: %1)" )
387 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
401 QgsDebugMsgLevel( QStringLiteral(
"Opened data source in update mode" ), 2 );
405 mCodec = QTextCodec::codecForName( fileEncoding.toLocal8Bit().constData() );
408 QgsDebugMsg(
"error finding QTextCodec for " + fileEncoding );
411 QString enc = settings.
value( QStringLiteral(
"UI/encoding" ),
"System" ).toString();
412 mCodec = QTextCodec::codecForName( enc.toLocal8Bit().constData() );
415 QgsDebugMsg(
"error finding QTextCodec for " + enc );
416 mCodec = QTextCodec::codecForLocale();
422 if ( driverName == QLatin1String(
"KML" ) || driverName == QLatin1String(
"LIBKML" ) || driverName == QLatin1String(
"GPX" ) )
424 if ( srs.
authid() != QLatin1String(
"EPSG:4326" ) )
439 int optIndex = layerOptions.indexOf( QLatin1String(
"FEATURE_DATASET=" ) );
440 if ( optIndex != -1 )
442 layerOptions.removeAt( optIndex );
445 if ( !layerOptions.isEmpty() )
447 options =
new char *[ layerOptions.size() + 1 ];
448 for (
int i = 0; i < layerOptions.size(); i++ )
451 options[i] = CPLStrdup( layerOptions[i].toLocal8Bit().constData() );
453 options[ layerOptions.size()] =
nullptr;
457 CPLSetConfigOption(
"SHAPE_ENCODING",
"" );
461 mLayer = OGR_DS_CreateLayer(
mDS.get(), layerName.toUtf8().constData(),
mOgrRef, wkbType, options );
464 *newLayer = OGR_L_GetName(
mLayer );
465 if ( driverName == QLatin1String(
"GPX" ) )
472 if ( !EQUAL( layerName.toUtf8().constData(),
"track_points" ) &&
473 !EQUAL( layerName.toUtf8().constData(),
"route_points" ) )
475 *newLayer = QStringLiteral(
"waypoints" );
482 const char *pszForceGPXTrack
483 = CSLFetchNameValue( options,
"FORCE_GPX_TRACK" );
484 if ( pszForceGPXTrack && CPLTestBool( pszForceGPXTrack ) )
485 *newLayer = QStringLiteral(
"tracks" );
487 *newLayer = QStringLiteral(
"routes" );
494 const char *pszForceGPXRoute
495 = CSLFetchNameValue( options,
"FORCE_GPX_ROUTE" );
496 if ( pszForceGPXRoute && CPLTestBool( pszForceGPXRoute ) )
497 *newLayer = QStringLiteral(
"routes" );
499 *newLayer = QStringLiteral(
"tracks" );
509 else if ( driverName == QLatin1String(
"DGN" ) )
511 mLayer = OGR_DS_GetLayerByName(
mDS.get(),
"elements" );
515 mLayer = OGR_DS_GetLayerByName(
mDS.get(), layerName.toUtf8().constData() );
520 for (
int i = 0; i < layerOptions.size(); i++ )
521 CPLFree( options[i] );
530 QString layerName = vectorFileName.left( vectorFileName.indexOf( QLatin1String(
".shp" ), Qt::CaseInsensitive ) );
531 QFile prjFile( layerName +
".qpj" );
532 if ( prjFile.exists() )
540 mErrorMessage = QObject::tr(
"Creation of layer failed (OGR error: %1)" )
541 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
543 mErrorMessage = QObject::tr(
"Opening of layer failed (OGR error: %1)" )
544 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
549 OGRFeatureDefnH defn = OGR_L_GetLayerDefn(
mLayer );
558 QSet<int> existingIdxs;
568 for (
int fldIdx = 0; fldIdx < fields.
count(); ++fldIdx )
572 if ( fieldValueConverter )
574 attrField = fieldValueConverter->fieldDefinition( fields.
at( fldIdx ) );
579 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( attrField.
name() ) );
588 switch ( fieldNameSource )
591 name = attrField.
name();
595 name = !attrField.
alias().isEmpty() ? attrField.
alias() : attrField.
name();
599 OGRFieldType ogrType = OFTString;
600 int ogrWidth = attrField.
length();
601 int ogrPrecision = attrField.
precision();
602 if ( ogrPrecision > 0 )
605 switch ( attrField.
type() )
607 case QVariant::LongLong:
609 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
610 if ( pszDataTypes && strstr( pszDataTypes,
"Integer64" ) )
611 ogrType = OFTInteger64;
614 ogrWidth = ogrWidth > 0 && ogrWidth <= 20 ? ogrWidth : 20;
618 case QVariant::String:
620 if ( ( ogrWidth <= 0 || ogrWidth > 255 ) &&
mOgrDriverName == QLatin1String(
"ESRI Shapefile" ) )
625 ogrType = OFTInteger;
626 ogrWidth = ogrWidth > 0 && ogrWidth <= 10 ? ogrWidth : 10;
631 ogrType = OFTInteger;
636 case QVariant::Double:
637 #if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,3,1)
638 if (
mOgrDriverName == QLatin1String(
"GPKG" ) && attrField.
precision() == 0 && attrField.
name().compare( fidFieldName, Qt::CaseInsensitive ) == 0 )
641 ogrType = OFTInteger64;
664 case QVariant::DateTime:
672 ogrType = OFTDateTime;
676 case QVariant::ByteArray:
680 case QVariant::StringList:
682 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
683 if ( pszDataTypes && strstr( pszDataTypes,
"StringList" ) )
685 ogrType = OFTStringList;
686 mSupportedListSubTypes.insert( QVariant::String );
698 if ( attrField.
subType() == QVariant::String )
700 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
701 if ( pszDataTypes && strstr( pszDataTypes,
"StringList" ) )
703 ogrType = OFTStringList;
704 mSupportedListSubTypes.insert( QVariant::String );
713 else if ( attrField.
subType() == QVariant::Int )
715 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
716 if ( pszDataTypes && strstr( pszDataTypes,
"IntegerList" ) )
718 ogrType = OFTIntegerList;
719 mSupportedListSubTypes.insert( QVariant::Int );
728 else if ( attrField.
subType() == QVariant::Double )
730 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
731 if ( pszDataTypes && strstr( pszDataTypes,
"RealList" ) )
733 ogrType = OFTRealList;
734 mSupportedListSubTypes.insert( QVariant::Double );
743 else if ( attrField.
subType() == QVariant::LongLong )
745 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
746 if ( pszDataTypes && strstr( pszDataTypes,
"Integer64List" ) )
748 ogrType = OFTInteger64List;
749 mSupportedListSubTypes.insert( QVariant::LongLong );
763 mErrorMessage = QObject::tr(
"Unsupported type for field %1" )
764 .arg( attrField.
name() );
769 if (
mOgrDriverName == QLatin1String(
"SQLite" ) && name.compare( QLatin1String(
"ogc_fid" ), Qt::CaseInsensitive ) == 0 )
772 for ( i = 0; i < 10; i++ )
774 name = QStringLiteral(
"ogc_fid%1" ).arg( i );
777 for ( j = 0; j < fields.
size() && name.compare( fields.
at( j ).
name(), Qt::CaseInsensitive ) != 0; j++ )
780 if ( j == fields.
size() )
786 mErrorMessage = QObject::tr(
"No available replacement for internal fieldname ogc_fid found" ).arg( attrField.
name() );
791 QgsMessageLog::logMessage( QObject::tr(
"Reserved attribute name ogc_fid replaced with %1" ).arg( name ), QObject::tr(
"OGR" ) );
798 OGR_Fld_SetWidth( fld.get(), ogrWidth );
801 if ( ogrPrecision >= 0 )
803 OGR_Fld_SetPrecision( fld.get(), ogrPrecision );
806 switch ( attrField.
type() )
809 OGR_Fld_SetSubType( fld.get(), OFSTBoolean );
817 " type " + QString( QVariant::typeToName( attrField.
type() ) ) +
818 " width " + QString::number( ogrWidth ) +
819 " precision " + QString::number( ogrPrecision ), 2 );
820 if ( OGR_L_CreateField(
mLayer, fld.get(),
true ) != OGRERR_NONE )
823 mErrorMessage = QObject::tr(
"Creation of field %1 failed (OGR error: %2)" )
824 .arg( attrField.
name(),
825 QString::fromUtf8( CPLGetLastErrorMsg() ) );
830 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( name ) );
831 QgsDebugMsgLevel( QStringLiteral(
"returned field index for %1: %2" ).arg( name ).arg( ogrIdx ), 2 );
832 if ( ogrIdx < 0 || existingIdxs.contains( ogrIdx ) )
835 ogrIdx = OGR_FD_GetFieldCount( defn ) - 1;
840 mErrorMessage = QObject::tr(
"Created field %1 not found (OGR error: %2)" )
841 .arg( attrField.
name(),
842 QString::fromUtf8( CPLGetLastErrorMsg() ) );
848 existingIdxs.insert( ogrIdx );
856 for (
int fldIdx = 0; fldIdx < fields.
count(); ++fldIdx )
859 QString name( attrField.
name() );
860 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( name ) );
872 int fidIdx = fields.
lookupField( QStringLiteral(
"FID" ) );
883 *newFilename = vectorFileName;
886 mUsingTransaction =
true;
887 if ( OGRERR_NONE != OGR_L_StartTransaction(
mLayer ) )
889 mUsingTransaction =
false;
899 class QgsVectorFileWriterMetadataContainer
903 QgsVectorFileWriterMetadataContainer()
905 QMap<QString, QgsVectorFileWriter::Option *> datasetOptions;
906 QMap<QString, QgsVectorFileWriter::Option *> layerOptions;
909 datasetOptions.clear();
910 layerOptions.clear();
912 driverMetadata.insert( QStringLiteral(
"AVCE00" ),
914 QStringLiteral(
"Arc/Info ASCII Coverage" ),
915 QObject::tr(
"Arc/Info ASCII Coverage" ),
916 QStringLiteral(
"*.e00" ),
917 QStringLiteral(
"e00" ),
924 #if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,3,0)
928 datasetOptions.clear();
929 layerOptions.clear();
932 QObject::tr(
"New BNA files are created by the "
933 "systems default line termination conventions. "
934 "This may be overridden here." ),
936 << QStringLiteral(
"CRLF" )
937 << QStringLiteral(
"LF" ),
943 QObject::tr(
"By default, BNA files are created in multi-line format. "
944 "For each record, the first line contains the identifiers and the "
945 "type/number of coordinates to follow. Each following line contains "
946 "a pair of coordinates." ),
951 QObject::tr(
"BNA records may contain from 2 to 4 identifiers per record. "
952 "Some software packages only support a precise number of identifiers. "
953 "You can override the default value (2) by a precise value." ),
955 << QStringLiteral(
"2" )
956 << QStringLiteral(
"3" )
957 << QStringLiteral(
"4" )
958 << QStringLiteral(
"NB_SOURCE_FIELDS" ),
959 QStringLiteral(
"2" )
963 QObject::tr(
"The BNA writer will try to recognize ellipses and circles when writing a polygon. "
964 "This will only work if the feature has previously been read from a BNA file. "
965 "As some software packages do not support ellipses/circles in BNA data file, "
966 "it may be useful to tell the writer by specifying ELLIPSES_AS_ELLIPSES=NO not "
967 "to export them as such, but keep them as polygons." ),
972 QObject::tr(
"Limit the number of coordinate pairs per line in multiline format." ),
977 QObject::tr(
"Set the number of decimal for coordinates. Default value is 10." ),
981 driverMetadata.insert( QStringLiteral(
"BNA" ),
983 QStringLiteral(
"Atlas BNA" ),
984 QObject::tr(
"Atlas BNA" ),
985 QStringLiteral(
"*.bna" ),
986 QStringLiteral(
"bna" ),
994 datasetOptions.clear();
995 layerOptions.clear();
998 QObject::tr(
"By default when creating new .csv files they "
999 "are created with the line termination conventions "
1000 "of the local platform (CR/LF on Win32 or LF on all other systems). "
1001 "This may be overridden through the use of the LINEFORMAT option." ),
1003 << QStringLiteral(
"CRLF" )
1004 << QStringLiteral(
"LF" ),
1010 QObject::tr(
"By default, the geometry of a feature written to a .csv file is discarded. "
1011 "It is possible to export the geometry in its WKT representation by "
1012 "specifying GEOMETRY=AS_WKT. It is also possible to export point geometries "
1013 "into their X,Y,Z components by specifying GEOMETRY=AS_XYZ, GEOMETRY=AS_XY "
1014 "or GEOMETRY=AS_YX." ),
1016 << QStringLiteral(
"AS_WKT" )
1017 << QStringLiteral(
"AS_XYZ" )
1018 << QStringLiteral(
"AS_XY" )
1019 << QStringLiteral(
"AS_YX" ),
1025 QObject::tr(
"Create the associated .csvt file to describe the type of each "
1026 "column of the layer and its optional width and precision." ),
1031 QObject::tr(
"Field separator character." ),
1033 << QStringLiteral(
"COMMA" )
1034 << QStringLiteral(
"SEMICOLON" )
1035 << QStringLiteral(
"TAB" ),
1036 QStringLiteral(
"COMMA" )
1040 QObject::tr(
"Double-quote strings. IF_AMBIGUOUS means that string values that look like numbers will be quoted." ),
1042 << QStringLiteral(
"IF_NEEDED" )
1043 << QStringLiteral(
"IF_AMBIGUOUS" )
1044 << QStringLiteral(
"ALWAYS" ),
1045 QStringLiteral(
"IF_AMBIGUOUS" )
1049 QObject::tr(
"Write a UTF-8 Byte Order Mark (BOM) at the start of the file." ),
1053 driverMetadata.insert( QStringLiteral(
"CSV" ),
1055 QStringLiteral(
"Comma Separated Value [CSV]" ),
1056 QObject::tr(
"Comma Separated Value [CSV]" ),
1057 QStringLiteral(
"*.csv" ),
1058 QStringLiteral(
"csv" ),
1064 #if defined(GDAL_COMPUTE_VERSION) && GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,1,0)
1066 datasetOptions.clear();
1067 layerOptions.clear();
1069 driverMetadata.insert( QStringLiteral(
"FlatGeobuf" ),
1071 QStringLiteral(
"FlatGeobuf" ),
1072 QObject::tr(
"FlatGeobuf" ),
1073 QStringLiteral(
"*.fgb" ),
1074 QStringLiteral(
"fgb" ),
1077 QStringLiteral(
"UTF-8" )
1083 datasetOptions.clear();
1084 layerOptions.clear();
1087 QObject::tr(
"Override the type of shapefile created. "
1088 "Can be one of NULL for a simple .dbf file with no .shp file, POINT, "
1089 "ARC, POLYGON or MULTIPOINT for 2D, or POINTZ, ARCZ, POLYGONZ or "
1090 "MULTIPOINTZ for 3D;" ) +
1091 QObject::tr(
" POINTM, ARCM, POLYGONM or MULTIPOINTM for measured geometries"
1092 " and POINTZM, ARCZM, POLYGONZM or MULTIPOINTZM for 3D measured"
1094 QObject::tr(
" MULTIPATCH files are supported since GDAL 2.2." ) +
1097 << QStringLiteral(
"NULL" )
1098 << QStringLiteral(
"POINT" )
1099 << QStringLiteral(
"ARC" )
1100 << QStringLiteral(
"POLYGON" )
1101 << QStringLiteral(
"MULTIPOINT" )
1102 << QStringLiteral(
"POINTZ" )
1103 << QStringLiteral(
"ARCZ" )
1104 << QStringLiteral(
"POLYGONZ" )
1105 << QStringLiteral(
"MULTIPOINTZ" )
1106 << QStringLiteral(
"POINTM" )
1107 << QStringLiteral(
"ARCM" )
1108 << QStringLiteral(
"POLYGONM" )
1109 << QStringLiteral(
"MULTIPOINTM" )
1110 << QStringLiteral(
"POINTZM" )
1111 << QStringLiteral(
"ARCZM" )
1112 << QStringLiteral(
"POLYGONZM" )
1113 << QStringLiteral(
"MULTIPOINTZM" )
1114 << QStringLiteral(
"MULTIPATCH" )
1124 QObject::tr(
"Set the encoding value in the DBF file. "
1125 "The default value is LDID/87. It is not clear "
1126 "what other values may be appropriate." ),
1134 QObject::tr(
"Set to YES to resize fields to their optimal size." ),
1138 driverMetadata.insert( QStringLiteral(
"ESRI" ),
1140 QStringLiteral(
"ESRI Shapefile" ),
1141 QObject::tr(
"ESRI Shapefile" ),
1142 QStringLiteral(
"*.shp" ),
1143 QStringLiteral(
"shp" ),
1150 datasetOptions.clear();
1151 layerOptions.clear();
1153 driverMetadata.insert( QStringLiteral(
"DBF File" ),
1155 QStringLiteral(
"DBF File" ),
1156 QObject::tr(
"DBF File" ),
1157 QStringLiteral(
"*.dbf" ),
1158 QStringLiteral(
"dbf" ),
1165 datasetOptions.clear();
1166 layerOptions.clear();
1168 driverMetadata.insert( QStringLiteral(
"FMEObjects Gateway" ),
1170 QStringLiteral(
"FMEObjects Gateway" ),
1171 QObject::tr(
"FMEObjects Gateway" ),
1172 QStringLiteral(
"*.fdd" ),
1173 QStringLiteral(
"fdd" ),
1180 datasetOptions.clear();
1181 layerOptions.clear();
1184 QObject::tr(
"Set to YES to write a bbox property with the bounding box "
1185 "of the geometries at the feature and feature collection level." ),
1190 QObject::tr(
"Maximum number of figures after decimal separator to write in coordinates. "
1191 "Defaults to 15. Truncation will occur to remove trailing zeros." ),
1196 QObject::tr(
"Whether to use RFC 7946 standard. "
1197 "If disabled GeoJSON 2008 initial version will be used. "
1198 "Default is NO (thus GeoJSON 2008). See also Documentation (via Help button)" ),
1202 driverMetadata.insert( QStringLiteral(
"GeoJSON" ),
1204 QStringLiteral(
"GeoJSON" ),
1205 QObject::tr(
"GeoJSON" ),
1206 QStringLiteral(
"*.geojson" ),
1207 QStringLiteral(
"geojson" ),
1210 QStringLiteral(
"UTF-8" )
1215 datasetOptions.clear();
1216 layerOptions.clear();
1219 QObject::tr(
"Maximum number of figures after decimal separator to write in coordinates. "
1220 "Defaults to 15. Truncation will occur to remove trailing zeros." ),
1225 QObject::tr(
"Whether to start records with the RS=0x1E character (RFC 8142 standard). "
1226 "Defaults to NO: Newline Delimited JSON (geojsonl). \n"
1227 "If set to YES: RFC 8142 standard: GeoJSON Text Sequences (geojsons)." ),
1231 driverMetadata.insert( QStringLiteral(
"GeoJSONSeq" ),
1233 QStringLiteral(
"GeoJSON - Newline Delimited" ),
1234 QObject::tr(
"GeoJSON - Newline Delimited" ),
1235 QStringLiteral(
"*.geojsonl *.geojsons *.json" ),
1236 QStringLiteral(
"json" ),
1239 QStringLiteral(
"UTF-8" )
1244 datasetOptions.clear();
1245 layerOptions.clear();
1248 QObject::tr(
"whether the document must be in RSS 2.0 or Atom 1.0 format. "
1249 "Default value : RSS" ),
1251 << QStringLiteral(
"RSS" )
1252 << QStringLiteral(
"ATOM" ),
1253 QStringLiteral(
"RSS" )
1257 QObject::tr(
"The encoding of location information. Default value : SIMPLE. "
1258 "W3C_GEO only supports point geometries. "
1259 "SIMPLE or W3C_GEO only support geometries in geographic WGS84 coordinates." ),
1261 << QStringLiteral(
"SIMPLE" )
1262 << QStringLiteral(
"GML" )
1263 << QStringLiteral(
"W3C_GEO" ),
1264 QStringLiteral(
"SIMPLE" )
1268 QObject::tr(
"If defined to YES, extension fields will be written. "
1269 "If the field name not found in the base schema matches "
1270 "the foo_bar pattern, foo will be considered as the namespace "
1271 "of the element, and a <foo:bar> element will be written. "
1272 "Otherwise, elements will be written in the <ogr:> namespace." ),
1277 QObject::tr(
"If defined to NO, only <entry> or <item> elements will be written. "
1278 "The user will have to provide the appropriate header and footer of the document." ),
1283 QObject::tr(
"XML content that will be put between the <channel> element and the "
1284 "first <item> element for a RSS document, or between the xml tag and "
1285 "the first <entry> element for an Atom document." ),
1290 QObject::tr(
"Value put inside the <title> element in the header. "
1291 "If not provided, a dummy value will be used as that element is compulsory." ),
1296 QObject::tr(
"Value put inside the <description> element in the header. "
1297 "If not provided, a dummy value will be used as that element is compulsory." ),
1302 QObject::tr(
"Value put inside the <link> element in the header. "
1303 "If not provided, a dummy value will be used as that element is compulsory." ),
1308 QObject::tr(
"Value put inside the <updated> element in the header. "
1309 "Should be formatted as a XML datetime. "
1310 "If not provided, a dummy value will be used as that element is compulsory." ),
1315 QObject::tr(
"Value put inside the <author><name> element in the header. "
1316 "If not provided, a dummy value will be used as that element is compulsory." ),
1321 QObject::tr(
"Value put inside the <id> element in the header. "
1322 "If not provided, a dummy value will be used as that element is compulsory." ),
1326 driverMetadata.insert( QStringLiteral(
"GeoRSS" ),
1328 QStringLiteral(
"GeoRSS" ),
1329 QObject::tr(
"GeoRSS" ),
1330 QStringLiteral(
"*.xml" ),
1331 QStringLiteral(
"xml" ),
1334 QStringLiteral(
"UTF-8" )
1339 datasetOptions.clear();
1340 layerOptions.clear();
1343 QObject::tr(
"If provided, this URI will be inserted as the schema location. "
1344 "Note that the schema file isn't actually accessed by OGR, so it "
1345 "is up to the user to ensure it will match the schema of the OGR "
1346 "produced GML data file." ),
1351 QObject::tr(
"This writes a GML application schema file to a corresponding "
1352 ".xsd file (with the same basename). If INTERNAL is used the "
1353 "schema is written within the GML file, but this is experimental "
1354 "and almost certainly not valid XML. "
1355 "OFF disables schema generation (and is implicit if XSISCHEMAURI is used)." ),
1357 << QStringLiteral(
"EXTERNAL" )
1358 << QStringLiteral(
"INTERNAL" )
1359 << QStringLiteral(
"OFF" ),
1360 QStringLiteral(
"EXTERNAL" )
1364 QObject::tr(
"This is the prefix for the application target namespace." ),
1365 QStringLiteral(
"ogr" )
1369 QObject::tr(
"Can be set to TRUE to avoid writing the prefix of the "
1370 "application target namespace in the GML file." ),
1375 QObject::tr(
"Defaults to 'http://ogr.maptools.org/'. "
1376 "This is the application target namespace." ),
1377 QStringLiteral(
"http://ogr.maptools.org/" )
1381 QObject::tr(
"If not specified, GML2 will be used." ),
1383 << QStringLiteral(
"GML3" )
1384 << QStringLiteral(
"GML3Deegree" )
1385 << QStringLiteral(
"GML3.2" ),
1391 QObject::tr(
"Only valid when FORMAT=GML3/GML3Degree/GML3.2. Default to YES. "
1392 "If YES, SRS with EPSG authority will be written with the "
1393 "'urn:ogc:def:crs:EPSG::' prefix. In the case the SRS is a "
1394 "geographic SRS without explicit AXIS order, but that the same "
1395 "SRS authority code imported with ImportFromEPSGA() should be "
1396 "treated as lat/long, then the function will take care of coordinate "
1397 "order swapping. If set to NO, SRS with EPSG authority will be "
1398 "written with the 'EPSG:' prefix, even if they are in lat/long order." ),
1403 QObject::tr(
"only valid when FORMAT=GML3/GML3Degree/GML3.2) Default to YES. "
1404 "If set to NO, the <gml:boundedBy> element will not be written for "
1410 QObject::tr(
"Default to YES. If YES, the output will be indented with spaces "
1411 "for more readability, but at the expense of file size." ),
1416 driverMetadata.insert( QStringLiteral(
"GML" ),
1418 QStringLiteral(
"Geography Markup Language [GML]" ),
1419 QObject::tr(
"Geography Markup Language [GML]" ),
1420 QStringLiteral(
"*.gml" ),
1421 QStringLiteral(
"gml" ),
1424 QStringLiteral(
"UTF-8" )
1429 datasetOptions.clear();
1430 layerOptions.clear();
1433 QObject::tr(
"Human-readable identifier (e.g. short name) for the layer content" ),
1438 QObject::tr(
"Human-readable description for the layer content" ),
1443 QObject::tr(
"Name for the feature identifier column" ),
1444 QStringLiteral(
"fid" )
1448 QObject::tr(
"Name for the geometry column" ),
1449 QStringLiteral(
"geom" )
1453 QObject::tr(
"If a spatial index must be created." ),
1457 driverMetadata.insert( QStringLiteral(
"GPKG" ),
1459 QStringLiteral(
"GeoPackage" ),
1460 QObject::tr(
"GeoPackage" ),
1461 QStringLiteral(
"*.gpkg" ),
1462 QStringLiteral(
"gpkg" ),
1465 QStringLiteral(
"UTF-8" )
1470 datasetOptions.clear();
1471 layerOptions.clear();
1473 driverMetadata.insert( QStringLiteral(
"GMT" ),
1475 QStringLiteral(
"Generic Mapping Tools [GMT]" ),
1476 QObject::tr(
"Generic Mapping Tools [GMT]" ),
1477 QStringLiteral(
"*.gmt" ),
1478 QStringLiteral(
"gmt" ),
1485 datasetOptions.clear();
1486 layerOptions.clear();
1489 QObject::tr(
"By default when writing a layer whose features are of "
1490 "type wkbLineString, the GPX driver chooses to write "
1491 "them as routes. If FORCE_GPX_TRACK=YES is specified, "
1492 "they will be written as tracks." ),
1497 QObject::tr(
"By default when writing a layer whose features are of "
1498 "type wkbMultiLineString, the GPX driver chooses to write "
1499 "them as tracks. If FORCE_GPX_ROUTE=YES is specified, "
1500 "they will be written as routes, provided that the multilines "
1501 "are composed of only one single line." ),
1506 QObject::tr(
"If GPX_USE_EXTENSIONS=YES is specified, "
1507 "extra fields will be written inside the <extensions> tag." ),
1512 QObject::tr(
"Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS_URL "
1513 "is set. The namespace value used for extension tags. By default, 'ogr'." ),
1514 QStringLiteral(
"ogr" )
1518 QObject::tr(
"Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS "
1519 "is set. The namespace URI. By default, 'http://osgeo.org/gdal'." ),
1520 QStringLiteral(
"http://osgeo.org/gdal" )
1524 QObject::tr(
"By default files are created with the line termination "
1525 "conventions of the local platform (CR/LF on win32 or LF "
1526 "on all other systems). This may be overridden through use "
1527 "of the LINEFORMAT layer creation option which may have a value "
1528 "of CRLF (DOS format) or LF (Unix format)." ),
1530 << QStringLiteral(
"CRLF" )
1531 << QStringLiteral(
"LF" ),
1536 driverMetadata.insert( QStringLiteral(
"GPX" ),
1538 QStringLiteral(
"GPS eXchange Format [GPX]" ),
1539 QObject::tr(
"GPS eXchange Format [GPX]" ),
1540 QStringLiteral(
"*.gpx" ),
1541 QStringLiteral(
"gpx" ),
1544 QStringLiteral(
"UTF-8" )
1549 datasetOptions.clear();
1550 layerOptions.clear();
1552 driverMetadata.insert( QStringLiteral(
"Interlis 1" ),
1554 QStringLiteral(
"INTERLIS 1" ),
1555 QObject::tr(
"INTERLIS 1" ),
1556 QStringLiteral(
"*.itf *.xml *.ili" ),
1557 QStringLiteral(
"ili" ),
1564 datasetOptions.clear();
1565 layerOptions.clear();
1567 driverMetadata.insert( QStringLiteral(
"Interlis 2" ),
1569 QStringLiteral(
"INTERLIS 2" ),
1570 QObject::tr(
"INTERLIS 2" ),
1571 QStringLiteral(
"*.xtf *.xml *.ili" ),
1572 QStringLiteral(
"ili" ),
1579 datasetOptions.clear();
1580 layerOptions.clear();
1583 QObject::tr(
"Allows you to specify the field to use for the KML <name> element." ),
1584 QStringLiteral(
"Name" )
1588 QObject::tr(
"Allows you to specify the field to use for the KML <description> element." ),
1589 QStringLiteral(
"Description" )
1593 QObject::tr(
"Allows you to specify the AltitudeMode to use for KML geometries. "
1594 "This will only affect 3D geometries and must be one of the valid KML options." ),
1596 << QStringLiteral(
"clampToGround" )
1597 << QStringLiteral(
"relativeToGround" )
1598 << QStringLiteral(
"absolute" ),
1599 QStringLiteral(
"relativeToGround" )
1603 QObject::tr(
"The DOCUMENT_ID datasource creation option can be used to specified "
1604 "the id of the root <Document> node. The default value is root_doc." ),
1605 QStringLiteral(
"root_doc" )
1608 driverMetadata.insert( QStringLiteral(
"KML" ),
1610 QStringLiteral(
"Keyhole Markup Language [KML]" ),
1611 QObject::tr(
"Keyhole Markup Language [KML]" ),
1612 QStringLiteral(
"*.kml" ),
1613 QStringLiteral(
"kml" ),
1616 QStringLiteral(
"UTF-8" )
1621 datasetOptions.clear();
1622 layerOptions.clear();
1624 auto insertMapInfoOptions = []( QMap<QString, QgsVectorFileWriter::Option *> &datasetOptions, QMap<QString, QgsVectorFileWriter::Option *> &layerOptions )
1627 QObject::tr(
"Use this to turn on 'quick spatial index mode'. "
1628 "In this mode writing files can be about 5 times faster, "
1629 "but spatial queries can be up to 30 times slower." ),
1631 << QStringLiteral(
"QUICK" )
1632 << QStringLiteral(
"OPTIMIZED" ),
1633 QStringLiteral(
"QUICK" ),
1638 QObject::tr(
"(multiples of 512): Block size for .map files. Defaults "
1639 "to 512. MapInfo 15.2 and above creates .tab files with a "
1640 "blocksize of 16384 bytes. Any MapInfo version should be "
1641 "able to handle block sizes from 512 to 32256." ),
1645 QObject::tr(
"xmin,ymin,xmax,ymax: Define custom layer bounds to increase the "
1646 "accuracy of the coordinates. Note: the geometry of written "
1647 "features must be within the defined box." ),
1651 insertMapInfoOptions( datasetOptions, layerOptions );
1653 driverMetadata.insert( QStringLiteral(
"MapInfo File" ),
1655 QStringLiteral(
"Mapinfo" ),
1656 QObject::tr(
"Mapinfo TAB" ),
1657 QStringLiteral(
"*.tab" ),
1658 QStringLiteral(
"tab" ),
1663 datasetOptions.clear();
1664 layerOptions.clear();
1665 insertMapInfoOptions( datasetOptions, layerOptions );
1668 driverMetadata.insert( QStringLiteral(
"MapInfo MIF" ),
1670 QStringLiteral(
"Mapinfo" ),
1671 QObject::tr(
"Mapinfo MIF" ),
1672 QStringLiteral(
"*.mif" ),
1673 QStringLiteral(
"mif" ),
1680 datasetOptions.clear();
1681 layerOptions.clear();
1684 QObject::tr(
"Determine whether 2D (seed_2d.dgn) or 3D (seed_3d.dgn) "
1685 "seed file should be used. This option is ignored if the SEED option is provided." ),
1690 QObject::tr(
"Override the seed file to use." ),
1695 QObject::tr(
"Indicate whether the whole seed file should be copied. "
1696 "If not, only the first three elements will be copied." ),
1701 QObject::tr(
"Indicates whether the color table should be copied from the seed file." ),
1706 QObject::tr(
"Override the master unit name from the seed file with "
1707 "the provided one or two character unit name." ),
1712 QObject::tr(
"Override the sub unit name from the seed file with the provided "
1713 "one or two character unit name." ),
1718 QObject::tr(
"Override the number of subunits per master unit. "
1719 "By default the seed file value is used." ),
1724 QObject::tr(
"Override the number of UORs (Units of Resolution) "
1725 "per sub unit. By default the seed file value is used." ),
1730 QObject::tr(
"ORIGIN=x,y,z: Override the origin of the design plane. "
1731 "By default the origin from the seed file is used." ),
1735 driverMetadata.insert( QStringLiteral(
"DGN" ),
1737 QStringLiteral(
"Microstation DGN" ),
1738 QObject::tr(
"Microstation DGN" ),
1739 QStringLiteral(
"*.dgn" ),
1740 QStringLiteral(
"dgn" ),
1747 datasetOptions.clear();
1748 layerOptions.clear();
1751 QObject::tr(
"Should update files be incorporated into the base data on the fly." ),
1753 << QStringLiteral(
"APPLY" )
1754 << QStringLiteral(
"IGNORE" ),
1755 QStringLiteral(
"APPLY" )
1759 QObject::tr(
"Should multipoint soundings be split into many single point sounding features. "
1760 "Multipoint geometries are not well handled by many formats, "
1761 "so it can be convenient to split single sounding features with many points "
1762 "into many single point features." ),
1767 QObject::tr(
"Should a DEPTH attribute be added on SOUNDG features and assign the depth "
1768 "of the sounding. This should only be enabled when SPLIT_MULTIPOINT is "
1774 QObject::tr(
"Should all the low level geometry primitives be returned as special "
1775 "IsolatedNode, ConnectedNode, Edge and Face layers." ),
1780 QObject::tr(
"If enabled, numeric attributes assigned an empty string as a value will "
1781 "be preserved as a special numeric value. This option should not generally "
1782 "be needed, but may be useful when translated S-57 to S-57 losslessly." ),
1787 QObject::tr(
"Should LNAM and LNAM_REFS fields be attached to features capturing "
1788 "the feature to feature relationships in the FFPT group of the S-57 file." ),
1793 QObject::tr(
"Should additional attributes relating features to their underlying "
1794 "geometric primitives be attached. These are the values of the FSPT group, "
1795 "and are primarily needed when doing S-57 to S-57 translations." ),
1800 QObject::tr(
"Should attribute values be recoded to UTF-8 from the character encoding "
1801 "specified in the S57 DSSI record." ),
1807 driverMetadata.insert( QStringLiteral(
"S57" ),
1809 QStringLiteral(
"S-57 Base file" ),
1810 QObject::tr(
"S-57 Base file" ),
1811 QStringLiteral(
"*.000" ),
1812 QStringLiteral(
"000" ),
1819 datasetOptions.clear();
1820 layerOptions.clear();
1822 driverMetadata.insert( QStringLiteral(
"SDTS" ),
1824 QStringLiteral(
"Spatial Data Transfer Standard [SDTS]" ),
1825 QObject::tr(
"Spatial Data Transfer Standard [SDTS]" ),
1826 QStringLiteral(
"*catd.ddf" ),
1827 QStringLiteral(
"ddf" ),
1834 datasetOptions.clear();
1835 layerOptions.clear();
1838 QObject::tr(
"Can be used to avoid creating the geometry_columns and spatial_ref_sys "
1839 "tables in a new database. By default these metadata tables are created "
1840 "when a new database is created." ),
1846 QStringLiteral(
"NO" )
1851 QStringLiteral(
"NO" )
1855 QObject::tr(
"Controls the format used for the geometry column. Defaults to WKB. "
1856 "This is generally more space and processing efficient, but harder "
1857 "to inspect or use in simple applications than WKT (Well Known Text)." ),
1859 << QStringLiteral(
"WKB" )
1860 << QStringLiteral(
"WKT" ),
1861 QStringLiteral(
"WKB" )
1865 QObject::tr(
"Controls whether layer and field names will be laundered for easier use "
1866 "in SQLite. Laundered names will be converted to lower case and some special "
1867 "characters(' - #) will be changed to underscores." ),
1872 QStringLiteral(
"NO" )
1876 QStringLiteral(
"NO" )
1884 QObject::tr(
"column_name1[,column_name2, …] A list of (String) columns that "
1885 "must be compressed with ZLib DEFLATE algorithm. This might be beneficial "
1886 "for databases that have big string blobs. However, use with care, since "
1887 "the value of such columns will be seen as compressed binary content with "
1888 "other SQLite utilities (or previous OGR versions). With OGR, when inserting, "
1889 "modifying or querying compressed columns, compression/decompression is "
1890 "done transparently. However, such columns cannot be (easily) queried with "
1891 "an attribute filter or WHERE clause. Note: in table definition, such columns "
1892 "have the 'VARCHAR_deflate' declaration type." ),
1896 driverMetadata.insert( QStringLiteral(
"SQLite" ),
1898 QStringLiteral(
"SQLite" ),
1899 QObject::tr(
"SQLite" ),
1900 QStringLiteral(
"*.sqlite" ),
1901 QStringLiteral(
"sqlite" ),
1904 QStringLiteral(
"UTF-8" )
1909 datasetOptions.clear();
1910 layerOptions.clear();
1913 QObject::tr(
"Can be used to avoid creating the geometry_columns and spatial_ref_sys "
1914 "tables in a new database. By default these metadata tables are created "
1915 "when a new database is created." ),
1920 QStringLiteral(
"YES" )
1924 QObject::tr(
"Insert the content of the EPSG CSV files into the spatial_ref_sys table. "
1925 "Set to NO for regular SQLite databases." ),
1930 QStringLiteral(
"SPATIALITE" )
1934 QObject::tr(
"Controls whether layer and field names will be laundered for easier use "
1935 "in SQLite. Laundered names will be converted to lower case and some special "
1936 "characters(' - #) will be changed to underscores." ),
1941 QObject::tr(
"If the database is of the SpatiaLite flavor, and if OGR is linked "
1942 "against libspatialite, this option can be used to control if a spatial "
1943 "index must be created." ),
1948 QObject::tr(
"If the format of the geometry BLOB is of the SpatiaLite flavor, "
1949 "this option can be used to control if the compressed format for "
1950 "geometries (LINESTRINGs, POLYGONs) must be used." ),
1955 QObject::tr(
"Used to force the SRID number of the SRS associated with the layer. "
1956 "When this option isn't specified and that a SRS is associated with the "
1957 "layer, a search is made in the spatial_ref_sys to find a match for the "
1958 "SRS, and, if there is no match, a new entry is inserted for the SRS in "
1959 "the spatial_ref_sys table. When the SRID option is specified, this "
1960 "search (and the eventual insertion of a new entry) will not be done: "
1961 "the specified SRID is used as such." ),
1966 QObject::tr(
"column_name1[,column_name2, …] A list of (String) columns that "
1967 "must be compressed with ZLib DEFLATE algorithm. This might be beneficial "
1968 "for databases that have big string blobs. However, use with care, since "
1969 "the value of such columns will be seen as compressed binary content with "
1970 "other SQLite utilities (or previous OGR versions). With OGR, when inserting, "
1971 "modifying or queryings compressed columns, compression/decompression is "
1972 "done transparently. However, such columns cannot be (easily) queried with "
1973 "an attribute filter or WHERE clause. Note: in table definition, such columns "
1974 "have the 'VARCHAR_deflate' declaration type." ),
1978 driverMetadata.insert( QStringLiteral(
"SpatiaLite" ),
1980 QStringLiteral(
"SpatiaLite" ),
1981 QObject::tr(
"SpatiaLite" ),
1982 QStringLiteral(
"*.sqlite" ),
1983 QStringLiteral(
"sqlite" ),
1986 QStringLiteral(
"UTF-8" )
1990 datasetOptions.clear();
1991 layerOptions.clear();
1994 QObject::tr(
"Override the header file used - in place of header.dxf." ),
1999 QObject::tr(
"Override the trailer file used - in place of trailer.dxf." ),
2003 driverMetadata.insert( QStringLiteral(
"DXF" ),
2005 QStringLiteral(
"AutoCAD DXF" ),
2006 QObject::tr(
"AutoCAD DXF" ),
2007 QStringLiteral(
"*.dxf" ),
2008 QStringLiteral(
"dxf" ),
2015 datasetOptions.clear();
2016 layerOptions.clear();
2019 QObject::tr(
"Indicates the GeoConcept export file extension. "
2020 "TXT was used by earlier releases of GeoConcept. GXT is currently used." ),
2022 << QStringLiteral(
"GXT" )
2023 << QStringLiteral(
"TXT" ),
2024 QStringLiteral(
"GXT" )
2028 QObject::tr(
"Path to the GCT: the GCT file describes the GeoConcept types definitions: "
2029 "In this file, every line must start with //# followed by a keyword. "
2030 "Lines starting with // are comments." ),
2035 QObject::tr(
"Defines the feature to be created. The TYPE corresponds to one of the Name "
2036 "found in the GCT file for a type section. The SUBTYPE corresponds to one of "
2037 "the Name found in the GCT file for a sub-type section within the previous "
2042 driverMetadata.insert( QStringLiteral(
"Geoconcept" ),
2044 QStringLiteral(
"Geoconcept" ),
2045 QObject::tr(
"Geoconcept" ),
2046 QStringLiteral(
"*.gxt *.txt" ),
2047 QStringLiteral(
"gxt" ),
2054 datasetOptions.clear();
2055 layerOptions.clear();
2058 QObject::tr(
"When this option is set, the new layer will be created inside the named "
2059 "FeatureDataset folder. If the folder does not already exist, it will be created." ),
2064 QObject::tr(
"Set name of geometry column in new layer. Defaults to 'SHAPE'." ),
2065 QStringLiteral(
"SHAPE" )
2069 QObject::tr(
"Name of the OID column to create. Defaults to 'OBJECTID'." ),
2070 QStringLiteral(
"OBJECTID" )
2073 driverMetadata.insert( QStringLiteral(
"FileGDB" ),
2075 QStringLiteral(
"ESRI FileGDB" ),
2076 QObject::tr(
"ESRI FileGDB" ),
2077 QStringLiteral(
"*.gdb" ),
2078 QStringLiteral(
"gdb" ),
2081 QStringLiteral(
"UTF-8" )
2086 datasetOptions.clear();
2087 layerOptions.clear();
2090 QObject::tr(
"By default, the driver will try to detect the data type of fields. If set "
2091 "to STRING, all fields will be of String type." ),
2093 << QStringLiteral(
"AUTO" )
2094 << QStringLiteral(
"STRING" ),
2095 QStringLiteral(
"AUTO" ),
2100 QObject::tr(
"By default, the driver will read the first lines of each sheet to detect "
2101 "if the first line might be the name of columns. If set to FORCE, the driver "
2102 "will consider the first line as the header line. If set to "
2103 "DISABLE, it will be considered as the first feature. Otherwise "
2104 "auto-detection will occur." ),
2106 << QStringLiteral(
"FORCE" )
2107 << QStringLiteral(
"DISABLE" )
2108 << QStringLiteral(
"AUTO" ),
2109 QStringLiteral(
"AUTO" ),
2113 driverMetadata.insert( QStringLiteral(
"XLSX" ),
2115 QStringLiteral(
"MS Office Open XML spreadsheet" ),
2116 QObject::tr(
"MS Office Open XML spreadsheet [XLSX]" ),
2117 QStringLiteral(
"*.xlsx" ),
2118 QStringLiteral(
"xlsx" ),
2121 QStringLiteral(
"UTF-8" )
2126 datasetOptions.clear();
2127 layerOptions.clear();
2130 QObject::tr(
"By default, the driver will try to detect the data type of fields. If set "
2131 "to STRING, all fields will be of String type." ),
2133 << QStringLiteral(
"AUTO" )
2134 << QStringLiteral(
"STRING" ),
2135 QStringLiteral(
"AUTO" ),
2140 QObject::tr(
"By default, the driver will read the first lines of each sheet to detect "
2141 "if the first line might be the name of columns. If set to FORCE, the driver "
2142 "will consider the first line as the header line. If set to "
2143 "DISABLE, it will be considered as the first feature. Otherwise "
2144 "auto-detection will occur." ),
2146 << QStringLiteral(
"FORCE" )
2147 << QStringLiteral(
"DISABLE" )
2148 << QStringLiteral(
"AUTO" ),
2149 QStringLiteral(
"AUTO" ),
2153 driverMetadata.insert( QStringLiteral(
"ODS" ),
2155 QStringLiteral(
"Open Document Spreadsheet" ),
2156 QObject::tr(
"Open Document Spreadsheet [ODS]" ),
2157 QStringLiteral(
"*.ods" ),
2158 QStringLiteral(
"ods" ),
2161 QStringLiteral(
"UTF-8" )
2166 datasetOptions.clear();
2167 layerOptions.clear();
2170 QObject::tr(
"Line termination character sequence." ),
2172 << QStringLiteral(
"CRLF" )
2173 << QStringLiteral(
"LF" ),
2174 QStringLiteral(
"LF" ),
2180 QObject::tr(
"Format of geometry columns." ),
2182 << QStringLiteral(
"geometry" )
2183 << QStringLiteral(
"geography" ),
2184 QStringLiteral(
"geometry" ),
2189 QObject::tr(
"Controls whether layer and field names will be laundered for easier use. "
2190 "Laundered names will be converted to lower case and some special "
2191 "characters(' - #) will be changed to underscores." ),
2196 QObject::tr(
"Name for the geometry column. Defaults to wkb_geometry "
2197 "for GEOM_TYPE=geometry or the_geog for GEOM_TYPE=geography" ) ) );
2200 QObject::tr(
"Name of schema into which to create the new table" ) ) );
2203 QObject::tr(
"Whether to explicitly emit the CREATE SCHEMA statement to create the specified schema." ),
2208 QObject::tr(
"Whether to explicitly recreate the table if necessary." ),
2213 QObject::tr(
"Whether to explicitly destroy tables before recreating them." ),
2215 << QStringLiteral(
"YES" )
2216 << QStringLiteral(
"NO" )
2217 << QStringLiteral(
"IF_EXISTS" ),
2218 QStringLiteral(
"YES" ),
2223 QObject::tr(
"Used to force the SRID number of the SRS associated with the layer. "
2224 "When this option isn't specified and that a SRS is associated with the "
2225 "layer, a search is made in the spatial_ref_sys to find a match for the "
2226 "SRS, and, if there is no match, a new entry is inserted for the SRS in "
2227 "the spatial_ref_sys table. When the SRID option is specified, this "
2228 "search (and the eventual insertion of a new entry) will not be done: "
2229 "the specified SRID is used as such." ),
2234 QObject::tr(
"Can be set to 2.0 or 2.2 for PostGIS 2.0/2.2 compatibility. "
2235 "Important to set it correctly if using non-linear geometry types" ),
2236 QStringLiteral(
"2.2" )
2239 driverMetadata.insert( QStringLiteral(
"PGDUMP" ),
2241 QStringLiteral(
"PostgreSQL SQL dump" ),
2242 QObject::tr(
"PostgreSQL SQL dump" ),
2243 QStringLiteral(
"*.sql" ),
2244 QStringLiteral(
"sql" ),
2247 QStringLiteral(
"UTF-8" )
2253 QgsVectorFileWriterMetadataContainer(
const QgsVectorFileWriterMetadataContainer &other ) =
delete;
2254 QgsVectorFileWriterMetadataContainer &operator=(
const QgsVectorFileWriterMetadataContainer &other ) =
delete;
2255 ~QgsVectorFileWriterMetadataContainer()
2257 for (
auto it = driverMetadata.constBegin(); it != driverMetadata.constEnd(); ++it )
2259 for (
auto optionIt = it.value().driverOptions.constBegin(); optionIt != it.value().driverOptions.constEnd(); ++optionIt )
2260 delete optionIt.value();
2261 for (
auto optionIt = it.value().layerOptions.constBegin(); optionIt != it.value().layerOptions.constEnd(); ++optionIt )
2262 delete optionIt.value();
2266 QMap<QString, QgsVectorFileWriter::MetaData> driverMetadata;
2273 static QgsVectorFileWriterMetadataContainer sDriverMetadata;
2274 QMap<QString, MetaData>::ConstIterator it = sDriverMetadata.driverMetadata.constBegin();
2276 for ( ; it != sDriverMetadata.driverMetadata.constEnd(); ++it )
2278 if ( it.key() == QLatin1String(
"PGDUMP" ) &&
2279 driverName != QLatin1String(
"PGDUMP" ) &&
2280 driverName != QLatin1String(
"PostgreSQL SQL dump" ) )
2285 if ( it.key().startsWith( driverName ) || it.value().longName.startsWith( driverName ) )
2300 return QStringList();
2309 return QStringList();
2316 OGRwkbGeometryType ogrType =
static_cast<OGRwkbGeometryType
>( type );
2342 QgsFeatureList::iterator fIt = features.begin();
2344 for ( ; fIt != features.end(); ++fIt )
2369 QString styleString;
2370 QString currentStyle;
2372 QgsSymbolList::const_iterator symbolIt = symbols.constBegin();
2373 for ( ; symbolIt != symbols.constEnd(); ++symbolIt )
2375 int nSymbolLayers = ( *symbolIt )->symbolLayerCount();
2376 for (
int i = 0; i < nSymbolLayers; ++i )
2379 QMap< QgsSymbolLayer *, QString >::const_iterator it =
mSymbolLayerTable.find( ( *symbolIt )->symbolLayer( i ) );
2385 double mmsf = mmScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
2386 double musf = mapUnitScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
2388 currentStyle = ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf );
2392 if ( symbolIt != symbols.constBegin() || i != 0 )
2394 styleString.append(
';' );
2396 styleString.append( currentStyle );
2400 OGR_F_SetStyleString( poFeature.get(), currentStyle.toLocal8Bit().constData() );
2401 if ( !writeFeature(
mLayer, poFeature.get() ) )
2408 OGR_F_SetStyleString( poFeature.get(), styleString.toLocal8Bit().constData() );
2413 if ( !writeFeature(
mLayer, poFeature.get() ) )
2432 int fldIdx = it.key();
2433 int ogrField = it.value();
2435 QVariant attrValue = feature.
attribute( fldIdx );
2438 if ( !attrValue.isValid() || attrValue.isNull() )
2447 #ifdef OGRNullMarker
2448 OGR_F_SetFieldNull( poFeature.get(), ogrField );
2463 mErrorMessage = QObject::tr(
"Error converting value (%1) for attribute field %2: %3" )
2464 .arg( feature.
attribute( fldIdx ).toString(),
2474 OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
2476 case QVariant::LongLong:
2477 OGR_F_SetFieldInteger64( poFeature.get(), ogrField, attrValue.toLongLong() );
2479 case QVariant::Bool:
2480 OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
2482 case QVariant::String:
2483 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toString() ).constData() );
2485 case QVariant::Double:
2486 OGR_F_SetFieldDouble( poFeature.get(), ogrField, attrValue.toDouble() );
2488 case QVariant::Date:
2489 OGR_F_SetFieldDateTime( poFeature.get(), ogrField,
2490 attrValue.toDate().year(),
2491 attrValue.toDate().month(),
2492 attrValue.toDate().day(),
2495 case QVariant::DateTime:
2498 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toDateTime().toString( QStringLiteral(
"yyyy/MM/dd hh:mm:ss.zzz" ) ) ).constData() );
2502 OGR_F_SetFieldDateTime( poFeature.get(), ogrField,
2503 attrValue.toDateTime().date().year(),
2504 attrValue.toDateTime().date().month(),
2505 attrValue.toDateTime().date().day(),
2506 attrValue.toDateTime().time().hour(),
2507 attrValue.toDateTime().time().minute(),
2508 attrValue.toDateTime().time().second(),
2512 case QVariant::Time:
2515 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toString() ).constData() );
2519 OGR_F_SetFieldDateTime( poFeature.get(), ogrField,
2521 attrValue.toTime().hour(),
2522 attrValue.toTime().minute(),
2523 attrValue.toTime().second(),
2528 case QVariant::ByteArray:
2530 const QByteArray ba = attrValue.toByteArray();
2531 OGR_F_SetFieldBinary( poFeature.get(), ogrField, ba.size(),
const_cast< GByte *
>(
reinterpret_cast< const GByte *
>( ba.data() ) ) );
2535 case QVariant::Invalid:
2538 case QVariant::StringList:
2540 QStringList list = attrValue.toStringList();
2541 if ( mSupportedListSubTypes.contains( QVariant::String ) )
2543 int count = list.count();
2544 char **lst =
new char *[count + 1];
2548 for (
const QString &
string : list )
2550 lst[pos] = CPLStrdup(
mCodec->fromUnicode(
string ).data() );
2554 lst[count] =
nullptr;
2555 OGR_F_SetFieldStringList( poFeature.get(), ogrField, lst );
2560 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( list.join(
',' ) ).constData() );
2565 case QVariant::List:
2569 QStringList list = attrValue.toStringList();
2570 if ( mSupportedListSubTypes.contains( QVariant::String ) )
2572 int count = list.count();
2573 char **lst =
new char *[count + 1];
2577 for (
const QString &
string : list )
2579 lst[pos] = CPLStrdup(
mCodec->fromUnicode(
string ).data() );
2583 lst[count] =
nullptr;
2584 OGR_F_SetFieldStringList( poFeature.get(), ogrField, lst );
2589 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( list.join(
',' ) ).constData() );
2595 const QVariantList list = attrValue.toList();
2596 if ( mSupportedListSubTypes.contains( QVariant::Int ) )
2598 const int count = list.count();
2599 int *lst =
new int[count];
2603 for (
const QVariant &value : list )
2605 lst[pos] = value.toInt();
2609 OGR_F_SetFieldIntegerList( poFeature.get(), ogrField, count, lst );
2614 QStringList strings;
2615 strings.reserve( list.size() );
2616 for (
const QVariant &value : list )
2618 strings << QString::number( value.toInt() );
2620 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
2626 const QVariantList list = attrValue.toList();
2627 if ( mSupportedListSubTypes.contains( QVariant::Double ) )
2629 const int count = list.count();
2630 double *lst =
new double[count];
2634 for (
const QVariant &value : list )
2636 lst[pos] = value.toDouble();
2640 OGR_F_SetFieldDoubleList( poFeature.get(), ogrField, count, lst );
2645 QStringList strings;
2646 strings.reserve( list.size() );
2647 for (
const QVariant &value : list )
2649 strings << QString::number( value.toDouble() );
2651 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
2657 const QVariantList list = attrValue.toList();
2658 if ( mSupportedListSubTypes.contains( QVariant::LongLong ) )
2660 const int count = list.count();
2661 long long *lst =
new long long[count];
2665 for (
const QVariant &value : list )
2667 lst[pos] = value.toLongLong();
2671 OGR_F_SetFieldInteger64List( poFeature.get(), ogrField, count, lst );
2676 QStringList strings;
2677 strings.reserve( list.size() );
2678 for (
const QVariant &value : list )
2680 strings << QString::number( value.toLongLong() );
2682 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
2690 mErrorMessage = QObject::tr(
"Invalid variant type for field %1[%2]: received %3 with type %4" )
2693 .arg( attrValue.typeName(),
2694 attrValue.toString() );
2707 if ( mCoordinateTransform )
2712 geom.
transform( *mCoordinateTransform );
2730 OGRGeometryH mGeom2 =
nullptr;
2776 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
2777 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
2783 QByteArray wkb( geom.
asWkb() );
2784 OGRErr err = OGR_G_ImportFromWkb( mGeom2,
reinterpret_cast<unsigned char *
>(
const_cast<char *
>( wkb.constData() ) ), wkb.length() );
2785 if ( err != OGRERR_NONE )
2787 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
2788 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
2795 OGR_F_SetGeometryDirectly( poFeature.get(), mGeom2 );
2801 OGRErr err = OGR_G_ImportFromWkb( ogrGeom,
reinterpret_cast<unsigned char *
>(
const_cast<char *
>( wkb.constData() ) ), wkb.length() );
2802 if ( err != OGRERR_NONE )
2804 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
2805 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
2812 OGR_F_SetGeometryDirectly( poFeature.get(), ogrGeom );
2827 for (
int i = 0; i < attributes.size(); i++ )
2829 if ( omap.find( i ) != omap.end() )
2834 bool QgsVectorFileWriter::writeFeature( OGRLayerH layer, OGRFeatureH feature )
2836 if ( OGR_L_CreateFeature( layer, feature ) != OGRERR_NONE )
2838 mErrorMessage = QObject::tr(
"Feature creation error (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
2848 if ( mUsingTransaction )
2850 if ( OGRERR_NONE != OGR_L_CommitTransaction(
mLayer ) )
2852 QgsDebugMsg( QStringLiteral(
"Error while committing transaction on OGRLayer." ) );
2856 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,1,0) && GDAL_VERSION_NUM <= GDAL_COMPUTE_VERSION(3,1,3)
2860 QString drvName = GDALGetDriverShortName( GDALGetDatasetDriver(
mDS.get() ) );
2861 if ( drvName == QLatin1String(
"XLSX" ) ||
2862 drvName == QLatin1String(
"ODS" ) )
2864 CPLSetThreadLocalConfigOption(
"CPL_CREATE_ZIP64",
"NO" );
2866 CPLSetThreadLocalConfigOption(
"CPL_CREATE_ZIP64",
nullptr );
2881 const QString &fileName,
2882 const QString &fileEncoding,
2884 const QString &driverName,
2886 QString *errorMessage,
2887 const QStringList &datasourceOptions,
2888 const QStringList &layerOptions,
2889 bool skipAttributeCreation,
2890 QString *newFilename,
2892 double symbologyScale,
2902 if ( destCRS.
isValid() && layer )
2928 const QString &fileName,
2929 const QString &fileEncoding,
2931 const QString &driverName,
2933 QString *errorMessage,
2934 const QStringList &datasourceOptions,
2935 const QStringList &layerOptions,
2936 bool skipAttributeCreation,
2937 QString *newFilename,
2939 double symbologyScale,
2970 : driverName( QStringLiteral(
"GPKG" ) )
2978 if ( !layer || !layer->
isValid() )
2985 details.sourceCrs = layer->
crs();
2986 details.sourceWkbType = layer->
wkbType();
2987 details.sourceFields = layer->
fields();
2996 if ( details.storageType == QLatin1String(
"ESRI Shapefile" ) )
3004 details.geometryTypeScanIterator = layer->
getFeatures( req );
3008 details.renderContext.setExpressionContext( details.expressionContext );
3009 details.renderContext.setRendererScale( options.
symbologyScale );
3011 details.shallTransform =
false;
3016 details.shallTransform =
true;
3021 details.outputCrs = details.sourceCrs;
3024 details.destWkbType = details.sourceWkbType;
3038 details.attributes.clear();
3039 else if ( details.attributes.isEmpty() )
3041 const QgsAttributeList allAttributes = details.sourceFields.allAttributesList();
3042 for (
int idx : allAttributes )
3044 QgsField fld = details.sourceFields.at( idx );
3045 if ( details.providerType == QLatin1String(
"oracle" ) && fld.
typeName().contains( QLatin1String(
"SDO_GEOMETRY" ) ) )
3047 details.attributes.append( idx );
3051 if ( !details.attributes.isEmpty() )
3053 for (
int attrIdx : std::as_const( details.attributes ) )
3055 details.outputFields.append( details.sourceFields.at( attrIdx ) );
3061 if ( details.providerType == QLatin1String(
"spatialite" ) )
3063 for (
int i = 0; i < details.outputFields.size(); i++ )
3065 if ( details.outputFields.at( i ).type() == QVariant::LongLong )
3070 if ( std::max( std::llabs( min.toLongLong() ), std::llabs( max.toLongLong() ) ) < std::numeric_limits<int>::max() )
3072 details.outputFields[i].setType( QVariant::Int );
3080 addRendererAttributes( details.renderer.get(), details.renderContext, details.sourceFields, details.attributes );
3090 bool useFilterRect =
true;
3091 if ( details.shallTransform )
3098 filterRect = extentTransform.
transformBoundingBox( filterRect, Qgis::TransformDirection::Reverse );
3102 useFilterRect =
false;
3105 if ( useFilterRect )
3111 details.filterRectEngine->prepareGeometry();
3113 details.sourceFeatureIterator = layer->
getFeatures( req );
3127 int lastProgressReport = 0;
3128 long long total = details.featureCount;
3131 if ( details.providerType == QLatin1String(
"ogr" ) && !details.dataSourceUri.isEmpty() )
3133 QString srcFileName( details.providerUriParams.value( QStringLiteral(
"path" ) ).toString() );
3134 if ( QFile::exists( srcFileName ) && QFileInfo( fileName ).canonicalFilePath() == QFileInfo( srcFileName ).canonicalFilePath() )
3138 if ( !( ( options.
driverName == QLatin1String(
"GPKG" ) ||
3139 options.
driverName == QLatin1String(
"SpatiaLite" ) ||
3140 options.
driverName == QLatin1String(
"SQLite" ) ) &&
3141 options.
layerName != details.providerUriParams.value( QStringLiteral(
"layerName" ) ) ) )
3144 *
errorMessage = QObject::tr(
"Cannot overwrite a OGR layer in place" );
3164 int newProgress =
static_cast<int>( ( 5.0 * scanned ) / total );
3165 if ( newProgress != lastProgressReport )
3167 lastProgressReport = newProgress;
3182 QString tempNewFilename;
3183 QString tempNewLayer;
3185 std::unique_ptr< QgsVectorFileWriter > writer(
create( fileName, details.outputFields, destWkbType, details.outputCrs, transformContext, options, QgsFeatureSink::SinkFlags(), &tempNewFilename, &tempNewLayer ) );
3189 *newFilename = tempNewFilename;
3192 *newLayer = tempNewLayer;
3232 int n = 0, errors = 0;
3241 writer->startRender( details.renderer.get(), details.sourceFields );
3243 writer->resetMap( details.attributes );
3245 writer->mFields = details.sourceFields;
3249 int initialProgress = lastProgressReport;
3250 while ( details.sourceFeatureIterator.nextFeature( fet ) )
3261 int newProgress =
static_cast<int>( initialProgress + ( ( 100.0 - initialProgress ) * saved ) / total );
3262 if ( newProgress < 100 && newProgress != lastProgressReport )
3264 lastProgressReport = newProgress;
3269 if ( details.shallTransform )
3282 QString msg = QObject::tr(
"Failed to transform a point while drawing a feature with ID '%1'. Writing stopped. (Exception: %2)" )
3283 .arg( fet.
id() ).arg( e.
what() );
3300 if ( !writer->addFeatureWithStyle( fet, writer->mRenderer.get(), mapUnits ) )
3307 *
errorMessage = QObject::tr(
"Feature write errors:" );
3313 if ( errors > 1000 )
3317 *
errorMessage += QObject::tr(
"Stopping after %1 errors" ).arg( errors );
3327 writer->stopRender();
3331 *
errorMessage += QObject::tr(
"\nOnly %1 of %2 features written." ).arg( n - errors ).arg( n );
3336 bool metadataFailure =
false;
3341 {QStringLiteral(
"path" ), tempNewFilename },
3342 {QStringLiteral(
"layerName" ), tempNewLayer }
3356 metadataFailure =
true;
3367 metadataFailure =
true;
3375 const QString &fileName,
3377 QString *newFilename,
3381 QgsVectorFileWriter::PreparedWriterDetails details;
3382 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
3390 const QString &fileName,
3393 QString *newFilename,
3397 QgsVectorFileWriter::PreparedWriterDetails details;
3398 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
3407 QgsVectorFileWriter::PreparedWriterDetails details;
3408 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
3417 QFileInfo fi( fileName );
3418 QDir dir = fi.dir();
3421 for (
const char *suffix : {
".shp",
".shx",
".dbf",
".prj",
".qix",
".qpj",
".cpg",
".sbn",
".sbx",
".idm",
".ind" } )
3423 filter << fi.completeBaseName() + suffix;
3427 const auto constEntryList = dir.entryList( filter );
3428 for (
const QString &file : constEntryList )
3430 QFile f( dir.canonicalPath() +
'/' + file );
3433 QgsDebugMsg( QStringLiteral(
"Removing file %1 failed: %2" ).arg( file, f.errorString() ) );
3449 static QReadWriteLock sFilterLock;
3450 static QMap< VectorFormatOptions, QList< QgsVectorFileWriter::FilterFormatDetails > > sFilters;
3454 const auto it = sFilters.constFind( options );
3455 if ( it != sFilters.constEnd() )
3459 QList< QgsVectorFileWriter::FilterFormatDetails > results;
3462 int const drvCount = OGRGetDriverCount();
3464 for (
int i = 0; i < drvCount; ++i )
3466 OGRSFDriverH drv = OGRGetDriver( i );
3469 QString drvName = OGR_Dr_GetName( drv );
3471 GDALDriverH gdalDriver = GDALGetDriverByName( drvName.toLocal8Bit().constData() );
3472 char **metadata =
nullptr;
3475 metadata = GDALGetMetadata( gdalDriver,
nullptr );
3478 bool nonSpatialFormat = CSLFetchBoolean( metadata, GDAL_DCAP_NONSPATIAL,
false );
3480 if ( OGR_Dr_TestCapability( drv,
"CreateDataSource" ) != 0 )
3485 if ( nonSpatialFormat )
3490 if ( filterString.isEmpty() )
3497 globs = metadata.
glob.toLower().split(
' ' );
3503 details.
globs = globs;
3512 if ( options & SortRecommended )
3514 if ( a.driverName == QLatin1String(
"GPKG" ) )
3516 else if ( b.driverName == QLatin1String(
"GPKG" ) )
3518 else if ( a.driverName == QLatin1String(
"ESRI Shapefile" ) )
3520 else if ( b.driverName == QLatin1String(
"ESRI Shapefile" ) )
3527 sFilters.insert( options, results );
3534 QSet< QString > extensions;
3536 const QRegularExpression rx( QStringLiteral(
"\\*\\.(.*)$" ) );
3540 for (
const QString &glob : format.globs )
3542 const QRegularExpressionMatch match = rx.match( glob );
3543 if ( !match.hasMatch() )
3546 const QString matched = match.captured( 1 );
3547 extensions.insert( matched );
3551 QStringList extensionList = qgis::setToList( extensions );
3553 std::sort( extensionList.begin(), extensionList.end(), [options](
const QString & a,
const QString & b ) ->
bool
3555 if ( options & SortRecommended )
3557 if ( a == QLatin1String(
"gpkg" ) )
3559 else if ( b == QLatin1String(
"gpkg" ) )
3561 else if ( a == QLatin1String(
"shp" ) )
3563 else if ( b == QLatin1String(
"shp" ) )
3567 return a.toLower().localeAwareCompare( b.toLower() ) < 0;
3570 return extensionList;
3575 QList< QgsVectorFileWriter::DriverDetails > results;
3578 const int drvCount = OGRGetDriverCount();
3580 QStringList writableDrivers;
3581 for (
int i = 0; i < drvCount; ++i )
3583 OGRSFDriverH drv = OGRGetDriver( i );
3586 QString drvName = OGR_Dr_GetName( drv );
3592 if ( drvName == QLatin1String(
"ODS" ) || drvName == QLatin1String(
"XLSX" ) || drvName == QLatin1String(
"XLS" ) )
3596 if ( drvName == QLatin1String(
"ESRI Shapefile" ) )
3598 writableDrivers << QStringLiteral(
"DBF file" );
3600 if ( OGR_Dr_TestCapability( drv,
"CreateDataSource" ) != 0 )
3603 if ( drvName == QLatin1String(
"MapInfo File" ) )
3605 writableDrivers << QStringLiteral(
"MapInfo MIF" );
3607 else if ( drvName == QLatin1String(
"SQLite" ) )
3614 QString option = QStringLiteral(
"SPATIALITE=YES" );
3615 char *options[2] = { CPLStrdup( option.toLocal8Bit().constData() ),
nullptr };
3616 OGRSFDriverH poDriver;
3618 poDriver = OGRGetDriverByName( drvName.toLocal8Bit().constData() );
3621 gdal::ogr_datasource_unique_ptr ds( OGR_Dr_CreateDataSource( poDriver, QStringLiteral(
"/vsimem/spatialitetest.sqlite" ).toUtf8().constData(), options ) );
3624 writableDrivers << QStringLiteral(
"SpatiaLite" );
3625 OGR_Dr_DeleteDataSource( poDriver, QStringLiteral(
"/vsimem/spatialitetest.sqlite" ).toUtf8().constData() );
3628 CPLFree( options[0] );
3630 writableDrivers << drvName;
3635 results.reserve( writableDrivers.count() );
3636 for (
const QString &drvName : std::as_const( writableDrivers ) )
3650 if ( options & SortRecommended )
3652 if ( a.driverName == QLatin1String(
"GPKG" ) )
3654 else if ( b.driverName == QLatin1String(
"GPKG" ) )
3656 else if ( a.driverName == QLatin1String(
"ESRI Shapefile" ) )
3658 else if ( b.driverName == QLatin1String(
"ESRI Shapefile" ) )
3662 return a.
longName.toLower().localeAwareCompare( b.
longName.toLower() ) < 0;
3669 QString ext = extension.trimmed();
3670 if ( ext.isEmpty() )
3673 if ( ext.startsWith(
'.' ) )
3677 int const drvCount = GDALGetDriverCount();
3679 for (
int i = 0; i < drvCount; ++i )
3681 GDALDriverH drv = GDALGetDriver( i );
3687 QString drvName = GDALGetDriverShortName( drv );
3688 QStringList driverExtensions = QString( GDALGetMetadataItem( drv, GDAL_DMD_EXTENSIONS,
nullptr ) ).split(
' ' );
3690 const auto constDriverExtensions = driverExtensions;
3691 for (
const QString &driver : constDriverExtensions )
3693 if ( driver.compare( ext, Qt::CaseInsensitive ) == 0 )
3704 QString filterString;
3708 if ( !filterString.isEmpty() )
3709 filterString += QLatin1String(
";;" );
3711 filterString += details.filterString;
3713 return filterString;
3722 return QStringLiteral(
"%1 (%2 %3)" ).arg( metadata.
trLongName,
3723 metadata.
glob.toLower(),
3724 metadata.
glob.toUpper() );
3729 if ( codecName == QLatin1String(
"System" ) )
3730 return QStringLiteral(
"LDID/0" );
3732 const QRegularExpression re( QRegularExpression::anchoredPattern( QString(
"(CP|windows-|ISO[ -])(.+)" ) ), QRegularExpression::CaseInsensitiveOption );
3733 const QRegularExpressionMatch match = re.match( codecName );
3734 if ( match.hasMatch() )
3736 QString
c = match.captured( 2 ).remove(
'-' );
3738 ( void )
c.toInt( &isNumber );
3766 OGRStyleTableH ogrStyleTable = OGR_STBL_Create();
3767 OGRStyleMgrH styleManager = OGR_SM_Create( ogrStyleTable );
3770 int nTotalLevels = 0;
3772 QgsSymbolList::iterator symbolIt = symbolList.begin();
3773 for ( ; symbolIt != symbolList.end(); ++symbolIt )
3775 double mmsf = mmScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
3776 double musf = mapUnitScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
3778 int nLevels = ( *symbolIt )->symbolLayerCount();
3779 for (
int i = 0; i < nLevels; ++i )
3781 mSymbolLayerTable.insert( ( *symbolIt )->symbolLayer( i ), QString::number( nTotalLevels ) );
3782 OGR_SM_AddStyle( styleManager, QString::number( nTotalLevels ).toLocal8Bit(),
3783 ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf ).toLocal8Bit() );
3787 OGR_DS_SetStyleTableDirectly( ds, ogrStyleTable );
3793 if ( !details.renderer )
3798 QHash< QgsSymbol *, QList<QgsFeature> > features;
3807 startRender( details.renderer.get(), details.sourceFields );
3827 QString msg = QObject::tr(
"Failed to transform, writing stopped. (Exception: %1)" )
3838 featureSymbol = mRenderer->symbolForFeature( fet, mRenderContext );
3839 if ( !featureSymbol )
3844 QHash< QgsSymbol *, QList<QgsFeature> >::iterator it = features.find( featureSymbol );
3845 if ( it == features.end() )
3847 it = features.insert( featureSymbol, QList<QgsFeature>() );
3849 it.value().append( fet );
3854 QgsSymbolList symbols = mRenderer->symbols( mRenderContext );
3855 for (
int i = 0; i < symbols.count(); i++ )
3861 if ( level < 0 || level >= 1000 )
3864 while ( level >= levels.count() )
3866 levels[level].append( item );
3871 int nTotalFeatures = 0;
3874 for (
int l = 0; l < levels.count(); l++ )
3877 for (
int i = 0; i < level.count(); i++ )
3880 QHash< QgsSymbol *, QList<QgsFeature> >::iterator levelIt = features.find( item.
symbol() );
3881 if ( levelIt == features.end() )
3887 double mmsf = mmScaleFactor(
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
3888 double musf = mapUnitScaleFactor(
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
3890 int llayer = item.
layer();
3891 QList<QgsFeature> &featureList = levelIt.value();
3892 QList<QgsFeature>::iterator featureIt = featureList.begin();
3893 for ( ; featureIt != featureList.end(); ++featureIt )
3903 QString styleString = levelIt.key()->symbolLayer( llayer )->ogrFeatureStyle( mmsf, musf );
3904 if ( !styleString.isEmpty() )
3906 OGR_F_SetStyleString( ogrFeature.get(), styleString.toLocal8Bit().constData() );
3907 if ( !writeFeature(
mLayer, ogrFeature.get() ) )
3920 *
errorMessage += QObject::tr(
"\nOnly %1 of %2 features written." ).arg( nTotalFeatures - nErrors ).arg( nTotalFeatures );
3937 return 1000 / scale;
3954 return scale / 1000;
3962 mRenderer = createSymbologyRenderer( sourceRenderer );
3968 mRenderer->startRender( mRenderContext, fields );
3971 void QgsVectorFileWriter::stopRender()
3978 mRenderer->stopRender( mRenderContext );
3981 std::unique_ptr<QgsFeatureRenderer> QgsVectorFileWriter::createSymbologyRenderer(
QgsFeatureRenderer *sourceRenderer )
const
3987 if ( !sourceRenderer )
3992 return std::unique_ptr< QgsFeatureRenderer >( sourceRenderer->
clone() );
3999 const QSet<QString> rendererAttributes = renderer->
usedAttributes( context );
4000 for (
const QString &attr : rendererAttributes )
4005 attList.append( index );
4011 QStringList QgsVectorFileWriter::concatenateOptions(
const QMap<QString, QgsVectorFileWriter::Option *> &options )
4014 QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
4016 for ( it = options.constBegin(); it != options.constEnd(); ++it )
4019 switch ( option->
type )
4026 list.append( QStringLiteral(
"%1=%2" ).arg( it.key() ).arg( opt->
defaultValue ) );
4036 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
defaultValue ) );
4046 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
defaultValue ) );
4055 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
mValue ) );
4066 OGRSFDriverH hDriver =
nullptr;
4069 return QgsVectorFileWriter::EditionCapabilities();
4070 QString drvName = OGR_Dr_GetName( hDriver );
4071 QgsVectorFileWriter::EditionCapabilities caps = QgsVectorFileWriter::EditionCapabilities();
4072 if ( OGR_DS_TestCapability( hDS.get(), ODsCCreateLayer ) )
4077 if ( !( drvName == QLatin1String(
"ESRI Shapefile" ) && QFile::exists( datasetName ) ) )
4080 if ( OGR_DS_TestCapability( hDS.get(), ODsCDeleteLayer ) )
4084 int layer_count = OGR_DS_GetLayerCount( hDS.get() );
4087 OGRLayerH hLayer = OGR_DS_GetLayer( hDS.get(), 0 );
4090 if ( OGR_L_TestCapability( hLayer, OLCSequentialWrite ) )
4093 if ( OGR_L_TestCapability( hLayer, OLCCreateField ) )
4104 const QString &layerNameIn )
4106 OGRSFDriverH hDriver =
nullptr;
4111 QString layerName( layerNameIn );
4112 if ( layerName.isEmpty() )
4113 layerName = QFileInfo( datasetName ).baseName();
4115 return OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
4120 const QString &layerName,
4124 OGRSFDriverH hDriver =
nullptr;
4128 OGRLayerH hLayer = OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
4134 OGRFeatureDefnH defn = OGR_L_GetLayerDefn( hLayer );
4135 const auto constAttributes = attributes;
4136 for (
int idx : constAttributes )
4139 if ( OGR_FD_GetFieldIndex( defn, fld.
name().toUtf8().constData() ) < 0 )
virtual bool addZValue(double zValue=0)=0
Adds a z-dimension to the geometry, initialized to a preset value.
virtual bool dropMValue()=0
Drops any measure values which exist in the geometry.
virtual bool addMValue(double mValue=0)=0
Adds a measure to the geometry, initialized to a preset value.
virtual bool dropZValue()=0
Drops any z-dimensions which exist in the geometry.
@ FlagExportTrianglesAsPolygons
Triangles should be exported as polygon geometries.
static void registerOgrDrivers()
Register OGR drivers ensuring this only happens once.
This class represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
static Q_INVOKABLE QgsCoordinateReferenceSystem fromEpsgId(long epsg)
Creates a CRS from a given EPSG ID.
QString authid() const
Returns the authority identifier for the CRS.
Q_GADGET QgsUnitTypes::DistanceUnit mapUnits
Contains information about the context in which a coordinate transform is executed.
Custom exception class for Coordinate Reference System related exceptions.
virtual QString dataSourceUri(bool expandAuthConfig=false) const
Gets the data source specification.
Class for storing the component parts of a RDBMS data source URI (e.g.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
virtual QgsFeatureRenderer * clone() const =0
Create a deep copy of this renderer.
virtual QgsSymbolList symbolsForFeature(const QgsFeature &feature, QgsRenderContext &context) const
Returns list of symbols used for rendering the feature.
virtual QgsSymbolList symbols(QgsRenderContext &context) const
Returns list of symbols used by the renderer.
bool usingSymbolLevels() const
virtual QgsFeatureRenderer::Capabilities capabilities()
Returns details about internals of this renderer.
@ SymbolLevels
Rendering with symbol levels (i.e. implements symbols(), symbolForFeature())
virtual QSet< QString > usedAttributes(const QgsRenderContext &context) const =0
Returns a list of attributes required by this renderer.
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Sets the feature IDs that should be fetched.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
QgsFeatureRequest & setFilterRect(const QgsRectangle &rectangle)
Sets the rectangle from which features will be taken.
@ RegeneratePrimaryKey
This flag indicates, that a primary key field cannot be guaranteed to be unique and the sink should i...
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
void initAttributes(int fieldCount)
Initialize this feature with the given number of fields.
bool hasGeometry() const
Returns true if the feature has an associated geometry.
QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
bool isCanceled() const SIP_HOLDGIL
Tells whether the operation has been canceled already.
void setProgress(double progress)
Sets the current progress for the feedback object.
Encapsulate a field in an attribute table or data source.
QString typeName() const
Gets the field type.
bool convertCompatible(QVariant &v, QString *errorMessage=nullptr) const
Converts the provided variant to a compatible format.
QVariant::Type subType() const
If the field is a collection, gets its element's type.
Container of fields for a vector layer.
int count() const
Returns number of items.
int size() const
Returns number of items.
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
A geometry is the spatial representation of a feature.
const QgsAbstractGeometry * constGet() const SIP_HOLDGIL
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false) SIP_THROW(QgsCsException)
Transforms this geometry as described by the coordinate transform ct.
QgsAbstractGeometry * get()
Returns a modifiable (non-const) reference to the underlying abstract geometry primitive.
static QgsGeometry fromRect(const QgsRectangle &rect) SIP_HOLDGIL
Creates a new geometry from a QgsRectangle.
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry)
Creates and returns a new geometry engine representing the specified geometry.
bool convertToMultiType()
Converts single type geometry into multitype geometry e.g.
QByteArray asWkb(QgsAbstractGeometry::WkbFlags flags=QgsAbstractGeometry::WkbFlags()) const
Export the geometry to WKB.
static void warning(const QString &msg)
Goes to qWarning.
QString providerType() const
Returns the provider type (provider key) for this layer.
QgsCoordinateReferenceSystem crs
QgsCoordinateTransformContext transformContext() const
Returns the layer data provider coordinate transform context or a default transform context if the la...
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
Custom exception class which is raised when an operation is not supported.
static OGRSpatialReferenceH crsToOGRSpatialReference(const QgsCoordinateReferenceSystem &crs)
Returns a OGRSpatialReferenceH corresponding to the specified crs object.
QVariantMap decodeUri(const QString &providerKey, const QString &uri)
Breaks a provider data source URI into its component paths (e.g.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
QString encodeUri(const QString &providerKey, const QVariantMap &parts)
Reassembles a provider data source URI from its component paths (e.g.
bool saveLayerMetadata(const QString &providerKey, const QString &uri, const QgsLayerMetadata &metadata, QString &errorMessage) SIP_THROW(QgsNotSupportedException)
Saves metadata to the layer corresponding to the specified uri.
The QgsReadWriteLocker class is a convenience class that simplifies locking and unlocking QReadWriteL...
void changeMode(Mode mode)
Change the mode of the lock to mode.
A rectangle specified with double values.
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()).
Contains information about the context of a rendering operation.
QgsExpressionContext & expressionContext()
Gets the expression context.
void setRendererScale(double scale)
Sets the renderer map scale.
This class is a composition of two QSettings instances:
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
int renderingPass() const
Specifies the rendering pass in which this symbol layer should be rendered.
int layer() const
The layer of this symbol level.
QgsSymbol * symbol() const
The symbol of this symbol level.
Abstract base class for all rendered symbols.
QgsSymbolLayer * symbolLayer(int layer)
Returns the symbol layer at the specified index.
int symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
DistanceUnit
Units of distance.
RenderUnit
Rendering size units.
@ RenderMillimeters
Millimeters.
@ RenderMapUnits
Map units.
Interface to convert raw field values to their user-friendly value.
virtual QVariant convert(int fieldIdxInLayer, const QVariant &value)
Convert the provided value, for field fieldIdxInLayer.
virtual QgsVectorFileWriter::FieldValueConverter * clone() const
Creates a clone of the FieldValueConverter.
virtual QgsField fieldDefinition(const QgsField &field)
Returns a possibly modified field definition.
QgsVectorFileWriter::OptionType type
Options to pass to writeAsVectorFormat()
QString fileEncoding
Encoding to use.
bool forceMulti
Sets to true to force creation of multi* geometries.
FieldNameSource fieldNameSource
Source for exported field names.
QString driverName
OGR driver to use.
QgsCoordinateTransform ct
Transform to reproject exported geometries with, or invalid transform for no transformation.
QgsLayerMetadata layerMetadata
Layer metadata to save for the exported vector file.
SaveVectorOptions()
Constructor.
QString layerName
Layer name. If let empty, it will be derived from the filename.
QgsRectangle filterExtent
If not empty, only features intersecting the extent will be saved.
QgsVectorFileWriter::FieldValueConverter * fieldValueConverter
Field value converter.
QStringList layerOptions
List of OGR layer creation options.
QgsVectorFileWriter::SymbologyExport symbologyExport
Symbology to export.
bool includeZ
Sets to true to include z dimension in output. This option is only valid if overrideGeometryType is s...
bool saveMetadata
Set to true to save layer metadata for the exported vector file.
QgsVectorFileWriter::ActionOnExistingFile actionOnExistingFile
Action on existing file.
QgsAttributeList attributes
Attributes to export (empty means all unless skipAttributeCreation is set)
bool onlySelectedFeatures
Write only selected features of layer.
bool skipAttributeCreation
Only write geometries.
double symbologyScale
Scale of symbology.
QStringList datasourceOptions
List of OGR data source creation options.
QgsWkbTypes::Type overrideGeometryType
Set to a valid geometry type to override the default geometry type for the layer.
QgsFeedback * feedback
Optional feedback object allowing cancellation of layer save.
A convenience class for writing vector layers to disk based formats (e.g.
static QgsVectorFileWriter::WriterError writeAsVectorFormatV3(QgsVectorLayer *layer, const QString &fileName, const QgsCoordinateTransformContext &transformContext, const QgsVectorFileWriter::SaveVectorOptions &options, QString *errorMessage=nullptr, QString *newFilename=nullptr, QString *newLayer=nullptr)
Writes a layer out to a vector file.
QString lastError() const override
Returns the most recent error encountered by the sink, e.g.
@ CanAddNewFieldsToExistingLayer
Flag to indicate that new fields can be added to an existing layer. Imply CanAppendToExistingLayer.
@ CanAppendToExistingLayer
Flag to indicate that new features can be added to an existing layer.
@ CanAddNewLayer
Flag to indicate that a new layer can be added to the dataset.
@ CanDeleteLayer
Flag to indicate that an existing layer can be deleted.
static QgsVectorFileWriter::EditionCapabilities editionCapabilities(const QString &datasetName)
Returns edition capabilities for an existing dataset name.
static QgsVectorFileWriter * create(const QString &fileName, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &srs, const QgsCoordinateTransformContext &transformContext, const QgsVectorFileWriter::SaveVectorOptions &options, QgsFeatureSink::SinkFlags sinkFlags=QgsFeatureSink::SinkFlags(), QString *newFilename=nullptr, QString *newLayer=nullptr)
Create a new vector file writer.
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a single feature to the sink.
static bool supportsFeatureStyles(const QString &driverName)
Returns true if the specified driverName supports feature styles.
bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a list of features to the sink.
double mSymbologyScale
Scale for symbology export (e.g. for symbols units in map units)
OGRGeometryH createEmptyGeometry(QgsWkbTypes::Type wkbType)
QMap< int, int > mAttrIdxToOgrIdx
Map attribute indizes to OGR field indexes.
@ ErrAttributeTypeUnsupported
@ Canceled
Writing was interrupted by manual cancellation.
@ ErrAttributeCreationFailed
@ ErrSavingMetadata
Metadata saving failed.
gdal::ogr_datasource_unique_ptr mDS
static Q_DECL_DEPRECATED QgsVectorFileWriter::WriterError writeAsVectorFormatV2(QgsVectorLayer *layer, const QString &fileName, const QgsCoordinateTransformContext &transformContext, const QgsVectorFileWriter::SaveVectorOptions &options, QString *newFilename=nullptr, QString *newLayer=nullptr, QString *errorMessage=nullptr)
Writes a layer out to a vector file.
~QgsVectorFileWriter() override
Close opened shapefile for writing.
static bool targetLayerExists(const QString &datasetName, const QString &layerName)
Returns whether the target layer already exists.
double symbologyScale() const
Returns the reference scale for output.
static QStringList defaultLayerOptions(const QString &driverName)
Returns a list of the default layer options for a specified driver.
SymbologyExport mSymbologyExport
static QString driverForExtension(const QString &extension)
Returns the OGR driver name for a specified file extension.
static QList< QgsVectorFileWriter::FilterFormatDetails > supportedFiltersAndFormats(VectorFormatOptions options=SortRecommended)
Returns a list or pairs, with format filter string as first element and OGR format key as second elem...
OGRSpatialReferenceH mOgrRef
static bool driverMetadata(const QString &driverName, MetaData &driverMetadata)
QgsVectorFileWriter::WriterError hasError()
Checks whether there were any errors in constructor.
static bool deleteShapeFile(const QString &fileName)
Delete a shapefile (and its accompanying shx / dbf / prj / qix / qpj / cpg / sbn / sbx / idm / ind)
static QString filterForDriver(const QString &driverName)
Creates a filter for an OGR driver key.
QgsWkbTypes::Type mWkbType
Geometry type which is being used.
static OGRwkbGeometryType ogrTypeFromWkbType(QgsWkbTypes::Type type)
Gets the ogr geometry type from an internal QGIS wkb type enum.
@ SkipNonSpatialFormats
Filter out any formats which do not have spatial support (e.g. those which cannot save geometries)
static bool areThereNewFieldsToCreate(const QString &datasetName, const QString &layerName, QgsVectorLayer *layer, const QgsAttributeList &attributes)
Returns whether there are among the attributes specified some that do not exist yet in the layer.
static QList< QgsVectorFileWriter::DriverDetails > ogrDriverList(VectorFormatOptions options=SortRecommended)
Returns the driver list that can be used for dialogs.
static Q_DECL_DEPRECATED QgsVectorFileWriter::WriterError writeAsVectorFormat(QgsVectorLayer *layer, const QString &fileName, const QString &fileEncoding, const QgsCoordinateReferenceSystem &destCRS=QgsCoordinateReferenceSystem(), const QString &driverName="GPKG", bool onlySelected=false, QString *errorMessage=nullptr, const QStringList &datasourceOptions=QStringList(), const QStringList &layerOptions=QStringList(), bool skipAttributeCreation=false, QString *newFilename=nullptr, QgsVectorFileWriter::SymbologyExport symbologyExport=QgsVectorFileWriter::NoSymbology, double symbologyScale=1.0, const QgsRectangle *filterExtent=nullptr, QgsWkbTypes::Type overrideGeometryType=QgsWkbTypes::Unknown, bool forceMulti=false, bool includeZ=false, const QgsAttributeList &attributes=QgsAttributeList(), QgsVectorFileWriter::FieldValueConverter *fieldValueConverter=nullptr, QString *newLayer=nullptr)
Write contents of vector layer to an (OGR supported) vector format.
WriterError mError
Contains error value if construction was not successful.
FieldNameSource
Source for exported field names.
@ PreferAlias
Use the field alias as the exported field name, wherever one is set. Otherwise use the original field...
@ Original
Use original field names.
static QStringList defaultDatasetOptions(const QString &driverName)
Returns a list of the default dataset options for a specified driver.
static QStringList supportedFormatExtensions(VectorFormatOptions options=SortRecommended)
Returns a list of file extensions for supported formats, e.g "shp", "gpkg".
QString errorMessage()
Retrieves error message.
static QString convertCodecNameForEncodingOption(const QString &codecName)
Converts codec name to string passed to ENCODING layer creation option of OGR Shapefile.
FieldValueConverter * mFieldValueConverter
Field value converter.
bool addFeatureWithStyle(QgsFeature &feature, QgsFeatureRenderer *renderer, QgsUnitTypes::DistanceUnit outputUnit=QgsUnitTypes::DistanceMeters)
Adds a feature to the currently opened data source, using the style from a specified renderer.
QgsVectorFileWriter::SymbologyExport symbologyExport() const
void setSymbologyScale(double scale)
Set reference scale for output.
Q_DECL_DEPRECATED QgsVectorFileWriter(const QString &vectorFileName, const QString &fileEncoding, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &srs=QgsCoordinateReferenceSystem(), const QString &driverName="GPKG", const QStringList &datasourceOptions=QStringList(), const QStringList &layerOptions=QStringList(), QString *newFilename=nullptr, QgsVectorFileWriter::SymbologyExport symbologyExport=QgsVectorFileWriter::NoSymbology, QgsFeatureSink::SinkFlags sinkFlags=QgsFeatureSink::SinkFlags(), QString *newLayer=nullptr, const QgsCoordinateTransformContext &transformContext=QgsCoordinateTransformContext(), FieldNameSource fieldNameSource=Original)
Create a new vector file writer.
QMap< QgsSymbolLayer *, QString > mSymbolLayerTable
static QString fileFilterString(VectorFormatOptions options=SortRecommended)
Returns filter string that can be used for dialogs.
ActionOnExistingFile
Combination of CanAddNewLayer, CanAppendToExistingLayer, CanAddNewFieldsToExistingLayer or CanDeleteL...
@ CreateOrOverwriteLayer
Create or overwrite layer.
@ CreateOrOverwriteFile
Create or overwrite file.
@ AppendToLayerNoNewFields
Append features to existing layer, but do not create new fields.
@ AppendToLayerAddFields
Append features to existing layer, and create new fields if needed.
Represents a vector layer which manages a vector based data sets.
Q_INVOKABLE QgsWkbTypes::Type wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
long long featureCount(const QString &legendKey) const
Number of features rendered with specified legend key.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
int selectedFeatureCount() const
Returns the number of features that are selected in this layer.
Q_INVOKABLE const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
void minimumAndMaximumValue(int index, QVariant &minimum, QVariant &maximum) const
Calculates both the minimum and maximum value for an attribute column.
QgsFeatureRenderer * renderer()
Returns the feature renderer used for rendering the features in the layer in 2D map views.
static bool isMultiType(Type type) SIP_HOLDGIL
Returns true if the WKB type is a multi type.
static bool hasM(Type type) SIP_HOLDGIL
Tests whether a WKB type contains m values.
Type
The WKB type describes the number of dimensions a geometry has.
static Type to25D(Type type) SIP_HOLDGIL
Will convert the 25D version of the flat type if supported or Unknown if not supported.
static Type singleType(Type type) SIP_HOLDGIL
Returns the single type for a WKB type.
static Type flatType(Type type) SIP_HOLDGIL
Returns the flat type for a WKB type.
static Type multiType(Type type) SIP_HOLDGIL
Returns the multi type for a WKB type.
static Type addZ(Type type) SIP_HOLDGIL
Adds the z dimension to a WKB type and returns the new type.
static bool hasZ(Type type) SIP_HOLDGIL
Tests whether a WKB type contains the z-dimension.
std::unique_ptr< std::remove_pointer< OGRFeatureH >::type, OGRFeatureDeleter > ogr_feature_unique_ptr
Scoped OGR feature.
std::unique_ptr< std::remove_pointer< OGRDataSourceH >::type, OGRDataSourceDeleter > ogr_datasource_unique_ptr
Scoped OGR data source.
std::unique_ptr< std::remove_pointer< OGRFieldDefnH >::type, OGRFldDeleter > ogr_field_def_unique_ptr
Scoped OGR field definition.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
#define Q_NOWARN_DEPRECATED_POP
#define Q_NOWARN_DEPRECATED_PUSH
QList< QgsFeature > QgsFeatureList
QList< int > QgsAttributeList
#define QgsDebugMsgLevel(str, level)
QList< QgsSymbolLevel > QgsSymbolLevelOrder
QList< QgsSymbolLevelItem > QgsSymbolLevel
QList< QgsSymbol * > QgsSymbolList
Details of available driver formats.
QString longName
Descriptive, user friendly name for the driver.
QString driverName
Unique driver name.