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,
114 init( vectorFileName, fileEncoding, fields, geometryType,
115 srs, driverName, datasourceOptions, layerOptions, newFilename,
nullptr,
120 const QString &fileEncoding,
124 const QString &driverName,
125 const QStringList &datasourceOptions,
126 const QStringList &layerOptions,
127 QString *newFilename,
130 const QString &layerName,
138 init( vectorFileName, fileEncoding, fields, geometryType, srs, driverName,
139 datasourceOptions, layerOptions, newFilename, fieldValueConverter,
140 layerName, action, newLayer,
nullptr );
145 if ( driverName == QLatin1String(
"MapInfo MIF" ) )
149 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,3,0) 150 GDALDriverH gdalDriver = GDALGetDriverByName( driverName.toLocal8Bit().constData() );
155 if ( !driverMetadata )
158 return CSLFetchBoolean( driverMetadata, GDAL_DCAP_FEATURE_STYLES,
false );
160 return driverName == QLatin1String(
"DXF" ) || driverName == QLatin1String(
"KML" ) || driverName == QLatin1String(
"MapInfo File" );
164 void QgsVectorFileWriter::init( QString vectorFileName,
165 QString fileEncoding,
169 const QString &driverName,
170 QStringList datasourceOptions,
171 QStringList layerOptions,
172 QString *newFilename,
174 const QString &layerNameIn,
176 QString *newLayer, SinkFlags sinkFlags )
180 if ( vectorFileName.isEmpty() )
187 if ( driverName == QLatin1String(
"MapInfo MIF" ) )
191 else if ( driverName == QLatin1String(
"SpatiaLite" ) )
194 if ( !datasourceOptions.contains( QStringLiteral(
"SPATIALITE=YES" ) ) )
196 datasourceOptions.append( QStringLiteral(
"SPATIALITE=YES" ) );
199 else if ( driverName == QLatin1String(
"DBF file" ) )
202 if ( !layerOptions.contains( QStringLiteral(
"SHPT=NULL" ) ) )
204 layerOptions.append( QStringLiteral(
"SHPT=NULL" ) );
214 OGRSFDriverH poDriver;
217 poDriver = OGRGetDriverByName(
mOgrDriverName.toLocal8Bit().constData() );
221 mErrorMessage = QObject::tr(
"OGR driver for '%1' not found (OGR error: %2)" )
223 QString::fromUtf8( CPLGetLastErrorMsg() ) );
233 if ( layerOptions.join( QString() ).toUpper().indexOf( QLatin1String(
"ENCODING=" ) ) == -1 )
238 if ( driverName == QLatin1String(
"ESRI Shapefile" ) && !vectorFileName.endsWith( QLatin1String(
".shp" ), Qt::CaseInsensitive ) )
240 vectorFileName += QLatin1String(
".shp" );
242 else if ( driverName == QLatin1String(
"DBF file" ) && !vectorFileName.endsWith( QLatin1String(
".dbf" ), Qt::CaseInsensitive ) )
244 vectorFileName += QLatin1String(
".dbf" );
254 QStringList allExts = metadata.
ext.split(
' ', QString::SkipEmptyParts );
256 const auto constAllExts = allExts;
257 for (
const QString &ext : constAllExts )
259 if ( vectorFileName.endsWith(
'.' + ext, Qt::CaseInsensitive ) )
268 vectorFileName +=
'.' + allExts[0];
274 if ( vectorFileName.endsWith( QLatin1String(
".gdb" ), Qt::CaseInsensitive ) )
276 QDir dir( vectorFileName );
279 QFileInfoList fileList = dir.entryInfoList(
280 QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files, QDir::DirsFirst );
281 const auto constFileList = fileList;
282 for (
const QFileInfo &info : constFileList )
284 QFile::remove( info.absoluteFilePath() );
287 QDir().rmdir( vectorFileName );
291 QFile::remove( vectorFileName );
306 char **options =
nullptr;
307 if ( !datasourceOptions.isEmpty() )
309 options =
new char *[ datasourceOptions.size() + 1 ];
310 for (
int i = 0; i < datasourceOptions.size(); i++ )
312 QgsDebugMsg( QStringLiteral(
"-dsco=%1" ).arg( datasourceOptions[i] ) );
313 options[i] = CPLStrdup( datasourceOptions[i].toLocal8Bit().constData() );
315 options[ datasourceOptions.size()] =
nullptr;
321 mDS.reset( OGR_Dr_CreateDataSource( poDriver, vectorFileName.toUtf8().constData(), options ) );
323 mDS.reset( myOGROpen( vectorFileName.toUtf8().constData(), TRUE, nullptr ) );
327 for (
int i = 0; i < datasourceOptions.size(); i++ )
328 CPLFree( options[i] );
337 mErrorMessage = QObject::tr(
"Creation of data source failed (OGR error: %1)" )
338 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
340 mErrorMessage = QObject::tr(
"Opening of data source in update mode failed (OGR error: %1)" )
341 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
345 QString layerName( layerNameIn );
346 if ( layerName.isEmpty() )
347 layerName = QFileInfo( vectorFileName ).baseName();
351 const int layer_count = OGR_DS_GetLayerCount(
mDS.get() );
352 for (
int i = 0; i < layer_count; i++ )
354 OGRLayerH hLayer = OGR_DS_GetLayer(
mDS.get(), i );
355 if ( EQUAL( OGR_L_GetName( hLayer ), layerName.toUtf8().constData() ) )
357 if ( OGR_DS_DeleteLayer(
mDS.get(), i ) != OGRERR_NONE )
360 mErrorMessage = QObject::tr(
"Overwriting of existing layer failed (OGR error: %1)" )
361 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
371 QgsDebugMsg( QStringLiteral(
"Created data source" ) );
375 QgsDebugMsg( QStringLiteral(
"Opened data source in update mode" ) );
379 mCodec = QTextCodec::codecForName( fileEncoding.toLocal8Bit().constData() );
382 QgsDebugMsg(
"error finding QTextCodec for " + fileEncoding );
385 QString enc = settings.
value( QStringLiteral(
"UI/encoding" ),
"System" ).toString();
386 mCodec = QTextCodec::codecForName( enc.toLocal8Bit().constData() );
389 QgsDebugMsg(
"error finding QTextCodec for " + enc );
390 mCodec = QTextCodec::codecForLocale();
398 QString srsWkt = srs.
toWkt();
400 mOgrRef = OSRNewSpatialReference( srsWkt.toLocal8Bit().constData() );
407 int optIndex = layerOptions.indexOf( QStringLiteral(
"FEATURE_DATASET=" ) );
408 if ( optIndex != -1 )
410 layerOptions.removeAt( optIndex );
413 if ( !layerOptions.isEmpty() )
415 options =
new char *[ layerOptions.size() + 1 ];
416 for (
int i = 0; i < layerOptions.size(); i++ )
418 QgsDebugMsg( QStringLiteral(
"-lco=%1" ).arg( layerOptions[i] ) );
419 options[i] = CPLStrdup( layerOptions[i].toLocal8Bit().constData() );
421 options[ layerOptions.size()] =
nullptr;
425 CPLSetConfigOption(
"SHAPE_ENCODING",
"" );
429 mLayer = OGR_DS_CreateLayer(
mDS.get(), layerName.toUtf8().constData(),
mOgrRef, wkbType, options );
432 *newLayer = OGR_L_GetName(
mLayer );
433 if ( driverName == QLatin1String(
"GPX" ) )
440 if ( !EQUAL( layerName.toUtf8().constData(),
"track_points" ) &&
441 !EQUAL( layerName.toUtf8().constData(),
"route_points" ) )
443 *newLayer = QStringLiteral(
"waypoints" );
450 const char *pszForceGPXTrack
451 = CSLFetchNameValue( options,
"FORCE_GPX_TRACK" );
452 if ( pszForceGPXTrack && CPLTestBool( pszForceGPXTrack ) )
453 *newLayer = QStringLiteral(
"tracks" );
455 *newLayer = QStringLiteral(
"routes" );
462 const char *pszForceGPXRoute
463 = CSLFetchNameValue( options,
"FORCE_GPX_ROUTE" );
464 if ( pszForceGPXRoute && CPLTestBool( pszForceGPXRoute ) )
465 *newLayer = QStringLiteral(
"routes" );
467 *newLayer = QStringLiteral(
"tracks" );
477 else if ( driverName == QLatin1String(
"DGN" ) )
479 mLayer = OGR_DS_GetLayerByName(
mDS.get(),
"elements" );
483 mLayer = OGR_DS_GetLayerByName(
mDS.get(), layerName.toUtf8().constData() );
488 for (
int i = 0; i < layerOptions.size(); i++ )
489 CPLFree( options[i] );
495 if ( !settings.
value( QStringLiteral(
"qgis/ignoreShapeEncoding" ),
true ).toBool() )
497 CPLSetConfigOption(
"SHAPE_ENCODING",
nullptr );
504 QString layerName = vectorFileName.left( vectorFileName.indexOf( QLatin1String(
".shp" ), Qt::CaseInsensitive ) );
505 QFile prjFile( layerName +
".qpj" );
506 if ( prjFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
508 QTextStream prjStream( &prjFile );
509 prjStream << srs.
toWkt().toLocal8Bit().constData() << endl;
514 QgsDebugMsg(
"Couldn't open file " + layerName +
".qpj" );
522 mErrorMessage = QObject::tr(
"Creation of layer failed (OGR error: %1)" )
523 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
525 mErrorMessage = QObject::tr(
"Opening of layer failed (OGR error: %1)" )
526 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
531 OGRFeatureDefnH defn = OGR_L_GetLayerDefn(
mLayer );
536 QgsDebugMsg(
"creating " + QString::number( fields.
size() ) +
" fields" );
540 QSet<int> existingIdxs;
550 for (
int fldIdx = 0; fldIdx < fields.
count(); ++fldIdx )
554 if ( fieldValueConverter )
559 QString name( attrField.
name() );
562 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( name ) );
570 OGRFieldType ogrType = OFTString;
571 int ogrWidth = attrField.
length();
572 int ogrPrecision = attrField.
precision();
573 if ( ogrPrecision > 0 )
576 switch ( attrField.
type() )
578 case QVariant::LongLong:
580 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
581 if ( pszDataTypes && strstr( pszDataTypes,
"Integer64" ) )
582 ogrType = OFTInteger64;
585 ogrWidth = ogrWidth > 0 && ogrWidth <= 20 ? ogrWidth : 20;
589 case QVariant::String:
591 if ( ( ogrWidth <= 0 || ogrWidth > 255 ) &&
mOgrDriverName == QLatin1String(
"ESRI Shapefile" ) )
596 ogrType = OFTInteger;
597 ogrWidth = ogrWidth > 0 && ogrWidth <= 10 ? ogrWidth : 10;
602 ogrType = OFTInteger;
607 case QVariant::Double:
627 case QVariant::DateTime:
635 ogrType = OFTDateTime;
639 case QVariant::ByteArray:
643 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,4,0) 646 if ( attrField.
subType() == QVariant::String )
648 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
649 if ( pszDataTypes && strstr( pszDataTypes,
"StringList" ) )
651 ogrType = OFTStringList;
652 supportsStringList =
true;
667 mErrorMessage = QObject::tr(
"Unsupported type for field %1" )
668 .arg( attrField.
name() );
673 if (
mOgrDriverName == QLatin1String(
"SQLite" ) && name.compare( QLatin1String(
"ogc_fid" ), Qt::CaseInsensitive ) == 0 )
676 for ( i = 0; i < 10; i++ )
678 name = QStringLiteral(
"ogc_fid%1" ).arg( i );
681 for ( j = 0; j < fields.
size() && name.compare( fields.
at( j ).
name(), Qt::CaseInsensitive ) != 0; j++ )
684 if ( j == fields.
size() )
690 mErrorMessage = QObject::tr(
"No available replacement for internal fieldname ogc_fid found" ).arg( attrField.
name() );
695 QgsMessageLog::logMessage( QObject::tr(
"Reserved attribute name ogc_fid replaced with %1" ).arg( name ), QObject::tr(
"OGR" ) );
702 OGR_Fld_SetWidth( fld.get(), ogrWidth );
705 if ( ogrPrecision >= 0 )
707 OGR_Fld_SetPrecision( fld.get(), ogrPrecision );
710 switch ( attrField.
type() )
713 OGR_Fld_SetSubType( fld.get(), OFSTBoolean );
721 " type " + QString( QVariant::typeToName( attrField.
type() ) ) +
722 " width " + QString::number( ogrWidth ) +
723 " precision " + QString::number( ogrPrecision ) );
724 if ( OGR_L_CreateField(
mLayer, fld.get(), true ) != OGRERR_NONE )
727 mErrorMessage = QObject::tr(
"Creation of field %1 failed (OGR error: %2)" )
728 .arg( attrField.
name(),
729 QString::fromUtf8( CPLGetLastErrorMsg() ) );
734 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( name ) );
735 QgsDebugMsg( QStringLiteral(
"returned field index for %1: %2" ).arg( name ).arg( ogrIdx ) );
736 if ( ogrIdx < 0 || existingIdxs.contains( ogrIdx ) )
739 ogrIdx = OGR_FD_GetFieldCount( defn ) - 1;
744 mErrorMessage = QObject::tr(
"Created field %1 not found (OGR error: %2)" )
745 .arg( attrField.
name(),
746 QString::fromUtf8( CPLGetLastErrorMsg() ) );
752 existingIdxs.insert( ogrIdx );
760 for (
int fldIdx = 0; fldIdx < fields.
count(); ++fldIdx )
763 QString name( attrField.
name() );
764 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( name ) );
776 int fidIdx = fields.
lookupField( QStringLiteral(
"FID" ) );
782 QgsDebugMsg( QStringLiteral(
"Done creating fields" ) );
787 *newFilename = vectorFileName;
790 mUsingTransaction =
true;
791 if ( OGRERR_NONE != OGR_L_StartTransaction(
mLayer ) )
793 mUsingTransaction =
false;
803 class QgsVectorFileWriterMetadataContainer
807 QgsVectorFileWriterMetadataContainer()
809 QMap<QString, QgsVectorFileWriter::Option *> datasetOptions;
810 QMap<QString, QgsVectorFileWriter::Option *> layerOptions;
813 datasetOptions.clear();
814 layerOptions.clear();
818 QStringLiteral(
"Arc/Info ASCII Coverage" ),
819 QObject::tr(
"Arc/Info ASCII Coverage" ),
820 QStringLiteral(
"*.e00" ),
821 QStringLiteral(
"e00" ),
828 datasetOptions.clear();
829 layerOptions.clear();
832 QObject::tr(
"New BNA files are created by the " 833 "systems default line termination conventions. " 834 "This may be overridden here." ),
836 << QStringLiteral(
"CRLF" )
837 << QStringLiteral(
"LF" ),
843 QObject::tr(
"By default, BNA files are created in multi-line format. " 844 "For each record, the first line contains the identifiers and the " 845 "type/number of coordinates to follow. Each following line contains " 846 "a pair of coordinates." ),
851 QObject::tr(
"BNA records may contain from 2 to 4 identifiers per record. " 852 "Some software packages only support a precise number of identifiers. " 853 "You can override the default value (2) by a precise value." ),
855 << QStringLiteral(
"2" )
856 << QStringLiteral(
"3" )
857 << QStringLiteral(
"4" )
858 << QStringLiteral(
"NB_SOURCE_FIELDS" ),
859 QStringLiteral(
"2" )
863 QObject::tr(
"The BNA writer will try to recognize ellipses and circles when writing a polygon. " 864 "This will only work if the feature has previously been read from a BNA file. " 865 "As some software packages do not support ellipses/circles in BNA data file, " 866 "it may be useful to tell the writer by specifying ELLIPSES_AS_ELLIPSES=NO not " 867 "to export them as such, but keep them as polygons." ),
872 QObject::tr(
"Limit the number of coordinate pairs per line in multiline format." ),
877 QObject::tr(
"Set the number of decimal for coordinates. Default value is 10." ),
883 QStringLiteral(
"Atlas BNA" ),
884 QObject::tr(
"Atlas BNA" ),
885 QStringLiteral(
"*.bna" ),
886 QStringLiteral(
"bna" ),
893 datasetOptions.clear();
894 layerOptions.clear();
897 QObject::tr(
"By default when creating new .csv files they " 898 "are created with the line termination conventions " 899 "of the local platform (CR/LF on Win32 or LF on all other systems). " 900 "This may be overridden through the use of the LINEFORMAT option." ),
902 << QStringLiteral(
"CRLF" )
903 << QStringLiteral(
"LF" ),
909 QObject::tr(
"By default, the geometry of a feature written to a .csv file is discarded. " 910 "It is possible to export the geometry in its WKT representation by " 911 "specifying GEOMETRY=AS_WKT. It is also possible to export point geometries " 912 "into their X,Y,Z components by specifying GEOMETRY=AS_XYZ, GEOMETRY=AS_XY " 913 "or GEOMETRY=AS_YX." ),
915 << QStringLiteral(
"AS_WKT" )
916 << QStringLiteral(
"AS_XYZ" )
917 << QStringLiteral(
"AS_XY" )
918 << QStringLiteral(
"AS_YX" ),
924 QObject::tr(
"Create the associated .csvt file to describe the type of each " 925 "column of the layer and its optional width and precision." ),
930 QObject::tr(
"Field separator character." ),
932 << QStringLiteral(
"COMMA" )
933 << QStringLiteral(
"SEMICOLON" )
934 << QStringLiteral(
"TAB" ),
935 QStringLiteral(
"COMMA" )
938 #if defined(GDAL_COMPUTE_VERSION) && GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,3,0) 940 QObject::tr(
"Double-quote strings. IF_AMBIGUOUS means that string values that look like numbers will be quoted." ),
942 << QStringLiteral(
"IF_NEEDED" )
943 << QStringLiteral(
"IF_AMBIGUOUS" )
944 << QStringLiteral(
"ALWAYS" ),
945 QStringLiteral(
"IF_AMBIGUOUS" )
950 QObject::tr(
"Write a UTF-8 Byte Order Mark (BOM) at the start of the file." ),
956 QStringLiteral(
"Comma Separated Value [CSV]" ),
957 QObject::tr(
"Comma Separated Value [CSV]" ),
958 QStringLiteral(
"*.csv" ),
959 QStringLiteral(
"csv" ),
966 datasetOptions.clear();
967 layerOptions.clear();
970 QObject::tr(
"Override the type of shapefile created. " 971 "Can be one of NULL for a simple .dbf file with no .shp file, POINT, " 972 "ARC, POLYGON or MULTIPOINT for 2D, or POINTZ, ARCZ, POLYGONZ or " 973 "MULTIPOINTZ for 3D;" ) +
974 QObject::tr(
" POINTM, ARCM, POLYGONM or MULTIPOINTM for measured geometries" 975 " and POINTZM, ARCZM, POLYGONZM or MULTIPOINTZM for 3D measured" 977 #
if defined(GDAL_COMPUTE_VERSION) && GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,2,0)
978 QObject::tr(
" MULTIPATCH files are supported since GDAL 2.2." ) +
982 << QStringLiteral(
"NULL" )
983 << QStringLiteral(
"POINT" )
984 << QStringLiteral(
"ARC" )
985 << QStringLiteral(
"POLYGON" )
986 << QStringLiteral(
"MULTIPOINT" )
987 << QStringLiteral(
"POINTZ" )
988 << QStringLiteral(
"ARCZ" )
989 << QStringLiteral(
"POLYGONZ" )
990 << QStringLiteral(
"MULTIPOINTZ" )
991 << QStringLiteral(
"POINTM" )
992 << QStringLiteral(
"ARCM" )
993 << QStringLiteral(
"POLYGONM" )
994 << QStringLiteral(
"MULTIPOINTM" )
995 << QStringLiteral(
"POINTZM" )
996 << QStringLiteral(
"ARCZM" )
997 << QStringLiteral(
"POLYGONZM" )
998 << QStringLiteral(
"MULTIPOINTZM" )
999 #
if defined(GDAL_COMPUTE_VERSION) && GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,2,0)
1000 << QStringLiteral(
"MULTIPATCH" )
1011 QObject::tr(
"Set the encoding value in the DBF file. " 1012 "The default value is LDID/87. It is not clear " 1013 "what other values may be appropriate." ),
1021 QObject::tr(
"Set to YES to resize fields to their optimal size." ),
1027 QStringLiteral(
"ESRI Shapefile" ),
1028 QObject::tr(
"ESRI Shapefile" ),
1029 QStringLiteral(
"*.shp" ),
1030 QStringLiteral(
"shp" ),
1037 datasetOptions.clear();
1038 layerOptions.clear();
1042 QStringLiteral(
"DBF File" ),
1043 QObject::tr(
"DBF File" ),
1044 QStringLiteral(
"*.dbf" ),
1045 QStringLiteral(
"dbf" ),
1052 datasetOptions.clear();
1053 layerOptions.clear();
1057 QStringLiteral(
"FMEObjects Gateway" ),
1058 QObject::tr(
"FMEObjects Gateway" ),
1059 QStringLiteral(
"*.fdd" ),
1060 QStringLiteral(
"fdd" ),
1067 datasetOptions.clear();
1068 layerOptions.clear();
1071 QObject::tr(
"Set to YES to write a bbox property with the bounding box " 1072 "of the geometries at the feature and feature collection level." ),
1077 QObject::tr(
"Maximum number of figures after decimal separator to write in coordinates. " 1078 "Defaults to 15. Truncation will occur to remove trailing zeros." ),
1083 QObject::tr(
"Whether to use RFC 7946 standard. " 1084 "If disabled GeoJSON 2008 initial version will be used. " 1085 "Default is NO (thus GeoJSON 2008). See also Documentation (via Help button)" ),
1091 QStringLiteral(
"GeoJSON" ),
1092 QObject::tr(
"GeoJSON" ),
1093 QStringLiteral(
"*.geojson" ),
1094 QStringLiteral(
"geojson" ),
1097 QStringLiteral(
"UTF-8" )
1102 datasetOptions.clear();
1103 layerOptions.clear();
1106 QObject::tr(
"Maximum number of figures after decimal separator to write in coordinates. " 1107 "Defaults to 15. Truncation will occur to remove trailing zeros." ),
1112 QObject::tr(
"Whether to start records with the RS=0x1E character (RFC 8142 standard). " 1113 "Defaults to NO: Newline Delimited JSON (geojsonl). \n" 1114 "If set to YES: RFC 8142 standard: GeoJSON Text Sequences (geojsons)." ),
1120 QStringLiteral(
"GeoJSON - Newline Delimited" ),
1121 QObject::tr(
"GeoJSON - Newline Delimited" ),
1122 QStringLiteral(
"*.geojsonl *.geojsons *.json" ),
1123 QStringLiteral(
"json" ),
1126 QStringLiteral(
"UTF-8" )
1131 datasetOptions.clear();
1132 layerOptions.clear();
1135 QObject::tr(
"whether the document must be in RSS 2.0 or Atom 1.0 format. " 1136 "Default value : RSS" ),
1138 << QStringLiteral(
"RSS" )
1139 << QStringLiteral(
"ATOM" ),
1140 QStringLiteral(
"RSS" )
1144 QObject::tr(
"The encoding of location information. Default value : SIMPLE. " 1145 "W3C_GEO only supports point geometries. " 1146 "SIMPLE or W3C_GEO only support geometries in geographic WGS84 coordinates." ),
1148 << QStringLiteral(
"SIMPLE" )
1149 << QStringLiteral(
"GML" )
1150 << QStringLiteral(
"W3C_GEO" ),
1151 QStringLiteral(
"SIMPLE" )
1155 QObject::tr(
"If defined to YES, extension fields will be written. " 1156 "If the field name not found in the base schema matches " 1157 "the foo_bar pattern, foo will be considered as the namespace " 1158 "of the element, and a <foo:bar> element will be written. " 1159 "Otherwise, elements will be written in the <ogr:> namespace." ),
1164 QObject::tr(
"If defined to NO, only <entry> or <item> elements will be written. " 1165 "The user will have to provide the appropriate header and footer of the document." ),
1170 QObject::tr(
"XML content that will be put between the <channel> element and the " 1171 "first <item> element for a RSS document, or between the xml tag and " 1172 "the first <entry> element for an Atom document." ),
1177 QObject::tr(
"Value put inside the <title> element in the header. " 1178 "If not provided, a dummy value will be used as that element is compulsory." ),
1183 QObject::tr(
"Value put inside the <description> element in the header. " 1184 "If not provided, a dummy value will be used as that element is compulsory." ),
1189 QObject::tr(
"Value put inside the <link> element in the header. " 1190 "If not provided, a dummy value will be used as that element is compulsory." ),
1195 QObject::tr(
"Value put inside the <updated> element in the header. " 1196 "Should be formatted as a XML datetime. " 1197 "If not provided, a dummy value will be used as that element is compulsory." ),
1202 QObject::tr(
"Value put inside the <author><name> element in the header. " 1203 "If not provided, a dummy value will be used as that element is compulsory." ),
1208 QObject::tr(
"Value put inside the <id> element in the header. " 1209 "If not provided, a dummy value will be used as that element is compulsory." ),
1215 QStringLiteral(
"GeoRSS" ),
1216 QObject::tr(
"GeoRSS" ),
1217 QStringLiteral(
"*.xml" ),
1218 QStringLiteral(
"xml" ),
1221 QStringLiteral(
"UTF-8" )
1226 datasetOptions.clear();
1227 layerOptions.clear();
1230 QObject::tr(
"If provided, this URI will be inserted as the schema location. " 1231 "Note that the schema file isn't actually accessed by OGR, so it " 1232 "is up to the user to ensure it will match the schema of the OGR " 1233 "produced GML data file." ),
1238 QObject::tr(
"This writes a GML application schema file to a corresponding " 1239 ".xsd file (with the same basename). If INTERNAL is used the " 1240 "schema is written within the GML file, but this is experimental " 1241 "and almost certainly not valid XML. " 1242 "OFF disables schema generation (and is implicit if XSISCHEMAURI is used)." ),
1244 << QStringLiteral(
"EXTERNAL" )
1245 << QStringLiteral(
"INTERNAL" )
1246 << QStringLiteral(
"OFF" ),
1247 QStringLiteral(
"EXTERNAL" )
1251 QObject::tr(
"This is the prefix for the application target namespace." ),
1252 QStringLiteral(
"ogr" )
1256 QObject::tr(
"Can be set to TRUE to avoid writing the prefix of the " 1257 "application target namespace in the GML file." ),
1262 QObject::tr(
"Defaults to 'http://ogr.maptools.org/'. " 1263 "This is the application target namespace." ),
1264 QStringLiteral(
"http://ogr.maptools.org/" )
1268 QObject::tr(
"If not specified, GML2 will be used." ),
1270 << QStringLiteral(
"GML3" )
1271 << QStringLiteral(
"GML3Deegree" )
1272 << QStringLiteral(
"GML3.2" ),
1278 QObject::tr(
"Only valid when FORMAT=GML3/GML3Degree/GML3.2. Default to YES. " 1279 "If YES, SRS with EPSG authority will be written with the " 1280 "'urn:ogc:def:crs:EPSG::' prefix. In the case the SRS is a " 1281 "geographic SRS without explicit AXIS order, but that the same " 1282 "SRS authority code imported with ImportFromEPSGA() should be " 1283 "treated as lat/long, then the function will take care of coordinate " 1284 "order swapping. If set to NO, SRS with EPSG authority will be " 1285 "written with the 'EPSG:' prefix, even if they are in lat/long order." ),
1290 QObject::tr(
"only valid when FORMAT=GML3/GML3Degree/GML3.2) Default to YES. " 1291 "If set to NO, the <gml:boundedBy> element will not be written for " 1297 QObject::tr(
"Default to YES. If YES, the output will be indented with spaces " 1298 "for more readability, but at the expense of file size." ),
1305 QStringLiteral(
"Geography Markup Language [GML]" ),
1306 QObject::tr(
"Geography Markup Language [GML]" ),
1307 QStringLiteral(
"*.gml" ),
1308 QStringLiteral(
"gml" ),
1311 QStringLiteral(
"UTF-8" )
1316 datasetOptions.clear();
1317 layerOptions.clear();
1320 QObject::tr(
"Human-readable identifier (e.g. short name) for the layer content" ),
1325 QObject::tr(
"Human-readable description for the layer content" ),
1330 QObject::tr(
"Name for the feature identifier column" ),
1331 QStringLiteral(
"fid" )
1335 QObject::tr(
"Name for the geometry column" ),
1336 QStringLiteral(
"geom" )
1340 QObject::tr(
"If a spatial index must be created." ),
1346 QStringLiteral(
"GeoPackage" ),
1347 QObject::tr(
"GeoPackage" ),
1348 QStringLiteral(
"*.gpkg" ),
1349 QStringLiteral(
"gpkg" ),
1352 QStringLiteral(
"UTF-8" )
1357 datasetOptions.clear();
1358 layerOptions.clear();
1362 QStringLiteral(
"Generic Mapping Tools [GMT]" ),
1363 QObject::tr(
"Generic Mapping Tools [GMT]" ),
1364 QStringLiteral(
"*.gmt" ),
1365 QStringLiteral(
"gmt" ),
1372 datasetOptions.clear();
1373 layerOptions.clear();
1376 QObject::tr(
"By default when writing a layer whose features are of " 1377 "type wkbLineString, the GPX driver chooses to write " 1378 "them as routes. If FORCE_GPX_TRACK=YES is specified, " 1379 "they will be written as tracks." ),
1384 QObject::tr(
"By default when writing a layer whose features are of " 1385 "type wkbMultiLineString, the GPX driver chooses to write " 1386 "them as tracks. If FORCE_GPX_ROUTE=YES is specified, " 1387 "they will be written as routes, provided that the multilines " 1388 "are composed of only one single line." ),
1393 QObject::tr(
"If GPX_USE_EXTENSIONS=YES is specified, " 1394 "extra fields will be written inside the <extensions> tag." ),
1399 QObject::tr(
"Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS_URL " 1400 "is set. The namespace value used for extension tags. By default, 'ogr'." ),
1401 QStringLiteral(
"ogr" )
1405 QObject::tr(
"Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS " 1406 "is set. The namespace URI. By default, 'http://osgeo.org/gdal'." ),
1407 QStringLiteral(
"http://osgeo.org/gdal" )
1411 QObject::tr(
"By default files are created with the line termination " 1412 "conventions of the local platform (CR/LF on win32 or LF " 1413 "on all other systems). This may be overridden through use " 1414 "of the LINEFORMAT layer creation option which may have a value " 1415 "of CRLF (DOS format) or LF (Unix format)." ),
1417 << QStringLiteral(
"CRLF" )
1418 << QStringLiteral(
"LF" ),
1425 QStringLiteral(
"GPS eXchange Format [GPX]" ),
1426 QObject::tr(
"GPS eXchange Format [GPX]" ),
1427 QStringLiteral(
"*.gpx" ),
1428 QStringLiteral(
"gpx" ),
1431 QStringLiteral(
"UTF-8" )
1436 datasetOptions.clear();
1437 layerOptions.clear();
1441 QStringLiteral(
"INTERLIS 1" ),
1442 QObject::tr(
"INTERLIS 1" ),
1443 QStringLiteral(
"*.itf *.xml *.ili" ),
1444 QStringLiteral(
"ili" ),
1451 datasetOptions.clear();
1452 layerOptions.clear();
1456 QStringLiteral(
"INTERLIS 2" ),
1457 QObject::tr(
"INTERLIS 2" ),
1458 QStringLiteral(
"*.xtf *.xml *.ili" ),
1459 QStringLiteral(
"ili" ),
1466 datasetOptions.clear();
1467 layerOptions.clear();
1470 QObject::tr(
"Allows you to specify the field to use for the KML <name> element." ),
1471 QStringLiteral(
"Name" )
1475 QObject::tr(
"Allows you to specify the field to use for the KML <description> element." ),
1476 QStringLiteral(
"Description" )
1480 QObject::tr(
"Allows you to specify the AltitudeMode to use for KML geometries. " 1481 "This will only affect 3D geometries and must be one of the valid KML options." ),
1483 << QStringLiteral(
"clampToGround" )
1484 << QStringLiteral(
"relativeToGround" )
1485 << QStringLiteral(
"absolute" ),
1486 QStringLiteral(
"relativeToGround" )
1489 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,2,0) 1491 QObject::tr(
"The DOCUMENT_ID datasource creation option can be used to specified " 1492 "the id of the root <Document> node. The default value is root_doc." ),
1493 QStringLiteral(
"root_doc" )
1499 QStringLiteral(
"Keyhole Markup Language [KML]" ),
1500 QObject::tr(
"Keyhole Markup Language [KML]" ),
1501 QStringLiteral(
"*.kml" ),
1502 QStringLiteral(
"kml" ),
1505 QStringLiteral(
"UTF-8" )
1510 datasetOptions.clear();
1511 layerOptions.clear();
1513 auto insertMapInfoOptions = []( QMap<QString, QgsVectorFileWriter::Option *> &datasetOptions, QMap<QString, QgsVectorFileWriter::Option *> &layerOptions )
1516 QObject::tr(
"Use this to turn on 'quick spatial index mode'. " 1517 "In this mode writing files can be about 5 times faster, " 1518 "but spatial queries can be up to 30 times slower." ),
1520 << QStringLiteral(
"QUICK" )
1521 << QStringLiteral(
"OPTIMIZED" ),
1522 QStringLiteral(
"QUICK" ),
1527 QObject::tr(
"(multiples of 512): Block size for .map files. Defaults " 1528 "to 512. MapInfo 15.2 and above creates .tab files with a " 1529 "blocksize of 16384 bytes. Any MapInfo version should be " 1530 "able to handle block sizes from 512 to 32256." ),
1534 QObject::tr(
"xmin,ymin,xmax,ymax: Define custom layer bounds to increase the " 1535 "accuracy of the coordinates. Note: the geometry of written " 1536 "features must be within the defined box." ),
1540 insertMapInfoOptions( datasetOptions, layerOptions );
1544 QStringLiteral(
"Mapinfo" ),
1545 QObject::tr(
"Mapinfo TAB" ),
1546 QStringLiteral(
"*.tab" ),
1547 QStringLiteral(
"tab" ),
1552 datasetOptions.clear();
1553 layerOptions.clear();
1554 insertMapInfoOptions( datasetOptions, layerOptions );
1559 QStringLiteral(
"Mapinfo" ),
1560 QObject::tr(
"Mapinfo MIF" ),
1561 QStringLiteral(
"*.mif" ),
1562 QStringLiteral(
"mif" ),
1569 datasetOptions.clear();
1570 layerOptions.clear();
1573 QObject::tr(
"Determine whether 2D (seed_2d.dgn) or 3D (seed_3d.dgn) " 1574 "seed file should be used. This option is ignored if the SEED option is provided." ),
1579 QObject::tr(
"Override the seed file to use." ),
1584 QObject::tr(
"Indicate whether the whole seed file should be copied. " 1585 "If not, only the first three elements will be copied." ),
1590 QObject::tr(
"Indicates whether the color table should be copied from the seed file." ),
1595 QObject::tr(
"Override the master unit name from the seed file with " 1596 "the provided one or two character unit name." ),
1601 QObject::tr(
"Override the sub unit name from the seed file with the provided " 1602 "one or two character unit name." ),
1607 QObject::tr(
"Override the number of subunits per master unit. " 1608 "By default the seed file value is used." ),
1613 QObject::tr(
"Override the number of UORs (Units of Resolution) " 1614 "per sub unit. By default the seed file value is used." ),
1619 QObject::tr(
"ORIGIN=x,y,z: Override the origin of the design plane. " 1620 "By default the origin from the seed file is used." ),
1626 QStringLiteral(
"Microstation DGN" ),
1627 QObject::tr(
"Microstation DGN" ),
1628 QStringLiteral(
"*.dgn" ),
1629 QStringLiteral(
"dgn" ),
1636 datasetOptions.clear();
1637 layerOptions.clear();
1640 QObject::tr(
"Should update files be incorporated into the base data on the fly." ),
1642 << QStringLiteral(
"APPLY" )
1643 << QStringLiteral(
"IGNORE" ),
1644 QStringLiteral(
"APPLY" )
1648 QObject::tr(
"Should multipoint soundings be split into many single point sounding features. " 1649 "Multipoint geometries are not well handled by many formats, " 1650 "so it can be convenient to split single sounding features with many points " 1651 "into many single point features." ),
1656 QObject::tr(
"Should a DEPTH attribute be added on SOUNDG features and assign the depth " 1657 "of the sounding. This should only be enabled when SPLIT_MULTIPOINT is " 1663 QObject::tr(
"Should all the low level geometry primitives be returned as special " 1664 "IsolatedNode, ConnectedNode, Edge and Face layers." ),
1669 QObject::tr(
"If enabled, numeric attributes assigned an empty string as a value will " 1670 "be preserved as a special numeric value. This option should not generally " 1671 "be needed, but may be useful when translated S-57 to S-57 losslessly." ),
1676 QObject::tr(
"Should LNAM and LNAM_REFS fields be attached to features capturing " 1677 "the feature to feature relationships in the FFPT group of the S-57 file." ),
1682 QObject::tr(
"Should additional attributes relating features to their underlying " 1683 "geometric primitives be attached. These are the values of the FSPT group, " 1684 "and are primarily needed when doing S-57 to S-57 translations." ),
1689 QObject::tr(
"Should attribute values be recoded to UTF-8 from the character encoding " 1690 "specified in the S57 DSSI record." ),
1698 QStringLiteral(
"S-57 Base file" ),
1699 QObject::tr(
"S-57 Base file" ),
1700 QStringLiteral(
"*.000" ),
1701 QStringLiteral(
"000" ),
1708 datasetOptions.clear();
1709 layerOptions.clear();
1713 QStringLiteral(
"Spatial Data Transfer Standard [SDTS]" ),
1714 QObject::tr(
"Spatial Data Transfer Standard [SDTS]" ),
1715 QStringLiteral(
"*catd.ddf" ),
1716 QStringLiteral(
"ddf" ),
1723 datasetOptions.clear();
1724 layerOptions.clear();
1727 QObject::tr(
"Can be used to avoid creating the geometry_columns and spatial_ref_sys " 1728 "tables in a new database. By default these metadata tables are created " 1729 "when a new database is created." ),
1735 QStringLiteral(
"NO" )
1740 QStringLiteral(
"NO" )
1744 QObject::tr(
"Controls the format used for the geometry column. Defaults to WKB. " 1745 "This is generally more space and processing efficient, but harder " 1746 "to inspect or use in simple applications than WKT (Well Known Text)." ),
1748 << QStringLiteral(
"WKB" )
1749 << QStringLiteral(
"WKT" ),
1750 QStringLiteral(
"WKB" )
1754 QObject::tr(
"Controls whether layer and field names will be laundered for easier use " 1755 "in SQLite. Laundered names will be converted to lower case and some special " 1756 "characters(' - #) will be changed to underscores." ),
1761 QStringLiteral(
"NO" )
1765 QStringLiteral(
"NO" )
1773 QObject::tr(
"column_name1[,column_name2, …] A list of (String) columns that " 1774 "must be compressed with ZLib DEFLATE algorithm. This might be beneficial " 1775 "for databases that have big string blobs. However, use with care, since " 1776 "the value of such columns will be seen as compressed binary content with " 1777 "other SQLite utilities (or previous OGR versions). With OGR, when inserting, " 1778 "modifying or querying compressed columns, compression/decompression is " 1779 "done transparently. However, such columns cannot be (easily) queried with " 1780 "an attribute filter or WHERE clause. Note: in table definition, such columns " 1781 "have the 'VARCHAR_deflate' declaration type." ),
1787 QStringLiteral(
"SQLite" ),
1788 QObject::tr(
"SQLite" ),
1789 QStringLiteral(
"*.sqlite" ),
1790 QStringLiteral(
"sqlite" ),
1793 QStringLiteral(
"UTF-8" )
1798 datasetOptions.clear();
1799 layerOptions.clear();
1802 QObject::tr(
"Can be used to avoid creating the geometry_columns and spatial_ref_sys " 1803 "tables in a new database. By default these metadata tables are created " 1804 "when a new database is created." ),
1809 QStringLiteral(
"YES" )
1813 QObject::tr(
"Insert the content of the EPSG CSV files into the spatial_ref_sys table. " 1814 "Set to NO for regular SQLite databases." ),
1819 QStringLiteral(
"SPATIALITE" )
1823 QObject::tr(
"Controls whether layer and field names will be laundered for easier use " 1824 "in SQLite. Laundered names will be converted to lower case and some special " 1825 "characters(' - #) will be changed to underscores." ),
1830 QObject::tr(
"If the database is of the SpatiaLite flavor, and if OGR is linked " 1831 "against libspatialite, this option can be used to control if a spatial " 1832 "index must be created." ),
1837 QObject::tr(
"If the format of the geometry BLOB is of the SpatiaLite flavor, " 1838 "this option can be used to control if the compressed format for " 1839 "geometries (LINESTRINGs, POLYGONs) must be used." ),
1844 QObject::tr(
"Used to force the SRID number of the SRS associated with the layer. " 1845 "When this option isn't specified and that a SRS is associated with the " 1846 "layer, a search is made in the spatial_ref_sys to find a match for the " 1847 "SRS, and, if there is no match, a new entry is inserted for the SRS in " 1848 "the spatial_ref_sys table. When the SRID option is specified, this " 1849 "search (and the eventual insertion of a new entry) will not be done: " 1850 "the specified SRID is used as such." ),
1855 QObject::tr(
"column_name1[,column_name2, …] A list of (String) columns that " 1856 "must be compressed with ZLib DEFLATE algorithm. This might be beneficial " 1857 "for databases that have big string blobs. However, use with care, since " 1858 "the value of such columns will be seen as compressed binary content with " 1859 "other SQLite utilities (or previous OGR versions). With OGR, when inserting, " 1860 "modifying or queryings compressed columns, compression/decompression is " 1861 "done transparently. However, such columns cannot be (easily) queried with " 1862 "an attribute filter or WHERE clause. Note: in table definition, such columns " 1863 "have the 'VARCHAR_deflate' declaration type." ),
1869 QStringLiteral(
"SpatiaLite" ),
1870 QObject::tr(
"SpatiaLite" ),
1871 QStringLiteral(
"*.sqlite" ),
1872 QStringLiteral(
"sqlite" ),
1875 QStringLiteral(
"UTF-8" )
1879 datasetOptions.clear();
1880 layerOptions.clear();
1883 QObject::tr(
"Override the header file used - in place of header.dxf." ),
1888 QObject::tr(
"Override the trailer file used - in place of trailer.dxf." ),
1894 QStringLiteral(
"AutoCAD DXF" ),
1895 QObject::tr(
"AutoCAD DXF" ),
1896 QStringLiteral(
"*.dxf" ),
1897 QStringLiteral(
"dxf" ),
1904 datasetOptions.clear();
1905 layerOptions.clear();
1908 QObject::tr(
"Indicates the GeoConcept export file extension. " 1909 "TXT was used by earlier releases of GeoConcept. GXT is currently used." ),
1911 << QStringLiteral(
"GXT" )
1912 << QStringLiteral(
"TXT" ),
1913 QStringLiteral(
"GXT" )
1917 QObject::tr(
"Path to the GCT: the GCT file describes the GeoConcept types definitions: " 1918 "In this file, every line must start with //# followed by a keyword. " 1919 "Lines starting with // are comments." ),
1924 QObject::tr(
"Defines the feature to be created. The TYPE corresponds to one of the Name " 1925 "found in the GCT file for a type section. The SUBTYPE corresponds to one of " 1926 "the Name found in the GCT file for a sub-type section within the previous " 1933 QStringLiteral(
"Geoconcept" ),
1934 QObject::tr(
"Geoconcept" ),
1935 QStringLiteral(
"*.gxt *.txt" ),
1936 QStringLiteral(
"gxt" ),
1943 datasetOptions.clear();
1944 layerOptions.clear();
1947 QObject::tr(
"When this option is set, the new layer will be created inside the named " 1948 "FeatureDataset folder. If the folder does not already exist, it will be created." ),
1953 QObject::tr(
"Set name of geometry column in new layer. Defaults to 'SHAPE'." ),
1954 QStringLiteral(
"SHAPE" )
1958 QObject::tr(
"Name of the OID column to create. Defaults to 'OBJECTID'." ),
1959 QStringLiteral(
"OBJECTID" )
1964 QStringLiteral(
"ESRI FileGDB" ),
1965 QObject::tr(
"ESRI FileGDB" ),
1966 QStringLiteral(
"*.gdb" ),
1967 QStringLiteral(
"gdb" ),
1970 QStringLiteral(
"UTF-8" )
1975 datasetOptions.clear();
1976 layerOptions.clear();
1979 QObject::tr(
"By default, the driver will try to detect the data type of fields. If set " 1980 "to STRING, all fields will be of String type." ),
1982 << QStringLiteral(
"AUTO" )
1983 << QStringLiteral(
"STRING" ),
1984 QStringLiteral(
"AUTO" ),
1989 QObject::tr(
"By default, the driver will read the first lines of each sheet to detect " 1990 "if the first line might be the name of columns. If set to FORCE, the driver " 1991 "will consider the first line as the header line. If set to " 1992 "DISABLE, it will be considered as the first feature. Otherwise " 1993 "auto-detection will occur." ),
1995 << QStringLiteral(
"FORCE" )
1996 << QStringLiteral(
"DISABLE" )
1997 << QStringLiteral(
"AUTO" ),
1998 QStringLiteral(
"AUTO" ),
2004 QStringLiteral(
"MS Office Open XML spreadsheet" ),
2005 QObject::tr(
"MS Office Open XML spreadsheet [XLSX]" ),
2006 QStringLiteral(
"*.xlsx" ),
2007 QStringLiteral(
"xlsx" ),
2010 QStringLiteral(
"UTF-8" )
2015 datasetOptions.clear();
2016 layerOptions.clear();
2019 QObject::tr(
"By default, the driver will try to detect the data type of fields. If set " 2020 "to STRING, all fields will be of String type." ),
2022 << QStringLiteral(
"AUTO" )
2023 << QStringLiteral(
"STRING" ),
2024 QStringLiteral(
"AUTO" ),
2029 QObject::tr(
"By default, the driver will read the first lines of each sheet to detect " 2030 "if the first line might be the name of columns. If set to FORCE, the driver " 2031 "will consider the first line as the header line. If set to " 2032 "DISABLE, it will be considered as the first feature. Otherwise " 2033 "auto-detection will occur." ),
2035 << QStringLiteral(
"FORCE" )
2036 << QStringLiteral(
"DISABLE" )
2037 << QStringLiteral(
"AUTO" ),
2038 QStringLiteral(
"AUTO" ),
2044 QStringLiteral(
"Open Document Spreadsheet" ),
2045 QObject::tr(
"Open Document Spreadsheet [ODS]" ),
2046 QStringLiteral(
"*.ods" ),
2047 QStringLiteral(
"ods" ),
2050 QStringLiteral(
"UTF-8" )
2055 datasetOptions.clear();
2056 layerOptions.clear();
2059 QObject::tr(
"Line termination character sequence." ),
2061 << QStringLiteral(
"CRLF" )
2062 << QStringLiteral(
"LF" ),
2069 QObject::tr(
"Format of geometry columns." ),
2071 << QStringLiteral(
"geometry" )
2072 << QStringLiteral(
"geography" ),
2073 QStringLiteral(
"geometry" ),
2078 QObject::tr(
"Controls whether layer and field names will be laundered for easier use. " 2079 "Laundered names will be converted to lower case and some special " 2080 "characters(' - #) will be changed to underscores." ),
2085 QObject::tr(
"Name for the geometry column. Defaults to wkb_geometry " 2086 "for GEOM_TYPE=geometry or the_geog for GEOM_TYPE=geography" ) ) );
2089 QObject::tr(
"Name of schema into which to create the new table" ) ) );
2092 QObject::tr(
"Whether to explicitly emit the CREATE SCHEMA statement to create the specified schema." ),
2097 QObject::tr(
"Whether to explicitly recreate the table if necessary." ),
2102 QObject::tr(
"Whether to explicitly destroy tables before recreating them." ),
2104 << QStringLiteral(
"YES" )
2105 << QStringLiteral(
"NO" )
2106 << QStringLiteral(
"IF_EXISTS" ),
2107 QStringLiteral(
"YES" ),
2112 QObject::tr(
"Used to force the SRID number of the SRS associated with the layer. " 2113 "When this option isn't specified and that a SRS is associated with the " 2114 "layer, a search is made in the spatial_ref_sys to find a match for the " 2115 "SRS, and, if there is no match, a new entry is inserted for the SRS in " 2116 "the spatial_ref_sys table. When the SRID option is specified, this " 2117 "search (and the eventual insertion of a new entry) will not be done: " 2118 "the specified SRID is used as such." ),
2123 QObject::tr(
"Can be set to 2.0 or 2.2 for PostGIS 2.0/2.2 compatibility. " 2124 "Important to set it correctly if using non-linear geometry types" ),
2130 QStringLiteral(
"PostgreSQL SQL dump" ),
2131 QObject::tr(
"PostgreSQL SQL dump" ),
2132 QStringLiteral(
"*.sql" ),
2133 QStringLiteral(
"sql" ),
2136 QStringLiteral(
"UTF-8" )
2142 QgsVectorFileWriterMetadataContainer(
const QgsVectorFileWriterMetadataContainer &other ) =
delete;
2143 QgsVectorFileWriterMetadataContainer &
operator=(
const QgsVectorFileWriterMetadataContainer &other ) =
delete;
2144 ~QgsVectorFileWriterMetadataContainer()
2148 for (
auto optionIt = it.value().driverOptions.constBegin(); optionIt != it.value().driverOptions.constEnd(); ++optionIt )
2149 delete optionIt.value();
2150 for (
auto optionIt = it.value().layerOptions.constBegin(); optionIt != it.value().layerOptions.constEnd(); ++optionIt )
2151 delete optionIt.value();
2162 static QgsVectorFileWriterMetadataContainer sDriverMetadata;
2163 QMap<QString, MetaData>::ConstIterator it = sDriverMetadata.driverMetadata.constBegin();
2165 for ( ; it != sDriverMetadata.driverMetadata.constEnd(); ++it )
2167 if ( it.key() == QLatin1String(
"PGDUMP" ) &&
2168 driverName != QLatin1String(
"PGDUMP" ) &&
2169 driverName != QLatin1String(
"PostgreSQL SQL dump" ) )
2174 if ( it.key().startsWith( driverName ) || it.value().longName.startsWith( driverName ) )
2176 driverMetadata = it.value();
2189 return QStringList();
2198 return QStringList();
2205 OGRwkbGeometryType ogrType =
static_cast<OGRwkbGeometryType
>( type );
2231 QgsFeatureList::iterator fIt = features.begin();
2233 for ( ; fIt != features.end(); ++fIt )
2250 mRenderContext.expressionContext().setFeature( feature );
2253 QString styleString;
2254 QString currentStyle;
2256 QgsSymbolList::const_iterator symbolIt = symbols.constBegin();
2257 for ( ; symbolIt != symbols.constEnd(); ++symbolIt )
2259 int nSymbolLayers = ( *symbolIt )->symbolLayerCount();
2260 for (
int i = 0; i < nSymbolLayers; ++i )
2263 QMap< QgsSymbolLayer *, QString >::const_iterator it =
mSymbolLayerTable.find( ( *symbolIt )->symbolLayer( i ) );
2269 double mmsf = mmScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
2270 double musf = mapUnitScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
2272 currentStyle = ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf );
2276 if ( symbolIt != symbols.constBegin() || i != 0 )
2278 styleString.append(
';' );
2280 styleString.append( currentStyle );
2284 OGR_F_SetStyleString( poFeature.get(), currentStyle.toLocal8Bit().constData() );
2285 if ( !writeFeature(
mLayer, poFeature.get() ) )
2292 OGR_F_SetStyleString( poFeature.get(), styleString.toLocal8Bit().constData() );
2297 if ( !writeFeature(
mLayer, poFeature.get() ) )
2314 if ( fid > std::numeric_limits<int>::max() )
2316 QgsDebugMsg( QStringLiteral(
"feature id %1 too large." ).arg( fid ) );
2317 OGRErr err = OGR_F_SetFID( poFeature.get(),
static_cast<long>( fid ) );
2318 if ( err != OGRERR_NONE )
2320 QgsDebugMsg( QStringLiteral(
"Failed to set feature id to %1: %2 (OGR error: %3)" )
2321 .arg( feature.
id() )
2322 .arg( err ).arg( CPLGetLastErrorMsg() )
2330 int fldIdx = it.key();
2331 int ogrField = it.value();
2333 QVariant attrValue = feature.
attribute( fldIdx );
2336 if ( !attrValue.isValid() || attrValue.isNull() )
2345 #ifdef OGRNullMarker 2346 OGR_F_SetFieldNull( poFeature.get(), ogrField );
2357 switch ( field.
type() )
2360 OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
2362 case QVariant::LongLong:
2363 OGR_F_SetFieldInteger64( poFeature.get(), ogrField, attrValue.toLongLong() );
2365 case QVariant::Bool:
2366 OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
2368 case QVariant::String:
2369 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toString() ).constData() );
2371 case QVariant::Double:
2372 OGR_F_SetFieldDouble( poFeature.get(), ogrField, attrValue.toDouble() );
2374 case QVariant::Date:
2375 OGR_F_SetFieldDateTime( poFeature.get(), ogrField,
2376 attrValue.toDate().year(),
2377 attrValue.toDate().month(),
2378 attrValue.toDate().day(),
2381 case QVariant::DateTime:
2384 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toDateTime().toString( QStringLiteral(
"yyyy/MM/dd hh:mm:ss.zzz" ) ) ).constData() );
2388 OGR_F_SetFieldDateTime( poFeature.get(), ogrField,
2389 attrValue.toDateTime().date().year(),
2390 attrValue.toDateTime().date().month(),
2391 attrValue.toDateTime().date().day(),
2392 attrValue.toDateTime().time().hour(),
2393 attrValue.toDateTime().time().minute(),
2394 attrValue.toDateTime().time().second(),
2398 case QVariant::Time:
2401 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toString() ).constData() );
2405 OGR_F_SetFieldDateTime( poFeature.get(), ogrField,
2407 attrValue.toTime().hour(),
2408 attrValue.toTime().minute(),
2409 attrValue.toTime().second(),
2414 case QVariant::ByteArray:
2416 const QByteArray ba = attrValue.toByteArray();
2417 OGR_F_SetFieldBinary( poFeature.get(), ogrField, ba.size(),
const_cast< GByte *
>(
reinterpret_cast< const GByte *
>( ba.data() ) ) );
2421 case QVariant::Invalid:
2424 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,4,0) 2425 case QVariant::List:
2427 if ( field.
subType() == QVariant::String )
2429 QStringList list = attrValue.toStringList();
2430 if ( supportsStringList )
2432 int count = list.count();
2433 char **lst =
new char *[count + 1];
2437 for ( QString
string : list )
2439 lst[pos] =
mCodec->fromUnicode(
string ).data();
2443 lst[count] =
nullptr;
2444 OGR_F_SetFieldStringList( poFeature.get(), ogrField, lst );
2448 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( list.join(
',' ) ).constData() );
2457 mErrorMessage = QObject::tr(
"Invalid variant type for field %1[%2]: received %3 with type %4" )
2460 .arg( attrValue.typeName(),
2461 attrValue.toString() );
2484 OGRGeometryH mGeom2 =
nullptr;
2530 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
2531 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
2537 QByteArray wkb( geom.
asWkb() );
2538 OGRErr err = OGR_G_ImportFromWkb( mGeom2, reinterpret_cast<unsigned char *>( const_cast<char *>( wkb.constData() ) ), wkb.length() );
2539 if ( err != OGRERR_NONE )
2541 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
2542 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
2549 OGR_F_SetGeometryDirectly( poFeature.get(), mGeom2 );
2553 QByteArray wkb( geom.
asWkb() );
2555 OGRErr err = OGR_G_ImportFromWkb( ogrGeom, reinterpret_cast<unsigned char *>( const_cast<char *>( wkb.constData() ) ), wkb.length() );
2556 if ( err != OGRERR_NONE )
2558 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
2559 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
2566 OGR_F_SetGeometryDirectly( poFeature.get(), ogrGeom );
2581 for (
int i = 0; i < attributes.size(); i++ )
2583 if ( omap.find( i ) != omap.end() )
2588 bool QgsVectorFileWriter::writeFeature( OGRLayerH layer, OGRFeatureH feature )
2590 if ( OGR_L_CreateFeature( layer, feature ) != OGRERR_NONE )
2592 mErrorMessage = QObject::tr(
"Feature creation error (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
2602 if ( mUsingTransaction )
2604 if ( OGRERR_NONE != OGR_L_CommitTransaction(
mLayer ) )
2606 QgsDebugMsg( QStringLiteral(
"Error while committing transaction on OGRLayer." ) );
2614 OSRDestroySpatialReference(
mOgrRef );
2620 const QString &fileName,
2621 const QString &fileEncoding,
2623 const QString &driverName,
2626 const QStringList &datasourceOptions,
2627 const QStringList &layerOptions,
2628 bool skipAttributeCreation,
2629 QString *newFilename,
2641 if ( destCRS.
isValid() && layer )
2647 errorMessage, datasourceOptions, layerOptions, skipAttributeCreation,
2648 newFilename, symbologyExport, symbologyScale, filterExtent,
2649 overrideGeometryType, forceMulti, includeZ, attributes,
2650 fieldValueConverter, newLayer );
2655 const QString &fileName,
2656 const QString &fileEncoding,
2658 const QString &driverName,
2661 const QStringList &datasourceOptions,
2662 const QStringList &layerOptions,
2663 bool skipAttributeCreation,
2664 QString *newFilename,
2692 return writeAsVectorFormat( layer, fileName, options, newFilename, errorMessage, newLayer );
2697 : driverName( QStringLiteral(
"GPKG" ) )
2705 if ( !layer || !layer->
isValid() )
2713 details.sourceCrs = layer->
crs();
2714 details.sourceWkbType = layer->
wkbType();
2715 details.sourceFields = layer->
fields();
2724 if ( details.storageType == QLatin1String(
"ESRI Shapefile" ) )
2732 details.geometryTypeScanIterator = layer->
getFeatures( req );
2736 details.renderContext.setExpressionContext( details.expressionContext );
2737 details.renderContext.setRendererScale( options.
symbologyScale );
2739 details.shallTransform =
false;
2744 details.shallTransform =
true;
2749 details.outputCrs = details.sourceCrs;
2752 details.destWkbType = details.sourceWkbType;
2766 details.attributes.clear();
2767 else if ( details.attributes.isEmpty() )
2769 const QgsAttributeList allAttributes = details.sourceFields.allAttributesList();
2770 for (
int idx : allAttributes )
2772 QgsField fld = details.sourceFields.at( idx );
2773 if ( details.providerType == QLatin1String(
"oracle" ) && fld.
typeName().contains( QLatin1String(
"SDO_GEOMETRY" ) ) )
2775 details.attributes.append( idx );
2779 if ( !details.attributes.isEmpty() )
2781 for (
int attrIdx : qgis::as_const( details.attributes ) )
2783 details.outputFields.append( details.sourceFields.at( attrIdx ) );
2789 if ( details.providerType == QLatin1String(
"spatialite" ) )
2791 for (
int i = 0; i < details.outputFields.size(); i++ )
2793 if ( details.outputFields.at( i ).type() == QVariant::LongLong )
2797 if ( std::max( std::llabs( min.toLongLong() ), std::llabs( max.toLongLong() ) ) < std::numeric_limits<int>::max() )
2799 details.outputFields[i].setType( QVariant::Int );
2807 addRendererAttributes( details.renderer.get(), details.renderContext, details.sourceFields, details.attributes );
2817 bool useFilterRect =
true;
2818 if ( details.shallTransform )
2827 useFilterRect =
false;
2830 if ( useFilterRect )
2832 req.setFilterRect( filterRect );
2836 details.filterRectEngine->prepareGeometry();
2838 details.sourceFeatureIterator = layer->
getFeatures( req );
2848 int lastProgressReport = 0;
2849 long total = details.featureCount;
2852 if ( details.providerType == QLatin1String(
"ogr" ) && !details.dataSourceUri.isEmpty() )
2854 QString srcFileName( details.providerUriParams.value( QLatin1String(
"path" ) ).toString() );
2855 if ( QFile::exists( srcFileName ) && QFileInfo( fileName ).canonicalFilePath() == QFileInfo( srcFileName ).canonicalFilePath() )
2859 if ( !( ( options.
driverName == QLatin1String(
"GPKG" ) ||
2860 options.
driverName == QLatin1String(
"SpatiaLite" ) ||
2861 options.
driverName == QLatin1String(
"SQLite" ) ) &&
2862 options.
layerName != details.providerUriParams.value( QLatin1String(
"layerName" ) ) ) )
2865 *errorMessage = QObject::tr(
"Cannot overwrite a OGR layer in place" );
2885 int newProgress =
static_cast<int>( ( 5.0 * scanned ) / total );
2886 if ( newProgress != lastProgressReport )
2888 lastProgressReport = newProgress;
2903 std::unique_ptr< QgsVectorFileWriter > writer =
2904 qgis::make_unique< QgsVectorFileWriter >( fileName,
2905 options.
fileEncoding, details.outputFields, destWkbType,
2927 *errorMessage = writer->errorMessage();
2933 errorMessage->clear();
2955 int n = 0, errors = 0;
2964 writer->startRender( details.renderer.get(), details.sourceFields );
2966 writer->resetMap( details.attributes );
2968 writer->mFields = details.sourceFields;
2972 int initialProgress = lastProgressReport;
2973 while ( details.sourceFeatureIterator.nextFeature( fet ) )
2984 int newProgress =
static_cast<int>( initialProgress + ( ( 100.0 - initialProgress ) * saved ) / total );
2985 if ( newProgress < 100 && newProgress != lastProgressReport )
2987 lastProgressReport = newProgress;
2992 if ( details.shallTransform )
3005 QString msg = QObject::tr(
"Failed to transform a point while drawing a feature with ID '%1'. Writing stopped. (Exception: %2)" )
3006 .arg( fet.
id() ).arg( e.
what() );
3009 *errorMessage = msg;
3023 if ( !writer->addFeatureWithStyle( fet, writer->mRenderer.get(), mapUnits ) )
3026 if ( err !=
NoError && errorMessage )
3028 if ( errorMessage->isEmpty() )
3030 *errorMessage = QObject::tr(
"Feature write errors:" );
3032 *errorMessage +=
'\n' + writer->errorMessage();
3036 if ( errors > 1000 )
3040 *errorMessage += QObject::tr(
"Stopping after %1 errors" ).arg( errors );
3050 writer->stopRender();
3052 if ( errors > 0 && errorMessage && n > 0 )
3054 *errorMessage += QObject::tr(
"\nOnly %1 of %2 features written." ).arg( n - errors ).arg( n );
3062 const QString &fileName,
3064 QString *newFilename,
3065 QString *errorMessage,
3068 QgsVectorFileWriter::PreparedWriterDetails details;
3069 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
3073 return writeAsVectorFormat( details, fileName, options, newFilename, errorMessage, newLayer );
3079 QFileInfo fi( fileName );
3080 QDir dir = fi.dir();
3083 const char *suffixes[] = {
".shp",
".shx",
".dbf",
".prj",
".qix",
".qpj",
".cpg",
".sbn",
".sbx",
".idm",
".ind" };
3084 for ( std::size_t i = 0; i <
sizeof( suffixes ) /
sizeof( *suffixes ); i++ )
3086 filter << fi.completeBaseName() + suffixes[i];
3090 const auto constEntryList = dir.entryList( filter );
3091 for (
const QString &file : constEntryList )
3093 QFile f( dir.canonicalPath() +
'/' + file );
3096 QgsDebugMsg( QStringLiteral(
"Removing file %1 failed: %2" ).arg( file, f.errorString() ) );
3112 QList< FilterFormatDetails > results;
3115 int const drvCount = OGRGetDriverCount();
3117 for (
int i = 0; i < drvCount; ++i )
3119 OGRSFDriverH drv = OGRGetDriver( i );
3122 QString drvName = OGR_Dr_GetName( drv );
3124 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,3,0) 3125 GDALDriverH gdalDriver = GDALGetDriverByName( drvName.toLocal8Bit().constData() );
3126 char **metadata =
nullptr;
3129 metadata = GDALGetMetadata( gdalDriver,
nullptr );
3132 bool nonSpatialFormat = CSLFetchBoolean( metadata, GDAL_DCAP_NONSPATIAL,
false );
3134 bool nonSpatialFormat = ( drvName == QLatin1String(
"ODS" ) || drvName == QLatin1String(
"XLSX" ) || drvName == QLatin1String(
"XLS" ) );
3137 if ( OGR_Dr_TestCapability( drv,
"CreateDataSource" ) != 0 )
3142 if ( nonSpatialFormat )
3147 if ( filterString.isEmpty() )
3154 globs = metadata.
glob.toLower().split(
' ' );
3160 details.
globs = globs;
3171 if ( a.
driverName == QLatin1String(
"GPKG" ) )
3173 else if ( b.driverName == QLatin1String(
"GPKG" ) )
3175 else if ( a.
driverName == QLatin1String(
"ESRI Shapefile" ) )
3177 else if ( b.driverName == QLatin1String(
"ESRI Shapefile" ) )
3181 return a.
filterString.toLower().localeAwareCompare( b.filterString.toLower() ) < 0;
3190 QSet< QString > extensions;
3192 const QRegularExpression rx( QStringLiteral(
"\\*\\.(.*)$" ) );
3196 for (
const QString &glob : format.globs )
3198 const QRegularExpressionMatch match = rx.match( glob );
3199 if ( !match.hasMatch() )
3202 const QString matched = match.captured( 1 );
3203 extensions.insert( matched );
3207 QStringList extensionList = extensions.toList();
3209 std::sort( extensionList.begin(), extensionList.end(), [options](
const QString & a,
const QString & b ) ->
bool 3213 if ( a == QLatin1String(
"gpkg" ) )
3215 else if ( b == QLatin1String(
"gpkg" ) )
3217 else if ( a == QLatin1String(
"shp" ) )
3219 else if ( b == QLatin1String(
"shp" ) )
3223 return a.toLower().localeAwareCompare( b.toLower() ) < 0;
3226 return extensionList;
3231 QList< QgsVectorFileWriter::DriverDetails > results;
3234 const int drvCount = OGRGetDriverCount();
3236 QStringList writableDrivers;
3237 for (
int i = 0; i < drvCount; ++i )
3239 OGRSFDriverH drv = OGRGetDriver( i );
3242 QString drvName = OGR_Dr_GetName( drv );
3248 if ( drvName == QLatin1String(
"ODS" ) || drvName == QLatin1String(
"XLSX" ) || drvName == QLatin1String(
"XLS" ) )
3252 if ( drvName == QLatin1String(
"ESRI Shapefile" ) )
3254 writableDrivers << QStringLiteral(
"DBF file" );
3256 if ( OGR_Dr_TestCapability( drv,
"CreateDataSource" ) != 0 )
3259 if ( drvName == QLatin1String(
"MapInfo File" ) )
3261 writableDrivers << QStringLiteral(
"MapInfo MIF" );
3263 else if ( drvName == QLatin1String(
"SQLite" ) )
3270 QString option = QStringLiteral(
"SPATIALITE=YES" );
3271 char *options[2] = { CPLStrdup( option.toLocal8Bit().constData() ),
nullptr };
3272 OGRSFDriverH poDriver;
3274 poDriver = OGRGetDriverByName( drvName.toLocal8Bit().constData() );
3277 gdal::ogr_datasource_unique_ptr ds( OGR_Dr_CreateDataSource( poDriver, QStringLiteral(
"/vsimem/spatialitetest.sqlite" ).toUtf8().constData(), options ) );
3280 writableDrivers << QStringLiteral(
"SpatiaLite" );
3281 OGR_Dr_DeleteDataSource( poDriver, QStringLiteral(
"/vsimem/spatialitetest.sqlite" ).toUtf8().constData() );
3284 CPLFree( options[0] );
3286 writableDrivers << drvName;
3291 results.reserve( writableDrivers.count() );
3292 for (
const QString &drvName : qgis::as_const( writableDrivers ) )
3308 if ( a.
driverName == QLatin1String(
"GPKG" ) )
3310 else if ( b.driverName == QLatin1String(
"GPKG" ) )
3312 else if ( a.
driverName == QLatin1String(
"ESRI Shapefile" ) )
3314 else if ( b.driverName == QLatin1String(
"ESRI Shapefile" ) )
3318 return a.
longName.toLower().localeAwareCompare( b.longName.toLower() ) < 0;
3325 QString ext = extension.trimmed();
3326 if ( ext.isEmpty() )
3329 if ( ext.startsWith(
'.' ) )
3333 int const drvCount = GDALGetDriverCount();
3335 for (
int i = 0; i < drvCount; ++i )
3337 GDALDriverH drv = GDALGetDriver( i );
3341 if ( CSLFetchBoolean( driverMetadata, GDAL_DCAP_CREATE,
false ) && CSLFetchBoolean( driverMetadata, GDAL_DCAP_VECTOR,
false ) )
3343 QString drvName = GDALGetDriverShortName( drv );
3344 QStringList driverExtensions = QString( GDALGetMetadataItem( drv, GDAL_DMD_EXTENSIONS,
nullptr ) ).split(
' ' );
3346 const auto constDriverExtensions = driverExtensions;
3347 for (
const QString &driver : constDriverExtensions )
3349 if ( driver.compare( ext, Qt::CaseInsensitive ) == 0 )
3360 QString filterString;
3364 if ( !filterString.isEmpty() )
3365 filterString += QLatin1String(
";;" );
3367 filterString += details.filterString;
3369 return filterString;
3378 return QStringLiteral(
"%1 (%2 %3)" ).arg( metadata.
trLongName,
3379 metadata.
glob.toLower(),
3380 metadata.
glob.toUpper() );
3385 if ( codecName == QLatin1String(
"System" ) )
3386 return QStringLiteral(
"LDID/0" );
3388 QRegExp re = QRegExp( QString(
"(CP|windows-|ISO[ -])(.+)" ), Qt::CaseInsensitive );
3389 if ( re.exactMatch( codecName ) )
3391 QString
c = re.cap( 2 ).remove(
'-' );
3393 c.toInt( &isNumber );
3421 OGRStyleTableH ogrStyleTable = OGR_STBL_Create();
3422 OGRStyleMgrH styleManager = OGR_SM_Create( ogrStyleTable );
3425 int nTotalLevels = 0;
3427 QgsSymbolList::iterator symbolIt = symbolList.begin();
3428 for ( ; symbolIt != symbolList.end(); ++symbolIt )
3430 double mmsf = mmScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
3431 double musf = mapUnitScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
3433 int nLevels = ( *symbolIt )->symbolLayerCount();
3434 for (
int i = 0; i < nLevels; ++i )
3436 mSymbolLayerTable.insert( ( *symbolIt )->symbolLayer( i ), QString::number( nTotalLevels ) );
3437 OGR_SM_AddStyle( styleManager, QString::number( nTotalLevels ).toLocal8Bit(),
3438 ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf ).toLocal8Bit() );
3442 OGR_DS_SetStyleTableDirectly( ds, ogrStyleTable );
3448 if ( !details.renderer )
3451 mRenderContext.expressionContext() = details.expressionContext;
3453 QHash< QgsSymbol *, QList<QgsFeature> > features;
3462 startRender( details.renderer.get(), details.sourceFields );
3473 if ( fet.hasGeometry() )
3477 fet.setGeometry( g );
3482 QString msg = QObject::tr(
"Failed to transform, writing stopped. (Exception: %1)" )
3486 *errorMessage = msg;
3491 mRenderContext.expressionContext().setFeature( fet );
3493 featureSymbol = mRenderer->symbolForFeature( fet, mRenderContext );
3494 if ( !featureSymbol )
3499 QHash< QgsSymbol *, QList<QgsFeature> >::iterator it = features.find( featureSymbol );
3500 if ( it == features.end() )
3502 it = features.insert( featureSymbol, QList<QgsFeature>() );
3504 it.value().append( fet );
3509 QgsSymbolList symbols = mRenderer->symbols( mRenderContext );
3510 for (
int i = 0; i < symbols.count(); i++ )
3516 if ( level < 0 || level >= 1000 )
3519 while ( level >= levels.count() )
3521 levels[level].append( item );
3526 int nTotalFeatures = 0;
3529 for (
int l = 0; l < levels.count(); l++ )
3532 for (
int i = 0; i < level.count(); i++ )
3535 QHash< QgsSymbol *, QList<QgsFeature> >::iterator levelIt = features.find( item.
symbol() );
3536 if ( levelIt == features.end() )
3542 double mmsf = mmScaleFactor(
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
3543 double musf = mapUnitScaleFactor(
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
3545 int llayer = item.
layer();
3546 QList<QgsFeature> &featureList = levelIt.value();
3547 QList<QgsFeature>::iterator featureIt = featureList.begin();
3548 for ( ; featureIt != featureList.end(); ++featureIt )
3558 QString styleString = levelIt.key()->symbolLayer( llayer )->ogrFeatureStyle( mmsf, musf );
3559 if ( !styleString.isEmpty() )
3561 OGR_F_SetStyleString( ogrFeature.get(), styleString.toLocal8Bit().constData() );
3562 if ( !writeFeature(
mLayer, ogrFeature.get() ) )
3573 if ( nErrors > 0 && errorMessage )
3575 *errorMessage += QObject::tr(
"\nOnly %1 of %2 features written." ).arg( nTotalFeatures - nErrors ).arg( nTotalFeatures );
3592 return 1000 / scale;
3609 return scale / 1000;
3617 mRenderer = createSymbologyRenderer( sourceRenderer );
3623 mRenderer->startRender( mRenderContext, fields );
3626 void QgsVectorFileWriter::stopRender()
3633 mRenderer->stopRender( mRenderContext );
3636 std::unique_ptr<QgsFeatureRenderer> QgsVectorFileWriter::createSymbologyRenderer(
QgsFeatureRenderer *sourceRenderer )
const 3642 if ( !sourceRenderer )
3647 return std::unique_ptr< QgsFeatureRenderer >( sourceRenderer->
clone() );
3654 const QSet<QString> rendererAttributes = renderer->
usedAttributes( context );
3655 for (
const QString &attr : rendererAttributes )
3660 attList.append( index );
3666 QStringList QgsVectorFileWriter::concatenateOptions(
const QMap<QString, QgsVectorFileWriter::Option *> &options )
3669 QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
3671 for ( it = options.constBegin(); it != options.constEnd(); ++it )
3674 switch ( option->
type )
3681 list.append( QStringLiteral(
"%1=%2" ).arg( it.key() ).arg( opt->
defaultValue ) );
3691 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
defaultValue ) );
3701 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
defaultValue ) );
3710 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
mValue ) );
3721 OGRSFDriverH hDriver =
nullptr;
3725 QString drvName = OGR_Dr_GetName( hDriver );
3726 QgsVectorFileWriter::EditionCapabilities caps =
nullptr;
3727 if ( OGR_DS_TestCapability( hDS.get(), ODsCCreateLayer ) )
3732 if ( !( drvName == QLatin1String(
"ESRI Shapefile" ) && QFile::exists( datasetName ) ) )
3735 if ( OGR_DS_TestCapability( hDS.get(), ODsCDeleteLayer ) )
3739 int layer_count = OGR_DS_GetLayerCount( hDS.get() );
3742 OGRLayerH hLayer = OGR_DS_GetLayer( hDS.get(), 0 );
3745 if ( OGR_L_TestCapability( hLayer, OLCSequentialWrite ) )
3748 if ( OGR_L_TestCapability( hLayer, OLCCreateField ) )
3759 const QString &layerNameIn )
3761 OGRSFDriverH hDriver =
nullptr;
3767 if ( layerName.isEmpty() )
3768 layerName = QFileInfo( datasetName ).baseName();
3770 return OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
3779 OGRSFDriverH hDriver =
nullptr;
3783 OGRLayerH hLayer = OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
3789 OGRFeatureDefnH defn = OGR_L_GetLayerDefn( hLayer );
3791 for (
int idx : constAttributes )
3794 if ( OGR_FD_GetFieldIndex( defn, fld.
name().toUtf8().constData() ) < 0 )
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=nullptr, QString *newLayer=nullptr)
Create a new vector file writer.
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
Append features to existing layer, but do not create new fields.
Wrapper for iterator of features from vector data provider or vector layer.
Flag to indicate that a new layer can be added to the dataset.
QgsVectorFileWriter::ActionOnExistingFile actionOnExistingFile
Action on existing file.
A rectangle specified with double values.
QgsVectorFileWriter::OptionType type
Details of available driver formats.
static Type to25D(Type type)
Will convert the 25D version of the flat type if supported or Unknown if not supported.
static Type singleType(Type type)
Returns the single type for a WKB type.
static Type multiType(Type type)
Returns the multi type for a WKB type.
int size() const
Returns number of items.
Flag to indicate that new features can be added to an existing layer.
Abstract base class for all rendered symbols.
OperationResult transform(const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection direction=QgsCoordinateTransform::ForwardTransform, bool transformZ=false) SIP_THROW(QgsCsException)
Transforms this geometry as described by the coordinate transform ct.
WriterError mError
Contains error value if construction was not successful.
This class is a composition of two QSettings instances:
static bool isMultiType(Type type)
Returns true if the WKB type is a multi type.
QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
bool forceMulti
Sets to true to force creation of multi* geometries.
QgsWkbTypes::Type wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
QgsVectorFileWriter & operator=(const QgsVectorFileWriter &rh)=delete
QgsVectorFileWriter cannot be copied.
Filter out any formats which do not have spatial support (e.g. those which cannot save geometries) ...
QList< QgsFeature > QgsFeatureList
QgsWkbTypes::Type wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
SymbologyExport mSymbologyExport
virtual QVariant convert(int fieldIdxInLayer, const QVariant &value)
Convert the provided value, for field fieldIdxInLayer.
static void warning(const QString &msg)
Goes to qWarning.
QgsAttributeList attributes
Attributes to export (empty means all unless skipAttributeCreation is set)
int selectedFeatureCount() const
Returns the number of features that are selected in this layer.
QString providerType() const
Returns the provider type (provider key) for this layer.
void setProgress(double progress)
Sets the current progress for the feedback object.
void setRendererScale(double scale)
Sets the renderer map scale.
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...
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QMap< QgsSymbolLayer *, QString > mSymbolLayerTable
static void registerOgrDrivers()
Register OGR drivers ensuring this only happens once.
Container of fields for a vector layer.
virtual bool addMValue(double mValue=0)=0
Adds a measure to the geometry, initialized to a preset value.
A geometry is the spatial representation of a feature.
QVariantMap decodeUri(const QString &providerKey, const QString &uri)
Breaks a provider data source URI into its component paths (e.g.
int symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
QgsUnitTypes::DistanceUnit mapUnits
static QString driverForExtension(const QString &extension)
Returns the OGR driver name for a specified file extension.
QStringList layerOptions
List of OGR layer creation options.
static bool supportsFeatureStyles(const QString &driverName)
Returns true if the specified driverName supports feature styles.
FieldValueConverter()=default
Constructor.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
gdal::ogr_datasource_unique_ptr mDS
bool isValid() const
Returns the status of the layer.
bool hasGeometry() const
Returns true if the feature has an associated geometry.
int count() const
Returns number of items.
static bool hasZ(Type type)
Tests whether a WKB type contains the z-dimension.
static QgsVectorFileWriter::EditionCapabilities editionCapabilities(const QString &datasetName)
Returns edition capabilities for an existing dataset name.
This flag indicates, that a primary key field cannot be guaranteed to be unique and the sink should i...
QgsWkbTypes::Type overrideGeometryType
Set to a valid geometry type to override the default geometry type for the layer. ...
QgsField at(int i) const
Gets field at particular index (must be in range 0..N-1)
QList< QgsSymbolLevel > QgsSymbolLevelOrder
QgsVectorFileWriter::SymbologyExport symbologyExport
Symbology to export.
Create or overwrite file.
QgsVectorFileWriter::SymbologyExport symbologyExport() const
~QgsVectorFileWriter() override
Close opened shapefile for writing.
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
Flag to indicate that new fields can be added to an existing layer. Imply CanAppendToExistingLayer.
bool onlySelectedFeatures
Write only selected features of layer.
virtual QSet< QString > usedAttributes(const QgsRenderContext &context) const =0
Returns a list of attributes required by this renderer.
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
Options to pass to writeAsVectorFormat()
virtual QgsVectorFileWriter::FieldValueConverter * clone() const
Creates a clone of the FieldValueConverter.
void setSymbologyScale(double scale)
Set reference scale for output.
int renderingPass() const
Specifies the rendering pass in which this symbol layer should be rendered.
Type
The WKB type describes the number of dimensions a geometry has.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
QList< QgsSymbol * > QgsSymbolList
QgsFields fields() const FINAL
Returns the list of fields of this layer.
const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=nullptr) override
Adds a single feature to the sink.
std::unique_ptr< std::remove_pointer< OGRFeatureH >::type, OGRFeatureDeleter > ogr_feature_unique_ptr
Scoped OGR feature.
QString typeName() const
Gets the field type.
static QStringList defaultLayerOptions(const QString &driverName)
Returns a list of the default layer options for a specified driver.
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...
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
QString driverName
Unique driver name.
long featureCount(const QString &legendKey) const
Number of features rendered with specified legend key.
void initAttributes(int fieldCount)
Initialize this feature with the given number of fields.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
virtual QString dataSourceUri(bool expandAuthConfig=false) const
Gets the data source specification.
QStringList datasourceOptions
List of OGR data source creation options.
static Type addZ(Type type)
Adds the z dimension to a WKB type and returns the new type.
static OGRwkbGeometryType ogrTypeFromWkbType(QgsWkbTypes::Type type)
Gets the ogr geometry type from an internal QGIS wkb type enum.
This class wraps a request for features to a vector layer (or directly its vector data provider)...
OGRGeometryH createEmptyGeometry(QgsWkbTypes::Type wkbType)
FieldValueConverter * mFieldValueConverter
Field value converter.
static QStringList supportedFormatExtensions(VectorFormatOptions options=SortRecommended)
Returns a list of file extensions for supported formats, e.g "shp", "gpkg".
Create or overwrite layer.
ActionOnExistingFile
Combination of CanAddNewLayer, CanAppendToExistingLayer, CanAddNewFieldsToExistingLayer or CanDeleteL...
QgsFeatureRenderer * renderer()
Returns renderer.
QString driverName
OGR driver to use.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Encapsulate a field in an attribute table or data source.
QgsCoordinateTransformContext transformContext() const
Returns the layer data provider coordinate transform context or a default transform context if the la...
static 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.
QVariant minimumValue(int index) const FINAL
Returns the minimum value for an attribute column or an invalid variant in case of error...
QgsSymbolLayer * symbolLayer(int layer)
Returns the symbol layer at the specified index.
QMap< int, int > mAttrIdxToOgrIdx
Map attribute indizes to OGR field indexes.
QgsRectangle filterExtent
If not empty, only features intersecting the extent will be saved.
OGRSpatialReferenceH mOgrRef
QByteArray asWkb() const
Export the geometry to WKB.
double symbologyScale() const
Returns the reference scale for output.
Append features to existing layer, and create new fields if needed.
QgsAbstractGeometry * get()
Returns a modifiable (non-const) reference to the underlying abstract geometry primitive.
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry)
Creates and returns a new geometry engine.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
Rendering with symbol levels (i.e. implements symbols(), symbolForFeature())
DistanceUnit
Units of distance.
QString errorMessage()
Retrieves error message.
static QString fileFilterString(VectorFormatOptions options=SortRecommended)
Returns filter string that can be used for dialogs.
Contains information about the context of a rendering operation.
bool usingSymbolLevels() const
static QString convertCodecNameForEncodingOption(const QString &codecName)
Converts codec name to string passed to ENCODING layer creation option of OGR Shapefile.
virtual QgsSymbolList symbolsForFeature(const QgsFeature &feature, QgsRenderContext &context) const
Returns list of symbols used for rendering the feature.
bool convertToMultiType()
Converts single type geometry into multitype geometry e.g.
QgsVectorFileWriter::WriterError hasError()
Checks whether there were any errors in constructor.
QString fileEncoding
Encoding to use.
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Sets feature IDs that should be fetched.
bool isCanceled() const
Tells whether the operation has been canceled already.
QList< QgsSymbolLevelItem > QgsSymbolLevel
bool skipAttributeCreation
Only write geometries.
double symbologyScale
Scale of symbology.
virtual QgsSymbolList symbols(QgsRenderContext &context) const
Returns list of symbols used by the renderer.
static QList< QgsVectorFileWriter::DriverDetails > ogrDriverList(VectorFormatOptions options=SortRecommended)
Returns the driver list that can be used for dialogs.
double mSymbologyScale
Scale for symbology export (e.g. for symbols units in map units)
virtual bool addZValue(double zValue=0)=0
Adds a z-dimension to the geometry, initialized to a preset value.
static QStringList defaultDatasetOptions(const QString &driverName)
Returns a list of the default dataset options for a specified driver.
This class represents a coordinate reference system (CRS).
std::unique_ptr< std::remove_pointer< OGRFieldDefnH >::type, OGRFldDeleter > ogr_field_def_unique_ptr
Scoped OGR field definition.
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()).
#define FID_TO_NUMBER(fid)
static bool deleteShapeFile(const QString &fileName)
Delete a shapefile (and its accompanying shx / dbf / prj / qix / qpj / cpg / sbn / sbx / idm / ind) ...
Flag to indicate that an existing layer can be deleted.
QgsCoordinateTransform ct
Transform to reproject exported geometries with, or invalid transform for no transformation.
Interface to convert raw field values to their user-friendly value.
QVariant::Type subType() const
If the field is a collection, gets its element's type.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
bool includeZ
Sets to true to include z dimension in output. This option is only valid if overrideGeometryType is s...
static bool hasM(Type type)
Tests whether a WKB type contains m values.
Custom exception class for Coordinate Reference System related exceptions.
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...
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
QList< int > QgsAttributeList
SaveVectorOptions()
Constructor.
virtual bool dropMValue()=0
Drops any measure values which exist in the geometry.
static bool targetLayerExists(const QString &datasetName, const QString &layerName)
Returns whether the target layer already exists.
QgsVectorFileWriter::FieldValueConverter * fieldValueConverter
Field value converter.
QString layerName
Layer name. If let empty, it will be derived from the filename.
bool nextFeature(QgsFeature &f)
virtual QgsField fieldDefinition(const QgsField &field)
Returns a possibly modified field definition.
std::unique_ptr< std::remove_pointer< OGRDataSourceH >::type, OGRDataSourceDeleter > ogr_datasource_unique_ptr
Scoped OGR data source.
Class for storing the component parts of a RDBMS data source URI (e.g.
bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=nullptr) override
Adds a list of features to the sink.
QgsFeedback * feedback
Optional feedback object allowing cancellation of layer save.
QVariant maximumValue(int index) const FINAL
Returns the maximum value for an attribute column or an invalid variant in case of error...
Represents a vector layer which manages a vector based data sets.
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
static Type flatType(Type type)
Returns the flat type for a WKB type.
Writing was interrupted by manual cancellation.
static QString filterForDriver(const QString &driverName)
Creates a filter for an OGR driver key.
QgsWkbTypes::Type mWkbType
Geometry type which is being used.
virtual QgsFeatureRenderer::Capabilities capabilities()
Returns details about internals of this renderer.
virtual QgsFeatureRenderer * clone() const =0
Create a deep copy of this renderer.
virtual bool dropZValue()=0
Drops any z-dimensions which exist in the geometry.
QgsCoordinateReferenceSystem crs
RenderUnit
Rendering size units.
QString toWkt(WktVariant variant=WKT1_GDAL, bool multiline=false, int indentationWidth=4) const
Returns a WKT representation of this CRS.
QString longName
Descriptive, user friendly name for the driver.
Use recommended sort order, with extremely commonly used formats listed first.
static bool driverMetadata(const QString &driverName, MetaData &driverMetadata)
bool isValid() const
Returns whether this CRS is correctly initialized and usable.