43 #include <QTextStream>
51 #include <ogr_srs_api.h>
52 #include <cpl_error.h>
54 #include <cpl_string.h>
60 static OGRDataSourceH myOGROpen(
const char *pszName,
int bUpdate, OGRSFDriverH *phDriver )
62 OGRSFDriverH hDriver =
nullptr;
63 OGRDataSourceH hDS = OGROpen( pszName, bUpdate, &hDriver );
66 QString drvName = OGR_Dr_GetName( hDriver );
67 if ( drvName ==
"BNA" )
69 OGR_DS_Destroy( hDS );
96 const QString &vectorFileName,
97 const QString &fileEncoding,
101 const QString &driverName,
102 const QStringList &datasourceOptions,
103 const QStringList &layerOptions,
104 QString *newFilename,
106 QgsFeatureSink::SinkFlags sinkFlags,
115 init( vectorFileName, fileEncoding, fields, geometryType,
116 srs, driverName, datasourceOptions, layerOptions, newFilename,
nullptr,
121 const QString &vectorFileName,
122 const QString &fileEncoding,
126 const QString &driverName,
127 const QStringList &datasourceOptions,
128 const QStringList &layerOptions,
129 QString *newFilename,
132 const QString &layerName,
136 QgsFeatureSink::SinkFlags sinkFlags
139 , mWkbType( geometryType )
140 , mSymbologyExport( symbologyExport )
141 , mSymbologyScale( 1.0 )
143 init( vectorFileName, fileEncoding, fields, geometryType, srs, driverName,
144 datasourceOptions, layerOptions, newFilename, fieldValueConverter,
145 layerName, action, newLayer, sinkFlags, transformContext );
149 const QString &fileName,
155 QgsFeatureSink::SinkFlags sinkFlags,
156 QString *newFilename,
170 if ( driverName == QLatin1String(
"MapInfo MIF" ) )
174 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,3,0)
175 GDALDriverH gdalDriver = GDALGetDriverByName( driverName.toLocal8Bit().constData() );
183 return CSLFetchBoolean(
driverMetadata, GDAL_DCAP_FEATURE_STYLES,
false );
185 return driverName == QLatin1String(
"DXF" ) || driverName == QLatin1String(
"KML" ) || driverName == QLatin1String(
"MapInfo File" );
189 void QgsVectorFileWriter::init( QString vectorFileName,
190 QString fileEncoding,
194 const QString &driverName,
195 QStringList datasourceOptions,
196 QStringList layerOptions,
197 QString *newFilename,
198 FieldValueConverter *fieldValueConverter,
199 const QString &layerNameIn,
200 ActionOnExistingFile action,
201 QString *newLayer, SinkFlags sinkFlags,
206 if ( vectorFileName.isEmpty() )
213 if ( driverName == QLatin1String(
"MapInfo MIF" ) )
217 else if ( driverName == QLatin1String(
"SpatiaLite" ) )
220 if ( !datasourceOptions.contains( QStringLiteral(
"SPATIALITE=YES" ) ) )
222 datasourceOptions.append( QStringLiteral(
"SPATIALITE=YES" ) );
225 else if ( driverName == QLatin1String(
"DBF file" ) )
228 if ( !layerOptions.contains( QStringLiteral(
"SHPT=NULL" ) ) )
230 layerOptions.append( QStringLiteral(
"SHPT=NULL" ) );
240 OGRSFDriverH poDriver;
243 poDriver = OGRGetDriverByName(
mOgrDriverName.toLocal8Bit().constData() );
247 mErrorMessage = QObject::tr(
"OGR driver for '%1' not found (OGR error: %2)" )
249 QString::fromUtf8( CPLGetLastErrorMsg() ) );
259 if ( layerOptions.join( QString() ).toUpper().indexOf( QLatin1String(
"ENCODING=" ) ) == -1 )
264 if ( driverName == QLatin1String(
"ESRI Shapefile" ) && !vectorFileName.endsWith( QLatin1String(
".shp" ), Qt::CaseInsensitive ) )
266 vectorFileName += QLatin1String(
".shp" );
268 else if ( driverName == QLatin1String(
"DBF file" ) && !vectorFileName.endsWith( QLatin1String(
".dbf" ), Qt::CaseInsensitive ) )
270 vectorFileName += QLatin1String(
".dbf" );
280 QStringList allExts = metadata.ext.split(
' ', QString::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 QgsDebugMsg( QStringLiteral(
"forced %1 encoding for %2" ).arg( metadata.compulsoryEncoding, driverName ) );
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 QgsDebugMsg( QStringLiteral(
"-dsco=%1" ).arg( datasourceOptions[i] ) );
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( myOGROpen( 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() ) );
397 QgsDebugMsg( QStringLiteral(
"Created data source" ) );
401 QgsDebugMsg( QStringLiteral(
"Opened data source in update mode" ) );
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(
"GPX" ) )
424 if ( srs.
authid() != QStringLiteral(
"EPSG:4326" ) )
437 mOgrRef = OSRNewSpatialReference( srsWkt.toLocal8Bit().constData() );
438 #if GDAL_VERSION_MAJOR >= 3
441 OSRSetAxisMappingStrategy(
mOgrRef, OAMS_TRADITIONAL_GIS_ORDER );
450 int optIndex = layerOptions.indexOf( QStringLiteral(
"FEATURE_DATASET=" ) );
451 if ( optIndex != -1 )
453 layerOptions.removeAt( optIndex );
456 if ( !layerOptions.isEmpty() )
458 options =
new char *[ layerOptions.size() + 1 ];
459 for (
int i = 0; i < layerOptions.size(); i++ )
461 QgsDebugMsg( QStringLiteral(
"-lco=%1" ).arg( layerOptions[i] ) );
462 options[i] = CPLStrdup( layerOptions[i].toLocal8Bit().constData() );
464 options[ layerOptions.size()] =
nullptr;
468 CPLSetConfigOption(
"SHAPE_ENCODING",
"" );
472 mLayer = OGR_DS_CreateLayer(
mDS.get(), layerName.toUtf8().constData(),
mOgrRef, wkbType, options );
475 *newLayer = OGR_L_GetName(
mLayer );
476 if ( driverName == QLatin1String(
"GPX" ) )
483 if ( !EQUAL( layerName.toUtf8().constData(),
"track_points" ) &&
484 !EQUAL( layerName.toUtf8().constData(),
"route_points" ) )
486 *newLayer = QStringLiteral(
"waypoints" );
493 const char *pszForceGPXTrack
494 = CSLFetchNameValue( options,
"FORCE_GPX_TRACK" );
495 if ( pszForceGPXTrack && CPLTestBool( pszForceGPXTrack ) )
496 *newLayer = QStringLiteral(
"tracks" );
498 *newLayer = QStringLiteral(
"routes" );
505 const char *pszForceGPXRoute
506 = CSLFetchNameValue( options,
"FORCE_GPX_ROUTE" );
507 if ( pszForceGPXRoute && CPLTestBool( pszForceGPXRoute ) )
508 *newLayer = QStringLiteral(
"routes" );
510 *newLayer = QStringLiteral(
"tracks" );
520 else if ( driverName == QLatin1String(
"DGN" ) )
522 mLayer = OGR_DS_GetLayerByName(
mDS.get(),
"elements" );
526 mLayer = OGR_DS_GetLayerByName(
mDS.get(), layerName.toUtf8().constData() );
531 for (
int i = 0; i < layerOptions.size(); i++ )
532 CPLFree( options[i] );
541 QString layerName = vectorFileName.left( vectorFileName.indexOf( QLatin1String(
".shp" ), Qt::CaseInsensitive ) );
542 QFile prjFile( layerName +
".qpj" );
543 #if PROJ_VERSION_MAJOR<6
544 if ( prjFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
546 QTextStream prjStream( &prjFile );
547 prjStream << srs.
toWkt().toLocal8Bit().constData() << endl;
552 QgsDebugMsg(
"Couldn't open file " + layerName +
".qpj" );
555 if ( prjFile.exists() )
564 mErrorMessage = QObject::tr(
"Creation of layer failed (OGR error: %1)" )
565 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
567 mErrorMessage = QObject::tr(
"Opening of layer failed (OGR error: %1)" )
568 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
573 OGRFeatureDefnH defn = OGR_L_GetLayerDefn(
mLayer );
578 QgsDebugMsg(
"creating " + QString::number( fields.
size() ) +
" fields" );
582 QSet<int> existingIdxs;
592 for (
int fldIdx = 0; fldIdx < fields.
count(); ++fldIdx )
596 if ( fieldValueConverter )
598 attrField = fieldValueConverter->fieldDefinition( fields.
at( fldIdx ) );
601 QString name( attrField.
name() );
604 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( name ) );
612 OGRFieldType ogrType = OFTString;
613 int ogrWidth = attrField.
length();
614 int ogrPrecision = attrField.
precision();
615 if ( ogrPrecision > 0 )
618 switch ( attrField.
type() )
620 case QVariant::LongLong:
622 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
623 if ( pszDataTypes && strstr( pszDataTypes,
"Integer64" ) )
624 ogrType = OFTInteger64;
627 ogrWidth = ogrWidth > 0 && ogrWidth <= 20 ? ogrWidth : 20;
631 case QVariant::String:
633 if ( ( ogrWidth <= 0 || ogrWidth > 255 ) &&
mOgrDriverName == QLatin1String(
"ESRI Shapefile" ) )
638 ogrType = OFTInteger;
639 ogrWidth = ogrWidth > 0 && ogrWidth <= 10 ? ogrWidth : 10;
644 ogrType = OFTInteger;
649 case QVariant::Double:
669 case QVariant::DateTime:
677 ogrType = OFTDateTime;
681 case QVariant::ByteArray:
685 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,4,0)
688 if ( attrField.
subType() == QVariant::String )
690 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
691 if ( pszDataTypes && strstr( pszDataTypes,
"StringList" ) )
693 ogrType = OFTStringList;
694 supportsStringList =
true;
709 mErrorMessage = QObject::tr(
"Unsupported type for field %1" )
710 .arg( attrField.
name() );
715 if (
mOgrDriverName == QLatin1String(
"SQLite" ) && name.compare( QLatin1String(
"ogc_fid" ), Qt::CaseInsensitive ) == 0 )
718 for ( i = 0; i < 10; i++ )
720 name = QStringLiteral(
"ogc_fid%1" ).arg( i );
723 for ( j = 0; j < fields.
size() && name.compare( fields.
at( j ).
name(), Qt::CaseInsensitive ) != 0; j++ )
726 if ( j == fields.
size() )
732 mErrorMessage = QObject::tr(
"No available replacement for internal fieldname ogc_fid found" ).arg( attrField.
name() );
737 QgsMessageLog::logMessage( QObject::tr(
"Reserved attribute name ogc_fid replaced with %1" ).arg( name ), QObject::tr(
"OGR" ) );
744 OGR_Fld_SetWidth( fld.get(), ogrWidth );
747 if ( ogrPrecision >= 0 )
749 OGR_Fld_SetPrecision( fld.get(), ogrPrecision );
752 switch ( attrField.
type() )
755 OGR_Fld_SetSubType( fld.get(), OFSTBoolean );
763 " type " + QString( QVariant::typeToName( attrField.
type() ) ) +
764 " width " + QString::number( ogrWidth ) +
765 " precision " + QString::number( ogrPrecision ) );
766 if ( OGR_L_CreateField(
mLayer, fld.get(),
true ) != OGRERR_NONE )
769 mErrorMessage = QObject::tr(
"Creation of field %1 failed (OGR error: %2)" )
770 .arg( attrField.
name(),
771 QString::fromUtf8( CPLGetLastErrorMsg() ) );
776 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( name ) );
777 QgsDebugMsg( QStringLiteral(
"returned field index for %1: %2" ).arg( name ).arg( ogrIdx ) );
778 if ( ogrIdx < 0 || existingIdxs.contains( ogrIdx ) )
781 ogrIdx = OGR_FD_GetFieldCount( defn ) - 1;
786 mErrorMessage = QObject::tr(
"Created field %1 not found (OGR error: %2)" )
787 .arg( attrField.
name(),
788 QString::fromUtf8( CPLGetLastErrorMsg() ) );
794 existingIdxs.insert( ogrIdx );
802 for (
int fldIdx = 0; fldIdx < fields.
count(); ++fldIdx )
805 QString name( attrField.
name() );
806 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( name ) );
818 int fidIdx = fields.
lookupField( QStringLiteral(
"FID" ) );
824 QgsDebugMsg( QStringLiteral(
"Done creating fields" ) );
829 *newFilename = vectorFileName;
832 mUsingTransaction =
true;
833 if ( OGRERR_NONE != OGR_L_StartTransaction(
mLayer ) )
835 mUsingTransaction =
false;
845 class QgsVectorFileWriterMetadataContainer
849 QgsVectorFileWriterMetadataContainer()
851 QMap<QString, QgsVectorFileWriter::Option *> datasetOptions;
852 QMap<QString, QgsVectorFileWriter::Option *> layerOptions;
855 datasetOptions.clear();
856 layerOptions.clear();
858 driverMetadata.insert( QStringLiteral(
"AVCE00" ),
860 QStringLiteral(
"Arc/Info ASCII Coverage" ),
861 QObject::tr(
"Arc/Info ASCII Coverage" ),
862 QStringLiteral(
"*.e00" ),
863 QStringLiteral(
"e00" ),
870 datasetOptions.clear();
871 layerOptions.clear();
874 QObject::tr(
"New BNA files are created by the "
875 "systems default line termination conventions. "
876 "This may be overridden here." ),
878 << QStringLiteral(
"CRLF" )
879 << QStringLiteral(
"LF" ),
885 QObject::tr(
"By default, BNA files are created in multi-line format. "
886 "For each record, the first line contains the identifiers and the "
887 "type/number of coordinates to follow. Each following line contains "
888 "a pair of coordinates." ),
893 QObject::tr(
"BNA records may contain from 2 to 4 identifiers per record. "
894 "Some software packages only support a precise number of identifiers. "
895 "You can override the default value (2) by a precise value." ),
897 << QStringLiteral(
"2" )
898 << QStringLiteral(
"3" )
899 << QStringLiteral(
"4" )
900 << QStringLiteral(
"NB_SOURCE_FIELDS" ),
901 QStringLiteral(
"2" )
905 QObject::tr(
"The BNA writer will try to recognize ellipses and circles when writing a polygon. "
906 "This will only work if the feature has previously been read from a BNA file. "
907 "As some software packages do not support ellipses/circles in BNA data file, "
908 "it may be useful to tell the writer by specifying ELLIPSES_AS_ELLIPSES=NO not "
909 "to export them as such, but keep them as polygons." ),
914 QObject::tr(
"Limit the number of coordinate pairs per line in multiline format." ),
919 QObject::tr(
"Set the number of decimal for coordinates. Default value is 10." ),
923 driverMetadata.insert( QStringLiteral(
"BNA" ),
925 QStringLiteral(
"Atlas BNA" ),
926 QObject::tr(
"Atlas BNA" ),
927 QStringLiteral(
"*.bna" ),
928 QStringLiteral(
"bna" ),
935 datasetOptions.clear();
936 layerOptions.clear();
939 QObject::tr(
"By default when creating new .csv files they "
940 "are created with the line termination conventions "
941 "of the local platform (CR/LF on Win32 or LF on all other systems). "
942 "This may be overridden through the use of the LINEFORMAT option." ),
944 << QStringLiteral(
"CRLF" )
945 << QStringLiteral(
"LF" ),
951 QObject::tr(
"By default, the geometry of a feature written to a .csv file is discarded. "
952 "It is possible to export the geometry in its WKT representation by "
953 "specifying GEOMETRY=AS_WKT. It is also possible to export point geometries "
954 "into their X,Y,Z components by specifying GEOMETRY=AS_XYZ, GEOMETRY=AS_XY "
955 "or GEOMETRY=AS_YX." ),
957 << QStringLiteral(
"AS_WKT" )
958 << QStringLiteral(
"AS_XYZ" )
959 << QStringLiteral(
"AS_XY" )
960 << QStringLiteral(
"AS_YX" ),
966 QObject::tr(
"Create the associated .csvt file to describe the type of each "
967 "column of the layer and its optional width and precision." ),
972 QObject::tr(
"Field separator character." ),
974 << QStringLiteral(
"COMMA" )
975 << QStringLiteral(
"SEMICOLON" )
976 << QStringLiteral(
"TAB" ),
977 QStringLiteral(
"COMMA" )
980 #if defined(GDAL_COMPUTE_VERSION) && GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,3,0)
982 QObject::tr(
"Double-quote strings. IF_AMBIGUOUS means that string values that look like numbers will be quoted." ),
984 << QStringLiteral(
"IF_NEEDED" )
985 << QStringLiteral(
"IF_AMBIGUOUS" )
986 << QStringLiteral(
"ALWAYS" ),
987 QStringLiteral(
"IF_AMBIGUOUS" )
992 QObject::tr(
"Write a UTF-8 Byte Order Mark (BOM) at the start of the file." ),
996 driverMetadata.insert( QStringLiteral(
"CSV" ),
998 QStringLiteral(
"Comma Separated Value [CSV]" ),
999 QObject::tr(
"Comma Separated Value [CSV]" ),
1000 QStringLiteral(
"*.csv" ),
1001 QStringLiteral(
"csv" ),
1007 #if defined(GDAL_COMPUTE_VERSION) && GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,1,0)
1009 datasetOptions.clear();
1010 layerOptions.clear();
1012 driverMetadata.insert( QStringLiteral(
"FlatGeobuf" ),
1014 QStringLiteral(
"FlatGeobuf" ),
1015 QObject::tr(
"FlatGeobuf" ),
1016 QStringLiteral(
"*.fgb" ),
1017 QStringLiteral(
"fgb" ),
1025 datasetOptions.clear();
1026 layerOptions.clear();
1029 QObject::tr(
"Override the type of shapefile created. "
1030 "Can be one of NULL for a simple .dbf file with no .shp file, POINT, "
1031 "ARC, POLYGON or MULTIPOINT for 2D, or POINTZ, ARCZ, POLYGONZ or "
1032 "MULTIPOINTZ for 3D;" ) +
1033 QObject::tr(
" POINTM, ARCM, POLYGONM or MULTIPOINTM for measured geometries"
1034 " and POINTZM, ARCZM, POLYGONZM or MULTIPOINTZM for 3D measured"
1036 #
if defined(GDAL_COMPUTE_VERSION) && GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,2,0)
1037 QObject::tr(
" MULTIPATCH files are supported since GDAL 2.2." ) +
1041 << QStringLiteral(
"NULL" )
1042 << QStringLiteral(
"POINT" )
1043 << QStringLiteral(
"ARC" )
1044 << QStringLiteral(
"POLYGON" )
1045 << QStringLiteral(
"MULTIPOINT" )
1046 << QStringLiteral(
"POINTZ" )
1047 << QStringLiteral(
"ARCZ" )
1048 << QStringLiteral(
"POLYGONZ" )
1049 << QStringLiteral(
"MULTIPOINTZ" )
1050 << QStringLiteral(
"POINTM" )
1051 << QStringLiteral(
"ARCM" )
1052 << QStringLiteral(
"POLYGONM" )
1053 << QStringLiteral(
"MULTIPOINTM" )
1054 << QStringLiteral(
"POINTZM" )
1055 << QStringLiteral(
"ARCZM" )
1056 << QStringLiteral(
"POLYGONZM" )
1057 << QStringLiteral(
"MULTIPOINTZM" )
1058 #
if defined(GDAL_COMPUTE_VERSION) && GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,2,0)
1059 << QStringLiteral(
"MULTIPATCH" )
1070 QObject::tr(
"Set the encoding value in the DBF file. "
1071 "The default value is LDID/87. It is not clear "
1072 "what other values may be appropriate." ),
1080 QObject::tr(
"Set to YES to resize fields to their optimal size." ),
1084 driverMetadata.insert( QStringLiteral(
"ESRI" ),
1086 QStringLiteral(
"ESRI Shapefile" ),
1087 QObject::tr(
"ESRI Shapefile" ),
1088 QStringLiteral(
"*.shp" ),
1089 QStringLiteral(
"shp" ),
1096 datasetOptions.clear();
1097 layerOptions.clear();
1099 driverMetadata.insert( QStringLiteral(
"DBF File" ),
1101 QStringLiteral(
"DBF File" ),
1102 QObject::tr(
"DBF File" ),
1103 QStringLiteral(
"*.dbf" ),
1104 QStringLiteral(
"dbf" ),
1111 datasetOptions.clear();
1112 layerOptions.clear();
1114 driverMetadata.insert( QStringLiteral(
"FMEObjects Gateway" ),
1116 QStringLiteral(
"FMEObjects Gateway" ),
1117 QObject::tr(
"FMEObjects Gateway" ),
1118 QStringLiteral(
"*.fdd" ),
1119 QStringLiteral(
"fdd" ),
1126 datasetOptions.clear();
1127 layerOptions.clear();
1130 QObject::tr(
"Set to YES to write a bbox property with the bounding box "
1131 "of the geometries at the feature and feature collection level." ),
1136 QObject::tr(
"Maximum number of figures after decimal separator to write in coordinates. "
1137 "Defaults to 15. Truncation will occur to remove trailing zeros." ),
1142 QObject::tr(
"Whether to use RFC 7946 standard. "
1143 "If disabled GeoJSON 2008 initial version will be used. "
1144 "Default is NO (thus GeoJSON 2008). See also Documentation (via Help button)" ),
1148 driverMetadata.insert( QStringLiteral(
"GeoJSON" ),
1150 QStringLiteral(
"GeoJSON" ),
1151 QObject::tr(
"GeoJSON" ),
1152 QStringLiteral(
"*.geojson" ),
1153 QStringLiteral(
"geojson" ),
1156 QStringLiteral(
"UTF-8" )
1161 datasetOptions.clear();
1162 layerOptions.clear();
1165 QObject::tr(
"Maximum number of figures after decimal separator to write in coordinates. "
1166 "Defaults to 15. Truncation will occur to remove trailing zeros." ),
1171 QObject::tr(
"Whether to start records with the RS=0x1E character (RFC 8142 standard). "
1172 "Defaults to NO: Newline Delimited JSON (geojsonl). \n"
1173 "If set to YES: RFC 8142 standard: GeoJSON Text Sequences (geojsons)." ),
1177 driverMetadata.insert( QStringLiteral(
"GeoJSONSeq" ),
1179 QStringLiteral(
"GeoJSON - Newline Delimited" ),
1180 QObject::tr(
"GeoJSON - Newline Delimited" ),
1181 QStringLiteral(
"*.geojsonl *.geojsons *.json" ),
1182 QStringLiteral(
"json" ),
1185 QStringLiteral(
"UTF-8" )
1190 datasetOptions.clear();
1191 layerOptions.clear();
1194 QObject::tr(
"whether the document must be in RSS 2.0 or Atom 1.0 format. "
1195 "Default value : RSS" ),
1197 << QStringLiteral(
"RSS" )
1198 << QStringLiteral(
"ATOM" ),
1199 QStringLiteral(
"RSS" )
1203 QObject::tr(
"The encoding of location information. Default value : SIMPLE. "
1204 "W3C_GEO only supports point geometries. "
1205 "SIMPLE or W3C_GEO only support geometries in geographic WGS84 coordinates." ),
1207 << QStringLiteral(
"SIMPLE" )
1208 << QStringLiteral(
"GML" )
1209 << QStringLiteral(
"W3C_GEO" ),
1210 QStringLiteral(
"SIMPLE" )
1214 QObject::tr(
"If defined to YES, extension fields will be written. "
1215 "If the field name not found in the base schema matches "
1216 "the foo_bar pattern, foo will be considered as the namespace "
1217 "of the element, and a <foo:bar> element will be written. "
1218 "Otherwise, elements will be written in the <ogr:> namespace." ),
1223 QObject::tr(
"If defined to NO, only <entry> or <item> elements will be written. "
1224 "The user will have to provide the appropriate header and footer of the document." ),
1229 QObject::tr(
"XML content that will be put between the <channel> element and the "
1230 "first <item> element for a RSS document, or between the xml tag and "
1231 "the first <entry> element for an Atom document." ),
1236 QObject::tr(
"Value put inside the <title> element in the header. "
1237 "If not provided, a dummy value will be used as that element is compulsory." ),
1242 QObject::tr(
"Value put inside the <description> element in the header. "
1243 "If not provided, a dummy value will be used as that element is compulsory." ),
1248 QObject::tr(
"Value put inside the <link> element in the header. "
1249 "If not provided, a dummy value will be used as that element is compulsory." ),
1254 QObject::tr(
"Value put inside the <updated> element in the header. "
1255 "Should be formatted as a XML datetime. "
1256 "If not provided, a dummy value will be used as that element is compulsory." ),
1261 QObject::tr(
"Value put inside the <author><name> element in the header. "
1262 "If not provided, a dummy value will be used as that element is compulsory." ),
1267 QObject::tr(
"Value put inside the <id> element in the header. "
1268 "If not provided, a dummy value will be used as that element is compulsory." ),
1272 driverMetadata.insert( QStringLiteral(
"GeoRSS" ),
1274 QStringLiteral(
"GeoRSS" ),
1275 QObject::tr(
"GeoRSS" ),
1276 QStringLiteral(
"*.xml" ),
1277 QStringLiteral(
"xml" ),
1280 QStringLiteral(
"UTF-8" )
1285 datasetOptions.clear();
1286 layerOptions.clear();
1289 QObject::tr(
"If provided, this URI will be inserted as the schema location. "
1290 "Note that the schema file isn't actually accessed by OGR, so it "
1291 "is up to the user to ensure it will match the schema of the OGR "
1292 "produced GML data file." ),
1297 QObject::tr(
"This writes a GML application schema file to a corresponding "
1298 ".xsd file (with the same basename). If INTERNAL is used the "
1299 "schema is written within the GML file, but this is experimental "
1300 "and almost certainly not valid XML. "
1301 "OFF disables schema generation (and is implicit if XSISCHEMAURI is used)." ),
1303 << QStringLiteral(
"EXTERNAL" )
1304 << QStringLiteral(
"INTERNAL" )
1305 << QStringLiteral(
"OFF" ),
1306 QStringLiteral(
"EXTERNAL" )
1310 QObject::tr(
"This is the prefix for the application target namespace." ),
1311 QStringLiteral(
"ogr" )
1315 QObject::tr(
"Can be set to TRUE to avoid writing the prefix of the "
1316 "application target namespace in the GML file." ),
1321 QObject::tr(
"Defaults to 'http://ogr.maptools.org/'. "
1322 "This is the application target namespace." ),
1323 QStringLiteral(
"http://ogr.maptools.org/" )
1327 QObject::tr(
"If not specified, GML2 will be used." ),
1329 << QStringLiteral(
"GML3" )
1330 << QStringLiteral(
"GML3Deegree" )
1331 << QStringLiteral(
"GML3.2" ),
1337 QObject::tr(
"Only valid when FORMAT=GML3/GML3Degree/GML3.2. Default to YES. "
1338 "If YES, SRS with EPSG authority will be written with the "
1339 "'urn:ogc:def:crs:EPSG::' prefix. In the case the SRS is a "
1340 "geographic SRS without explicit AXIS order, but that the same "
1341 "SRS authority code imported with ImportFromEPSGA() should be "
1342 "treated as lat/long, then the function will take care of coordinate "
1343 "order swapping. If set to NO, SRS with EPSG authority will be "
1344 "written with the 'EPSG:' prefix, even if they are in lat/long order." ),
1349 QObject::tr(
"only valid when FORMAT=GML3/GML3Degree/GML3.2) Default to YES. "
1350 "If set to NO, the <gml:boundedBy> element will not be written for "
1356 QObject::tr(
"Default to YES. If YES, the output will be indented with spaces "
1357 "for more readability, but at the expense of file size." ),
1362 driverMetadata.insert( QStringLiteral(
"GML" ),
1364 QStringLiteral(
"Geography Markup Language [GML]" ),
1365 QObject::tr(
"Geography Markup Language [GML]" ),
1366 QStringLiteral(
"*.gml" ),
1367 QStringLiteral(
"gml" ),
1370 QStringLiteral(
"UTF-8" )
1375 datasetOptions.clear();
1376 layerOptions.clear();
1379 QObject::tr(
"Human-readable identifier (e.g. short name) for the layer content" ),
1384 QObject::tr(
"Human-readable description for the layer content" ),
1389 QObject::tr(
"Name for the feature identifier column" ),
1390 QStringLiteral(
"fid" )
1394 QObject::tr(
"Name for the geometry column" ),
1395 QStringLiteral(
"geom" )
1399 QObject::tr(
"If a spatial index must be created." ),
1403 driverMetadata.insert( QStringLiteral(
"GPKG" ),
1405 QStringLiteral(
"GeoPackage" ),
1406 QObject::tr(
"GeoPackage" ),
1407 QStringLiteral(
"*.gpkg" ),
1408 QStringLiteral(
"gpkg" ),
1411 QStringLiteral(
"UTF-8" )
1416 datasetOptions.clear();
1417 layerOptions.clear();
1419 driverMetadata.insert( QStringLiteral(
"GMT" ),
1421 QStringLiteral(
"Generic Mapping Tools [GMT]" ),
1422 QObject::tr(
"Generic Mapping Tools [GMT]" ),
1423 QStringLiteral(
"*.gmt" ),
1424 QStringLiteral(
"gmt" ),
1431 datasetOptions.clear();
1432 layerOptions.clear();
1435 QObject::tr(
"By default when writing a layer whose features are of "
1436 "type wkbLineString, the GPX driver chooses to write "
1437 "them as routes. If FORCE_GPX_TRACK=YES is specified, "
1438 "they will be written as tracks." ),
1443 QObject::tr(
"By default when writing a layer whose features are of "
1444 "type wkbMultiLineString, the GPX driver chooses to write "
1445 "them as tracks. If FORCE_GPX_ROUTE=YES is specified, "
1446 "they will be written as routes, provided that the multilines "
1447 "are composed of only one single line." ),
1452 QObject::tr(
"If GPX_USE_EXTENSIONS=YES is specified, "
1453 "extra fields will be written inside the <extensions> tag." ),
1458 QObject::tr(
"Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS_URL "
1459 "is set. The namespace value used for extension tags. By default, 'ogr'." ),
1460 QStringLiteral(
"ogr" )
1464 QObject::tr(
"Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS "
1465 "is set. The namespace URI. By default, 'http://osgeo.org/gdal'." ),
1466 QStringLiteral(
"http://osgeo.org/gdal" )
1470 QObject::tr(
"By default files are created with the line termination "
1471 "conventions of the local platform (CR/LF on win32 or LF "
1472 "on all other systems). This may be overridden through use "
1473 "of the LINEFORMAT layer creation option which may have a value "
1474 "of CRLF (DOS format) or LF (Unix format)." ),
1476 << QStringLiteral(
"CRLF" )
1477 << QStringLiteral(
"LF" ),
1482 driverMetadata.insert( QStringLiteral(
"GPX" ),
1484 QStringLiteral(
"GPS eXchange Format [GPX]" ),
1485 QObject::tr(
"GPS eXchange Format [GPX]" ),
1486 QStringLiteral(
"*.gpx" ),
1487 QStringLiteral(
"gpx" ),
1490 QStringLiteral(
"UTF-8" )
1495 datasetOptions.clear();
1496 layerOptions.clear();
1498 driverMetadata.insert( QStringLiteral(
"Interlis 1" ),
1500 QStringLiteral(
"INTERLIS 1" ),
1501 QObject::tr(
"INTERLIS 1" ),
1502 QStringLiteral(
"*.itf *.xml *.ili" ),
1503 QStringLiteral(
"ili" ),
1510 datasetOptions.clear();
1511 layerOptions.clear();
1513 driverMetadata.insert( QStringLiteral(
"Interlis 2" ),
1515 QStringLiteral(
"INTERLIS 2" ),
1516 QObject::tr(
"INTERLIS 2" ),
1517 QStringLiteral(
"*.xtf *.xml *.ili" ),
1518 QStringLiteral(
"ili" ),
1525 datasetOptions.clear();
1526 layerOptions.clear();
1529 QObject::tr(
"Allows you to specify the field to use for the KML <name> element." ),
1530 QStringLiteral(
"Name" )
1534 QObject::tr(
"Allows you to specify the field to use for the KML <description> element." ),
1535 QStringLiteral(
"Description" )
1539 QObject::tr(
"Allows you to specify the AltitudeMode to use for KML geometries. "
1540 "This will only affect 3D geometries and must be one of the valid KML options." ),
1542 << QStringLiteral(
"clampToGround" )
1543 << QStringLiteral(
"relativeToGround" )
1544 << QStringLiteral(
"absolute" ),
1545 QStringLiteral(
"relativeToGround" )
1548 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,2,0)
1550 QObject::tr(
"The DOCUMENT_ID datasource creation option can be used to specified "
1551 "the id of the root <Document> node. The default value is root_doc." ),
1552 QStringLiteral(
"root_doc" )
1556 driverMetadata.insert( QStringLiteral(
"KML" ),
1558 QStringLiteral(
"Keyhole Markup Language [KML]" ),
1559 QObject::tr(
"Keyhole Markup Language [KML]" ),
1560 QStringLiteral(
"*.kml" ),
1561 QStringLiteral(
"kml" ),
1564 QStringLiteral(
"UTF-8" )
1569 datasetOptions.clear();
1570 layerOptions.clear();
1572 auto insertMapInfoOptions = []( QMap<QString, QgsVectorFileWriter::Option *> &datasetOptions, QMap<QString, QgsVectorFileWriter::Option *> &layerOptions )
1575 QObject::tr(
"Use this to turn on 'quick spatial index mode'. "
1576 "In this mode writing files can be about 5 times faster, "
1577 "but spatial queries can be up to 30 times slower." ),
1579 << QStringLiteral(
"QUICK" )
1580 << QStringLiteral(
"OPTIMIZED" ),
1581 QStringLiteral(
"QUICK" ),
1586 QObject::tr(
"(multiples of 512): Block size for .map files. Defaults "
1587 "to 512. MapInfo 15.2 and above creates .tab files with a "
1588 "blocksize of 16384 bytes. Any MapInfo version should be "
1589 "able to handle block sizes from 512 to 32256." ),
1593 QObject::tr(
"xmin,ymin,xmax,ymax: Define custom layer bounds to increase the "
1594 "accuracy of the coordinates. Note: the geometry of written "
1595 "features must be within the defined box." ),
1599 insertMapInfoOptions( datasetOptions, layerOptions );
1601 driverMetadata.insert( QStringLiteral(
"MapInfo File" ),
1603 QStringLiteral(
"Mapinfo" ),
1604 QObject::tr(
"Mapinfo TAB" ),
1605 QStringLiteral(
"*.tab" ),
1606 QStringLiteral(
"tab" ),
1611 datasetOptions.clear();
1612 layerOptions.clear();
1613 insertMapInfoOptions( datasetOptions, layerOptions );
1616 driverMetadata.insert( QStringLiteral(
"MapInfo MIF" ),
1618 QStringLiteral(
"Mapinfo" ),
1619 QObject::tr(
"Mapinfo MIF" ),
1620 QStringLiteral(
"*.mif" ),
1621 QStringLiteral(
"mif" ),
1628 datasetOptions.clear();
1629 layerOptions.clear();
1632 QObject::tr(
"Determine whether 2D (seed_2d.dgn) or 3D (seed_3d.dgn) "
1633 "seed file should be used. This option is ignored if the SEED option is provided." ),
1638 QObject::tr(
"Override the seed file to use." ),
1643 QObject::tr(
"Indicate whether the whole seed file should be copied. "
1644 "If not, only the first three elements will be copied." ),
1649 QObject::tr(
"Indicates whether the color table should be copied from the seed file." ),
1654 QObject::tr(
"Override the master unit name from the seed file with "
1655 "the provided one or two character unit name." ),
1660 QObject::tr(
"Override the sub unit name from the seed file with the provided "
1661 "one or two character unit name." ),
1666 QObject::tr(
"Override the number of subunits per master unit. "
1667 "By default the seed file value is used." ),
1672 QObject::tr(
"Override the number of UORs (Units of Resolution) "
1673 "per sub unit. By default the seed file value is used." ),
1678 QObject::tr(
"ORIGIN=x,y,z: Override the origin of the design plane. "
1679 "By default the origin from the seed file is used." ),
1683 driverMetadata.insert( QStringLiteral(
"DGN" ),
1685 QStringLiteral(
"Microstation DGN" ),
1686 QObject::tr(
"Microstation DGN" ),
1687 QStringLiteral(
"*.dgn" ),
1688 QStringLiteral(
"dgn" ),
1695 datasetOptions.clear();
1696 layerOptions.clear();
1699 QObject::tr(
"Should update files be incorporated into the base data on the fly." ),
1701 << QStringLiteral(
"APPLY" )
1702 << QStringLiteral(
"IGNORE" ),
1703 QStringLiteral(
"APPLY" )
1707 QObject::tr(
"Should multipoint soundings be split into many single point sounding features. "
1708 "Multipoint geometries are not well handled by many formats, "
1709 "so it can be convenient to split single sounding features with many points "
1710 "into many single point features." ),
1715 QObject::tr(
"Should a DEPTH attribute be added on SOUNDG features and assign the depth "
1716 "of the sounding. This should only be enabled when SPLIT_MULTIPOINT is "
1722 QObject::tr(
"Should all the low level geometry primitives be returned as special "
1723 "IsolatedNode, ConnectedNode, Edge and Face layers." ),
1728 QObject::tr(
"If enabled, numeric attributes assigned an empty string as a value will "
1729 "be preserved as a special numeric value. This option should not generally "
1730 "be needed, but may be useful when translated S-57 to S-57 losslessly." ),
1735 QObject::tr(
"Should LNAM and LNAM_REFS fields be attached to features capturing "
1736 "the feature to feature relationships in the FFPT group of the S-57 file." ),
1741 QObject::tr(
"Should additional attributes relating features to their underlying "
1742 "geometric primitives be attached. These are the values of the FSPT group, "
1743 "and are primarily needed when doing S-57 to S-57 translations." ),
1748 QObject::tr(
"Should attribute values be recoded to UTF-8 from the character encoding "
1749 "specified in the S57 DSSI record." ),
1755 driverMetadata.insert( QStringLiteral(
"S57" ),
1757 QStringLiteral(
"S-57 Base file" ),
1758 QObject::tr(
"S-57 Base file" ),
1759 QStringLiteral(
"*.000" ),
1760 QStringLiteral(
"000" ),
1767 datasetOptions.clear();
1768 layerOptions.clear();
1770 driverMetadata.insert( QStringLiteral(
"SDTS" ),
1772 QStringLiteral(
"Spatial Data Transfer Standard [SDTS]" ),
1773 QObject::tr(
"Spatial Data Transfer Standard [SDTS]" ),
1774 QStringLiteral(
"*catd.ddf" ),
1775 QStringLiteral(
"ddf" ),
1782 datasetOptions.clear();
1783 layerOptions.clear();
1786 QObject::tr(
"Can be used to avoid creating the geometry_columns and spatial_ref_sys "
1787 "tables in a new database. By default these metadata tables are created "
1788 "when a new database is created." ),
1794 QStringLiteral(
"NO" )
1799 QStringLiteral(
"NO" )
1803 QObject::tr(
"Controls the format used for the geometry column. Defaults to WKB. "
1804 "This is generally more space and processing efficient, but harder "
1805 "to inspect or use in simple applications than WKT (Well Known Text)." ),
1807 << QStringLiteral(
"WKB" )
1808 << QStringLiteral(
"WKT" ),
1809 QStringLiteral(
"WKB" )
1813 QObject::tr(
"Controls whether layer and field names will be laundered for easier use "
1814 "in SQLite. Laundered names will be converted to lower case and some special "
1815 "characters(' - #) will be changed to underscores." ),
1820 QStringLiteral(
"NO" )
1824 QStringLiteral(
"NO" )
1832 QObject::tr(
"column_name1[,column_name2, …] A list of (String) columns that "
1833 "must be compressed with ZLib DEFLATE algorithm. This might be beneficial "
1834 "for databases that have big string blobs. However, use with care, since "
1835 "the value of such columns will be seen as compressed binary content with "
1836 "other SQLite utilities (or previous OGR versions). With OGR, when inserting, "
1837 "modifying or querying compressed columns, compression/decompression is "
1838 "done transparently. However, such columns cannot be (easily) queried with "
1839 "an attribute filter or WHERE clause. Note: in table definition, such columns "
1840 "have the 'VARCHAR_deflate' declaration type." ),
1844 driverMetadata.insert( QStringLiteral(
"SQLite" ),
1846 QStringLiteral(
"SQLite" ),
1847 QObject::tr(
"SQLite" ),
1848 QStringLiteral(
"*.sqlite" ),
1849 QStringLiteral(
"sqlite" ),
1852 QStringLiteral(
"UTF-8" )
1857 datasetOptions.clear();
1858 layerOptions.clear();
1861 QObject::tr(
"Can be used to avoid creating the geometry_columns and spatial_ref_sys "
1862 "tables in a new database. By default these metadata tables are created "
1863 "when a new database is created." ),
1868 QStringLiteral(
"YES" )
1872 QObject::tr(
"Insert the content of the EPSG CSV files into the spatial_ref_sys table. "
1873 "Set to NO for regular SQLite databases." ),
1878 QStringLiteral(
"SPATIALITE" )
1882 QObject::tr(
"Controls whether layer and field names will be laundered for easier use "
1883 "in SQLite. Laundered names will be converted to lower case and some special "
1884 "characters(' - #) will be changed to underscores." ),
1889 QObject::tr(
"If the database is of the SpatiaLite flavor, and if OGR is linked "
1890 "against libspatialite, this option can be used to control if a spatial "
1891 "index must be created." ),
1896 QObject::tr(
"If the format of the geometry BLOB is of the SpatiaLite flavor, "
1897 "this option can be used to control if the compressed format for "
1898 "geometries (LINESTRINGs, POLYGONs) must be used." ),
1903 QObject::tr(
"Used to force the SRID number of the SRS associated with the layer. "
1904 "When this option isn't specified and that a SRS is associated with the "
1905 "layer, a search is made in the spatial_ref_sys to find a match for the "
1906 "SRS, and, if there is no match, a new entry is inserted for the SRS in "
1907 "the spatial_ref_sys table. When the SRID option is specified, this "
1908 "search (and the eventual insertion of a new entry) will not be done: "
1909 "the specified SRID is used as such." ),
1914 QObject::tr(
"column_name1[,column_name2, …] A list of (String) columns that "
1915 "must be compressed with ZLib DEFLATE algorithm. This might be beneficial "
1916 "for databases that have big string blobs. However, use with care, since "
1917 "the value of such columns will be seen as compressed binary content with "
1918 "other SQLite utilities (or previous OGR versions). With OGR, when inserting, "
1919 "modifying or queryings compressed columns, compression/decompression is "
1920 "done transparently. However, such columns cannot be (easily) queried with "
1921 "an attribute filter or WHERE clause. Note: in table definition, such columns "
1922 "have the 'VARCHAR_deflate' declaration type." ),
1926 driverMetadata.insert( QStringLiteral(
"SpatiaLite" ),
1928 QStringLiteral(
"SpatiaLite" ),
1929 QObject::tr(
"SpatiaLite" ),
1930 QStringLiteral(
"*.sqlite" ),
1931 QStringLiteral(
"sqlite" ),
1934 QStringLiteral(
"UTF-8" )
1938 datasetOptions.clear();
1939 layerOptions.clear();
1942 QObject::tr(
"Override the header file used - in place of header.dxf." ),
1947 QObject::tr(
"Override the trailer file used - in place of trailer.dxf." ),
1951 driverMetadata.insert( QStringLiteral(
"DXF" ),
1953 QStringLiteral(
"AutoCAD DXF" ),
1954 QObject::tr(
"AutoCAD DXF" ),
1955 QStringLiteral(
"*.dxf" ),
1956 QStringLiteral(
"dxf" ),
1963 datasetOptions.clear();
1964 layerOptions.clear();
1967 QObject::tr(
"Indicates the GeoConcept export file extension. "
1968 "TXT was used by earlier releases of GeoConcept. GXT is currently used." ),
1970 << QStringLiteral(
"GXT" )
1971 << QStringLiteral(
"TXT" ),
1972 QStringLiteral(
"GXT" )
1976 QObject::tr(
"Path to the GCT: the GCT file describes the GeoConcept types definitions: "
1977 "In this file, every line must start with //# followed by a keyword. "
1978 "Lines starting with // are comments." ),
1983 QObject::tr(
"Defines the feature to be created. The TYPE corresponds to one of the Name "
1984 "found in the GCT file for a type section. The SUBTYPE corresponds to one of "
1985 "the Name found in the GCT file for a sub-type section within the previous "
1990 driverMetadata.insert( QStringLiteral(
"Geoconcept" ),
1992 QStringLiteral(
"Geoconcept" ),
1993 QObject::tr(
"Geoconcept" ),
1994 QStringLiteral(
"*.gxt *.txt" ),
1995 QStringLiteral(
"gxt" ),
2002 datasetOptions.clear();
2003 layerOptions.clear();
2006 QObject::tr(
"When this option is set, the new layer will be created inside the named "
2007 "FeatureDataset folder. If the folder does not already exist, it will be created." ),
2012 QObject::tr(
"Set name of geometry column in new layer. Defaults to 'SHAPE'." ),
2013 QStringLiteral(
"SHAPE" )
2017 QObject::tr(
"Name of the OID column to create. Defaults to 'OBJECTID'." ),
2018 QStringLiteral(
"OBJECTID" )
2021 driverMetadata.insert( QStringLiteral(
"FileGDB" ),
2023 QStringLiteral(
"ESRI FileGDB" ),
2024 QObject::tr(
"ESRI FileGDB" ),
2025 QStringLiteral(
"*.gdb" ),
2026 QStringLiteral(
"gdb" ),
2029 QStringLiteral(
"UTF-8" )
2034 datasetOptions.clear();
2035 layerOptions.clear();
2038 QObject::tr(
"By default, the driver will try to detect the data type of fields. If set "
2039 "to STRING, all fields will be of String type." ),
2041 << QStringLiteral(
"AUTO" )
2042 << QStringLiteral(
"STRING" ),
2043 QStringLiteral(
"AUTO" ),
2048 QObject::tr(
"By default, the driver will read the first lines of each sheet to detect "
2049 "if the first line might be the name of columns. If set to FORCE, the driver "
2050 "will consider the first line as the header line. If set to "
2051 "DISABLE, it will be considered as the first feature. Otherwise "
2052 "auto-detection will occur." ),
2054 << QStringLiteral(
"FORCE" )
2055 << QStringLiteral(
"DISABLE" )
2056 << QStringLiteral(
"AUTO" ),
2057 QStringLiteral(
"AUTO" ),
2061 driverMetadata.insert( QStringLiteral(
"XLSX" ),
2063 QStringLiteral(
"MS Office Open XML spreadsheet" ),
2064 QObject::tr(
"MS Office Open XML spreadsheet [XLSX]" ),
2065 QStringLiteral(
"*.xlsx" ),
2066 QStringLiteral(
"xlsx" ),
2069 QStringLiteral(
"UTF-8" )
2074 datasetOptions.clear();
2075 layerOptions.clear();
2078 QObject::tr(
"By default, the driver will try to detect the data type of fields. If set "
2079 "to STRING, all fields will be of String type." ),
2081 << QStringLiteral(
"AUTO" )
2082 << QStringLiteral(
"STRING" ),
2083 QStringLiteral(
"AUTO" ),
2088 QObject::tr(
"By default, the driver will read the first lines of each sheet to detect "
2089 "if the first line might be the name of columns. If set to FORCE, the driver "
2090 "will consider the first line as the header line. If set to "
2091 "DISABLE, it will be considered as the first feature. Otherwise "
2092 "auto-detection will occur." ),
2094 << QStringLiteral(
"FORCE" )
2095 << QStringLiteral(
"DISABLE" )
2096 << QStringLiteral(
"AUTO" ),
2097 QStringLiteral(
"AUTO" ),
2101 driverMetadata.insert( QStringLiteral(
"ODS" ),
2103 QStringLiteral(
"Open Document Spreadsheet" ),
2104 QObject::tr(
"Open Document Spreadsheet [ODS]" ),
2105 QStringLiteral(
"*.ods" ),
2106 QStringLiteral(
"ods" ),
2109 QStringLiteral(
"UTF-8" )
2114 datasetOptions.clear();
2115 layerOptions.clear();
2118 QObject::tr(
"Line termination character sequence." ),
2120 << QStringLiteral(
"CRLF" )
2121 << QStringLiteral(
"LF" ),
2128 QObject::tr(
"Format of geometry columns." ),
2130 << QStringLiteral(
"geometry" )
2131 << QStringLiteral(
"geography" ),
2132 QStringLiteral(
"geometry" ),
2137 QObject::tr(
"Controls whether layer and field names will be laundered for easier use. "
2138 "Laundered names will be converted to lower case and some special "
2139 "characters(' - #) will be changed to underscores." ),
2144 QObject::tr(
"Name for the geometry column. Defaults to wkb_geometry "
2145 "for GEOM_TYPE=geometry or the_geog for GEOM_TYPE=geography" ) ) );
2148 QObject::tr(
"Name of schema into which to create the new table" ) ) );
2151 QObject::tr(
"Whether to explicitly emit the CREATE SCHEMA statement to create the specified schema." ),
2156 QObject::tr(
"Whether to explicitly recreate the table if necessary." ),
2161 QObject::tr(
"Whether to explicitly destroy tables before recreating them." ),
2163 << QStringLiteral(
"YES" )
2164 << QStringLiteral(
"NO" )
2165 << QStringLiteral(
"IF_EXISTS" ),
2166 QStringLiteral(
"YES" ),
2171 QObject::tr(
"Used to force the SRID number of the SRS associated with the layer. "
2172 "When this option isn't specified and that a SRS is associated with the "
2173 "layer, a search is made in the spatial_ref_sys to find a match for the "
2174 "SRS, and, if there is no match, a new entry is inserted for the SRS in "
2175 "the spatial_ref_sys table. When the SRID option is specified, this "
2176 "search (and the eventual insertion of a new entry) will not be done: "
2177 "the specified SRID is used as such." ),
2182 QObject::tr(
"Can be set to 2.0 or 2.2 for PostGIS 2.0/2.2 compatibility. "
2183 "Important to set it correctly if using non-linear geometry types" ),
2187 driverMetadata.insert( QStringLiteral(
"PGDUMP" ),
2189 QStringLiteral(
"PostgreSQL SQL dump" ),
2190 QObject::tr(
"PostgreSQL SQL dump" ),
2191 QStringLiteral(
"*.sql" ),
2192 QStringLiteral(
"sql" ),
2195 QStringLiteral(
"UTF-8" )
2201 QgsVectorFileWriterMetadataContainer(
const QgsVectorFileWriterMetadataContainer &other ) =
delete;
2202 QgsVectorFileWriterMetadataContainer &operator=(
const QgsVectorFileWriterMetadataContainer &other ) =
delete;
2203 ~QgsVectorFileWriterMetadataContainer()
2205 for (
auto it = driverMetadata.constBegin(); it != driverMetadata.constEnd(); ++it )
2207 for (
auto optionIt = it.value().driverOptions.constBegin(); optionIt != it.value().driverOptions.constEnd(); ++optionIt )
2208 delete optionIt.value();
2209 for (
auto optionIt = it.value().layerOptions.constBegin(); optionIt != it.value().layerOptions.constEnd(); ++optionIt )
2210 delete optionIt.value();
2214 QMap<QString, QgsVectorFileWriter::MetaData> driverMetadata;
2221 static QgsVectorFileWriterMetadataContainer sDriverMetadata;
2222 QMap<QString, MetaData>::ConstIterator it = sDriverMetadata.driverMetadata.constBegin();
2224 for ( ; it != sDriverMetadata.driverMetadata.constEnd(); ++it )
2226 if ( it.key() == QLatin1String(
"PGDUMP" ) &&
2227 driverName != QLatin1String(
"PGDUMP" ) &&
2228 driverName != QLatin1String(
"PostgreSQL SQL dump" ) )
2233 if ( it.key().startsWith( driverName ) || it.value().longName.startsWith( driverName ) )
2248 return QStringList();
2257 return QStringList();
2264 OGRwkbGeometryType ogrType =
static_cast<OGRwkbGeometryType
>( type );
2290 QgsFeatureList::iterator fIt = features.begin();
2292 for ( ; fIt != features.end(); ++fIt )
2312 QString styleString;
2313 QString currentStyle;
2315 QgsSymbolList::const_iterator symbolIt = symbols.constBegin();
2316 for ( ; symbolIt != symbols.constEnd(); ++symbolIt )
2318 int nSymbolLayers = ( *symbolIt )->symbolLayerCount();
2319 for (
int i = 0; i < nSymbolLayers; ++i )
2322 QMap< QgsSymbolLayer *, QString >::const_iterator it =
mSymbolLayerTable.find( ( *symbolIt )->symbolLayer( i ) );
2328 double mmsf = mmScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
2329 double musf = mapUnitScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
2331 currentStyle = ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf );
2335 if ( symbolIt != symbols.constBegin() || i != 0 )
2337 styleString.append(
';' );
2339 styleString.append( currentStyle );
2343 OGR_F_SetStyleString( poFeature.get(), currentStyle.toLocal8Bit().constData() );
2344 if ( !writeFeature(
mLayer, poFeature.get() ) )
2351 OGR_F_SetStyleString( poFeature.get(), styleString.toLocal8Bit().constData() );
2356 if ( !writeFeature(
mLayer, poFeature.get() ) )
2373 if ( fid > std::numeric_limits<int>::max() )
2375 QgsDebugMsg( QStringLiteral(
"feature id %1 too large." ).arg( fid ) );
2376 OGRErr err = OGR_F_SetFID( poFeature.get(),
static_cast<long>( fid ) );
2377 if ( err != OGRERR_NONE )
2379 QgsDebugMsg( QStringLiteral(
"Failed to set feature id to %1: %2 (OGR error: %3)" )
2380 .arg( feature.
id() )
2381 .arg( err ).arg( CPLGetLastErrorMsg() )
2389 int fldIdx = it.key();
2390 int ogrField = it.value();
2392 QVariant attrValue = feature.
attribute( fldIdx );
2395 if ( !attrValue.isValid() || attrValue.isNull() )
2404 #ifdef OGRNullMarker
2405 OGR_F_SetFieldNull( poFeature.get(), ogrField );
2416 switch ( field.
type() )
2419 OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
2421 case QVariant::LongLong:
2422 OGR_F_SetFieldInteger64( poFeature.get(), ogrField, attrValue.toLongLong() );
2424 case QVariant::Bool:
2425 OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
2427 case QVariant::String:
2428 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toString() ).constData() );
2430 case QVariant::Double:
2431 OGR_F_SetFieldDouble( poFeature.get(), ogrField, attrValue.toDouble() );
2433 case QVariant::Date:
2434 OGR_F_SetFieldDateTime( poFeature.get(), ogrField,
2435 attrValue.toDate().year(),
2436 attrValue.toDate().month(),
2437 attrValue.toDate().day(),
2440 case QVariant::DateTime:
2443 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toDateTime().toString( QStringLiteral(
"yyyy/MM/dd hh:mm:ss.zzz" ) ) ).constData() );
2447 OGR_F_SetFieldDateTime( poFeature.get(), ogrField,
2448 attrValue.toDateTime().date().year(),
2449 attrValue.toDateTime().date().month(),
2450 attrValue.toDateTime().date().day(),
2451 attrValue.toDateTime().time().hour(),
2452 attrValue.toDateTime().time().minute(),
2453 attrValue.toDateTime().time().second(),
2457 case QVariant::Time:
2460 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toString() ).constData() );
2464 OGR_F_SetFieldDateTime( poFeature.get(), ogrField,
2466 attrValue.toTime().hour(),
2467 attrValue.toTime().minute(),
2468 attrValue.toTime().second(),
2473 case QVariant::ByteArray:
2475 const QByteArray ba = attrValue.toByteArray();
2476 OGR_F_SetFieldBinary( poFeature.get(), ogrField, ba.size(),
const_cast< GByte *
>(
reinterpret_cast< const GByte *
>( ba.data() ) ) );
2480 case QVariant::Invalid:
2483 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,4,0)
2484 case QVariant::List:
2486 if ( field.
subType() == QVariant::String )
2488 QStringList list = attrValue.toStringList();
2489 if ( supportsStringList )
2491 int count = list.count();
2492 char **lst =
new char *[count + 1];
2496 for ( QString
string : list )
2498 lst[pos] =
mCodec->fromUnicode(
string ).data();
2502 lst[count] =
nullptr;
2503 OGR_F_SetFieldStringList( poFeature.get(), ogrField, lst );
2507 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( list.join(
',' ) ).constData() );
2516 mErrorMessage = QObject::tr(
"Invalid variant type for field %1[%2]: received %3 with type %4" )
2519 .arg( attrValue.typeName(),
2520 attrValue.toString() );
2533 if ( mCoordinateTransform )
2538 geom.
transform( *mCoordinateTransform );
2556 OGRGeometryH mGeom2 =
nullptr;
2602 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
2603 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
2609 QByteArray wkb( geom.
asWkb() );
2610 OGRErr err = OGR_G_ImportFromWkb( mGeom2,
reinterpret_cast<unsigned char *
>(
const_cast<char *
>( wkb.constData() ) ), wkb.length() );
2611 if ( err != OGRERR_NONE )
2613 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
2614 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
2621 OGR_F_SetGeometryDirectly( poFeature.get(), mGeom2 );
2627 OGRErr err = OGR_G_ImportFromWkb( ogrGeom,
reinterpret_cast<unsigned char *
>(
const_cast<char *
>( wkb.constData() ) ), wkb.length() );
2628 if ( err != OGRERR_NONE )
2630 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
2631 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
2638 OGR_F_SetGeometryDirectly( poFeature.get(), ogrGeom );
2653 for (
int i = 0; i < attributes.size(); i++ )
2655 if ( omap.find( i ) != omap.end() )
2660 bool QgsVectorFileWriter::writeFeature( OGRLayerH layer, OGRFeatureH feature )
2662 if ( OGR_L_CreateFeature( layer, feature ) != OGRERR_NONE )
2664 mErrorMessage = QObject::tr(
"Feature creation error (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
2674 if ( mUsingTransaction )
2676 if ( OGRERR_NONE != OGR_L_CommitTransaction(
mLayer ) )
2678 QgsDebugMsg( QStringLiteral(
"Error while committing transaction on OGRLayer." ) );
2686 OSRDestroySpatialReference(
mOgrRef );
2692 const QString &fileName,
2693 const QString &fileEncoding,
2695 const QString &driverName,
2697 QString *errorMessage,
2698 const QStringList &datasourceOptions,
2699 const QStringList &layerOptions,
2700 bool skipAttributeCreation,
2701 QString *newFilename,
2703 double symbologyScale,
2713 if ( destCRS.
isValid() && layer )
2739 const QString &fileName,
2740 const QString &fileEncoding,
2742 const QString &driverName,
2744 QString *errorMessage,
2745 const QStringList &datasourceOptions,
2746 const QStringList &layerOptions,
2747 bool skipAttributeCreation,
2748 QString *newFilename,
2750 double symbologyScale,
2781 : driverName( QStringLiteral(
"GPKG" ) )
2789 if ( !layer || !layer->
isValid() )
2796 details.sourceCrs = layer->
crs();
2797 details.sourceWkbType = layer->
wkbType();
2798 details.sourceFields = layer->
fields();
2807 if ( details.storageType == QLatin1String(
"ESRI Shapefile" ) )
2815 details.geometryTypeScanIterator = layer->
getFeatures( req );
2819 details.renderContext.setExpressionContext( details.expressionContext );
2820 details.renderContext.setRendererScale( options.
symbologyScale );
2822 details.shallTransform =
false;
2827 details.shallTransform =
true;
2832 details.outputCrs = details.sourceCrs;
2835 details.destWkbType = details.sourceWkbType;
2849 details.attributes.clear();
2850 else if ( details.attributes.isEmpty() )
2852 const QgsAttributeList allAttributes = details.sourceFields.allAttributesList();
2853 for (
int idx : allAttributes )
2855 QgsField fld = details.sourceFields.at( idx );
2856 if ( details.providerType == QLatin1String(
"oracle" ) && fld.
typeName().contains( QLatin1String(
"SDO_GEOMETRY" ) ) )
2858 details.attributes.append( idx );
2862 if ( !details.attributes.isEmpty() )
2864 for (
int attrIdx : qgis::as_const( details.attributes ) )
2866 details.outputFields.append( details.sourceFields.at( attrIdx ) );
2872 if ( details.providerType == QLatin1String(
"spatialite" ) )
2874 for (
int i = 0; i < details.outputFields.size(); i++ )
2876 if ( details.outputFields.at( i ).type() == QVariant::LongLong )
2880 if ( std::max( std::llabs( min.toLongLong() ), std::llabs( max.toLongLong() ) ) < std::numeric_limits<int>::max() )
2882 details.outputFields[i].setType( QVariant::Int );
2890 addRendererAttributes( details.renderer.get(), details.renderContext, details.sourceFields, details.attributes );
2900 bool useFilterRect =
true;
2901 if ( details.shallTransform )
2910 useFilterRect =
false;
2913 if ( useFilterRect )
2919 details.filterRectEngine->prepareGeometry();
2921 details.sourceFeatureIterator = layer->
getFeatures( req );
2935 int lastProgressReport = 0;
2936 long total = details.featureCount;
2939 if ( details.providerType == QLatin1String(
"ogr" ) && !details.dataSourceUri.isEmpty() )
2941 QString srcFileName( details.providerUriParams.value( QLatin1String(
"path" ) ).toString() );
2942 if ( QFile::exists( srcFileName ) && QFileInfo( fileName ).canonicalFilePath() == QFileInfo( srcFileName ).canonicalFilePath() )
2946 if ( !( ( options.
driverName == QLatin1String(
"GPKG" ) ||
2947 options.
driverName == QLatin1String(
"SpatiaLite" ) ||
2948 options.
driverName == QLatin1String(
"SQLite" ) ) &&
2949 options.
layerName != details.providerUriParams.value( QLatin1String(
"layerName" ) ) ) )
2952 *
errorMessage = QObject::tr(
"Cannot overwrite a OGR layer in place" );
2972 int newProgress =
static_cast<int>( ( 5.0 * scanned ) / total );
2973 if ( newProgress != lastProgressReport )
2975 lastProgressReport = newProgress;
2990 std::unique_ptr< QgsVectorFileWriter > writer(
create( fileName, details.outputFields, destWkbType, details.outputCrs, transformContext, options,
nullptr, newFilename, newLayer ) );
3031 int n = 0, errors = 0;
3040 writer->startRender( details.renderer.get(), details.sourceFields );
3042 writer->resetMap( details.attributes );
3044 writer->mFields = details.sourceFields;
3048 int initialProgress = lastProgressReport;
3049 while ( details.sourceFeatureIterator.nextFeature( fet ) )
3060 int newProgress =
static_cast<int>( initialProgress + ( ( 100.0 - initialProgress ) * saved ) / total );
3061 if ( newProgress < 100 && newProgress != lastProgressReport )
3063 lastProgressReport = newProgress;
3068 if ( details.shallTransform )
3081 QString msg = QObject::tr(
"Failed to transform a point while drawing a feature with ID '%1'. Writing stopped. (Exception: %2)" )
3082 .arg( fet.
id() ).arg( e.
what() );
3099 if ( !writer->addFeatureWithStyle( fet, writer->mRenderer.get(), mapUnits ) )
3106 *
errorMessage = QObject::tr(
"Feature write errors:" );
3112 if ( errors > 1000 )
3116 *
errorMessage += QObject::tr(
"Stopping after %1 errors" ).arg( errors );
3126 writer->stopRender();
3130 *
errorMessage += QObject::tr(
"\nOnly %1 of %2 features written." ).arg( n - errors ).arg( n );
3137 const QString &fileName,
3139 QString *newFilename,
3143 QgsVectorFileWriter::PreparedWriterDetails details;
3144 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
3152 const QString &fileName,
3155 QString *newFilename,
3159 QgsVectorFileWriter::PreparedWriterDetails details;
3160 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
3169 QFileInfo fi( fileName );
3170 QDir dir = fi.dir();
3173 const char *suffixes[] = {
".shp",
".shx",
".dbf",
".prj",
".qix",
".qpj",
".cpg",
".sbn",
".sbx",
".idm",
".ind" };
3174 for ( std::size_t i = 0; i <
sizeof( suffixes ) /
sizeof( *suffixes ); i++ )
3176 filter << fi.completeBaseName() + suffixes[i];
3180 const auto constEntryList = dir.entryList( filter );
3181 for (
const QString &file : constEntryList )
3183 QFile f( dir.canonicalPath() +
'/' + file );
3186 QgsDebugMsg( QStringLiteral(
"Removing file %1 failed: %2" ).arg( file, f.errorString() ) );
3202 QList< FilterFormatDetails > results;
3205 int const drvCount = OGRGetDriverCount();
3207 for (
int i = 0; i < drvCount; ++i )
3209 OGRSFDriverH drv = OGRGetDriver( i );
3212 QString drvName = OGR_Dr_GetName( drv );
3214 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,3,0)
3215 GDALDriverH gdalDriver = GDALGetDriverByName( drvName.toLocal8Bit().constData() );
3216 char **metadata =
nullptr;
3219 metadata = GDALGetMetadata( gdalDriver,
nullptr );
3222 bool nonSpatialFormat = CSLFetchBoolean( metadata, GDAL_DCAP_NONSPATIAL,
false );
3224 bool nonSpatialFormat = ( drvName == QLatin1String(
"ODS" ) || drvName == QLatin1String(
"XLSX" ) || drvName == QLatin1String(
"XLS" ) );
3227 if ( OGR_Dr_TestCapability( drv,
"CreateDataSource" ) != 0 )
3232 if ( nonSpatialFormat )
3237 if ( filterString.isEmpty() )
3244 globs = metadata.
glob.toLower().split(
' ' );
3250 details.
globs = globs;
3259 if ( options & SortRecommended )
3261 if ( a.driverName == QLatin1String(
"GPKG" ) )
3263 else if ( b.driverName == QLatin1String(
"GPKG" ) )
3265 else if ( a.driverName == QLatin1String(
"ESRI Shapefile" ) )
3267 else if ( b.driverName == QLatin1String(
"ESRI Shapefile" ) )
3280 QSet< QString > extensions;
3282 const QRegularExpression rx( QStringLiteral(
"\\*\\.(.*)$" ) );
3286 for (
const QString &glob : format.globs )
3288 const QRegularExpressionMatch match = rx.match( glob );
3289 if ( !match.hasMatch() )
3292 const QString matched = match.captured( 1 );
3293 extensions.insert( matched );
3297 QStringList extensionList = qgis::setToList( extensions );
3299 std::sort( extensionList.begin(), extensionList.end(), [options](
const QString & a,
const QString & b ) ->
bool
3301 if ( options & SortRecommended )
3303 if ( a == QLatin1String(
"gpkg" ) )
3305 else if ( b == QLatin1String(
"gpkg" ) )
3307 else if ( a == QLatin1String(
"shp" ) )
3309 else if ( b == QLatin1String(
"shp" ) )
3313 return a.toLower().localeAwareCompare( b.toLower() ) < 0;
3316 return extensionList;
3321 QList< QgsVectorFileWriter::DriverDetails > results;
3324 const int drvCount = OGRGetDriverCount();
3326 QStringList writableDrivers;
3327 for (
int i = 0; i < drvCount; ++i )
3329 OGRSFDriverH drv = OGRGetDriver( i );
3332 QString drvName = OGR_Dr_GetName( drv );
3338 if ( drvName == QLatin1String(
"ODS" ) || drvName == QLatin1String(
"XLSX" ) || drvName == QLatin1String(
"XLS" ) )
3342 if ( drvName == QLatin1String(
"ESRI Shapefile" ) )
3344 writableDrivers << QStringLiteral(
"DBF file" );
3346 if ( OGR_Dr_TestCapability( drv,
"CreateDataSource" ) != 0 )
3349 if ( drvName == QLatin1String(
"MapInfo File" ) )
3351 writableDrivers << QStringLiteral(
"MapInfo MIF" );
3353 else if ( drvName == QLatin1String(
"SQLite" ) )
3360 QString option = QStringLiteral(
"SPATIALITE=YES" );
3361 char *options[2] = { CPLStrdup( option.toLocal8Bit().constData() ),
nullptr };
3362 OGRSFDriverH poDriver;
3364 poDriver = OGRGetDriverByName( drvName.toLocal8Bit().constData() );
3367 gdal::ogr_datasource_unique_ptr ds( OGR_Dr_CreateDataSource( poDriver, QStringLiteral(
"/vsimem/spatialitetest.sqlite" ).toUtf8().constData(), options ) );
3370 writableDrivers << QStringLiteral(
"SpatiaLite" );
3371 OGR_Dr_DeleteDataSource( poDriver, QStringLiteral(
"/vsimem/spatialitetest.sqlite" ).toUtf8().constData() );
3374 CPLFree( options[0] );
3376 writableDrivers << drvName;
3381 results.reserve( writableDrivers.count() );
3382 for (
const QString &drvName : qgis::as_const( writableDrivers ) )
3396 if ( options & SortRecommended )
3398 if ( a.driverName == QLatin1String(
"GPKG" ) )
3400 else if ( b.driverName == QLatin1String(
"GPKG" ) )
3402 else if ( a.driverName == QLatin1String(
"ESRI Shapefile" ) )
3404 else if ( b.driverName == QLatin1String(
"ESRI Shapefile" ) )
3408 return a.
longName.toLower().localeAwareCompare( b.
longName.toLower() ) < 0;
3415 QString ext = extension.trimmed();
3416 if ( ext.isEmpty() )
3419 if ( ext.startsWith(
'.' ) )
3423 int const drvCount = GDALGetDriverCount();
3425 for (
int i = 0; i < drvCount; ++i )
3427 GDALDriverH drv = GDALGetDriver( i );
3433 QString drvName = GDALGetDriverShortName( drv );
3434 QStringList driverExtensions = QString( GDALGetMetadataItem( drv, GDAL_DMD_EXTENSIONS,
nullptr ) ).split(
' ' );
3436 const auto constDriverExtensions = driverExtensions;
3437 for (
const QString &driver : constDriverExtensions )
3439 if ( driver.compare( ext, Qt::CaseInsensitive ) == 0 )
3450 QString filterString;
3454 if ( !filterString.isEmpty() )
3455 filterString += QLatin1String(
";;" );
3457 filterString += details.filterString;
3459 return filterString;
3468 return QStringLiteral(
"%1 (%2 %3)" ).arg( metadata.
trLongName,
3469 metadata.
glob.toLower(),
3470 metadata.
glob.toUpper() );
3475 if ( codecName == QLatin1String(
"System" ) )
3476 return QStringLiteral(
"LDID/0" );
3478 QRegExp re = QRegExp( QString(
"(CP|windows-|ISO[ -])(.+)" ), Qt::CaseInsensitive );
3479 if ( re.exactMatch( codecName ) )
3481 QString
c = re.cap( 2 ).remove(
'-' );
3483 ( void )
c.toInt( &isNumber );
3511 OGRStyleTableH ogrStyleTable = OGR_STBL_Create();
3512 OGRStyleMgrH styleManager = OGR_SM_Create( ogrStyleTable );
3515 int nTotalLevels = 0;
3517 QgsSymbolList::iterator symbolIt = symbolList.begin();
3518 for ( ; symbolIt != symbolList.end(); ++symbolIt )
3520 double mmsf = mmScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
3521 double musf = mapUnitScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
3523 int nLevels = ( *symbolIt )->symbolLayerCount();
3524 for (
int i = 0; i < nLevels; ++i )
3526 mSymbolLayerTable.insert( ( *symbolIt )->symbolLayer( i ), QString::number( nTotalLevels ) );
3527 OGR_SM_AddStyle( styleManager, QString::number( nTotalLevels ).toLocal8Bit(),
3528 ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf ).toLocal8Bit() );
3532 OGR_DS_SetStyleTableDirectly( ds, ogrStyleTable );
3538 if ( !details.renderer )
3543 QHash< QgsSymbol *, QList<QgsFeature> > features;
3552 startRender( details.renderer.get(), details.sourceFields );
3572 QString msg = QObject::tr(
"Failed to transform, writing stopped. (Exception: %1)" )
3583 featureSymbol = mRenderer->symbolForFeature( fet, mRenderContext );
3584 if ( !featureSymbol )
3589 QHash< QgsSymbol *, QList<QgsFeature> >::iterator it = features.find( featureSymbol );
3590 if ( it == features.end() )
3592 it = features.insert( featureSymbol, QList<QgsFeature>() );
3594 it.value().append( fet );
3599 QgsSymbolList symbols = mRenderer->symbols( mRenderContext );
3600 for (
int i = 0; i < symbols.count(); i++ )
3606 if ( level < 0 || level >= 1000 )
3609 while ( level >= levels.count() )
3611 levels[level].append( item );
3616 int nTotalFeatures = 0;
3619 for (
int l = 0; l < levels.count(); l++ )
3622 for (
int i = 0; i < level.count(); i++ )
3625 QHash< QgsSymbol *, QList<QgsFeature> >::iterator levelIt = features.find( item.
symbol() );
3626 if ( levelIt == features.end() )
3632 double mmsf = mmScaleFactor(
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
3633 double musf = mapUnitScaleFactor(
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
3635 int llayer = item.
layer();
3636 QList<QgsFeature> &featureList = levelIt.value();
3637 QList<QgsFeature>::iterator featureIt = featureList.begin();
3638 for ( ; featureIt != featureList.end(); ++featureIt )
3648 QString styleString = levelIt.key()->symbolLayer( llayer )->ogrFeatureStyle( mmsf, musf );
3649 if ( !styleString.isEmpty() )
3651 OGR_F_SetStyleString( ogrFeature.get(), styleString.toLocal8Bit().constData() );
3652 if ( !writeFeature(
mLayer, ogrFeature.get() ) )
3665 *
errorMessage += QObject::tr(
"\nOnly %1 of %2 features written." ).arg( nTotalFeatures - nErrors ).arg( nTotalFeatures );
3682 return 1000 / scale;
3699 return scale / 1000;
3707 mRenderer = createSymbologyRenderer( sourceRenderer );
3713 mRenderer->startRender( mRenderContext, fields );
3716 void QgsVectorFileWriter::stopRender()
3723 mRenderer->stopRender( mRenderContext );
3726 std::unique_ptr<QgsFeatureRenderer> QgsVectorFileWriter::createSymbologyRenderer(
QgsFeatureRenderer *sourceRenderer )
const
3732 if ( !sourceRenderer )
3737 return std::unique_ptr< QgsFeatureRenderer >( sourceRenderer->
clone() );
3744 const QSet<QString> rendererAttributes = renderer->
usedAttributes( context );
3745 for (
const QString &attr : rendererAttributes )
3750 attList.append( index );
3756 QStringList QgsVectorFileWriter::concatenateOptions(
const QMap<QString, QgsVectorFileWriter::Option *> &options )
3759 QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
3761 for ( it = options.constBegin(); it != options.constEnd(); ++it )
3764 switch ( option->
type )
3771 list.append( QStringLiteral(
"%1=%2" ).arg( it.key() ).arg( opt->
defaultValue ) );
3781 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
defaultValue ) );
3791 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
defaultValue ) );
3800 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
mValue ) );
3811 OGRSFDriverH hDriver =
nullptr;
3815 QString drvName = OGR_Dr_GetName( hDriver );
3816 QgsVectorFileWriter::EditionCapabilities caps =
nullptr;
3817 if ( OGR_DS_TestCapability( hDS.get(), ODsCCreateLayer ) )
3822 if ( !( drvName == QLatin1String(
"ESRI Shapefile" ) && QFile::exists( datasetName ) ) )
3825 if ( OGR_DS_TestCapability( hDS.get(), ODsCDeleteLayer ) )
3829 int layer_count = OGR_DS_GetLayerCount( hDS.get() );
3832 OGRLayerH hLayer = OGR_DS_GetLayer( hDS.get(), 0 );
3835 if ( OGR_L_TestCapability( hLayer, OLCSequentialWrite ) )
3838 if ( OGR_L_TestCapability( hLayer, OLCCreateField ) )
3849 const QString &layerNameIn )
3851 OGRSFDriverH hDriver =
nullptr;
3856 QString layerName( layerNameIn );
3857 if ( layerName.isEmpty() )
3858 layerName = QFileInfo( datasetName ).baseName();
3860 return OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
3865 const QString &layerName,
3869 OGRSFDriverH hDriver =
nullptr;
3873 OGRLayerH hLayer = OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
3879 OGRFeatureDefnH defn = OGR_L_GetLayerDefn( hLayer );
3880 const auto constAttributes = attributes;
3881 for (
int idx : constAttributes )
3884 if ( OGR_FD_GetFieldIndex( defn, fld.
name().toUtf8().constData() ) < 0 )