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." ),
1084 QStringLiteral(
"GeoJSON" ),
1085 QObject::tr(
"GeoJSON" ),
1086 QStringLiteral(
"*.geojson" ),
1087 QStringLiteral(
"geojson" ),
1090 QStringLiteral(
"UTF-8" )
1095 datasetOptions.clear();
1096 layerOptions.clear();
1099 QObject::tr(
"Maximum number of figures after decimal separator to write in coordinates. " 1100 "Defaults to 15. Truncation will occur to remove trailing zeros." ),
1105 QObject::tr(
"Whether to start records with the RS=0x1E character (RFC 8142 standard). " 1106 "Defaults to NO: Newline Delimited JSON (geojsonl). \n" 1107 "If set to YES: RFC 8142 standard: GeoJSON Text Sequences (geojsons)." ),
1113 QStringLiteral(
"GeoJSON - Newline Delimited" ),
1114 QObject::tr(
"GeoJSON - Newline Delimited" ),
1115 QStringLiteral(
"*.geojsonl *.geojsons *.json" ),
1116 QStringLiteral(
"json" ),
1119 QStringLiteral(
"UTF-8" )
1124 datasetOptions.clear();
1125 layerOptions.clear();
1128 QObject::tr(
"whether the document must be in RSS 2.0 or Atom 1.0 format. " 1129 "Default value : RSS" ),
1131 << QStringLiteral(
"RSS" )
1132 << QStringLiteral(
"ATOM" ),
1133 QStringLiteral(
"RSS" )
1137 QObject::tr(
"The encoding of location information. Default value : SIMPLE. " 1138 "W3C_GEO only supports point geometries. " 1139 "SIMPLE or W3C_GEO only support geometries in geographic WGS84 coordinates." ),
1141 << QStringLiteral(
"SIMPLE" )
1142 << QStringLiteral(
"GML" )
1143 << QStringLiteral(
"W3C_GEO" ),
1144 QStringLiteral(
"SIMPLE" )
1148 QObject::tr(
"If defined to YES, extension fields will be written. " 1149 "If the field name not found in the base schema matches " 1150 "the foo_bar pattern, foo will be considered as the namespace " 1151 "of the element, and a <foo:bar> element will be written. " 1152 "Otherwise, elements will be written in the <ogr:> namespace." ),
1157 QObject::tr(
"If defined to NO, only <entry> or <item> elements will be written. " 1158 "The user will have to provide the appropriate header and footer of the document." ),
1163 QObject::tr(
"XML content that will be put between the <channel> element and the " 1164 "first <item> element for a RSS document, or between the xml tag and " 1165 "the first <entry> element for an Atom document." ),
1170 QObject::tr(
"Value put inside the <title> element in the header. " 1171 "If not provided, a dummy value will be used as that element is compulsory." ),
1176 QObject::tr(
"Value put inside the <description> element in the header. " 1177 "If not provided, a dummy value will be used as that element is compulsory." ),
1182 QObject::tr(
"Value put inside the <link> element in the header. " 1183 "If not provided, a dummy value will be used as that element is compulsory." ),
1188 QObject::tr(
"Value put inside the <updated> element in the header. " 1189 "Should be formatted as a XML datetime. " 1190 "If not provided, a dummy value will be used as that element is compulsory." ),
1195 QObject::tr(
"Value put inside the <author><name> element in the header. " 1196 "If not provided, a dummy value will be used as that element is compulsory." ),
1201 QObject::tr(
"Value put inside the <id> element in the header. " 1202 "If not provided, a dummy value will be used as that element is compulsory." ),
1208 QStringLiteral(
"GeoRSS" ),
1209 QObject::tr(
"GeoRSS" ),
1210 QStringLiteral(
"*.xml" ),
1211 QStringLiteral(
"xml" ),
1214 QStringLiteral(
"UTF-8" )
1219 datasetOptions.clear();
1220 layerOptions.clear();
1223 QObject::tr(
"If provided, this URI will be inserted as the schema location. " 1224 "Note that the schema file isn't actually accessed by OGR, so it " 1225 "is up to the user to ensure it will match the schema of the OGR " 1226 "produced GML data file." ),
1231 QObject::tr(
"This writes a GML application schema file to a corresponding " 1232 ".xsd file (with the same basename). If INTERNAL is used the " 1233 "schema is written within the GML file, but this is experimental " 1234 "and almost certainly not valid XML. " 1235 "OFF disables schema generation (and is implicit if XSISCHEMAURI is used)." ),
1237 << QStringLiteral(
"EXTERNAL" )
1238 << QStringLiteral(
"INTERNAL" )
1239 << QStringLiteral(
"OFF" ),
1240 QStringLiteral(
"EXTERNAL" )
1244 QObject::tr(
"This is the prefix for the application target namespace." ),
1245 QStringLiteral(
"ogr" )
1249 QObject::tr(
"Can be set to TRUE to avoid writing the prefix of the " 1250 "application target namespace in the GML file." ),
1255 QObject::tr(
"Defaults to 'http://ogr.maptools.org/'. " 1256 "This is the application target namespace." ),
1257 QStringLiteral(
"http://ogr.maptools.org/" )
1261 QObject::tr(
"If not specified, GML2 will be used." ),
1263 << QStringLiteral(
"GML3" )
1264 << QStringLiteral(
"GML3Deegree" )
1265 << QStringLiteral(
"GML3.2" ),
1271 QObject::tr(
"Only valid when FORMAT=GML3/GML3Degree/GML3.2. Default to YES. " 1272 "If YES, SRS with EPSG authority will be written with the " 1273 "'urn:ogc:def:crs:EPSG::' prefix. In the case the SRS is a " 1274 "geographic SRS without explicit AXIS order, but that the same " 1275 "SRS authority code imported with ImportFromEPSGA() should be " 1276 "treated as lat/long, then the function will take care of coordinate " 1277 "order swapping. If set to NO, SRS with EPSG authority will be " 1278 "written with the 'EPSG:' prefix, even if they are in lat/long order." ),
1283 QObject::tr(
"only valid when FORMAT=GML3/GML3Degree/GML3.2) Default to YES. " 1284 "If set to NO, the <gml:boundedBy> element will not be written for " 1290 QObject::tr(
"Default to YES. If YES, the output will be indented with spaces " 1291 "for more readability, but at the expense of file size." ),
1298 QStringLiteral(
"Geography Markup Language [GML]" ),
1299 QObject::tr(
"Geography Markup Language [GML]" ),
1300 QStringLiteral(
"*.gml" ),
1301 QStringLiteral(
"gml" ),
1304 QStringLiteral(
"UTF-8" )
1309 datasetOptions.clear();
1310 layerOptions.clear();
1313 QObject::tr(
"Human-readable identifier (e.g. short name) for the layer content" ),
1318 QObject::tr(
"Human-readable description for the layer content" ),
1323 QObject::tr(
"Name for the feature identifier column" ),
1324 QStringLiteral(
"fid" )
1328 QObject::tr(
"Name for the geometry column" ),
1329 QStringLiteral(
"geom" )
1333 QObject::tr(
"If a spatial index must be created." ),
1339 QStringLiteral(
"GeoPackage" ),
1340 QObject::tr(
"GeoPackage" ),
1341 QStringLiteral(
"*.gpkg" ),
1342 QStringLiteral(
"gpkg" ),
1345 QStringLiteral(
"UTF-8" )
1350 datasetOptions.clear();
1351 layerOptions.clear();
1355 QStringLiteral(
"Generic Mapping Tools [GMT]" ),
1356 QObject::tr(
"Generic Mapping Tools [GMT]" ),
1357 QStringLiteral(
"*.gmt" ),
1358 QStringLiteral(
"gmt" ),
1365 datasetOptions.clear();
1366 layerOptions.clear();
1369 QObject::tr(
"By default when writing a layer whose features are of " 1370 "type wkbLineString, the GPX driver chooses to write " 1371 "them as routes. If FORCE_GPX_TRACK=YES is specified, " 1372 "they will be written as tracks." ),
1377 QObject::tr(
"By default when writing a layer whose features are of " 1378 "type wkbMultiLineString, the GPX driver chooses to write " 1379 "them as tracks. If FORCE_GPX_ROUTE=YES is specified, " 1380 "they will be written as routes, provided that the multilines " 1381 "are composed of only one single line." ),
1386 QObject::tr(
"If GPX_USE_EXTENSIONS=YES is specified, " 1387 "extra fields will be written inside the <extensions> tag." ),
1392 QObject::tr(
"Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS_URL " 1393 "is set. The namespace value used for extension tags. By default, 'ogr'." ),
1394 QStringLiteral(
"ogr" )
1398 QObject::tr(
"Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS " 1399 "is set. The namespace URI. By default, 'http://osgeo.org/gdal'." ),
1400 QStringLiteral(
"http://osgeo.org/gdal" )
1404 QObject::tr(
"By default files are created with the line termination " 1405 "conventions of the local platform (CR/LF on win32 or LF " 1406 "on all other systems). This may be overridden through use " 1407 "of the LINEFORMAT layer creation option which may have a value " 1408 "of CRLF (DOS format) or LF (Unix format)." ),
1410 << QStringLiteral(
"CRLF" )
1411 << QStringLiteral(
"LF" ),
1418 QStringLiteral(
"GPS eXchange Format [GPX]" ),
1419 QObject::tr(
"GPS eXchange Format [GPX]" ),
1420 QStringLiteral(
"*.gpx" ),
1421 QStringLiteral(
"gpx" ),
1424 QStringLiteral(
"UTF-8" )
1429 datasetOptions.clear();
1430 layerOptions.clear();
1434 QStringLiteral(
"INTERLIS 1" ),
1435 QObject::tr(
"INTERLIS 1" ),
1436 QStringLiteral(
"*.itf *.xml *.ili" ),
1437 QStringLiteral(
"ili" ),
1444 datasetOptions.clear();
1445 layerOptions.clear();
1449 QStringLiteral(
"INTERLIS 2" ),
1450 QObject::tr(
"INTERLIS 2" ),
1451 QStringLiteral(
"*.xtf *.xml *.ili" ),
1452 QStringLiteral(
"ili" ),
1459 datasetOptions.clear();
1460 layerOptions.clear();
1463 QObject::tr(
"Allows you to specify the field to use for the KML <name> element." ),
1464 QStringLiteral(
"Name" )
1468 QObject::tr(
"Allows you to specify the field to use for the KML <description> element." ),
1469 QStringLiteral(
"Description" )
1473 QObject::tr(
"Allows you to specify the AltitudeMode to use for KML geometries. " 1474 "This will only affect 3D geometries and must be one of the valid KML options." ),
1476 << QStringLiteral(
"clampToGround" )
1477 << QStringLiteral(
"relativeToGround" )
1478 << QStringLiteral(
"absolute" ),
1479 QStringLiteral(
"relativeToGround" )
1482 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,2,0) 1484 QObject::tr(
"The DOCUMENT_ID datasource creation option can be used to specified " 1485 "the id of the root <Document> node. The default value is root_doc." ),
1486 QStringLiteral(
"root_doc" )
1492 QStringLiteral(
"Keyhole Markup Language [KML]" ),
1493 QObject::tr(
"Keyhole Markup Language [KML]" ),
1494 QStringLiteral(
"*.kml" ),
1495 QStringLiteral(
"kml" ),
1498 QStringLiteral(
"UTF-8" )
1503 datasetOptions.clear();
1504 layerOptions.clear();
1506 auto insertMapInfoOptions = []( QMap<QString, QgsVectorFileWriter::Option *> &datasetOptions, QMap<QString, QgsVectorFileWriter::Option *> &layerOptions )
1509 QObject::tr(
"Use this to turn on 'quick spatial index mode'. " 1510 "In this mode writing files can be about 5 times faster, " 1511 "but spatial queries can be up to 30 times slower." ),
1513 << QStringLiteral(
"QUICK" )
1514 << QStringLiteral(
"OPTIMIZED" ),
1515 QStringLiteral(
"QUICK" ),
1520 QObject::tr(
"(multiples of 512): Block size for .map files. Defaults " 1521 "to 512. MapInfo 15.2 and above creates .tab files with a " 1522 "blocksize of 16384 bytes. Any MapInfo version should be " 1523 "able to handle block sizes from 512 to 32256." ),
1527 QObject::tr(
"xmin,ymin,xmax,ymax: Define custom layer bounds to increase the " 1528 "accuracy of the coordinates. Note: the geometry of written " 1529 "features must be within the defined box." ),
1533 insertMapInfoOptions( datasetOptions, layerOptions );
1537 QStringLiteral(
"Mapinfo" ),
1538 QObject::tr(
"Mapinfo TAB" ),
1539 QStringLiteral(
"*.tab" ),
1540 QStringLiteral(
"tab" ),
1545 datasetOptions.clear();
1546 layerOptions.clear();
1547 insertMapInfoOptions( datasetOptions, layerOptions );
1552 QStringLiteral(
"Mapinfo" ),
1553 QObject::tr(
"Mapinfo MIF" ),
1554 QStringLiteral(
"*.mif" ),
1555 QStringLiteral(
"mif" ),
1562 datasetOptions.clear();
1563 layerOptions.clear();
1566 QObject::tr(
"Determine whether 2D (seed_2d.dgn) or 3D (seed_3d.dgn) " 1567 "seed file should be used. This option is ignored if the SEED option is provided." ),
1572 QObject::tr(
"Override the seed file to use." ),
1577 QObject::tr(
"Indicate whether the whole seed file should be copied. " 1578 "If not, only the first three elements will be copied." ),
1583 QObject::tr(
"Indicates whether the color table should be copied from the seed file." ),
1588 QObject::tr(
"Override the master unit name from the seed file with " 1589 "the provided one or two character unit name." ),
1594 QObject::tr(
"Override the sub unit name from the seed file with the provided " 1595 "one or two character unit name." ),
1600 QObject::tr(
"Override the number of subunits per master unit. " 1601 "By default the seed file value is used." ),
1606 QObject::tr(
"Override the number of UORs (Units of Resolution) " 1607 "per sub unit. By default the seed file value is used." ),
1612 QObject::tr(
"ORIGIN=x,y,z: Override the origin of the design plane. " 1613 "By default the origin from the seed file is used." ),
1619 QStringLiteral(
"Microstation DGN" ),
1620 QObject::tr(
"Microstation DGN" ),
1621 QStringLiteral(
"*.dgn" ),
1622 QStringLiteral(
"dgn" ),
1629 datasetOptions.clear();
1630 layerOptions.clear();
1633 QObject::tr(
"Should update files be incorporated into the base data on the fly." ),
1635 << QStringLiteral(
"APPLY" )
1636 << QStringLiteral(
"IGNORE" ),
1637 QStringLiteral(
"APPLY" )
1641 QObject::tr(
"Should multipoint soundings be split into many single point sounding features. " 1642 "Multipoint geometries are not well handled by many formats, " 1643 "so it can be convenient to split single sounding features with many points " 1644 "into many single point features." ),
1649 QObject::tr(
"Should a DEPTH attribute be added on SOUNDG features and assign the depth " 1650 "of the sounding. This should only be enabled when SPLIT_MULTIPOINT is " 1656 QObject::tr(
"Should all the low level geometry primitives be returned as special " 1657 "IsolatedNode, ConnectedNode, Edge and Face layers." ),
1662 QObject::tr(
"If enabled, numeric attributes assigned an empty string as a value will " 1663 "be preserved as a special numeric value. This option should not generally " 1664 "be needed, but may be useful when translated S-57 to S-57 losslessly." ),
1669 QObject::tr(
"Should LNAM and LNAM_REFS fields be attached to features capturing " 1670 "the feature to feature relationships in the FFPT group of the S-57 file." ),
1675 QObject::tr(
"Should additional attributes relating features to their underlying " 1676 "geometric primitives be attached. These are the values of the FSPT group, " 1677 "and are primarily needed when doing S-57 to S-57 translations." ),
1682 QObject::tr(
"Should attribute values be recoded to UTF-8 from the character encoding " 1683 "specified in the S57 DSSI record." ),
1691 QStringLiteral(
"S-57 Base file" ),
1692 QObject::tr(
"S-57 Base file" ),
1693 QStringLiteral(
"*.000" ),
1694 QStringLiteral(
"000" ),
1701 datasetOptions.clear();
1702 layerOptions.clear();
1706 QStringLiteral(
"Spatial Data Transfer Standard [SDTS]" ),
1707 QObject::tr(
"Spatial Data Transfer Standard [SDTS]" ),
1708 QStringLiteral(
"*catd.ddf" ),
1709 QStringLiteral(
"ddf" ),
1716 datasetOptions.clear();
1717 layerOptions.clear();
1720 QObject::tr(
"Can be used to avoid creating the geometry_columns and spatial_ref_sys " 1721 "tables in a new database. By default these metadata tables are created " 1722 "when a new database is created." ),
1728 QStringLiteral(
"NO" )
1733 QStringLiteral(
"NO" )
1737 QObject::tr(
"Controls the format used for the geometry column. Defaults to WKB. " 1738 "This is generally more space and processing efficient, but harder " 1739 "to inspect or use in simple applications than WKT (Well Known Text)." ),
1741 << QStringLiteral(
"WKB" )
1742 << QStringLiteral(
"WKT" ),
1743 QStringLiteral(
"WKB" )
1747 QObject::tr(
"Controls whether layer and field names will be laundered for easier use " 1748 "in SQLite. Laundered names will be converted to lower case and some special " 1749 "characters(' - #) will be changed to underscores." ),
1754 QStringLiteral(
"NO" )
1758 QStringLiteral(
"NO" )
1766 QObject::tr(
"column_name1[,column_name2, …] A list of (String) columns that " 1767 "must be compressed with ZLib DEFLATE algorithm. This might be beneficial " 1768 "for databases that have big string blobs. However, use with care, since " 1769 "the value of such columns will be seen as compressed binary content with " 1770 "other SQLite utilities (or previous OGR versions). With OGR, when inserting, " 1771 "modifying or querying compressed columns, compression/decompression is " 1772 "done transparently. However, such columns cannot be (easily) queried with " 1773 "an attribute filter or WHERE clause. Note: in table definition, such columns " 1774 "have the 'VARCHAR_deflate' declaration type." ),
1780 QStringLiteral(
"SQLite" ),
1781 QObject::tr(
"SQLite" ),
1782 QStringLiteral(
"*.sqlite" ),
1783 QStringLiteral(
"sqlite" ),
1786 QStringLiteral(
"UTF-8" )
1791 datasetOptions.clear();
1792 layerOptions.clear();
1795 QObject::tr(
"Can be used to avoid creating the geometry_columns and spatial_ref_sys " 1796 "tables in a new database. By default these metadata tables are created " 1797 "when a new database is created." ),
1802 QStringLiteral(
"YES" )
1806 QObject::tr(
"Insert the content of the EPSG CSV files into the spatial_ref_sys table. " 1807 "Set to NO for regular SQLite databases." ),
1812 QStringLiteral(
"SPATIALITE" )
1816 QObject::tr(
"Controls whether layer and field names will be laundered for easier use " 1817 "in SQLite. Laundered names will be converted to lower case and some special " 1818 "characters(' - #) will be changed to underscores." ),
1823 QObject::tr(
"If the database is of the SpatiaLite flavor, and if OGR is linked " 1824 "against libspatialite, this option can be used to control if a spatial " 1825 "index must be created." ),
1830 QObject::tr(
"If the format of the geometry BLOB is of the SpatiaLite flavor, " 1831 "this option can be used to control if the compressed format for " 1832 "geometries (LINESTRINGs, POLYGONs) must be used." ),
1837 QObject::tr(
"Used to force the SRID number of the SRS associated with the layer. " 1838 "When this option isn't specified and that a SRS is associated with the " 1839 "layer, a search is made in the spatial_ref_sys to find a match for the " 1840 "SRS, and, if there is no match, a new entry is inserted for the SRS in " 1841 "the spatial_ref_sys table. When the SRID option is specified, this " 1842 "search (and the eventual insertion of a new entry) will not be done: " 1843 "the specified SRID is used as such." ),
1848 QObject::tr(
"column_name1[,column_name2, …] A list of (String) columns that " 1849 "must be compressed with ZLib DEFLATE algorithm. This might be beneficial " 1850 "for databases that have big string blobs. However, use with care, since " 1851 "the value of such columns will be seen as compressed binary content with " 1852 "other SQLite utilities (or previous OGR versions). With OGR, when inserting, " 1853 "modifying or queryings compressed columns, compression/decompression is " 1854 "done transparently. However, such columns cannot be (easily) queried with " 1855 "an attribute filter or WHERE clause. Note: in table definition, such columns " 1856 "have the 'VARCHAR_deflate' declaration type." ),
1862 QStringLiteral(
"SpatiaLite" ),
1863 QObject::tr(
"SpatiaLite" ),
1864 QStringLiteral(
"*.sqlite" ),
1865 QStringLiteral(
"sqlite" ),
1868 QStringLiteral(
"UTF-8" )
1872 datasetOptions.clear();
1873 layerOptions.clear();
1876 QObject::tr(
"Override the header file used - in place of header.dxf." ),
1881 QObject::tr(
"Override the trailer file used - in place of trailer.dxf." ),
1887 QStringLiteral(
"AutoCAD DXF" ),
1888 QObject::tr(
"AutoCAD DXF" ),
1889 QStringLiteral(
"*.dxf" ),
1890 QStringLiteral(
"dxf" ),
1897 datasetOptions.clear();
1898 layerOptions.clear();
1901 QObject::tr(
"Indicates the GeoConcept export file extension. " 1902 "TXT was used by earlier releases of GeoConcept. GXT is currently used." ),
1904 << QStringLiteral(
"GXT" )
1905 << QStringLiteral(
"TXT" ),
1906 QStringLiteral(
"GXT" )
1910 QObject::tr(
"Path to the GCT: the GCT file describes the GeoConcept types definitions: " 1911 "In this file, every line must start with //# followed by a keyword. " 1912 "Lines starting with // are comments." ),
1917 QObject::tr(
"Defines the feature to be created. The TYPE corresponds to one of the Name " 1918 "found in the GCT file for a type section. The SUBTYPE corresponds to one of " 1919 "the Name found in the GCT file for a sub-type section within the previous " 1926 QStringLiteral(
"Geoconcept" ),
1927 QObject::tr(
"Geoconcept" ),
1928 QStringLiteral(
"*.gxt *.txt" ),
1929 QStringLiteral(
"gxt" ),
1936 datasetOptions.clear();
1937 layerOptions.clear();
1940 QObject::tr(
"When this option is set, the new layer will be created inside the named " 1941 "FeatureDataset folder. If the folder does not already exist, it will be created." ),
1946 QObject::tr(
"Set name of geometry column in new layer. Defaults to 'SHAPE'." ),
1947 QStringLiteral(
"SHAPE" )
1951 QObject::tr(
"Name of the OID column to create. Defaults to 'OBJECTID'." ),
1952 QStringLiteral(
"OBJECTID" )
1957 QStringLiteral(
"ESRI FileGDB" ),
1958 QObject::tr(
"ESRI FileGDB" ),
1959 QStringLiteral(
"*.gdb" ),
1960 QStringLiteral(
"gdb" ),
1963 QStringLiteral(
"UTF-8" )
1968 datasetOptions.clear();
1969 layerOptions.clear();
1972 QObject::tr(
"By default, the driver will try to detect the data type of fields. If set " 1973 "to STRING, all fields will be of String type." ),
1975 << QStringLiteral(
"AUTO" )
1976 << QStringLiteral(
"STRING" ),
1977 QStringLiteral(
"AUTO" ),
1982 QObject::tr(
"By default, the driver will read the first lines of each sheet to detect " 1983 "if the first line might be the name of columns. If set to FORCE, the driver " 1984 "will consider the first line as the header line. If set to " 1985 "DISABLE, it will be considered as the first feature. Otherwise " 1986 "auto-detection will occur." ),
1988 << QStringLiteral(
"FORCE" )
1989 << QStringLiteral(
"DISABLE" )
1990 << QStringLiteral(
"AUTO" ),
1991 QStringLiteral(
"AUTO" ),
1997 QStringLiteral(
"MS Office Open XML spreadsheet" ),
1998 QObject::tr(
"MS Office Open XML spreadsheet [XLSX]" ),
1999 QStringLiteral(
"*.xlsx" ),
2000 QStringLiteral(
"xlsx" ),
2003 QStringLiteral(
"UTF-8" )
2008 datasetOptions.clear();
2009 layerOptions.clear();
2012 QObject::tr(
"By default, the driver will try to detect the data type of fields. If set " 2013 "to STRING, all fields will be of String type." ),
2015 << QStringLiteral(
"AUTO" )
2016 << QStringLiteral(
"STRING" ),
2017 QStringLiteral(
"AUTO" ),
2022 QObject::tr(
"By default, the driver will read the first lines of each sheet to detect " 2023 "if the first line might be the name of columns. If set to FORCE, the driver " 2024 "will consider the first line as the header line. If set to " 2025 "DISABLE, it will be considered as the first feature. Otherwise " 2026 "auto-detection will occur." ),
2028 << QStringLiteral(
"FORCE" )
2029 << QStringLiteral(
"DISABLE" )
2030 << QStringLiteral(
"AUTO" ),
2031 QStringLiteral(
"AUTO" ),
2037 QStringLiteral(
"Open Document Spreadsheet" ),
2038 QObject::tr(
"Open Document Spreadsheet [ODS]" ),
2039 QStringLiteral(
"*.ods" ),
2040 QStringLiteral(
"ods" ),
2043 QStringLiteral(
"UTF-8" )
2048 QgsVectorFileWriterMetadataContainer(
const QgsVectorFileWriterMetadataContainer &other ) =
delete;
2049 QgsVectorFileWriterMetadataContainer &
operator=(
const QgsVectorFileWriterMetadataContainer &other ) =
delete;
2050 ~QgsVectorFileWriterMetadataContainer()
2054 for (
auto optionIt = it.value().driverOptions.constBegin(); optionIt != it.value().driverOptions.constEnd(); ++optionIt )
2055 delete optionIt.value();
2056 for (
auto optionIt = it.value().layerOptions.constBegin(); optionIt != it.value().layerOptions.constEnd(); ++optionIt )
2057 delete optionIt.value();
2068 static QgsVectorFileWriterMetadataContainer sDriverMetadata;
2069 QMap<QString, MetaData>::ConstIterator it = sDriverMetadata.driverMetadata.constBegin();
2071 for ( ; it != sDriverMetadata.driverMetadata.constEnd(); ++it )
2073 if ( it.key().startsWith( driverName ) || it.value().longName.startsWith( driverName ) )
2075 driverMetadata = it.value();
2088 return QStringList();
2097 return QStringList();
2104 OGRwkbGeometryType ogrType =
static_cast<OGRwkbGeometryType
>( type );
2130 QgsFeatureList::iterator fIt = features.begin();
2132 for ( ; fIt != features.end(); ++fIt )
2149 mRenderContext.expressionContext().setFeature( feature );
2152 QString styleString;
2153 QString currentStyle;
2155 QgsSymbolList::const_iterator symbolIt = symbols.constBegin();
2156 for ( ; symbolIt != symbols.constEnd(); ++symbolIt )
2158 int nSymbolLayers = ( *symbolIt )->symbolLayerCount();
2159 for (
int i = 0; i < nSymbolLayers; ++i )
2162 QMap< QgsSymbolLayer *, QString >::const_iterator it =
mSymbolLayerTable.find( ( *symbolIt )->symbolLayer( i ) );
2168 double mmsf = mmScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
2169 double musf = mapUnitScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
2171 currentStyle = ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf );
2175 if ( symbolIt != symbols.constBegin() || i != 0 )
2177 styleString.append(
';' );
2179 styleString.append( currentStyle );
2183 OGR_F_SetStyleString( poFeature.get(), currentStyle.toLocal8Bit().constData() );
2184 if ( !writeFeature(
mLayer, poFeature.get() ) )
2191 OGR_F_SetStyleString( poFeature.get(), styleString.toLocal8Bit().constData() );
2196 if ( !writeFeature(
mLayer, poFeature.get() ) )
2213 if ( fid > std::numeric_limits<int>::max() )
2215 QgsDebugMsg( QStringLiteral(
"feature id %1 too large." ).arg( fid ) );
2216 OGRErr err = OGR_F_SetFID( poFeature.get(),
static_cast<long>( fid ) );
2217 if ( err != OGRERR_NONE )
2219 QgsDebugMsg( QStringLiteral(
"Failed to set feature id to %1: %2 (OGR error: %3)" )
2220 .arg( feature.
id() )
2221 .arg( err ).arg( CPLGetLastErrorMsg() )
2229 int fldIdx = it.key();
2230 int ogrField = it.value();
2232 QVariant attrValue = feature.
attribute( fldIdx );
2235 if ( !attrValue.isValid() || attrValue.isNull() )
2244 #ifdef OGRNullMarker 2245 OGR_F_SetFieldNull( poFeature.get(), ogrField );
2256 switch ( field.
type() )
2259 OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
2261 case QVariant::LongLong:
2262 OGR_F_SetFieldInteger64( poFeature.get(), ogrField, attrValue.toLongLong() );
2264 case QVariant::Bool:
2265 OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
2267 case QVariant::String:
2268 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toString() ).constData() );
2270 case QVariant::Double:
2271 OGR_F_SetFieldDouble( poFeature.get(), ogrField, attrValue.toDouble() );
2273 case QVariant::Date:
2274 OGR_F_SetFieldDateTime( poFeature.get(), ogrField,
2275 attrValue.toDate().year(),
2276 attrValue.toDate().month(),
2277 attrValue.toDate().day(),
2280 case QVariant::DateTime:
2283 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toDateTime().toString( QStringLiteral(
"yyyy/MM/dd hh:mm:ss.zzz" ) ) ).constData() );
2287 OGR_F_SetFieldDateTime( poFeature.get(), ogrField,
2288 attrValue.toDateTime().date().year(),
2289 attrValue.toDateTime().date().month(),
2290 attrValue.toDateTime().date().day(),
2291 attrValue.toDateTime().time().hour(),
2292 attrValue.toDateTime().time().minute(),
2293 attrValue.toDateTime().time().second(),
2297 case QVariant::Time:
2300 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toString() ).constData() );
2304 OGR_F_SetFieldDateTime( poFeature.get(), ogrField,
2306 attrValue.toTime().hour(),
2307 attrValue.toTime().minute(),
2308 attrValue.toTime().second(),
2313 case QVariant::ByteArray:
2315 const QByteArray ba = attrValue.toByteArray();
2316 OGR_F_SetFieldBinary( poFeature.get(), ogrField, ba.size(),
const_cast< GByte *
>(
reinterpret_cast< const GByte *
>( ba.data() ) ) );
2320 case QVariant::Invalid:
2323 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,4,0) 2324 case QVariant::List:
2326 if ( field.
subType() == QVariant::String )
2328 QStringList list = attrValue.toStringList();
2329 if ( supportsStringList )
2331 int count = list.count();
2332 char **lst =
new char *[count + 1];
2336 for ( QString
string : list )
2338 lst[pos] =
mCodec->fromUnicode(
string ).data();
2342 lst[count] =
nullptr;
2343 OGR_F_SetFieldStringList( poFeature.get(), ogrField, lst );
2347 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( list.join(
',' ) ).constData() );
2356 mErrorMessage = QObject::tr(
"Invalid variant type for field %1[%2]: received %3 with type %4" )
2359 .arg( attrValue.typeName(),
2360 attrValue.toString() );
2383 OGRGeometryH mGeom2 =
nullptr;
2429 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
2430 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
2436 QByteArray wkb( geom.
asWkb() );
2437 OGRErr err = OGR_G_ImportFromWkb( mGeom2, reinterpret_cast<unsigned char *>( const_cast<char *>( wkb.constData() ) ), wkb.length() );
2438 if ( err != OGRERR_NONE )
2440 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
2441 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
2448 OGR_F_SetGeometryDirectly( poFeature.get(), mGeom2 );
2452 QByteArray wkb( geom.
asWkb() );
2454 OGRErr err = OGR_G_ImportFromWkb( ogrGeom, reinterpret_cast<unsigned char *>( const_cast<char *>( wkb.constData() ) ), wkb.length() );
2455 if ( err != OGRERR_NONE )
2457 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
2458 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
2465 OGR_F_SetGeometryDirectly( poFeature.get(), ogrGeom );
2480 for (
int i = 0; i < attributes.size(); i++ )
2482 if ( omap.find( i ) != omap.end() )
2487 bool QgsVectorFileWriter::writeFeature( OGRLayerH layer, OGRFeatureH feature )
2489 if ( OGR_L_CreateFeature( layer, feature ) != OGRERR_NONE )
2491 mErrorMessage = QObject::tr(
"Feature creation error (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
2501 if ( mUsingTransaction )
2503 if ( OGRERR_NONE != OGR_L_CommitTransaction(
mLayer ) )
2505 QgsDebugMsg( QStringLiteral(
"Error while committing transaction on OGRLayer." ) );
2513 OSRDestroySpatialReference(
mOgrRef );
2519 const QString &fileName,
2520 const QString &fileEncoding,
2522 const QString &driverName,
2525 const QStringList &datasourceOptions,
2526 const QStringList &layerOptions,
2527 bool skipAttributeCreation,
2528 QString *newFilename,
2540 if ( destCRS.
isValid() && layer )
2546 errorMessage, datasourceOptions, layerOptions, skipAttributeCreation,
2547 newFilename, symbologyExport, symbologyScale, filterExtent,
2548 overrideGeometryType, forceMulti, includeZ, attributes,
2549 fieldValueConverter, newLayer );
2554 const QString &fileName,
2555 const QString &fileEncoding,
2557 const QString &driverName,
2560 const QStringList &datasourceOptions,
2561 const QStringList &layerOptions,
2562 bool skipAttributeCreation,
2563 QString *newFilename,
2591 return writeAsVectorFormat( layer, fileName, options, newFilename, errorMessage, newLayer );
2596 : driverName( QStringLiteral(
"GPKG" ) )
2604 if ( !layer || !layer->
isValid() )
2612 details.sourceCrs = layer->
crs();
2613 details.sourceWkbType = layer->
wkbType();
2614 details.sourceFields = layer->
fields();
2623 if ( details.storageType == QLatin1String(
"ESRI Shapefile" ) )
2631 details.geometryTypeScanIterator = layer->
getFeatures( req );
2635 details.renderContext.setExpressionContext( details.expressionContext );
2636 details.renderContext.setRendererScale( options.
symbologyScale );
2638 details.shallTransform =
false;
2643 details.shallTransform =
true;
2648 details.outputCrs = details.sourceCrs;
2651 details.destWkbType = details.sourceWkbType;
2665 details.attributes.clear();
2666 else if ( details.attributes.isEmpty() )
2668 const QgsAttributeList allAttributes = details.sourceFields.allAttributesList();
2669 for (
int idx : allAttributes )
2671 QgsField fld = details.sourceFields.at( idx );
2672 if ( details.providerType == QLatin1String(
"oracle" ) && fld.
typeName().contains( QLatin1String(
"SDO_GEOMETRY" ) ) )
2674 details.attributes.append( idx );
2678 if ( !details.attributes.isEmpty() )
2680 for (
int attrIdx : qgis::as_const( details.attributes ) )
2682 details.outputFields.append( details.sourceFields.at( attrIdx ) );
2688 if ( details.providerType == QLatin1String(
"spatialite" ) )
2690 for (
int i = 0; i < details.outputFields.size(); i++ )
2692 if ( details.outputFields.at( i ).type() == QVariant::LongLong )
2696 if ( std::max( std::llabs( min.toLongLong() ), std::llabs( max.toLongLong() ) ) < std::numeric_limits<int>::max() )
2698 details.outputFields[i].setType( QVariant::Int );
2706 addRendererAttributes( details.renderer.get(), details.renderContext, details.sourceFields, details.attributes );
2716 bool useFilterRect =
true;
2717 if ( details.shallTransform )
2726 useFilterRect =
false;
2729 if ( useFilterRect )
2731 req.setFilterRect( filterRect );
2735 details.filterRectEngine->prepareGeometry();
2737 details.sourceFeatureIterator = layer->
getFeatures( req );
2747 int lastProgressReport = 0;
2748 long total = details.featureCount;
2751 if ( details.providerType == QLatin1String(
"ogr" ) && !details.dataSourceUri.isEmpty() )
2753 QString srcFileName( details.providerUriParams.value( QLatin1String(
"path" ) ).toString() );
2754 if ( QFile::exists( srcFileName ) && QFileInfo( fileName ).canonicalFilePath() == QFileInfo( srcFileName ).canonicalFilePath() )
2758 if ( !( ( options.
driverName == QLatin1String(
"GPKG" ) ||
2759 options.
driverName == QLatin1String(
"SpatiaLite" ) ||
2760 options.
driverName == QLatin1String(
"SQLite" ) ) &&
2761 options.
layerName != details.providerUriParams.value( QLatin1String(
"layerName" ) ) ) )
2764 *errorMessage = QObject::tr(
"Cannot overwrite a OGR layer in place" );
2784 int newProgress =
static_cast<int>( ( 5.0 * scanned ) / total );
2785 if ( newProgress != lastProgressReport )
2787 lastProgressReport = newProgress;
2802 std::unique_ptr< QgsVectorFileWriter > writer =
2803 qgis::make_unique< QgsVectorFileWriter >( fileName,
2804 options.
fileEncoding, details.outputFields, destWkbType,
2826 *errorMessage = writer->errorMessage();
2832 errorMessage->clear();
2854 int n = 0, errors = 0;
2863 writer->startRender( details.renderer.get(), details.sourceFields );
2865 writer->resetMap( details.attributes );
2867 writer->mFields = details.sourceFields;
2871 int initialProgress = lastProgressReport;
2872 while ( details.sourceFeatureIterator.nextFeature( fet ) )
2883 int newProgress =
static_cast<int>( initialProgress + ( ( 100.0 - initialProgress ) * saved ) / total );
2884 if ( newProgress < 100 && newProgress != lastProgressReport )
2886 lastProgressReport = newProgress;
2891 if ( details.shallTransform )
2904 QString msg = QObject::tr(
"Failed to transform a point while drawing a feature with ID '%1'. Writing stopped. (Exception: %2)" )
2905 .arg( fet.
id() ).arg( e.
what() );
2908 *errorMessage = msg;
2922 if ( !writer->addFeatureWithStyle( fet, writer->mRenderer.get(), mapUnits ) )
2925 if ( err !=
NoError && errorMessage )
2927 if ( errorMessage->isEmpty() )
2929 *errorMessage = QObject::tr(
"Feature write errors:" );
2931 *errorMessage +=
'\n' + writer->errorMessage();
2935 if ( errors > 1000 )
2939 *errorMessage += QObject::tr(
"Stopping after %1 errors" ).arg( errors );
2949 writer->stopRender();
2951 if ( errors > 0 && errorMessage && n > 0 )
2953 *errorMessage += QObject::tr(
"\nOnly %1 of %2 features written." ).arg( n - errors ).arg( n );
2961 const QString &fileName,
2963 QString *newFilename,
2964 QString *errorMessage,
2967 QgsVectorFileWriter::PreparedWriterDetails details;
2968 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
2972 return writeAsVectorFormat( details, fileName, options, newFilename, errorMessage, newLayer );
2978 QFileInfo fi( fileName );
2979 QDir dir = fi.dir();
2982 const char *suffixes[] = {
".shp",
".shx",
".dbf",
".prj",
".qix",
".qpj",
".cpg",
".sbn",
".sbx",
".idm",
".ind" };
2983 for ( std::size_t i = 0; i <
sizeof( suffixes ) /
sizeof( *suffixes ); i++ )
2985 filter << fi.completeBaseName() + suffixes[i];
2989 const auto constEntryList = dir.entryList( filter );
2990 for (
const QString &file : constEntryList )
2992 QFile f( dir.canonicalPath() +
'/' + file );
2995 QgsDebugMsg( QStringLiteral(
"Removing file %1 failed: %2" ).arg( file, f.errorString() ) );
3011 QList< FilterFormatDetails > results;
3014 int const drvCount = OGRGetDriverCount();
3016 for (
int i = 0; i < drvCount; ++i )
3018 OGRSFDriverH drv = OGRGetDriver( i );
3021 QString drvName = OGR_Dr_GetName( drv );
3023 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,3,0) 3024 GDALDriverH gdalDriver = GDALGetDriverByName( drvName.toLocal8Bit().constData() );
3025 char **metadata =
nullptr;
3028 metadata = GDALGetMetadata( gdalDriver,
nullptr );
3031 bool nonSpatialFormat = CSLFetchBoolean( metadata, GDAL_DCAP_NONSPATIAL,
false );
3033 bool nonSpatialFormat = ( drvName == QLatin1String(
"ODS" ) || drvName == QLatin1String(
"XLSX" ) || drvName == QLatin1String(
"XLS" ) );
3036 if ( OGR_Dr_TestCapability( drv,
"CreateDataSource" ) != 0 )
3041 if ( nonSpatialFormat )
3046 if ( filterString.isEmpty() )
3053 globs = metadata.
glob.toLower().split(
' ' );
3059 details.
globs = globs;
3070 if ( a.
driverName == QLatin1String(
"GPKG" ) )
3072 else if ( b.driverName == QLatin1String(
"GPKG" ) )
3074 else if ( a.
driverName == QLatin1String(
"ESRI Shapefile" ) )
3076 else if ( b.driverName == QLatin1String(
"ESRI Shapefile" ) )
3080 return a.
filterString.toLower().localeAwareCompare( b.filterString.toLower() ) < 0;
3089 QSet< QString > extensions;
3091 const QRegularExpression rx( QStringLiteral(
"\\*\\.(.*)$" ) );
3095 for (
const QString &glob : format.globs )
3097 const QRegularExpressionMatch match = rx.match( glob );
3098 if ( !match.hasMatch() )
3101 const QString matched = match.captured( 1 );
3102 extensions.insert( matched );
3106 QStringList extensionList = extensions.toList();
3108 std::sort( extensionList.begin(), extensionList.end(), [options](
const QString & a,
const QString & b ) ->
bool 3112 if ( a == QLatin1String(
"gpkg" ) )
3114 else if ( b == QLatin1String(
"gpkg" ) )
3116 else if ( a == QLatin1String(
"shp" ) )
3118 else if ( b == QLatin1String(
"shp" ) )
3122 return a.toLower().localeAwareCompare( b.toLower() ) < 0;
3125 return extensionList;
3130 QList< QgsVectorFileWriter::DriverDetails > results;
3133 const int drvCount = OGRGetDriverCount();
3135 QStringList writableDrivers;
3136 for (
int i = 0; i < drvCount; ++i )
3138 OGRSFDriverH drv = OGRGetDriver( i );
3141 QString drvName = OGR_Dr_GetName( drv );
3147 if ( drvName == QLatin1String(
"ODS" ) || drvName == QLatin1String(
"XLSX" ) || drvName == QLatin1String(
"XLS" ) )
3151 if ( drvName == QLatin1String(
"ESRI Shapefile" ) )
3153 writableDrivers << QStringLiteral(
"DBF file" );
3155 if ( OGR_Dr_TestCapability( drv,
"CreateDataSource" ) != 0 )
3158 if ( drvName == QLatin1String(
"MapInfo File" ) )
3160 writableDrivers << QStringLiteral(
"MapInfo MIF" );
3162 else if ( drvName == QLatin1String(
"SQLite" ) )
3169 QString option = QStringLiteral(
"SPATIALITE=YES" );
3170 char *options[2] = { CPLStrdup( option.toLocal8Bit().constData() ),
nullptr };
3171 OGRSFDriverH poDriver;
3173 poDriver = OGRGetDriverByName( drvName.toLocal8Bit().constData() );
3176 gdal::ogr_datasource_unique_ptr ds( OGR_Dr_CreateDataSource( poDriver, QStringLiteral(
"/vsimem/spatialitetest.sqlite" ).toUtf8().constData(), options ) );
3179 writableDrivers << QStringLiteral(
"SpatiaLite" );
3180 OGR_Dr_DeleteDataSource( poDriver, QStringLiteral(
"/vsimem/spatialitetest.sqlite" ).toUtf8().constData() );
3183 CPLFree( options[0] );
3185 writableDrivers << drvName;
3190 results.reserve( writableDrivers.count() );
3191 for (
const QString &drvName : qgis::as_const( writableDrivers ) )
3207 if ( a.
driverName == QLatin1String(
"GPKG" ) )
3209 else if ( b.driverName == QLatin1String(
"GPKG" ) )
3211 else if ( a.
driverName == QLatin1String(
"ESRI Shapefile" ) )
3213 else if ( b.driverName == QLatin1String(
"ESRI Shapefile" ) )
3217 return a.
longName.toLower().localeAwareCompare( b.longName.toLower() ) < 0;
3224 QString ext = extension.trimmed();
3225 if ( ext.isEmpty() )
3228 if ( ext.startsWith(
'.' ) )
3232 int const drvCount = GDALGetDriverCount();
3234 for (
int i = 0; i < drvCount; ++i )
3236 GDALDriverH drv = GDALGetDriver( i );
3240 if ( CSLFetchBoolean( driverMetadata, GDAL_DCAP_CREATE,
false ) && CSLFetchBoolean( driverMetadata, GDAL_DCAP_VECTOR,
false ) )
3242 QString drvName = GDALGetDriverShortName( drv );
3243 QStringList driverExtensions = QString( GDALGetMetadataItem( drv, GDAL_DMD_EXTENSIONS,
nullptr ) ).split(
' ' );
3245 const auto constDriverExtensions = driverExtensions;
3246 for (
const QString &driver : constDriverExtensions )
3248 if ( driver.compare( ext, Qt::CaseInsensitive ) == 0 )
3259 QString filterString;
3263 if ( !filterString.isEmpty() )
3264 filterString += QLatin1String(
";;" );
3266 filterString += details.filterString;
3268 return filterString;
3277 return QStringLiteral(
"%1 (%2 %3)" ).arg( metadata.
trLongName,
3278 metadata.
glob.toLower(),
3279 metadata.
glob.toUpper() );
3284 if ( codecName == QLatin1String(
"System" ) )
3285 return QStringLiteral(
"LDID/0" );
3287 QRegExp re = QRegExp( QString(
"(CP|windows-|ISO[ -])(.+)" ), Qt::CaseInsensitive );
3288 if ( re.exactMatch( codecName ) )
3290 QString
c = re.cap( 2 ).remove(
'-' );
3292 c.toInt( &isNumber );
3320 OGRStyleTableH ogrStyleTable = OGR_STBL_Create();
3321 OGRStyleMgrH styleManager = OGR_SM_Create( ogrStyleTable );
3324 int nTotalLevels = 0;
3326 QgsSymbolList::iterator symbolIt = symbolList.begin();
3327 for ( ; symbolIt != symbolList.end(); ++symbolIt )
3329 double mmsf = mmScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
3330 double musf = mapUnitScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
3332 int nLevels = ( *symbolIt )->symbolLayerCount();
3333 for (
int i = 0; i < nLevels; ++i )
3335 mSymbolLayerTable.insert( ( *symbolIt )->symbolLayer( i ), QString::number( nTotalLevels ) );
3336 OGR_SM_AddStyle( styleManager, QString::number( nTotalLevels ).toLocal8Bit(),
3337 ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf ).toLocal8Bit() );
3341 OGR_DS_SetStyleTableDirectly( ds, ogrStyleTable );
3347 if ( !details.renderer )
3350 mRenderContext.expressionContext() = details.expressionContext;
3352 QHash< QgsSymbol *, QList<QgsFeature> > features;
3361 startRender( details.renderer.get(), details.sourceFields );
3372 if ( fet.hasGeometry() )
3376 fet.setGeometry( g );
3381 QString msg = QObject::tr(
"Failed to transform, writing stopped. (Exception: %1)" )
3385 *errorMessage = msg;
3390 mRenderContext.expressionContext().setFeature( fet );
3392 featureSymbol = mRenderer->symbolForFeature( fet, mRenderContext );
3393 if ( !featureSymbol )
3398 QHash< QgsSymbol *, QList<QgsFeature> >::iterator it = features.find( featureSymbol );
3399 if ( it == features.end() )
3401 it = features.insert( featureSymbol, QList<QgsFeature>() );
3403 it.value().append( fet );
3408 QgsSymbolList symbols = mRenderer->symbols( mRenderContext );
3409 for (
int i = 0; i < symbols.count(); i++ )
3415 if ( level < 0 || level >= 1000 )
3418 while ( level >= levels.count() )
3420 levels[level].append( item );
3425 int nTotalFeatures = 0;
3428 for (
int l = 0; l < levels.count(); l++ )
3431 for (
int i = 0; i < level.count(); i++ )
3434 QHash< QgsSymbol *, QList<QgsFeature> >::iterator levelIt = features.find( item.
symbol() );
3435 if ( levelIt == features.end() )
3441 double mmsf = mmScaleFactor(
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
3442 double musf = mapUnitScaleFactor(
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
3444 int llayer = item.
layer();
3445 QList<QgsFeature> &featureList = levelIt.value();
3446 QList<QgsFeature>::iterator featureIt = featureList.begin();
3447 for ( ; featureIt != featureList.end(); ++featureIt )
3457 QString styleString = levelIt.key()->symbolLayer( llayer )->ogrFeatureStyle( mmsf, musf );
3458 if ( !styleString.isEmpty() )
3460 OGR_F_SetStyleString( ogrFeature.get(), styleString.toLocal8Bit().constData() );
3461 if ( !writeFeature(
mLayer, ogrFeature.get() ) )
3472 if ( nErrors > 0 && errorMessage )
3474 *errorMessage += QObject::tr(
"\nOnly %1 of %2 features written." ).arg( nTotalFeatures - nErrors ).arg( nTotalFeatures );
3491 return 1000 / scale;
3508 return scale / 1000;
3516 mRenderer = createSymbologyRenderer( sourceRenderer );
3522 mRenderer->startRender( mRenderContext, fields );
3525 void QgsVectorFileWriter::stopRender()
3532 mRenderer->stopRender( mRenderContext );
3535 std::unique_ptr<QgsFeatureRenderer> QgsVectorFileWriter::createSymbologyRenderer(
QgsFeatureRenderer *sourceRenderer )
const 3541 if ( !sourceRenderer )
3546 return std::unique_ptr< QgsFeatureRenderer >( sourceRenderer->
clone() );
3553 const QSet<QString> rendererAttributes = renderer->
usedAttributes( context );
3554 for (
const QString &attr : rendererAttributes )
3559 attList.append( index );
3565 QStringList QgsVectorFileWriter::concatenateOptions(
const QMap<QString, QgsVectorFileWriter::Option *> &options )
3568 QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
3570 for ( it = options.constBegin(); it != options.constEnd(); ++it )
3573 switch ( option->
type )
3580 list.append( QStringLiteral(
"%1=%2" ).arg( it.key() ).arg( opt->
defaultValue ) );
3590 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
defaultValue ) );
3600 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
defaultValue ) );
3609 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
mValue ) );
3620 OGRSFDriverH hDriver =
nullptr;
3624 QString drvName = OGR_Dr_GetName( hDriver );
3625 QgsVectorFileWriter::EditionCapabilities caps =
nullptr;
3626 if ( OGR_DS_TestCapability( hDS.get(), ODsCCreateLayer ) )
3631 if ( !( drvName == QLatin1String(
"ESRI Shapefile" ) && QFile::exists( datasetName ) ) )
3634 if ( OGR_DS_TestCapability( hDS.get(), ODsCDeleteLayer ) )
3638 int layer_count = OGR_DS_GetLayerCount( hDS.get() );
3641 OGRLayerH hLayer = OGR_DS_GetLayer( hDS.get(), 0 );
3644 if ( OGR_L_TestCapability( hLayer, OLCSequentialWrite ) )
3647 if ( OGR_L_TestCapability( hLayer, OLCCreateField ) )
3658 const QString &layerNameIn )
3660 OGRSFDriverH hDriver =
nullptr;
3666 if ( layerName.isEmpty() )
3667 layerName = QFileInfo( datasetName ).baseName();
3669 return OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
3678 OGRSFDriverH hDriver =
nullptr;
3682 OGRLayerH hLayer = OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
3688 OGRFeatureDefnH defn = OGR_L_GetLayerDefn( hLayer );
3690 for (
int idx : constAttributes )
3693 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 a specific symbol layer contained in the symbol.
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).
QString toWkt() const
Returns a WKT representation of this 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 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.